2024-04-30 12:08:37 +00:00
import QtQuick 2.15
2024-05-31 09:58:47 +00:00
2024-04-30 12:08:37 +00:00
import QtTest 1.15
2024-05-31 09:58:47 +00:00
import "helpers/wallet_connect.js" as Testing
2024-04-30 12:08:37 +00:00
2024-05-31 09:58:47 +00:00
import StatusQ . Core . Utils 0.1
2024-04-30 13:21:19 +00:00
2024-04-30 12:08:37 +00:00
import QtQuick . Controls 2.15
import Storybook 1.0
2024-05-06 20:22:43 +00:00
import AppLayouts . Wallet . services . dapps 1.0
2024-05-31 09:58:47 +00:00
import AppLayouts . Wallet . services . dapps . types 1.0
2024-05-31 09:34:59 +00:00
import AppLayouts . Profile . stores 1.0
import AppLayouts . Wallet . panels 1.0
2024-07-17 15:49:30 +00:00
import AppLayouts . Wallet . stores 1.0 as WalletStore
2024-05-06 20:22:43 +00:00
2024-05-31 09:58:47 +00:00
import shared . stores 1.0
import utils 1.0
2024-04-30 12:08:37 +00:00
Item {
id: root
2024-05-31 09:58:47 +00:00
2024-06-04 20:45:03 +00:00
width: 600
height: 400
2024-05-31 09:58:47 +00:00
2024-11-07 09:10:10 +00:00
function mockActiveSession ( accountsModel , networksModel , sdk , topic ) {
2024-10-03 18:41:41 +00:00
const account = accountsModel . get ( 1 )
2024-11-07 09:10:10 +00:00
const networks = ModelUtils . modelToFlatArray ( networksModel , "chainId" )
2024-10-03 18:41:41 +00:00
const requestId = 1717149885151715
2024-11-07 09:10:10 +00:00
const session = JSON . parse ( Testing . formatApproveSessionResponse ( networks , [ account . address ] ) )
const sessionProposal = JSON . parse ( Testing . formatSessionProposal ( ) )
sdk . sessionProposal ( sessionProposal )
2024-10-03 18:41:41 +00:00
// Expect to have calls to getActiveSessions from service initialization
const prevRequests = sdk . getActiveSessionsCallbacks . length
2024-11-07 09:10:10 +00:00
sdk . approveSessionResult ( sessionProposal . id , session , null )
2024-10-03 18:41:41 +00:00
// Service might trigger a sessionRequest event following the getActiveSessions call
const callback = sdk . getActiveSessionsCallbacks [ prevRequests ] . callback
callback ( { "b536a" : session } )
2024-11-07 09:10:10 +00:00
return session
}
function mockSessionRequestEvent ( tc , sdk , accountsModel , networksModel ) {
const account = accountsModel . get ( 1 )
const network = networksModel . get ( 1 )
const topic = "b536a"
const requestId = 1717149885151715
const session = mockActiveSession ( accountsModel , networksModel , sdk , topic )
const request = buildSessionRequestResolved ( tc , account . address , network . chainId , topic , requestId )
2024-10-03 18:41:41 +00:00
return { sdk , session , account , network , topic , request }
}
function buildSessionRequest ( chainId , method , params , topic , requestId ) {
return JSON . parse ( Testing . formatSessionRequest ( chainId , method , params , topic , requestId ) )
}
function buildSessionRequestResolved ( testCase , account , network , topic , requestId ) {
const requestObj = buildSessionRequest ( network , Constants . personal_sign , [ ` "${DAppsHelpers.strToHex(" hello world ")}" ` , ` "${account}" ` ] , topic , requestId )
const requestItem = testCase . createTemporaryObject ( sessionRequestComponent , root , {
event: requestObj ,
topic ,
2024-10-18 20:36:10 +00:00
requestId: requestObj . id ,
2024-10-03 18:41:41 +00:00
method: Constants . personal_sign ,
accountAddress: account ,
chainId: network ,
data: "hello world" ,
preparedData: "hello world" ,
2024-10-04 12:49:16 +00:00
expirationTimestamp: ( Date . now ( ) + 10000 ) / 1000 ,
2024-11-07 09:10:10 +00:00
sourceId: Constants . DAppConnectors . WalletConnect ,
dappName: "Test DApp" ,
dappUrl: "https://test.dapp" ,
dappIcon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAcCAYAAACdz7SqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAM2SURBVHgBtVbNbtNAEJ7ZpBQ4pRGF9kQqWqkBRNwnwLlxI9y4NX2CiiOntE9QeINw49a8QdwT3NhKQCKaSj4WUVXmABRqe5hxE+PGTuyk5ZOSXe/ftzs/3y5CBiw/NEzw/cdAaCJAifgXdCA4QGAjggbEvbMf0LJt7aSth6lkHjW4akIG8GI2/1k5H7e7XW2PGRdHqWQU8jdoNytZIrnC7YNPupnUnxtuWF01SjhD77hqwPQosNlrxdt34OTb172xpELoKvrA1QW4EqCZRJyLEnpI7ZBQggThlGvXYVLI3HAeE88vfj85Pno/6FaDiqeoEUZlMA9bvc/7cxyxVa6/SeM5j2Tcdn/hnHsNly520s7KAyN0V17+7pWNGhHVhxYJTNLraosLi8e0kMBxT0FH00IW830oeT/ButBertjRQ5BPO1xUQ1IE2oQUHHZ0K6mdI1RzoSEdpqRg76O2lPgSElKDdz919JYMoxA95QDow7qUykWoxTo5z2YIXsGUsLV2CPD1cDu7MODiQKKnsVmI1jhFyQJvFrb6URxFQWJAYYIZSEF6tKZATitFQpehEm1PkCraWYCE+8Nt5ENBwX8EAd2NNaKQxu0ukVuCqwATQHwnjhphShMuiSAVKZ527E6bzYt78Q3SulxvcAm44K8ntXMqagmkJDUpzNwMZGsqBDqLuDXcLvkvqajcWWgm+ZUI6svlym5fsbITlh9tsgi0Ezs5//vkMtBocqSJOZw84ZrHPiXFJ6UwECx5A/FbqNXX2hAiefkzqCNRha1Wi8yJgddeCk4qHzkK1aMgdypfshYRbkTGm3z0Rs6LW0REgDXVEMuMI0TE5kDlgkv8+PjIKRYXfzPxEyH2EYzDzv7L4q1FHsvpg8Gkt186OlGp5uYXZMjzkYS8txwfQnj63//APmzDIF1yWJVrCDJgeZVfjTjCj0KicC3qlny0053FZ/k/PFnyy6P2yv1Kk1T/1eCGF/pEYCncGI6DCzIo/uGnRvg8CfzE5MEPoQGT4Pz5Uj3oxp+hMe0V4oOOrssOMfmWyMJo5X1cG2WZkYIvO2Tn85sGXwg5B5Q9kiKMas5DntPr6Oq4+/gvs8hkkbAzoC8AAAAASUVORK5CYII="
2024-10-03 18:41:41 +00:00
} )
return requestItem
}
2024-07-04 13:32:04 +00:00
Component {
id: sdkComponent
WalletConnectSDKBase {
property bool sdkReady: true
2024-11-07 09:10:10 +00:00
enabled: true
2024-07-04 13:32:04 +00:00
property var getActiveSessionsCallbacks: [ ]
getActiveSessions: function ( callback ) {
getActiveSessionsCallbacks . push ( { callback } )
}
property int pairCalled: 0
pair: function ( ) {
pairCalled ++
}
property var buildApprovedNamespacesCalls: [ ]
2024-10-03 18:41:41 +00:00
buildApprovedNamespaces: function ( id , params , supportedNamespaces ) {
buildApprovedNamespacesCalls . push ( { id , params , supportedNamespaces } )
2024-07-04 13:32:04 +00:00
}
property var approveSessionCalls: [ ]
approveSession: function ( sessionProposalJson , approvedNamespaces ) {
approveSessionCalls . push ( { sessionProposalJson , approvedNamespaces } )
}
2024-07-15 17:30:27 +00:00
property var acceptSessionRequestCalls: [ ]
acceptSessionRequest: function ( topic , id , signature ) {
acceptSessionRequestCalls . push ( { topic , id , signature } )
}
2024-07-04 13:32:04 +00:00
property var rejectSessionRequestCalls: [ ]
rejectSessionRequest: function ( topic , id , error ) {
rejectSessionRequestCalls . push ( { topic , id , error } )
}
}
}
Component {
id: serviceComponent
2024-11-07 09:10:10 +00:00
DAppsService {
2024-07-04 13:32:04 +00:00
property var onApproveSessionResultTriggers: [ ]
onApproveSessionResult: function ( session , error ) {
onApproveSessionResultTriggers . push ( { session , error } )
}
property var onDisplayToastMessageTriggers: [ ]
2024-10-04 12:49:16 +00:00
onDisplayToastMessage: function ( message , type ) {
onDisplayToastMessageTriggers . push ( { message , type } )
2024-07-04 13:32:04 +00:00
}
2024-07-24 12:50:54 +00:00
property var onPairingValidatedTriggers: [ ]
onPairingValidated: function ( validationState ) {
onPairingValidatedTriggers . push ( { validationState } )
}
2024-07-04 13:32:04 +00:00
}
}
Component {
id: dappsStoreComponent
DAppsStore {
property string dappsListReceivedJsonStr: '[]'
signal dappsListReceived ( string dappsJson )
signal userAuthenticated ( string topic , string id , string password , string pin )
signal userAuthenticationFailed ( string topic , string id )
2024-10-03 18:41:41 +00:00
signal signingResult ( string topic , string id , string data )
2024-07-04 13:32:04 +00:00
2024-11-18 13:20:10 +00:00
signal estimatedTimeResponse ( string topic , int timeCategory , bool success )
signal suggestedFeesResponse ( string topic , var suggestedFeesJsonObj , bool success )
signal estimatedGasResponse ( string topic , string gasEstimate , bool success )
2024-07-04 13:32:04 +00:00
// By default, return no dapps in store
function getDapps ( ) {
dappsListReceived ( dappsListReceivedJsonStr )
return true
}
property var addWalletConnectSessionCalls: [ ]
function addWalletConnectSession ( sessionJson ) {
addWalletConnectSessionCalls . push ( { sessionJson } )
2024-07-24 12:50:54 +00:00
return true
2024-07-04 13:32:04 +00:00
}
property var authenticateUserCalls: [ ]
function authenticateUser ( topic , id , address ) {
authenticateUserCalls . push ( { topic , id , address } )
}
property var signMessageCalls: [ ]
function signMessage ( topic , id , address , password , message ) {
signMessageCalls . push ( { topic , id , address , password , message } )
}
2024-07-01 21:02:05 +00:00
property var safeSignTypedDataCalls: [ ]
function safeSignTypedData ( topic , id , address , password , message , chainId , legacy ) {
safeSignTypedDataCalls . push ( { topic , id , address , password , message , chainId , legacy } )
2024-07-04 13:32:04 +00:00
}
2024-06-27 14:15:17 +00:00
property var updateWalletConnectSessionsCalls: [ ]
function updateWalletConnectSessions ( activeTopicsJson ) {
updateWalletConnectSessionsCalls . push ( { activeTopicsJson } )
}
2024-07-17 15:49:30 +00:00
2024-11-18 13:20:10 +00:00
function requestEstimatedTime ( topic , chainId , maxFeePerGas ) {
estimatedTimeResponse ( topic , Constants . TransactionEstimatedTime . LessThanThreeMins , true )
2024-07-17 15:49:30 +00:00
}
property var mockedSuggestedFees: ( {
gasPrice: 2.0 ,
baseFee: 5.0 ,
maxPriorityFeePerGas: 2.0 ,
2024-11-18 13:20:10 +00:00
maxFeePerGasLow: 1.0 ,
maxFeePerGasMedium: 1.1 ,
maxFeePerGasHigh: 1.2 ,
2024-07-17 15:49:30 +00:00
l1GasFee: 0.0 ,
eip1559Enabled: true
} )
2024-07-17 16:36:32 +00:00
2024-11-18 13:20:10 +00:00
function requestSuggestedFees ( topic , chainId ) {
suggestedFeesResponse ( topic , mockedSuggestedFees , true )
}
function requestGasEstimate ( topic , chainId , tx ) {
estimatedGasResponse ( topic , "0x5208" , true )
2024-07-17 15:49:30 +00:00
}
2024-07-17 16:36:32 +00:00
function hexToDec ( hex ) {
if ( hex . length > "0xfffffffffffff" . length ) {
console . warn ( ` Beware of possible loss of precision converting $ { hex } ` )
}
return parseInt ( hex , 16 ) . toString ( )
}
2024-07-04 13:32:04 +00:00
}
}
Component {
id: walletStoreComponent
2024-07-03 20:46:00 +00:00
QtObject {
2024-06-29 20:24:05 +00:00
readonly property ListModel filteredFlatModel: ListModel {
2024-07-17 15:49:30 +00:00
ListElement {
chainId: 1
layer: 1
}
2024-07-04 13:32:04 +00:00
ListElement {
chainId: 2
chainName: "Test Chain"
iconUrl: "network/Network=Ethereum"
2024-07-17 15:49:30 +00:00
layer: 2
}
// Used by tst_balanceCheck
ListElement {
chainId: 11155111
layer: 1
}
// Used by tst_balanceCheck
ListElement {
2024-10-16 20:28:32 +00:00
chainId: 421614
2024-07-17 15:49:30 +00:00
layer: 2
2024-07-04 13:32:04 +00:00
}
}
2024-10-23 12:58:45 +00:00
readonly property ListModel filteredFlatModelWithOnlineStat: ListModel {
ListElement {
chainId: 1
layer: 1
isOnline: true
}
ListElement {
chainId: 2
chainName: "Test Chain"
iconUrl: "network/Network=Ethereum"
layer: 2
isOnline: true
}
// Used by tst_balanceCheck
ListElement {
chainId: 11155111
layer: 1
isOnline: true
}
// Used by tst_balanceCheck
ListElement {
2024-11-07 09:10:10 +00:00
chainId: 421614
2024-10-23 12:58:45 +00:00
layer: 2
isOnline: true
}
}
2024-06-29 20:24:05 +00:00
readonly property ListModel nonWatchAccounts: ListModel {
2024-08-05 13:41:20 +00:00
ListElement {
address: "0x1"
keycardAccount: false
}
2024-07-04 13:32:04 +00:00
ListElement {
address: "0x2"
name: "helloworld"
emoji: "😋"
color: "#2A4AF5"
2024-08-05 13:41:20 +00:00
keycardAccount: false
}
ListElement {
address: "0x3a"
keycardAccount: false
2024-07-04 13:32:04 +00:00
}
2024-07-17 15:49:30 +00:00
// Account from GroupedAccountsAssetsModel
2024-08-05 13:41:20 +00:00
ListElement {
address: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240"
keycardAccount: false
}
2024-07-04 13:32:04 +00:00
}
2024-07-17 15:49:30 +00:00
readonly property var currencyStore: CurrenciesStore { }
readonly property var walletAssetsStore: assetsStoreMock
2024-10-03 18:41:41 +00:00
readonly property string selectedAddress: "0x1"
}
}
Component {
id: sessionRequestComponent
SessionRequestResolved {
2024-07-04 13:32:04 +00:00
}
}
2024-07-17 15:49:30 +00:00
WalletStore . WalletAssetsStore {
id: assetsStoreMock
// Silence warnings
assetsWithFilteredBalances: ListModel { }
readonly property var groupedAccountAssetsModel: groupedAccountsAssetsModel
}
2024-07-04 13:32:04 +00:00
Component {
2024-11-07 09:10:10 +00:00
id: dappsModuleComponent
2024-07-04 13:32:04 +00:00
2024-11-07 09:10:10 +00:00
DAppsModule {
2024-07-17 10:46:43 +00:00
currenciesStore: CurrenciesStore { }
2024-11-07 09:10:10 +00:00
groupedAccountAssetsModel: assetsStoreMock . groupedAccountAssetsModel
2024-07-04 13:32:04 +00:00
}
}
TestCase {
2024-11-07 09:10:10 +00:00
id: dappsModuleTest
name: "DAppsModuleTest"
2024-07-17 15:49:30 +00:00
// Ensure mocked GroupedAccountsAssetsModel is properly initialized
when: windowShown
2024-07-04 13:32:04 +00:00
2024-11-07 09:10:10 +00:00
property DAppsModule handler: null
2024-07-04 13:32:04 +00:00
function init ( ) {
let walletStore = createTemporaryObject ( walletStoreComponent , root )
verify ( ! ! walletStore )
2024-11-07 09:10:10 +00:00
let sdk = createTemporaryObject ( sdkComponent , root , { projectId: "12ab" , enabled: true } )
2024-07-04 13:32:04 +00:00
verify ( ! ! sdk )
2024-11-07 09:10:10 +00:00
let bcSdk = createTemporaryObject ( sdkComponent , root , { projectId: "12ab" , enabled: false } )
verify ( ! ! bcSdk )
2024-07-04 13:32:04 +00:00
let store = createTemporaryObject ( dappsStoreComponent , root )
verify ( ! ! store )
2024-11-07 09:10:10 +00:00
handler = createTemporaryObject ( dappsModuleComponent , root , {
wcSdk: sdk ,
bcSdk: bcSdk ,
2024-06-29 20:24:05 +00:00
store: store ,
accountsModel: walletStore . nonWatchAccounts ,
2024-10-23 12:58:45 +00:00
networksModel: walletStore . filteredFlatModelWithOnlineStat
2024-06-29 20:24:05 +00:00
} )
2024-07-04 13:32:04 +00:00
verify ( ! ! handler )
2024-10-23 12:58:45 +00:00
sdk . getActiveSessionsCallbacks = [ ]
2024-07-04 13:32:04 +00:00
}
function test_TestAuthentication ( ) {
2024-11-07 09:10:10 +00:00
let td = mockSessionRequestEvent ( this , handler . wcSdk , handler . accountsModel , handler . networksModel )
handler . wcSdk . sessionRequestEvent ( td . request . event )
2024-10-18 21:22:06 +00:00
let request = handler . requestsModel . findById ( td . request . requestId )
request . accept ( )
2024-07-04 13:32:04 +00:00
compare ( handler . store . authenticateUserCalls . length , 1 , "expected a call to store.authenticateUser" )
let store = handler . store
2024-10-18 20:36:10 +00:00
store . userAuthenticated ( td . topic , td . request . requestId , "hello world" , "" )
2024-07-04 13:32:04 +00:00
compare ( store . signMessageCalls . length , 1 , "expected a call to store.signMessage" )
compare ( store . signMessageCalls [ 0 ] . message , td . request . data )
}
function test_onSessionRequestEventDifferentCaseForAddress ( ) {
2024-11-07 09:10:10 +00:00
const sdk = handler . wcSdk
2024-07-29 14:39:56 +00:00
const testAddressUpper = "0x3A"
const chainId = 2
const method = "personal_sign"
const message = "hello world"
const params = [ ` "${DAppsHelpers.strToHex(message)}" ` , ` "${testAddressUpper}" ` ]
const topic = "b536a"
const session = JSON . parse ( Testing . formatSessionRequest ( chainId , method , params , topic ) )
2024-07-04 13:32:04 +00:00
// Expect to have calls to getActiveSessions from service initialization
2024-07-29 14:39:56 +00:00
const prevRequests = sdk . getActiveSessionsCallbacks . length
2024-11-07 09:10:10 +00:00
mockActiveSession ( handler . accountsModel , handler . networksModel , sdk , topic )
2024-07-04 13:32:04 +00:00
sdk . sessionRequestEvent ( session )
compare ( sdk . getActiveSessionsCallbacks . length , 1 , "expected DAppsRequestHandler call sdk.getActiveSessions" )
}
2024-07-17 15:49:30 +00:00
2024-07-23 10:49:34 +00:00
// Tests that the request is ignored if not in the current profile (don't have the PK for the address)
function test_onSessionRequestEventMissingAddress ( ) {
2024-11-07 09:10:10 +00:00
const sdk = handler . wcSdk
2024-07-29 14:39:56 +00:00
const testAddressUpper = "0xY"
const chainId = 2
const method = "personal_sign"
const message = "hello world"
const params = [ ` "${DAppsHelpers.strToHex(message)}" ` , ` "${testAddressUpper}" ` ]
const topic = "b536a"
const session = JSON . parse ( Testing . formatSessionRequest ( chainId , method , params , topic ) )
2024-11-07 09:10:10 +00:00
mockActiveSession ( handler . accountsModel , handler . networksModel , sdk , topic )
sdk . getActiveSessionsCallbacks = [ ]
2024-07-23 10:49:34 +00:00
sdk . sessionRequestEvent ( session )
compare ( sdk . getActiveSessionsCallbacks . length , 0 , "expected DAppsRequestHandler don't call sdk.getActiveSessions" )
2024-11-07 09:10:10 +00:00
compare ( sdk . rejectSessionRequestCalls . length , 1 , "expected to reject the request" )
2024-07-23 10:49:34 +00:00
}
2024-07-17 15:49:30 +00:00
function test_balanceCheck_data ( ) {
return [ {
tag: "have_enough_funds" ,
chainId: 11155111 ,
expect: {
haveEnoughForFees: true ,
2024-10-03 18:41:41 +00:00
fee: "0.0000231"
2024-07-17 15:49:30 +00:00
}
} ,
{
tag: "doest_have_enough_funds" ,
chainId: 11155111 ,
// Override the suggestedFees to a higher value
maxFeePerGasM: 1000000.0 , /*GWEI*/
expect: {
haveEnoughForFees: false ,
2024-10-03 18:41:41 +00:00
fee: "21"
2024-07-17 15:49:30 +00:00
}
} ,
{
tag: "check_l2_doesnt_have_enough_funds_on_l1" ,
2024-10-16 20:28:32 +00:00
chainId: 421614 ,
2024-07-17 15:49:30 +00:00
// Override the l1 additional fees
l1GasFee: 1000000000.0 ,
expect: {
haveEnoughForFees: false ,
2024-10-03 18:41:41 +00:00
fee: "1.0000231"
2024-07-17 15:49:30 +00:00
}
} ,
{
tag: "check_l2_doesnt_have_enough_funds_on_l2" ,
2024-10-16 20:28:32 +00:00
chainId: 421614 ,
2024-07-17 15:49:30 +00:00
// Override the l2 to a higher value
maxFeePerGasM: 1000000.0 , /*GWEI*/
// Override the l1 additional fees
l1GasFee: 10.0 ,
expect: {
haveEnoughForFees: false ,
2024-10-03 18:41:41 +00:00
fee: "21.00000001"
2024-07-17 15:49:30 +00:00
}
} ]
}
function test_balanceCheck ( data ) {
2024-11-07 09:10:10 +00:00
let sdk = handler . wcSdk
2024-07-17 15:49:30 +00:00
// Override the suggestedFees
if ( ! ! data . maxFeePerGasM ) {
2024-11-18 13:20:10 +00:00
handler . store . mockedSuggestedFees . maxFeePerGasMedium = data . maxFeePerGasM
2024-07-17 15:49:30 +00:00
}
if ( ! ! data . l1GasFee ) {
handler . store . mockedSuggestedFees . l1GasFee = data . l1GasFee
}
let testAddress = "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240"
let chainId = data . chainId
let method = "eth_sendTransaction"
let message = "hello world"
let params = [ ` {
"data" : "0x" ,
"from" : "${testAddress}" ,
"to" : "0x2" ,
"value" : "0x12345"
} ` ]
let topic = "b536a"
let session = JSON . parse ( Testing . formatSessionRequest ( chainId , method , params , topic ) )
2024-11-07 09:10:10 +00:00
mockActiveSession ( handler . accountsModel , handler . networksModel , sdk , topic )
2024-07-17 15:49:30 +00:00
sdk . sessionRequestEvent ( session )
compare ( sdk . getActiveSessionsCallbacks . length , 1 , "expected DAppsRequestHandler call sdk.getActiveSessions" )
let callback = sdk . getActiveSessionsCallbacks [ 0 ] . callback
callback ( { "b536a" : JSON . parse ( Testing . formatApproveSessionResponse ( [ chainId , 7 ] , [ testAddress ] ) ) } )
2024-10-03 18:41:41 +00:00
let request = handler . requestsModel . findById ( session . id )
2024-11-18 13:20:10 +00:00
request . setActive ( )
2024-10-03 18:41:41 +00:00
verify ( ! ! request , "expected request to be found" )
2024-11-18 13:20:10 +00:00
compare ( request . fiatMaxFees . toFixed ( ) , data . expect . fee , "expected fiatMaxFees to be set" )
2024-07-17 15:49:30 +00:00
// storybook's CurrenciesStore mock up getFiatValue returns the balance
2024-11-18 13:20:10 +00:00
compare ( request . ethMaxFees , data . expect . fee , "expected ethMaxFees to be set" )
2024-10-03 18:41:41 +00:00
verify ( request . haveEnoughFunds , "expected haveEnoughFunds to be set" )
compare ( request . haveEnoughFees , data . expect . haveEnoughForFees , "expected haveEnoughForFees to be set" )
verify ( ! ! request . feesInfo , "expected feesInfo to be set" )
2024-07-17 15:49:30 +00:00
}
2024-10-04 12:49:16 +00:00
function test_sessionRequestExpiryInTheFuture ( ) {
2024-11-07 09:10:10 +00:00
const sdk = handler . wcSdk
2024-10-04 12:49:16 +00:00
const testAddressUpper = "0x3A"
const chainId = 2
const method = "personal_sign"
const message = "hello world"
const params = [ ` "${DAppsHelpers.strToHex(message)}" ` , ` "${testAddressUpper}" ` ]
const topic = "b536a"
const session = JSON . parse ( Testing . formatSessionRequest ( chainId , method , params , topic ) )
verify ( session . params . request . expiryTimestamp > Date . now ( ) / 1000 , "expected expiryTimestamp to be in the future" )
// Expect to have calls to getActiveSessions from service initialization
const prevRequests = sdk . getActiveSessionsCallbacks . length
2024-11-07 09:10:10 +00:00
mockActiveSession ( handler . accountsModel , handler . networksModel , sdk , topic )
2024-10-04 12:49:16 +00:00
sdk . sessionRequestEvent ( session )
verify ( handler . requestsModel . count === 1 , "expected a request to be added" )
const request = handler . requestsModel . findRequest ( topic , session . id )
verify ( ! ! request , "expected request to be found" )
verify ( ! request . isExpired ( ) , "expected request to not be expired" )
}
function test_sessionRequestExpiryInThePast ( )
{
2024-11-07 09:10:10 +00:00
const sdk = handler . wcSdk
2024-10-04 12:49:16 +00:00
const testAddressUpper = "0x3A"
const chainId = 2
const method = "personal_sign"
const message = "hello world"
const params = [ ` "${DAppsHelpers.strToHex(message)}" ` , ` "${testAddressUpper}" ` ]
const topic = "b536a"
const session = JSON . parse ( Testing . formatSessionRequest ( chainId , method , params , topic ) )
session . params . request . expiryTimestamp = ( Date . now ( ) - 10000 ) / 1000
verify ( session . params . request . expiryTimestamp < Date . now ( ) / 1000 , "expected expiryTimestamp to be in the past" )
2024-11-07 09:10:10 +00:00
mockActiveSession ( handler . accountsModel , handler . networksModel , sdk , topic )
2024-10-04 12:49:16 +00:00
sdk . sessionRequestEvent ( session )
verify ( handler . requestsModel . count === 1 , "expected a request to be added" )
const request = handler . requestsModel . findRequest ( topic , session . id )
verify ( ! ! request , "expected request to be found" )
verify ( request . isExpired ( ) , "expected request to be expired" )
}
function test_wcSignalsSessionRequestExpiry ( )
{
2024-11-07 09:10:10 +00:00
const sdk = handler . wcSdk
2024-10-04 12:49:16 +00:00
const testAddressUpper = "0x3A"
const chainId = 2
const method = "personal_sign"
const message = "hello world"
const params = [ ` "${DAppsHelpers.strToHex(message)}" ` , ` "${testAddressUpper}" ` ]
const topic = "b536a"
const session = JSON . parse ( Testing . formatSessionRequest ( chainId , method , params , topic ) )
verify ( session . params . request . expiryTimestamp > Date . now ( ) / 1000 , "expected expiryTimestamp to be in the future" )
2024-11-07 09:10:10 +00:00
mockActiveSession ( handler . accountsModel , handler . networksModel , sdk , topic )
2024-10-04 12:49:16 +00:00
sdk . sessionRequestEvent ( session )
const request = handler . requestsModel . findRequest ( topic , session . id )
verify ( ! ! request , "expected request to be found" )
verify ( ! request . isExpired ( ) , "expected request to not be expired" )
sdk . sessionRequestExpired ( session . id )
verify ( request . isExpired ( ) , "expected request to be expired" )
}
function test_acceptExpiredSessionRequest ( )
{
2024-11-07 09:10:10 +00:00
const sdk = handler . wcSdk
2024-10-04 12:49:16 +00:00
const testAddressUpper = "0x3A"
const chainId = 2
const method = "personal_sign"
const message = "hello world"
const params = [ ` "${DAppsHelpers.strToHex(message)}" ` , ` "${testAddressUpper}" ` ]
const topic = "b536a"
const session = JSON . parse ( Testing . formatSessionRequest ( chainId , method , params , topic ) )
session . params . request . expiryTimestamp = ( Date . now ( ) - 10000 ) / 1000
verify ( session . params . request . expiryTimestamp < Date . now ( ) / 1000 , "expected expiryTimestamp to be in the past" )
2024-11-07 09:10:10 +00:00
mockActiveSession ( handler . accountsModel , handler . networksModel , sdk , topic )
2024-10-04 12:49:16 +00:00
sdk . sessionRequestEvent ( session )
verify ( handler . requestsModel . count === 1 , "expected a request to be added" )
const request = handler . requestsModel . findRequest ( topic , session . id )
verify ( ! ! request , "expected request to be found" )
verify ( request . isExpired ( ) , "expected request to be expired" )
verify ( sdk . rejectSessionRequestCalls . length === 0 , "expected no call to sdk.rejectSessionRequest" )
ignoreWarning ( "Error: request expired" )
2024-10-18 21:22:06 +00:00
request . accept ( )
2024-10-04 12:49:16 +00:00
handler . store . userAuthenticated ( topic , session . id , "1234" , "" , message )
verify ( sdk . rejectSessionRequestCalls . length === 1 , "expected a call to sdk.rejectSessionRequest" )
sdk . sessionRequestUserAnswerResult ( topic , session . id , false , "" )
}
function test_rejectExpiredSessionRequest ( )
{
2024-11-07 09:10:10 +00:00
const sdk = handler . wcSdk
2024-10-04 12:49:16 +00:00
const testAddressUpper = "0x3A"
const chainId = 2
const method = "personal_sign"
const message = "hello world"
const params = [ ` "${DAppsHelpers.strToHex(message)}" ` , ` "${testAddressUpper}" ` ]
const topic = "b536a"
const session = JSON . parse ( Testing . formatSessionRequest ( chainId , method , params , topic ) )
session . params . request . expiryTimestamp = ( Date . now ( ) - 10000 ) / 1000
verify ( session . params . request . expiryTimestamp < Date . now ( ) / 1000 , "expected expiryTimestamp to be in the past" )
2024-11-07 09:10:10 +00:00
mockActiveSession ( handler . accountsModel , handler . networksModel , sdk , topic )
2024-10-04 12:49:16 +00:00
sdk . sessionRequestEvent ( session )
verify ( sdk . rejectSessionRequestCalls . length === 0 , "expected no call to sdk.rejectSessionRequest" )
ignoreWarning ( "Error: request expired" )
2024-10-18 21:22:06 +00:00
handler . requestsModel . findRequest ( topic , session . id ) . accept ( )
2024-10-04 12:49:16 +00:00
handler . store . userAuthenticationFailed ( topic , session . id )
verify ( sdk . rejectSessionRequestCalls . length === 1 , "expected a call to sdk.rejectSessionRequest" )
}
function test_signFailedAuthOnExpiredRequest ( )
{
2024-11-07 09:10:10 +00:00
const sdk = handler . wcSdk
2024-10-04 12:49:16 +00:00
const testAddressUpper = "0x3A"
const chainId = 2
const method = "personal_sign"
const message = "hello world"
const params = [ ` "${DAppsHelpers.strToHex(message)}" ` , ` "${testAddressUpper}" ` ]
const topic = "b536a"
const session = JSON . parse ( Testing . formatSessionRequest ( chainId , method , params , topic ) )
session . params . request . expiryTimestamp = ( Date . now ( ) - 10000 ) / 1000
verify ( session . params . request . expiryTimestamp < Date . now ( ) / 1000 , "expected expiryTimestamp to be in the past" )
2024-11-07 09:10:10 +00:00
mockActiveSession ( handler . accountsModel , handler . networksModel , sdk , topic )
2024-10-04 12:49:16 +00:00
sdk . sessionRequestEvent ( session )
verify ( sdk . rejectSessionRequestCalls . length === 0 , "expected no call to sdk.rejectSessionRequest" )
ignoreWarning ( "Error: request expired" )
2024-10-18 21:22:06 +00:00
handler . requestsModel . findRequest ( topic , session . id ) . accept ( )
2024-10-04 12:49:16 +00:00
handler . store . userAuthenticationFailed ( topic , session . id )
verify ( sdk . rejectSessionRequestCalls . length === 1 , "expected a call to sdk.rejectSessionRequest" )
}
2024-07-04 13:32:04 +00:00
}
TestCase {
2024-11-07 09:10:10 +00:00
id: dappsServiceTest
name: "DAppsService"
2024-07-04 13:32:04 +00:00
2024-11-07 09:10:10 +00:00
property DAppsService service: null
2024-07-04 13:32:04 +00:00
SignalSpy {
id: connectDAppSpy
2024-11-07 09:10:10 +00:00
target: dappsServiceTest . service
2024-07-04 13:32:04 +00:00
signalName: "connectDApp"
property var argPos: {
"dappChains" : 0 ,
2024-10-03 18:41:41 +00:00
"dappUrl" : 1 ,
"dappName" : 2 ,
"dappIcon" : 3 ,
"key" : 4 ,
2024-07-04 13:32:04 +00:00
}
}
2024-11-07 09:10:10 +00:00
function populateDAppData ( topic ) {
const dapp = {
topic ,
name: Testing . dappName ,
url: Testing . dappUrl ,
iconUrl: Testing . dappFirstIcon ,
connectorId: 0 ,
accountAddresses: [ { address: "0x123" } ] ,
rawSessions: [ { session: { topic } } ]
2024-07-04 13:32:04 +00:00
}
2024-11-07 09:10:10 +00:00
findChild ( service . dappsModule , "DAppsModel" ) . model . append ( dapp )
2024-07-04 13:32:04 +00:00
}
function init ( ) {
let walletStore = createTemporaryObject ( walletStoreComponent , root )
verify ( ! ! walletStore )
2024-11-07 09:10:10 +00:00
let sdk = createTemporaryObject ( sdkComponent , root , { projectId: "12ab" , enabled: true } )
2024-07-04 13:32:04 +00:00
verify ( ! ! sdk )
2024-11-07 09:10:10 +00:00
let bcSdk = createTemporaryObject ( sdkComponent , root , { projectId: "12ab" , enabled: false } )
2024-07-04 13:32:04 +00:00
let store = createTemporaryObject ( dappsStoreComponent , root )
verify ( ! ! store )
2024-11-07 09:10:10 +00:00
let dappsModuleObj = createTemporaryObject ( dappsModuleComponent , root , {
wcSdk: sdk ,
bcSdk: bcSdk ,
store: store ,
accountsModel: walletStore . nonWatchAccounts ,
networksModel: walletStore . filteredFlatModelWithOnlineStat
} )
service = createTemporaryObject ( serviceComponent , root , {
dappsModule: dappsModuleObj ,
selectedAddress: "" ,
accountsModel: walletStore . nonWatchAccounts
} )
2024-07-04 13:32:04 +00:00
verify ( ! ! service )
}
function cleanup ( ) {
connectDAppSpy . clear ( )
}
2024-07-24 12:50:54 +00:00
function testSetupPair ( sessionProposalPayload ) {
2024-11-07 09:10:10 +00:00
let sdk = service . dappsModule . wcSdk
let accountsModel = service . dappsModule . accountsModel
let networksModel = service . dappsModule . networksModel
let store = service . dappsModule . store
2024-07-04 13:32:04 +00:00
service . pair ( "wc:12ab@1?bridge=https%3A%2F%2Fbridge.walletconnect.org&key=12ab" )
compare ( sdk . pairCalled , 1 , "expected a call to sdk.pair" )
2024-07-24 12:50:54 +00:00
sdk . sessionProposal ( JSON . parse ( sessionProposalPayload ) )
2024-07-04 13:32:04 +00:00
compare ( sdk . buildApprovedNamespacesCalls . length , 1 , "expected a call to sdk.buildApprovedNamespaces" )
var args = sdk . buildApprovedNamespacesCalls [ 0 ]
verify ( ! ! args . supportedNamespaces , "expected supportedNamespaces to be set" )
2024-07-24 12:50:54 +00:00
// All calls to SDK are expected as events to be made by the wallet connect SDK
2024-07-04 13:32:04 +00:00
let chainsForApproval = args . supportedNamespaces . eip155 . chains
2024-11-07 09:10:10 +00:00
let networksArray = ModelUtils . modelToArray ( networksModel ) . map ( entry = > entry . chainId )
2024-07-04 13:32:04 +00:00
verify ( networksArray . every ( chainId = > chainsForApproval . some ( eip155Chain = > eip155Chain === ` eip155: $ { chainId } ` ) ) ,
"expect all the networks to be present" )
// We test here all accounts for one chain only, we have separate tests to validate that all accounts are present
let allAccountsForApproval = args . supportedNamespaces . eip155 . accounts
2024-11-07 09:10:10 +00:00
let accountsArray = ModelUtils . modelToArray ( accountsModel ) . map ( entry = > entry . address )
2024-07-04 13:32:04 +00:00
verify ( accountsArray . every ( address = > allAccountsForApproval . some ( eip155Address = > eip155Address === ` eip155: $ { networksArray [ 0 ] } : $ { address } ` ) ) ,
"expect at least all accounts for the first chain to be present"
)
2024-11-07 09:10:10 +00:00
return { sdk , store , networksArray , accountsArray , networksModel , accountsModel }
2024-07-24 12:50:54 +00:00
}
function test_TestPairing ( ) {
2024-11-07 09:10:10 +00:00
const { sdk , store , networksArray , accountsArray , networksModel , accountsModel } = testSetupPair ( Testing . formatSessionProposal ( ) )
2024-07-24 12:50:54 +00:00
2024-10-03 18:41:41 +00:00
compare ( sdk . buildApprovedNamespacesCalls . length , 1 , "expected a call to sdk.buildApprovedNamespaces" )
2024-07-04 13:32:04 +00:00
let allApprovedNamespaces = JSON . parse ( Testing . formatBuildApprovedNamespacesResult ( networksArray , accountsArray ) )
2024-10-03 18:41:41 +00:00
sdk . buildApprovedNamespacesResult ( sdk . buildApprovedNamespacesCalls [ 0 ] . id , allApprovedNamespaces , "" )
2024-07-04 13:32:04 +00:00
compare ( connectDAppSpy . count , 1 , "expected a call to service.connectDApp" )
let connectArgs = connectDAppSpy . signalArguments [ 0 ]
2024-10-03 18:41:41 +00:00
2024-06-29 20:24:05 +00:00
compare ( connectArgs [ connectDAppSpy . argPos . dappChains ] , networksArray , "expected all provided networks (walletStore.filteredFlatModel) for the dappChains" )
2024-10-03 18:41:41 +00:00
compare ( connectArgs [ connectDAppSpy . argPos . dappUrl ] , Testing . dappUrl , "expected dappUrl to be set" )
compare ( connectArgs [ connectDAppSpy . argPos . dappName ] , Testing . dappName , "expected dappName to be set" )
compare ( connectArgs [ connectDAppSpy . argPos . dappIcon ] , Testing . dappFirstIcon , "expected dappIcon to be set" )
verify ( ! ! connectArgs [ connectDAppSpy . argPos . key ] , "expected key to be set" )
2024-07-04 13:32:04 +00:00
2024-11-07 09:10:10 +00:00
let selectedAccount = accountsModel . get ( 1 ) . address
2024-10-03 18:41:41 +00:00
service . approvePairSession ( connectArgs [ connectDAppSpy . argPos . key ] , connectArgs [ connectDAppSpy . argPos . dappChains ] , selectedAccount )
2024-07-04 13:32:04 +00:00
compare ( sdk . buildApprovedNamespacesCalls . length , 2 , "expected a call to sdk.buildApprovedNamespaces" )
2024-07-24 12:50:54 +00:00
const approvedArgs = sdk . buildApprovedNamespacesCalls [ 1 ]
verify ( ! ! approvedArgs . supportedNamespaces , "expected supportedNamespaces to be set" )
2024-07-04 13:32:04 +00:00
// We test here that only one account for all chains is provided
2024-07-24 12:50:54 +00:00
let accountsForApproval = approvedArgs . supportedNamespaces . eip155 . accounts
2024-07-04 13:32:04 +00:00
compare ( accountsForApproval . length , networksArray . length , "expect only one account per chain" )
2024-10-03 18:41:41 +00:00
compare ( accountsForApproval [ 0 ] , ` eip155: $ { networksArray [ 0 ] } : $ { selectedAccount } ` )
compare ( accountsForApproval [ 1 ] , ` eip155: $ { networksArray [ 1 ] } : $ { selectedAccount } ` )
2024-07-04 13:32:04 +00:00
2024-10-03 18:41:41 +00:00
let approvedNamespaces = JSON . parse ( Testing . formatBuildApprovedNamespacesResult ( networksArray , [ selectedAccount ] ) )
sdk . buildApprovedNamespacesResult ( approvedArgs . id , approvedNamespaces , "" )
2024-07-04 13:32:04 +00:00
compare ( sdk . approveSessionCalls . length , 1 , "expected a call to sdk.approveSession" )
verify ( ! ! sdk . approveSessionCalls [ 0 ] . sessionProposalJson , "expected sessionProposalJson to be set" )
verify ( ! ! sdk . approveSessionCalls [ 0 ] . approvedNamespaces , "expected approvedNamespaces to be set" )
let finalApprovedNamespaces = JSON . parse ( Testing . formatApproveSessionResponse ( networksArray , [ selectedAccount . address ] ) )
2024-10-03 18:41:41 +00:00
sdk . approveSessionResult ( connectArgs [ connectDAppSpy . argPos . key ] , finalApprovedNamespaces , "" )
2024-07-04 13:32:04 +00:00
verify ( store . addWalletConnectSessionCalls . length === 1 )
verify ( store . addWalletConnectSessionCalls [ 0 ] . sessionJson , "expected sessionJson to be set" )
verify ( service . onApproveSessionResultTriggers . length === 1 )
verify ( service . onApproveSessionResultTriggers [ 0 ] . session , "expected session to be set" )
compare ( service . onDisplayToastMessageTriggers . length , 1 , "expected a success message to be displayed" )
2024-10-04 12:49:16 +00:00
verify ( service . onDisplayToastMessageTriggers [ 0 ] . type !== Constants . ephemeralNotificationType . danger , "expected no error" )
2024-07-04 13:32:04 +00:00
verify ( service . onDisplayToastMessageTriggers [ 0 ] . message , "expected message to be set" )
}
2024-07-24 12:50:54 +00:00
function test_TestPairingUnsupportedNetworks ( ) {
2024-11-07 09:10:10 +00:00
const { sdk , store } = testSetupPair ( Testing . formatSessionProposal ( ) )
2024-07-24 12:50:54 +00:00
2024-10-03 18:41:41 +00:00
const approvedArgs = sdk . buildApprovedNamespacesCalls [ 0 ]
2024-10-18 21:22:06 +00:00
sdk . buildApprovedNamespacesResult ( approvedArgs . id , { } , "Non conforming namespaces. approve() namespaces chains don't satisfy required namespaces" )
2024-07-24 12:50:54 +00:00
compare ( connectDAppSpy . count , 0 , "expected not to have calls to service.connectDApp" )
compare ( service . onPairingValidatedTriggers . length , 1 , "expected a call to service.onPairingValidated" )
compare ( service . onPairingValidatedTriggers [ 0 ] . validationState , Pairing . errors . unsupportedNetwork , "expected unsupportedNetwork state error" )
}
2024-07-04 13:32:04 +00:00
function test_SessionRequestMainFlow ( ) {
// All calls to SDK are expected as events to be made by the wallet connect SDK
2024-11-07 09:10:10 +00:00
const sdk = service . dappsModule . wcSdk
2024-07-29 14:39:56 +00:00
const walletStore = service . walletRootStore
const store = service . store
const testAddress = "0x3a"
2024-09-17 07:42:01 +00:00
const chainId = "2"
2024-07-29 14:39:56 +00:00
const method = "personal_sign"
const message = "hello world"
const params = [ ` "${DAppsHelpers.strToHex(message)}" ` , ` "${testAddress}" ` ]
const topic = "b536a"
const session = JSON . parse ( Testing . formatSessionRequest ( chainId , method , params , topic ) )
2024-07-04 13:32:04 +00:00
2024-11-07 09:10:10 +00:00
populateDAppData ( topic )
sdk . sessionRequestEvent ( session )
2024-07-04 13:32:04 +00:00
2024-11-07 09:10:10 +00:00
const request = service . sessionRequestsModel . findById ( session . id )
2024-10-03 18:41:41 +00:00
verify ( ! ! request , "expected request to be found" )
2024-07-04 13:32:04 +00:00
compare ( request . topic , topic , "expected topic to be set" )
compare ( request . method , method , "expected method to be set" )
compare ( request . event , session , "expected event to be the one sent by the sdk" )
compare ( request . dappName , Testing . dappName , "expected dappName to be set" )
compare ( request . dappUrl , Testing . dappUrl , "expected dappUrl to be set" )
compare ( request . dappIcon , Testing . dappFirstIcon , "expected dappIcon to be set" )
2024-09-17 07:42:01 +00:00
verify ( ! ! request . accountAddress , "expected account to be set" )
compare ( request . accountAddress , testAddress , "expected look up of the right account" )
verify ( ! ! request . chainId , "expected network to be set" )
compare ( request . chainId , chainId , "expected look up of the right network" )
2024-07-04 13:32:04 +00:00
verify ( ! ! request . data , "expected data to be set" )
compare ( request . data . message , message , "expected message to be set" )
}
2024-07-24 12:50:54 +00:00
2024-07-04 13:32:04 +00:00
// TODO #14757: add tests with multiple session requests coming in; validate that authentication is serialized and in order
// function tst_SessionRequestQueueMultiple() {
// }
}
TestCase {
name: "ServiceHelpers"
function test_extractChainsAndAccountsFromApprovedNamespaces ( ) {
2024-07-29 14:39:56 +00:00
const res = DAppsHelpers . extractChainsAndAccountsFromApprovedNamespaces ( JSON . parse ( ` {
2024-07-04 13:32:04 +00:00
"eip155" : {
"accounts" : [
"eip155:1:0x1" ,
"eip155:1:0x2" ,
"eip155:2:0x1" ,
"eip155:2:0x2"
] ,
"chains" : [
"eip155:1" ,
"eip155:2"
] ,
"events" : [
"accountsChanged" ,
"chainChanged"
] ,
"methods" : [
"eth_sendTransaction" ,
"personal_sign"
]
}
} ` ) )
verify ( res . chains . length === 2 )
verify ( res . accounts . length === 2 )
verify ( res . chains [ 0 ] === 1 )
verify ( res . chains [ 1 ] === 2 )
verify ( res . accounts [ 0 ] === "0x1" )
verify ( res . accounts [ 1 ] === "0x2" )
}
readonly property ListModel chainsModel: ListModel {
ListElement { chainId: 1 }
ListElement { chainId: 2 }
}
readonly property ListModel accountsModel: ListModel {
ListElement { address: "0x1" }
ListElement { address: "0x2" }
}
function test_buildSupportedNamespacesFromModels ( ) {
2024-07-29 14:39:56 +00:00
const methods = [ "eth_sendTransaction" , "personal_sign" ]
const resStr = DAppsHelpers . buildSupportedNamespacesFromModels ( chainsModel , accountsModel , methods )
const jsonObj = JSON . parse ( resStr )
2024-07-04 13:32:04 +00:00
verify ( jsonObj . hasOwnProperty ( "eip155" ) )
2024-07-29 14:39:56 +00:00
const eip155 = jsonObj . eip155
2024-07-04 13:32:04 +00:00
verify ( eip155 . hasOwnProperty ( "chains" ) )
2024-07-29 14:39:56 +00:00
const chains = eip155 . chains
2024-07-04 13:32:04 +00:00
verify ( chains . length === 2 )
verify ( chains [ 0 ] === "eip155:1" )
verify ( chains [ 1 ] === "eip155:2" )
verify ( eip155 . hasOwnProperty ( "accounts" ) )
2024-07-29 14:39:56 +00:00
const accounts = eip155 . accounts
2024-07-04 13:32:04 +00:00
verify ( accounts . length === 4 )
for ( let chainI = 0 ; chainI < chainsModel . count ; chainI ++ ) {
for ( let accountI = 0 ; accountI < chainsModel . count ; accountI ++ ) {
var found = false
2024-07-29 14:39:56 +00:00
for ( const entry of accounts ) {
2024-07-04 13:32:04 +00:00
if ( entry === ` eip155: $ { chainsModel . get ( chainI ) . chainId } : $ { accountsModel . get ( accountI ) . address } ` ) {
found = true
break
}
}
verify ( found , ` found $ { accountsModel . get ( accountI ) . address } for chain $ { chainsModel . get ( chainI ) . chainId } ` )
}
}
verify ( eip155 . hasOwnProperty ( "methods" ) )
verify ( eip155 . methods . length > 0 )
verify ( eip155 . hasOwnProperty ( "events" ) )
2024-08-21 05:42:25 +00:00
compare ( eip155 . events . length , 5 )
2024-07-04 13:32:04 +00:00
}
2024-07-23 14:26:55 +00:00
2024-08-05 13:41:20 +00:00
function test_getAccountsInSession ( ) {
2024-07-23 14:26:55 +00:00
const account1 = accountsModel . get ( 0 )
const account2 = accountsModel . get ( 1 )
const chainIds = [ chainsModel . get ( 0 ) . chainId , chainsModel . get ( 1 ) . chainId ]
2024-08-05 13:41:20 +00:00
const oneAccountSession = JSON . parse ( Testing . formatApproveSessionResponse ( chainIds , [ account2 . address ] ) )
const twoAccountsSession = JSON . parse ( Testing . formatApproveSessionResponse ( chainIds , [ '0x03acc' , account1 . address ] ) )
const duplicateAccountsSession = JSON . parse ( Testing . formatApproveSessionResponse ( chainIds , [ '0x83acb' , '0x83acb' ] ) )
const res = DAppsHelpers . getAccountsInSession ( oneAccountSession )
compare ( res . length , 1 , "expected the only account to be returned" )
compare ( res [ 0 ] , account2 . address , "expected the only account to be the one in the session" )
const res2 = DAppsHelpers . getAccountsInSession ( twoAccountsSession )
compare ( res2 . length , 2 , "expected the two accounts to be returned" )
compare ( res2 [ 0 ] , '0x03acc' , "expected the first account to be the one in the session" )
compare ( res2 [ 1 ] , account1 . address , "expected the second account to be the one in the session" )
const res3 = DAppsHelpers . getAccountsInSession ( duplicateAccountsSession )
compare ( res3 . length , 1 , "expected the only account to be returned" )
compare ( res3 [ 0 ] , '0x83acb' , "expected the duplicated account" )
2024-07-23 14:26:55 +00:00
}
2024-07-04 13:32:04 +00:00
}
Component {
id: componentUnderTest
DAppsWorkflow {
2024-07-11 21:00:15 +00:00
loginType: Constants . LoginType . Password
2024-10-03 18:41:41 +00:00
model: ListModel { }
accountsModel: ListModel { }
networksModel: ListModel { }
sessionRequestsModel: SessionRequestsModel { }
selectedAccountAddress: ""
formatBigNumber: ( number , symbol , noSymbolOption ) = > number + symbol
2024-07-04 13:32:04 +00:00
}
}
// TODO #15151: this TestCase if placed before ServiceHelpers was not run with `when: windowShown`. Check if related to the CI crash
TestCase {
id: dappsWorkflowTest
name: "DAppsWorkflow"
when: windowShown
property DAppsWorkflow controlUnderTest: null
SignalSpy {
2024-10-03 18:41:41 +00:00
id: pairWCReadySpy
2024-07-04 13:32:04 +00:00
target: dappsWorkflowTest . controlUnderTest
2024-10-03 18:41:41 +00:00
signalName: "pairWCReady"
2024-07-04 13:32:04 +00:00
}
SignalSpy {
2024-10-03 18:41:41 +00:00
id: disconnectRequestedSpy
2024-07-04 13:32:04 +00:00
target: dappsWorkflowTest . controlUnderTest
2024-10-03 18:41:41 +00:00
signalName: "disconnectRequested"
}
SignalSpy {
id: pairingRequestedSpy
target: dappsWorkflowTest . controlUnderTest
signalName: "pairingRequested"
}
SignalSpy {
id: pairingValidationRequestedSpy
target: dappsWorkflowTest . controlUnderTest
signalName: "pairingValidationRequested"
}
SignalSpy {
id: connectionAcceptedSpy
target: dappsWorkflowTest . controlUnderTest
signalName: "connectionAccepted"
}
SignalSpy {
id: connectionDeclinedSpy
target: dappsWorkflowTest . controlUnderTest
signalName: "connectionDeclined"
}
SignalSpy {
id: signRequestAcceptedSpy
target: dappsWorkflowTest . controlUnderTest
signalName: "signRequestAccepted"
}
SignalSpy {
id: signRequestRejectedSpy
target: dappsWorkflowTest . controlUnderTest
signalName: "signRequestRejected"
2024-07-04 13:32:04 +00:00
}
function init ( ) {
2024-10-03 18:41:41 +00:00
controlUnderTest = createTemporaryObject ( componentUnderTest , root )
2024-07-04 13:32:04 +00:00
verify ( ! ! controlUnderTest )
}
function cleanup ( ) {
pairWCReadySpy . clear ( )
2024-10-03 18:41:41 +00:00
disconnectRequestedSpy . clear ( )
pairingRequestedSpy . clear ( )
pairingValidationRequestedSpy . clear ( )
connectionAcceptedSpy . clear ( )
connectionDeclinedSpy . clear ( )
signRequestAcceptedSpy . clear ( )
signRequestRejectedSpy . clear ( )
2024-07-04 13:32:04 +00:00
}
function test_OpenAndCloseDappList ( ) {
waitForRendering ( controlUnderTest )
mouseClick ( controlUnderTest )
waitForRendering ( controlUnderTest )
let popup = findChild ( controlUnderTest , "dappsListPopup" )
verify ( ! ! popup )
verify ( popup . opened )
popup . close ( )
waitForRendering ( controlUnderTest )
verify ( ! popup . opened )
}
2024-10-03 18:41:41 +00:00
function openPairModal ( ) {
2024-07-04 13:32:04 +00:00
waitForRendering ( controlUnderTest )
mouseClick ( controlUnderTest )
let popup = findChild ( controlUnderTest , "dappsListPopup" )
verify ( ! ! popup )
verify ( popup . opened )
let connectButton = findChild ( popup , "connectDappButton" )
verify ( ! ! connectButton )
mouseClick ( connectButton )
2024-09-03 12:57:07 +00:00
const btnWalletConnect = findChild ( controlUnderTest , "btnWalletConnect" )
verify ( ! ! btnWalletConnect )
mouseClick ( btnWalletConnect )
2024-07-04 13:32:04 +00:00
verify ( pairWCReadySpy . count === 1 , "expected pairWCReady signal to be emitted" )
let pairWCModal = findChild ( controlUnderTest , "pairWCModal" )
verify ( ! ! pairWCModal )
2024-10-03 18:41:41 +00:00
return pairWCModal
2024-07-04 13:32:04 +00:00
}
2024-10-03 18:41:41 +00:00
function test_OpenPairModal ( ) {
const pairWCModal = openPairModal ( )
}
2024-07-04 13:32:04 +00:00
2024-10-03 18:41:41 +00:00
function test_uriPairingSuccess ( ) {
const pairWCModal = openPairModal ( )
//type: test url
keyClick ( "a" )
keyClick ( "b" )
keyClick ( "c" )
keyClick ( "d" )
compare ( pairingValidationRequestedSpy . count , 4 , "expected pairingValidationRequested signal to be emitted" )
controlUnderTest . pairingValidated ( Pairing . errors . uriOk )
compare ( pairingRequestedSpy . count , 1 , "expected pairingRequested signal to be emitted" )
2024-07-04 13:32:04 +00:00
}
2024-10-03 18:41:41 +00:00
function test_uriPairingFail ( ) {
const pairWCModal = openPairModal ( )
//type: test url
keyClick ( "a" )
keyClick ( "b" )
keyClick ( "c" )
2024-07-04 13:32:04 +00:00
2024-10-03 18:41:41 +00:00
compare ( pairingValidationRequestedSpy . count , 3 , "expected pairingValidationRequested signal to be emitted" )
controlUnderTest . pairingValidated ( Pairing . errors . invalidUri )
compare ( pairingRequestedSpy . count , 0 , "expected pairingRequested signal to not be emitted" )
}
2024-07-04 13:32:04 +00:00
2024-10-03 18:41:41 +00:00
function test_OpenDappRequestModal ( ) {
waitForRendering ( controlUnderTest )
const request = buildSessionRequestResolved ( dappsWorkflowTest , "0x1" , "1" , "b536a" )
controlUnderTest . accountsModel . append ( {
address: request . accountAddress ,
name: "helloworld" ,
emoji: "😋" ,
color: "#2A4AF5" ,
keycardAccount: false
} )
controlUnderTest . networksModel . append ( {
chainId: request . chainId ,
chainName: "Test Chain" ,
iconUrl: "network/Network=Ethereum" ,
layer: 1
} )
controlUnderTest . sessionRequestsModel . enqueue ( request )
2024-07-04 13:32:04 +00:00
waitForRendering ( controlUnderTest )
let popup = findChild ( controlUnderTest , "dappsRequestModal" )
verify ( ! ! popup )
verify ( popup . opened )
verify ( popup . visible )
2024-10-03 18:41:41 +00:00
compare ( popup . dappName , request . dappName )
compare ( popup . accountAddress , request . accountAddress )
2024-07-04 13:32:04 +00:00
popup . close ( )
waitForRendering ( controlUnderTest )
verify ( ! popup . opened )
verify ( ! popup . visible )
}
2024-10-03 18:41:41 +00:00
function showRequestModal ( topic , requestId ) {
2024-07-04 13:32:04 +00:00
waitForRendering ( controlUnderTest )
2024-10-03 18:41:41 +00:00
const request = buildSessionRequestResolved ( dappsWorkflowTest , "0x1" , "1" , topic , requestId )
controlUnderTest . accountsModel . append ( {
address: request . accountAddress ,
name: "helloworld" ,
emoji: "😋" ,
color: "#2A4AF5" ,
keycardAccount: false
} )
controlUnderTest . networksModel . append ( {
chainId: request . chainId ,
chainName: "Test Chain" ,
iconUrl: "network/Network=Ethereum" ,
layer: 1
} )
controlUnderTest . sessionRequestsModel . enqueue ( request )
2024-07-04 13:32:04 +00:00
waitForRendering ( controlUnderTest )
2024-10-03 18:41:41 +00:00
const popup = findChild ( controlUnderTest , "dappsRequestModal" )
verify ( popup . opened )
2024-10-15 09:38:36 +00:00
const acceptButton = findChild ( popup , "signButton" )
const rejectButton = findChild ( popup , "rejectButton" )
// Workaround for the buttons not being aligned yet
// Removing this could cause the wrong button to be clicked
tryVerify ( ( ) = > acceptButton . x > rejectButton . x + rejectButton . width )
2024-10-03 18:41:41 +00:00
return popup
2024-07-15 17:30:27 +00:00
}
function test_RejectDappRequestModal ( ) {
2024-10-03 18:41:41 +00:00
const topic = "abcd"
const requestId = "12345"
let popup = showRequestModal ( topic , requestId )
let rejectButton = findChild ( popup , "rejectButton" )
2024-07-04 13:32:04 +00:00
2024-10-15 09:38:36 +00:00
verify ( ! ! rejectButton )
2024-07-04 13:32:04 +00:00
mouseClick ( rejectButton )
2024-10-03 18:41:41 +00:00
compare ( signRequestRejectedSpy . count , 1 , "expected signRequestRejected signal to be emitted" )
compare ( signRequestAcceptedSpy . count , 0 , "expected signRequestAccepted signal to not be emitted" )
compare ( signRequestRejectedSpy . signalArguments [ 0 ] [ 0 ] , topic , "expected id to be set" )
compare ( signRequestRejectedSpy . signalArguments [ 0 ] [ 1 ] , requestId , "expected requestId to be set" )
verify ( ! popup . opened )
verify ( ! popup . visible )
2024-07-15 17:30:27 +00:00
}
function test_AcceptDappRequestModal ( ) {
2024-10-03 18:41:41 +00:00
const topic = "abcd"
const requestId = "12345"
let popup = showRequestModal ( topic , requestId )
2024-07-15 17:30:27 +00:00
2024-10-03 18:41:41 +00:00
let signButton = findChild ( popup , "signButton" )
2024-07-15 17:30:27 +00:00
mouseClick ( signButton )
2024-10-03 18:41:41 +00:00
compare ( signRequestAcceptedSpy . count , 1 , "expected signRequestAccepted signal to be emitted" )
compare ( signRequestRejectedSpy . count , 0 , "expected signRequestRejected signal to not be emitted" )
compare ( signRequestAcceptedSpy . signalArguments [ 0 ] [ 0 ] , topic , "expected id to be set" )
compare ( signRequestAcceptedSpy . signalArguments [ 0 ] [ 1 ] , requestId , "expected requestId to be set" )
2024-07-15 17:30:27 +00:00
waitForRendering ( controlUnderTest )
2024-10-03 18:41:41 +00:00
verify ( ! popup . opened )
verify ( ! popup . visible )
2024-07-04 13:32:04 +00:00
}
2024-10-04 12:49:16 +00:00
function test_SignRequestExpired ( ) {
const topic = "abcd"
const requestId = "12345"
let popup = showRequestModal ( topic , requestId )
const request = controlUnderTest . sessionRequestsModel . findRequest ( topic , requestId )
verify ( ! ! request )
const countDownPill = findChild ( popup , "countdownPill" )
verify ( ! ! countDownPill )
tryVerify ( ( ) = > countDownPill . remainingSeconds > 0 )
// Hackish -> countdownPill internals ask for a refresh before going to expired state
const remainingSeconds = countDownPill . remainingSeconds
tryVerify ( ( ) = > countDownPill . visible )
tryVerify ( ( ) = > countDownPill . remainingSeconds !== remainingSeconds )
request . setExpired ( )
tryVerify ( ( ) = > countDownPill . isExpired )
verify ( countDownPill . visible )
const signButton = findChild ( popup , "signButton" )
const rejectButton = findChild ( popup , "rejectButton" )
const closeButton = findChild ( popup , "closeButton" )
tryVerify ( ( ) = > ! signButton . visible )
verify ( ! rejectButton . visible )
verify ( closeButton . visible )
}
function test_SignRequestDoesWithoutExpiry ( )
{
const topic = "abcd"
const requestId = "12345"
let popup = showRequestModal ( topic , requestId )
const request = controlUnderTest . sessionRequestsModel . findRequest ( topic , requestId )
verify ( ! ! request )
request . expirationTimestamp = undefined
const countDownPill = findChild ( popup , "countdownPill" )
verify ( ! ! countDownPill )
tryVerify ( ( ) = > ! countDownPill . visible )
request . setExpired ( )
tryVerify ( ( ) = > countDownPill . visible )
const signButton = findChild ( popup , "signButton" )
const rejectButton = findChild ( popup , "rejectButton" )
const closeButton = findChild ( popup , "closeButton" )
verify ( signButton . visible )
verify ( rejectButton . visible )
verify ( ! closeButton . visible )
}
function test_SignRequestModalAfterModelRemove ( )
{
const topic = "abcd"
const requestId = "12345"
let popup = showRequestModal ( topic , requestId )
const request = controlUnderTest . sessionRequestsModel . findRequest ( topic , requestId )
verify ( ! ! request )
controlUnderTest . sessionRequestsModel . removeRequest ( topic , requestId )
verify ( ! controlUnderTest . sessionRequestsModel . findRequest ( topic , requestId ) )
waitForRendering ( controlUnderTest )
popup = findChild ( controlUnderTest , "dappsRequestModal" )
verify ( ! popup )
}
2024-07-04 13:32:04 +00:00
}
2024-04-30 12:08:37 +00:00
}