fix(dapps): filter out dApps connected on other profiles
Add helper function to filter out dApps with sessions that don't have any supported account in the available accounts list. Use helper function to filter out dApps connected on other profiles when listing dApps in the dApps list. When disconnecting an app only disconnect sessions for the current profile. Closes: #14888, #15707
This commit is contained in:
parent
35b7f0583d
commit
7fb241b964
|
@ -552,7 +552,9 @@ Item {
|
||||||
dappsListReceivedJsonStr: dappsListReceivedJsonStr
|
dappsListReceivedJsonStr: dappsListReceivedJsonStr
|
||||||
})
|
})
|
||||||
verify(!!store)
|
verify(!!store)
|
||||||
provider = createTemporaryObject(dappsListProviderComponent, root, {sdk: sdk, store: store})
|
const walletStore = createTemporaryObject(walletStoreComponent, root)
|
||||||
|
verify(!!walletStore)
|
||||||
|
provider = createTemporaryObject(dappsListProviderComponent, root, {sdk: sdk, store: store, supportedAccountsModel: walletStore.nonWatchAccounts})
|
||||||
verify(!!provider)
|
verify(!!provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -576,7 +578,8 @@ Item {
|
||||||
sdk.sdkReady = true
|
sdk.sdkReady = true
|
||||||
compare(sdk.getActiveSessionsCallbacks.length, 1, "expected a call to sdk.getActiveSessions when SDK becomes ready")
|
compare(sdk.getActiveSessionsCallbacks.length, 1, "expected a call to sdk.getActiveSessions when SDK becomes ready")
|
||||||
let callback = sdk.getActiveSessionsCallbacks[0].callback
|
let callback = sdk.getActiveSessionsCallbacks[0].callback
|
||||||
let session = JSON.parse(Testing.formatApproveSessionResponse([1, 2], ["0x1"], {dappMetadataJsonString: Testing.noIconsDappMetadataJsonString}))
|
const address = ModelUtils.get(provider.supportedAccountsModel, 0, "address")
|
||||||
|
let session = JSON.parse(Testing.formatApproveSessionResponse([1, 2], [address], {dappMetadataJsonString: Testing.noIconsDappMetadataJsonString}))
|
||||||
callback({"b536a": session, "b537b": session})
|
callback({"b536a": session, "b537b": session})
|
||||||
compare(provider.dappsModel.count, 1, "expected dappsModel have the SDK's reported dapps")
|
compare(provider.dappsModel.count, 1, "expected dappsModel have the SDK's reported dapps")
|
||||||
compare(provider.dappsModel.get(0).iconUrl, "", "expected iconUrl to be missing")
|
compare(provider.dappsModel.get(0).iconUrl, "", "expected iconUrl to be missing")
|
||||||
|
@ -665,6 +668,28 @@ Item {
|
||||||
verify(eip155.hasOwnProperty("events"))
|
verify(eip155.hasOwnProperty("events"))
|
||||||
compare(eip155.events.length, 2)
|
compare(eip155.events.length, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_filterActiveSessionsForKnownAccounts() {
|
||||||
|
const account1 = accountsModel.get(0)
|
||||||
|
const account2 = accountsModel.get(1)
|
||||||
|
const chainIds = [chainsModel.get(0).chainId, chainsModel.get(1).chainId]
|
||||||
|
const knownSession = JSON.parse(Testing.formatApproveSessionResponse(chainIds, [account2.address]))
|
||||||
|
// Allow the unlikely unknown accounts to cover for the deleted accounts case
|
||||||
|
const unknownSessionWithKnownAccount = JSON.parse(Testing.formatApproveSessionResponse(chainIds, ['0x03acc', account1.address]))
|
||||||
|
const unknownSession1 = JSON.parse(Testing.formatApproveSessionResponse(chainIds, ['0x83acc']))
|
||||||
|
const unknownSession2 = JSON.parse(Testing.formatApproveSessionResponse(chainIds, ['0x12acc']))
|
||||||
|
let testSessions = {
|
||||||
|
"b536a": knownSession,
|
||||||
|
"b537b": unknownSession1,
|
||||||
|
"b538c": unknownSession2,
|
||||||
|
"b539d": unknownSessionWithKnownAccount
|
||||||
|
}
|
||||||
|
let res = Helpers.filterActiveSessionsForKnownAccounts(testSessions, accountsModel)
|
||||||
|
compare(Object.keys(res).length, 2, "expected two sessions to be returned")
|
||||||
|
// Also test that order is stable
|
||||||
|
compare(res["b536a"], knownSession, "expected the known session to be returned")
|
||||||
|
compare(res["b539d"], unknownSessionWithKnownAccount, "expected the known session to be returned")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
|
|
|
@ -2,6 +2,8 @@ import QtQuick 2.15
|
||||||
|
|
||||||
import StatusQ.Core.Utils 0.1
|
import StatusQ.Core.Utils 0.1
|
||||||
|
|
||||||
|
import AppLayouts.Wallet.services.dapps 1.0
|
||||||
|
|
||||||
import shared.stores 1.0
|
import shared.stores 1.0
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
@ -11,6 +13,7 @@ QObject {
|
||||||
|
|
||||||
required property WalletConnectSDKBase sdk
|
required property WalletConnectSDKBase sdk
|
||||||
required property DAppsStore store
|
required property DAppsStore store
|
||||||
|
required property var supportedAccountsModel
|
||||||
|
|
||||||
readonly property alias dappsModel: d.dappsModel
|
readonly property alias dappsModel: d.dappsModel
|
||||||
|
|
||||||
|
@ -46,11 +49,12 @@ QObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
getActiveSessionsFn = () => {
|
getActiveSessionsFn = () => {
|
||||||
sdk.getActiveSessions((sessions) => {
|
sdk.getActiveSessions((allSessions) => {
|
||||||
root.store.dappsListReceived.disconnect(dappsListReceivedFn);
|
root.store.dappsListReceived.disconnect(dappsListReceivedFn);
|
||||||
|
|
||||||
let tmpMap = {}
|
let tmpMap = {}
|
||||||
var topics = []
|
var topics = []
|
||||||
|
const sessions = Helpers.filterActiveSessionsForKnownAccounts(allSessions, root.supportedAccountsModel)
|
||||||
for (let key in sessions) {
|
for (let key in sessions) {
|
||||||
let dapp = sessions[key].peer.metadata
|
let dapp = sessions[key].peer.metadata
|
||||||
if (!!dapp.icons && dapp.icons.length > 0) {
|
if (!!dapp.icons && dapp.icons.length > 0) {
|
||||||
|
@ -61,7 +65,7 @@ QObject {
|
||||||
tmpMap[dapp.url] = dapp;
|
tmpMap[dapp.url] = dapp;
|
||||||
topics.push(key)
|
topics.push(key)
|
||||||
}
|
}
|
||||||
// TODO #14755: 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 (let key in tmpMap) {
|
||||||
|
|
|
@ -36,7 +36,7 @@ QObject {
|
||||||
readonly property alias requestHandler: requestHandler
|
readonly property alias requestHandler: requestHandler
|
||||||
|
|
||||||
readonly property var validAccounts: SortFilterProxyModel {
|
readonly property var validAccounts: SortFilterProxyModel {
|
||||||
sourceModel: root.walletRootStore.nonWatchAccounts
|
sourceModel: d.supportedAccountsModel
|
||||||
proxyRoles: [
|
proxyRoles: [
|
||||||
FastExpressionRole {
|
FastExpressionRole {
|
||||||
name: "colorizedChainPrefixes"
|
name: "colorizedChainPrefixes"
|
||||||
|
@ -108,10 +108,11 @@ QObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
function disconnectDapp(url) {
|
function disconnectDapp(url) {
|
||||||
wcSDK.getActiveSessions((sessions) => {
|
wcSDK.getActiveSessions((allSessions) => {
|
||||||
for (let key in sessions) {
|
const sessions = Helpers.filterActiveSessionsForKnownAccounts(allSessions, d.supportedAccountsModel)
|
||||||
let dapp = sessions[key].peer.metadata
|
for (let session in sessions) {
|
||||||
let topic = sessions[key].topic
|
let dapp = session.peer.metadata
|
||||||
|
let topic = session.topic
|
||||||
if (dapp.url == url) {
|
if (dapp.url == url) {
|
||||||
wcSDK.disconnectSession(topic)
|
wcSDK.disconnectSession(topic)
|
||||||
}
|
}
|
||||||
|
@ -218,6 +219,8 @@ QObject {
|
||||||
QObject {
|
QObject {
|
||||||
id: d
|
id: d
|
||||||
|
|
||||||
|
readonly property var supportedAccountsModel: root.walletRootStore.nonWatchAccounts
|
||||||
|
|
||||||
property var currentSessionProposal: null
|
property var currentSessionProposal: null
|
||||||
property var acceptedSessionProposal: null
|
property var acceptedSessionProposal: null
|
||||||
|
|
||||||
|
@ -255,6 +258,7 @@ QObject {
|
||||||
|
|
||||||
sdk: root.wcSDK
|
sdk: root.wcSDK
|
||||||
store: root.store
|
store: root.store
|
||||||
|
supportedAccountsModel: d.supportedAccountsModel
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timeout for the corner case where the URL was already dismissed and the SDK doesn't respond with an error nor advances with the proposal
|
// Timeout for the corner case where the URL was already dismissed and the SDK doesn't respond with an error nor advances with the proposal
|
||||||
|
|
|
@ -100,3 +100,23 @@ function extractInfoFromPairUri(uri) {
|
||||||
}
|
}
|
||||||
return { topic, expiry }
|
return { topic, expiry }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function filterActiveSessionsForKnownAccounts(sessions, accountsModel) {
|
||||||
|
let knownSessions = ({})
|
||||||
|
Object.keys(sessions).forEach((topic) => {
|
||||||
|
const session = sessions[topic]
|
||||||
|
const eip155Addresses = session.namespaces.eip155.accounts
|
||||||
|
const accountSet = new Set(
|
||||||
|
eip155Addresses.map(eip155Address => eip155Address.split(':').pop().trim())
|
||||||
|
);
|
||||||
|
const uniqueAddresses = Array.from(accountSet);
|
||||||
|
const firstAccount = SQUtils.ModelUtils.getFirstModelEntryIf(accountsModel, (account) => {
|
||||||
|
return uniqueAddresses.includes(account.address)
|
||||||
|
})
|
||||||
|
if (!firstAccount) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
knownSessions[topic] = session
|
||||||
|
})
|
||||||
|
return knownSessions
|
||||||
|
}
|
Loading…
Reference in New Issue