Alex Jbanca 8d78f0fab2 fix(WalletConnect): dApp connection state presented in the UI is out-of sync
1. The DAppsListProvider needs to receive all the user accounts so that it can process all dapps the user is connected to (the dapps filtering based on selected account is an internal impl. detail)
2. Call `revokeSession` on disconnect only if the dapp cannot be found in the WC active sessions. There is some overlapping between Browser connector and Wallet connect because both operate on the same data stored in the DB. If Browser connector controller removes WC data, the WC disconnect flows cannot be successfully completed.
3. Reuse the same notification flow for Browser connector as it's used for WC
4. Fix dapp filtering when processing the dapps that will be displayed in the UI.

(cherry picked from commit 21227893c2f18ab487c367853f9648fc94d67afb)
2024-08-13 11:35:04 +03:00

140 lines
5.3 KiB
QML

import QtQuick 2.15
import StatusQ 0.1
import StatusQ.Core.Utils 0.1
import SortFilterProxyModel 0.2
import AppLayouts.Wallet.services.dapps 1.0
import shared.stores 1.0
import utils 1.0
QObject {
id: root
required property WalletConnectSDKBase sdk
required property DAppsStore store
required property var supportedAccountsModel
property string selectedAddress: ""
readonly property SortFilterProxyModel dappsModel: SortFilterProxyModel {
objectName: "DAppsModelFiltered"
sourceModel: d.dappsModel
filters: FastExpressionFilter {
enabled: !!root.selectedAddress
function isAddressIncluded(accountAddressesSubModel, selectedAddress) {
const addresses = ModelUtils.modelToFlatArray(accountAddressesSubModel, "address")
return addresses.includes(root.selectedAddress)
}
expression: isAddressIncluded(model.accountAddresses, root.selectedAddress)
expectedRoles: "accountAddresses"
}
}
function updateDapps() {
d.updateDappsModel()
}
QObject {
id: d
property ListModel dappsModel: ListModel {
id: dapps
objectName: "DAppsModel"
}
property var dappsListReceivedFn: null
property var getActiveSessionsFn: null
function updateDappsModel()
{
dappsListReceivedFn = (dappsJson) => {
root.store.dappsListReceived.disconnect(dappsListReceivedFn);
dapps.clear();
let dappsList = JSON.parse(dappsJson);
for (let i = 0; i < dappsList.length; i++) {
const cachedEntry = dappsList[i];
// TODO #15075: on SDK dApps refresh update the model that has data source from persistence instead of using reset
const dappEntryWithRequiredRoles = {
description: "",
url: cachedEntry.url,
name: cachedEntry.name,
iconUrl: cachedEntry.iconUrl,
accountAddresses: [{address: ''}]
}
dapps.append(dappEntryWithRequiredRoles);
}
}
root.store.dappsListReceived.connect(dappsListReceivedFn);
// triggers a potential fast response from store.dappsListReceived
if (!store.getDapps()) {
console.warn("Failed retrieving dapps from persistence")
root.store.dappsListReceived.disconnect(dappsListReceivedFn);
}
getActiveSessionsFn = () => {
sdk.getActiveSessions((allSessionsAllProfiles) => {
root.store.dappsListReceived.disconnect(dappsListReceivedFn);
const dAppsMap = {}
const topics = []
const sessions = DAppsHelpers.filterActiveSessionsForKnownAccounts(allSessionsAllProfiles, supportedAccountsModel)
for (const sessionID in sessions) {
const session = sessions[sessionID]
const dapp = session.peer.metadata
if (!!dapp.icons && dapp.icons.length > 0) {
dapp.iconUrl = dapp.icons[0]
} else {
dapp.iconUrl = ""
}
const accounts = DAppsHelpers.getAccountsInSession(session)
const existingDApp = dAppsMap[dapp.url]
if (existingDApp) {
// In Qt5.15.2 this is the way to make a "union" of two arrays
// more modern syntax (ES-6) is not available yet
const combinedAddresses = new Set(existingDApp.accountAddresses.concat(accounts));
existingDApp.accountAddresses = Array.from(combinedAddresses);
} else {
dapp.accountAddresses = accounts
dAppsMap[dapp.url] = dapp
}
topics.push(sessionID)
}
// TODO #15075: on SDK dApps refresh update the model that has data source from persistence instead of using reset
dapps.clear();
// Iterate dAppsMap and fill dapps
for (const topic in dAppsMap) {
const dAppEntry = dAppsMap[topic];
// Due to ListModel converting flat array to empty nested ListModel
// having array of key value pair fixes the problem
dAppEntry.accountAddresses = dAppEntry.accountAddresses.filter(account => (!!account)).map(account => ({address: account}));
dapps.append(dAppEntry);
}
root.store.updateWalletConnectSessions(JSON.stringify(topics))
});
}
if (root.sdk.sdkReady) {
getActiveSessionsFn()
} else {
let conn = root.sdk.sdkReadyChanged.connect(() => {
if (root.sdk.sdkReady) {
getActiveSessionsFn()
}
});
}
}
}
}