fix(dApps): Improved logic for disconnecting of dApps in the app. (#15819)

Closes: #15814
This commit is contained in:
Roman Chornii 2024-07-29 19:46:03 +03:00 committed by GitHub
parent 1813e1a3da
commit d7e3af8165
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 100 additions and 99 deletions

View File

@ -270,17 +270,17 @@ Item {
} }
function test_onSessionRequestEventDifferentCaseForAddress() { function test_onSessionRequestEventDifferentCaseForAddress() {
let sdk = handler.sdk const sdk = handler.sdk
let testAddressUpper = "0x3A" const testAddressUpper = "0x3A"
let chainId = 2 const chainId = 2
let method = "personal_sign" const method = "personal_sign"
let message = "hello world" const message = "hello world"
let params = [`"${Helpers.strToHex(message)}"`, `"${testAddressUpper}"`] const params = [`"${DAppsHelpers.strToHex(message)}"`, `"${testAddressUpper}"`]
let topic = "b536a" const topic = "b536a"
let session = JSON.parse(Testing.formatSessionRequest(chainId, method, params, topic)) const session = JSON.parse(Testing.formatSessionRequest(chainId, method, params, topic))
// Expect to have calls to getActiveSessions from service initialization // Expect to have calls to getActiveSessions from service initialization
let prevRequests = sdk.getActiveSessionsCallbacks.length const prevRequests = sdk.getActiveSessionsCallbacks.length
sdk.sessionRequestEvent(session) sdk.sessionRequestEvent(session)
compare(sdk.getActiveSessionsCallbacks.length, 1, "expected DAppsRequestHandler call sdk.getActiveSessions") compare(sdk.getActiveSessionsCallbacks.length, 1, "expected DAppsRequestHandler call sdk.getActiveSessions")
@ -288,17 +288,17 @@ Item {
// Tests that the request is ignored if not in the current profile (don't have the PK for the address) // Tests that the request is ignored if not in the current profile (don't have the PK for the address)
function test_onSessionRequestEventMissingAddress() { function test_onSessionRequestEventMissingAddress() {
let sdk = handler.sdk const sdk = handler.sdk
let testAddressUpper = "0xY" const testAddressUpper = "0xY"
let chainId = 2 const chainId = 2
let method = "personal_sign" const method = "personal_sign"
let message = "hello world" const message = "hello world"
let params = [`"${Helpers.strToHex(message)}"`, `"${testAddressUpper}"`] const params = [`"${DAppsHelpers.strToHex(message)}"`, `"${testAddressUpper}"`]
let topic = "b536a" const topic = "b536a"
let session = JSON.parse(Testing.formatSessionRequest(chainId, method, params, topic)) const session = JSON.parse(Testing.formatSessionRequest(chainId, method, params, topic))
// Expect to have calls to getActiveSessions from service initialization // Expect to have calls to getActiveSessions from service initialization
let prevRequests = sdk.getActiveSessionsCallbacks.length const prevRequests = sdk.getActiveSessionsCallbacks.length
sdk.sessionRequestEvent(session) sdk.sessionRequestEvent(session)
compare(sdk.getActiveSessionsCallbacks.length, 0, "expected DAppsRequestHandler don't call sdk.getActiveSessions") compare(sdk.getActiveSessionsCallbacks.length, 0, "expected DAppsRequestHandler don't call sdk.getActiveSessions")
@ -514,27 +514,27 @@ Item {
function test_SessionRequestMainFlow() { function test_SessionRequestMainFlow() {
// All calls to SDK are expected as events to be made by the wallet connect SDK // All calls to SDK are expected as events to be made by the wallet connect SDK
let sdk = service.wcSDK const sdk = service.wcSDK
let walletStore = service.walletRootStore const walletStore = service.walletRootStore
let store = service.store const store = service.store
let testAddress = "0x3a" const testAddress = "0x3a"
let chainId = 2 const chainId = 2
let method = "personal_sign" const method = "personal_sign"
let message = "hello world" const message = "hello world"
let params = [`"${Helpers.strToHex(message)}"`, `"${testAddress}"`] const params = [`"${DAppsHelpers.strToHex(message)}"`, `"${testAddress}"`]
let topic = "b536a" const topic = "b536a"
let session = JSON.parse(Testing.formatSessionRequest(chainId, method, params, topic)) const session = JSON.parse(Testing.formatSessionRequest(chainId, method, params, topic))
// Expect to have calls to getActiveSessions from service initialization // Expect to have calls to getActiveSessions from service initialization
let prevRequests = sdk.getActiveSessionsCallbacks.length const prevRequests = sdk.getActiveSessionsCallbacks.length
sdk.sessionRequestEvent(session) sdk.sessionRequestEvent(session)
compare(sdk.getActiveSessionsCallbacks.length, prevRequests + 1, "expected DAppsRequestHandler call sdk.getActiveSessions") compare(sdk.getActiveSessionsCallbacks.length, prevRequests + 1, "expected DAppsRequestHandler call sdk.getActiveSessions")
let callback = sdk.getActiveSessionsCallbacks[prevRequests].callback const callback = sdk.getActiveSessionsCallbacks[prevRequests].callback
callback({"b536a": JSON.parse(Testing.formatApproveSessionResponse([chainId, 7], [testAddress]))}) callback({"b536a": JSON.parse(Testing.formatApproveSessionResponse([chainId, 7], [testAddress]))})
compare(sessionRequestSpy.count, 1, "expected service.sessionRequest trigger") compare(sessionRequestSpy.count, 1, "expected service.sessionRequest trigger")
let request = sessionRequestSpy.signalArguments[0][sessionRequestSpy.argPos.request] const request = sessionRequestSpy.signalArguments[0][sessionRequestSpy.argPos.request]
compare(request.topic, topic, "expected topic to be set") compare(request.topic, topic, "expected topic to be set")
compare(request.method, method, "expected method 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.event, session, "expected event to be the one sent by the sdk")
@ -619,7 +619,7 @@ Item {
name: "ServiceHelpers" name: "ServiceHelpers"
function test_extractChainsAndAccountsFromApprovedNamespaces() { function test_extractChainsAndAccountsFromApprovedNamespaces() {
let res = Helpers.extractChainsAndAccountsFromApprovedNamespaces(JSON.parse(`{ const res = DAppsHelpers.extractChainsAndAccountsFromApprovedNamespaces(JSON.parse(`{
"eip155": { "eip155": {
"accounts": [ "accounts": [
"eip155:1:0x1", "eip155:1:0x1",
@ -660,25 +660,25 @@ Item {
} }
function test_buildSupportedNamespacesFromModels() { function test_buildSupportedNamespacesFromModels() {
let methods = ["eth_sendTransaction", "personal_sign"] const methods = ["eth_sendTransaction", "personal_sign"]
let resStr = Helpers.buildSupportedNamespacesFromModels(chainsModel, accountsModel, methods) const resStr = DAppsHelpers.buildSupportedNamespacesFromModels(chainsModel, accountsModel, methods)
let jsonObj = JSON.parse(resStr) const jsonObj = JSON.parse(resStr)
verify(jsonObj.hasOwnProperty("eip155")) verify(jsonObj.hasOwnProperty("eip155"))
let eip155 = jsonObj.eip155 const eip155 = jsonObj.eip155
verify(eip155.hasOwnProperty("chains")) verify(eip155.hasOwnProperty("chains"))
let chains = eip155.chains const chains = eip155.chains
verify(chains.length === 2) verify(chains.length === 2)
verify(chains[0] === "eip155:1") verify(chains[0] === "eip155:1")
verify(chains[1] === "eip155:2") verify(chains[1] === "eip155:2")
verify(eip155.hasOwnProperty("accounts")) verify(eip155.hasOwnProperty("accounts"))
let accounts = eip155.accounts const accounts = eip155.accounts
verify(accounts.length === 4) verify(accounts.length === 4)
for (let chainI = 0; chainI < chainsModel.count; chainI++) { for (let chainI = 0; chainI < chainsModel.count; chainI++) {
for (let accountI = 0; accountI < chainsModel.count; accountI++) { for (let accountI = 0; accountI < chainsModel.count; accountI++) {
var found = false var found = false
for (let entry of accounts) { for (const entry of accounts) {
if(entry === `eip155:${chainsModel.get(chainI).chainId}:${accountsModel.get(accountI).address}`) { if(entry === `eip155:${chainsModel.get(chainI).chainId}:${accountsModel.get(accountI).address}`) {
found = true found = true
break break
@ -709,7 +709,7 @@ Item {
"b538c": unknownSession2, "b538c": unknownSession2,
"b539d": unknownSessionWithKnownAccount "b539d": unknownSessionWithKnownAccount
} }
let res = Helpers.filterActiveSessionsForKnownAccounts(testSessions, accountsModel) const res = DAppsHelpers.filterActiveSessionsForKnownAccounts(testSessions, accountsModel)
compare(Object.keys(res).length, 2, "expected two sessions to be returned") compare(Object.keys(res).length, 2, "expected two sessions to be returned")
// Also test that order is stable // Also test that order is stable
compare(res["b536a"], knownSession, "expected the known session to be returned") compare(res["b536a"], knownSession, "expected the known session to be returned")
@ -882,14 +882,14 @@ Item {
} }
function mockSessionRequestEvent(tc, sdk, accountsModel, networksModel) { function mockSessionRequestEvent(tc, sdk, accountsModel, networksModel) {
let account = accountsModel.get(1) const account = accountsModel.get(1)
let network = networksModel.get(1) const network = networksModel.get(1)
let method = "personal_sign" const method = "personal_sign"
let message = "hello world" const message = "hello world"
let params = [`"${Helpers.strToHex(message)}"`, `"${account.address}"`] const params = [`"${DAppsHelpers.strToHex(message)}"`, `"${account.address}"`]
let topic = "b536a" const topic = "b536a"
let requestEvent = JSON.parse(Testing.formatSessionRequest(network.chainId, method, params, topic)) const requestEvent = JSON.parse(Testing.formatSessionRequest(network.chainId, method, params, topic))
let request = tc.createTemporaryObject(sessionRequestComponent, root, { const request = tc.createTemporaryObject(sessionRequestComponent, root, {
event: requestEvent, event: requestEvent,
topic, topic,
id: requestEvent.id, id: requestEvent.id,
@ -900,11 +900,11 @@ Item {
preparedData: message preparedData: message
}) })
// Expect to have calls to getActiveSessions from service initialization // Expect to have calls to getActiveSessions from service initialization
let prevRequests = sdk.getActiveSessionsCallbacks.length const prevRequests = sdk.getActiveSessionsCallbacks.length
sdk.sessionRequestEvent(requestEvent) sdk.sessionRequestEvent(requestEvent)
// Service might trigger a sessionRequest event following the getActiveSessions call // Service might trigger a sessionRequest event following the getActiveSessions call
let callback = sdk.getActiveSessionsCallbacks[prevRequests].callback const callback = sdk.getActiveSessionsCallbacks[prevRequests].callback
let session = JSON.parse(Testing.formatApproveSessionResponse([network.chainId, 7], [account.address])) const session = JSON.parse(Testing.formatApproveSessionResponse([network.chainId, 7], [account.address]))
callback({"b536a": session}) callback({"b536a": session})
return {sdk, session, account, network, topic, request} return {sdk, session, account, network, topic, request}

View File

@ -54,9 +54,9 @@ QObject {
let tmpMap = {} let tmpMap = {}
var topics = [] var topics = []
const sessions = Helpers.filterActiveSessionsForKnownAccounts(allSessions, root.supportedAccountsModel) const sessions = DAppsHelpers.filterActiveSessionsForKnownAccounts(allSessions, root.supportedAccountsModel)
for (let key in sessions) { for (const key in sessions) {
let dapp = sessions[key].peer.metadata const dapp = sessions[key].peer.metadata
if (!!dapp.icons && dapp.icons.length > 0) { if (!!dapp.icons && dapp.icons.length > 0) {
dapp.iconUrl = dapp.icons[0] dapp.iconUrl = dapp.icons[0]
} else { } else {
@ -68,7 +68,7 @@ QObject {
// TODO #15075: on SDK dApps refresh update the model that has data source from persistence instead of using reset // TODO #15075: on SDK dApps refresh update the model that has data source from persistence instead of using reset
dapps.clear(); dapps.clear();
// Iterate tmpMap and fill dapps // Iterate tmpMap and fill dapps
for (let key in tmpMap) { for (const key in tmpMap) {
dapps.append(tmpMap[key]); dapps.append(tmpMap[key]);
} }

View File

@ -263,7 +263,7 @@ SQUtils.QObject {
if (SessionRequest.getSupportedMethods().includes(method) === false) { if (SessionRequest.getSupportedMethods().includes(method) === false) {
return null return null
} }
let chainId = Helpers.chainIdFromEip155(event.params.chainId) const chainId = DAppsHelpers.chainIdFromEip155(event.params.chainId)
return SQUtils.ModelUtils.getByKey(root.networksModel, "chainId", chainId) return SQUtils.ModelUtils.getByKey(root.networksModel, "chainId", chainId)
} }
@ -280,11 +280,11 @@ SQUtils.QObject {
return null return null
} }
let message = "" let message = ""
let messageIndex = (method === SessionRequest.methods.personalSign.name ? 0 : 1) const messageIndex = (method === SessionRequest.methods.personalSign.name ? 0 : 1)
let messageParam = event.params.request.params[messageIndex] const messageParam = event.params.request.params[messageIndex]
// There is no standard on how data is encoded. Therefore we support hex or utf8 // There is no standard on how data is encoded. Therefore we support hex or utf8
if (Helpers.isHex(messageParam)) { if (DAppsHelpers.isHex(messageParam)) {
message = Helpers.hexToString(messageParam) message = DAppsHelpers.hexToString(messageParam)
} else { } else {
message = messageParam message = messageParam
} }
@ -295,8 +295,8 @@ SQUtils.QObject {
if (event.params.request.params.length < 2) { if (event.params.request.params.length < 2) {
return null return null
} }
let jsonMessage = event.params.request.params[1] const jsonMessage = event.params.request.params[1]
let methodObj = method === SessionRequest.methods.signTypedData_v4.name const methodObj = method === SessionRequest.methods.signTypedData_v4.name
? SessionRequest.methods.signTypedData_v4 ? SessionRequest.methods.signTypedData_v4
: SessionRequest.methods.signTypedData : SessionRequest.methods.signTypedData
return methodObj.buildDataObject(jsonMessage) return methodObj.buildDataObject(jsonMessage)
@ -304,13 +304,13 @@ SQUtils.QObject {
if (event.params.request.params.length == 0) { if (event.params.request.params.length == 0) {
return null return null
} }
let tx = event.params.request.params[0] const tx = event.params.request.params[0]
return SessionRequest.methods.signTransaction.buildDataObject(tx) return SessionRequest.methods.signTransaction.buildDataObject(tx)
} else if (method === SessionRequest.methods.sendTransaction.name) { } else if (method === SessionRequest.methods.sendTransaction.name) {
if (event.params.request.params.length == 0) { if (event.params.request.params.length == 0) {
return null return null
} }
let tx = event.params.request.params[0] const tx = event.params.request.params[0]
return SessionRequest.methods.sendTransaction.buildDataObject(tx) return SessionRequest.methods.sendTransaction.buildDataObject(tx)
} else { } else {
return null return null

View File

@ -156,7 +156,7 @@ WalletConnectSDKBase {
if (SessionRequest.getSupportedMethods().includes(method) === false) { if (SessionRequest.getSupportedMethods().includes(method) === false) {
return null return null
} }
let chainId = Helpers.chainIdFromEip155(event.params.chainId) const chainId = DAppsHelpers.chainIdFromEip155(event.params.chainId)
return SQUtils.ModelUtils.getByKey(networksModule.flatNetworks, "chainId", chainId) return SQUtils.ModelUtils.getByKey(networksModule.flatNetworks, "chainId", chainId)
} }
@ -167,13 +167,13 @@ WalletConnectSDKBase {
if (event.params.request.params.length < 1) { if (event.params.request.params.length < 1) {
return null return null
} }
var message = "" let message = ""
let messageIndex = (method === SessionRequest.methods.personalSign.name ? 0 : 1) const messageIndex = (method === SessionRequest.methods.personalSign.name ? 0 : 1)
let messageParam = event.params.request.tx.data const messageParam = event.params.request.tx.data
// There is no standard on how data is encoded. Therefore we support hex or utf8 // There is no standard on how data is encoded. Therefore we support hex or utf8
if (Helpers.isHex(messageParam)) { if (DAppsHelpers.isHex(messageParam)) {
message = Helpers.hexToString(messageParam) message = DAppsHelpers.hexToString(messageParam)
} else { } else {
message = messageParam message = messageParam
} }

View File

@ -56,24 +56,24 @@ QObject {
if(Constants.regularExpressions.emoji.test(uri)) { if(Constants.regularExpressions.emoji.test(uri)) {
root.pairingValidated(Pairing.errors.tooCool) root.pairingValidated(Pairing.errors.tooCool)
return return
} else if(!Helpers.validURI(uri)) { } else if(!DAppsHelpers.validURI(uri)) {
root.pairingValidated(Pairing.errors.invalidUri) root.pairingValidated(Pairing.errors.invalidUri)
return return
} }
let info = Helpers.extractInfoFromPairUri(uri) const info = DAppsHelpers.extractInfoFromPairUri(uri)
wcSDK.getActiveSessions((sessions) => { wcSDK.getActiveSessions((sessions) => {
// Check if the URI is already paired // Check if the URI is already paired
var validationState = Pairing.errors.uriOk let validationState = Pairing.errors.uriOk
for (let key in sessions) { for (const key in sessions) {
if (sessions[key].pairingTopic == info.topic) { if (sessions[key].pairingTopic === info.topic) {
validationState = Pairing.errors.alreadyUsed validationState = Pairing.errors.alreadyUsed
break break
} }
} }
// Check if expired // Check if expired
if (validationState == Pairing.errors.uriOk) { if (validationState === Pairing.errors.uriOk) {
const now = (new Date().getTime())/1000 const now = (new Date().getTime())/1000
if (info.expiry < now) { if (info.expiry < now) {
validationState = Pairing.errors.expired validationState = Pairing.errors.expired
@ -92,8 +92,8 @@ QObject {
function approvePairSession(sessionProposal, approvedChainIds, approvedAccount) { function approvePairSession(sessionProposal, approvedChainIds, approvedAccount) {
d.acceptedSessionProposal = sessionProposal d.acceptedSessionProposal = sessionProposal
let approvedNamespaces = JSON.parse( const approvedNamespaces = JSON.parse(
Helpers.buildSupportedNamespaces(approvedChainIds, DAppsHelpers.buildSupportedNamespaces(approvedChainIds,
[approvedAccount.address], [approvedAccount.address],
SessionRequest.getSupportedMethods()) SessionRequest.getSupportedMethods())
) )
@ -110,11 +110,12 @@ QObject {
function disconnectDapp(url) { function disconnectDapp(url) {
wcSDK.getActiveSessions((allSessions) => { wcSDK.getActiveSessions((allSessions) => {
const sessions = Helpers.filterActiveSessionsForKnownAccounts(allSessions, d.supportedAccountsModel) const sessions = DAppsHelpers.filterActiveSessionsForKnownAccounts(allSessions, d.supportedAccountsModel)
for (let session in sessions) { for (const sessionID in sessions) {
let dapp = session.peer.metadata const session = sessions[sessionID]
let topic = session.topic const dapp = session.peer.metadata
if (dapp.url == url) { const topic = session.topic
if (dapp.url === url) {
wcSDK.disconnectSession(topic) wcSDK.disconnectSession(topic)
} }
} }
@ -145,7 +146,7 @@ QObject {
function onSessionProposal(sessionProposal) { function onSessionProposal(sessionProposal) {
d.currentSessionProposal = sessionProposal d.currentSessionProposal = sessionProposal
let supportedNamespacesStr = Helpers.buildSupportedNamespacesFromModels( const supportedNamespacesStr = DAppsHelpers.buildSupportedNamespacesFromModels(
root.flatNetworks, root.validAccounts, SessionRequest.getSupportedMethods()) root.flatNetworks, root.validAccounts, SessionRequest.getSupportedMethods())
wcSDK.buildApprovedNamespaces(sessionProposal.params, JSON.parse(supportedNamespacesStr)) wcSDK.buildApprovedNamespaces(sessionProposal.params, JSON.parse(supportedNamespacesStr))
} }
@ -169,7 +170,7 @@ QObject {
if (d.acceptedSessionProposal) { if (d.acceptedSessionProposal) {
wcSDK.approveSession(d.acceptedSessionProposal, approvedNamespaces) wcSDK.approveSession(d.acceptedSessionProposal, approvedNamespaces)
} else { } else {
let res = Helpers.extractChainsAndAccountsFromApprovedNamespaces(approvedNamespaces) const res = DAppsHelpers.extractChainsAndAccountsFromApprovedNamespaces(approvedNamespaces)
root.connectDApp(res.chains, d.currentSessionProposal, approvedNamespaces) root.connectDApp(res.chains, d.currentSessionProposal, approvedNamespaces)
} }

View File

@ -6,4 +6,4 @@ DappsConnectorSDK 1.0 DappsConnectorSDK.qml
DAppsListProvider 1.0 DAppsListProvider.qml DAppsListProvider 1.0 DAppsListProvider.qml
DAppsRequestHandler 1.0 DAppsRequestHandler.qml DAppsRequestHandler 1.0 DAppsRequestHandler.qml
Helpers 1.0 helpers.js DAppsHelpers 1.0 helpers.js