2024-05-06 20:22:43 +00:00
|
|
|
import QtQuick 2.15
|
|
|
|
|
2024-05-14 18:22:50 +00:00
|
|
|
import StatusQ.Core.Theme 0.1
|
2024-05-21 10:42:50 +00:00
|
|
|
import StatusQ.Core.Utils 0.1
|
2024-05-14 18:22:50 +00:00
|
|
|
|
2024-05-06 20:22:43 +00:00
|
|
|
import AppLayouts.Wallet.services.dapps 1.0
|
|
|
|
import AppLayouts.Profile.stores 1.0
|
|
|
|
import shared.stores 1.0
|
|
|
|
import shared.popups.walletconnect 1.0
|
|
|
|
|
|
|
|
import SortFilterProxyModel 0.2
|
|
|
|
import utils 1.0
|
|
|
|
|
2024-05-31 09:58:47 +00:00
|
|
|
import "types"
|
|
|
|
|
2024-05-21 10:42:50 +00:00
|
|
|
QObject {
|
2024-05-06 20:22:43 +00:00
|
|
|
id: root
|
|
|
|
|
2024-05-31 09:34:59 +00:00
|
|
|
required property WalletConnectSDKBase wcSDK
|
2024-05-20 18:42:31 +00:00
|
|
|
required property DAppsStore store
|
2024-05-06 20:22:43 +00:00
|
|
|
required property WalletStore walletStore
|
|
|
|
|
2024-05-31 09:34:59 +00:00
|
|
|
readonly property alias dappsModel: dappsProvider.dappsModel
|
2024-05-31 09:58:47 +00:00
|
|
|
readonly property alias requestHandler: requestHandler
|
2024-05-21 10:42:50 +00:00
|
|
|
|
2024-05-06 20:22:43 +00:00
|
|
|
readonly property var validAccounts: SortFilterProxyModel {
|
2024-05-31 09:58:47 +00:00
|
|
|
sourceModel: root.walletStore ? root.walletStore.accounts : null
|
2024-05-06 20:22:43 +00:00
|
|
|
filters: ValueFilter {
|
|
|
|
roleName: "walletType"
|
|
|
|
value: Constants.watchWalletType
|
|
|
|
inverted: true
|
|
|
|
}
|
|
|
|
}
|
2024-05-31 09:58:47 +00:00
|
|
|
readonly property var flatNetworks: root.walletStore ? root.walletStore.flatNetworks : null
|
2024-05-06 20:22:43 +00:00
|
|
|
|
|
|
|
function pair(uri) {
|
2024-05-21 10:42:50 +00:00
|
|
|
d.acceptedSessionProposal = null
|
2024-05-06 20:22:43 +00:00
|
|
|
wcSDK.pair(uri)
|
|
|
|
}
|
|
|
|
|
|
|
|
function approvePairSession(sessionProposal, approvedChainIds, approvedAccount) {
|
2024-05-21 10:42:50 +00:00
|
|
|
d.acceptedSessionProposal = sessionProposal
|
2024-05-31 09:58:47 +00:00
|
|
|
let approvedNamespaces = JSON.parse(
|
|
|
|
Helpers.buildSupportedNamespaces(approvedChainIds,
|
|
|
|
[approvedAccount.address],
|
|
|
|
requestHandler.getSupportedMethods())
|
|
|
|
)
|
2024-05-06 20:22:43 +00:00
|
|
|
wcSDK.buildApprovedNamespaces(sessionProposal.params, approvedNamespaces)
|
|
|
|
}
|
|
|
|
|
|
|
|
function rejectPairSession(id) {
|
|
|
|
wcSDK.rejectSession(id)
|
|
|
|
}
|
|
|
|
|
|
|
|
function disconnectDapp(sessionTopic) {
|
|
|
|
wcSDK.disconnectSession(sessionTopic)
|
|
|
|
}
|
|
|
|
|
|
|
|
signal connectDApp(var dappChains, var sessionProposal, var approvedNamespaces)
|
|
|
|
signal approveSessionResult(var session, var error)
|
2024-05-31 09:58:47 +00:00
|
|
|
signal sessionRequest(SessionRequestResolved request)
|
2024-05-31 09:34:59 +00:00
|
|
|
signal displayToastMessage(string message, bool error)
|
2024-05-06 20:22:43 +00:00
|
|
|
|
|
|
|
readonly property Connections sdkConnections: Connections {
|
|
|
|
target: wcSDK
|
|
|
|
|
|
|
|
function onSessionProposal(sessionProposal) {
|
2024-05-21 10:42:50 +00:00
|
|
|
d.currentSessionProposal = sessionProposal
|
2024-05-06 20:22:43 +00:00
|
|
|
|
2024-05-31 09:58:47 +00:00
|
|
|
let supportedNamespacesStr = Helpers.buildSupportedNamespacesFromModels(
|
|
|
|
root.flatNetworks, root.validAccounts, requestHandler.getSupportedMethods())
|
2024-05-06 20:22:43 +00:00
|
|
|
wcSDK.buildApprovedNamespaces(sessionProposal.params, JSON.parse(supportedNamespacesStr))
|
|
|
|
}
|
|
|
|
|
|
|
|
function onBuildApprovedNamespacesResult(approvedNamespaces, error) {
|
|
|
|
if(error) {
|
|
|
|
// TODO: error reporting
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-05-21 10:42:50 +00:00
|
|
|
if (d.acceptedSessionProposal) {
|
|
|
|
wcSDK.approveSession(d.acceptedSessionProposal, approvedNamespaces)
|
2024-05-06 20:22:43 +00:00
|
|
|
} else {
|
|
|
|
let res = Helpers.extractChainsAndAccountsFromApprovedNamespaces(approvedNamespaces)
|
|
|
|
|
2024-05-21 10:42:50 +00:00
|
|
|
root.connectDApp(res.chains, d.currentSessionProposal, approvedNamespaces)
|
2024-05-06 20:22:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function onApproveSessionResult(session, err) {
|
2024-05-20 18:42:31 +00:00
|
|
|
if (err) {
|
2024-05-21 10:42:50 +00:00
|
|
|
// TODO #14676: handle the error
|
|
|
|
console.error("Failed to approve session", err)
|
2024-05-20 18:42:31 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-05-14 18:22:50 +00:00
|
|
|
// TODO #14754: implement custom dApp notification
|
2024-05-21 10:42:50 +00:00
|
|
|
let app_url = d.currentSessionProposal ? d.currentSessionProposal.params.proposer.metadata.url : "-"
|
2024-05-31 09:34:59 +00:00
|
|
|
root.displayToastMessage(qsTr("Connected to %1 via WalletConnect").arg(app_url), false)
|
2024-05-20 18:42:31 +00:00
|
|
|
|
|
|
|
// Persist session
|
|
|
|
store.addWalletConnectSession(JSON.stringify(session))
|
2024-05-21 10:42:50 +00:00
|
|
|
|
2024-05-31 09:34:59 +00:00
|
|
|
// Notify client
|
|
|
|
root.approveSessionResult(session, err)
|
|
|
|
|
|
|
|
dappsProvider.updateDapps()
|
2024-05-06 20:22:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function onRejectSessionResult(err) {
|
2024-05-21 10:42:50 +00:00
|
|
|
let app_url = d.currentSessionProposal ? d.currentSessionProposal.params.proposer.metadata.url : "-"
|
2024-05-06 20:22:43 +00:00
|
|
|
if(err) {
|
2024-05-31 09:34:59 +00:00
|
|
|
root.displayToastMessage(qsTr("Failed to reject connection request for %1").arg(app_url), true)
|
2024-05-06 20:22:43 +00:00
|
|
|
} else {
|
2024-05-31 09:34:59 +00:00
|
|
|
root.displayToastMessage(qsTr("Connection request for %1 was rejected").arg(app_url), false)
|
2024-05-06 20:22:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-14 18:22:50 +00:00
|
|
|
function onSessionDelete(topic, err) {
|
2024-05-21 10:42:50 +00:00
|
|
|
let app_url = d.currentSessionProposal ? d.currentSessionProposal.params.proposer.metadata.url : "-"
|
2024-05-14 18:22:50 +00:00
|
|
|
if(err) {
|
2024-05-31 09:34:59 +00:00
|
|
|
root.displayToastMessage(qsTr("Failed to disconnect from %1").arg(app_url), true)
|
2024-05-06 20:22:43 +00:00
|
|
|
} else {
|
2024-05-31 09:34:59 +00:00
|
|
|
root.displayToastMessage(qsTr("Disconnected from %1").arg(app_url), false)
|
2024-05-06 20:22:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-31 09:34:59 +00:00
|
|
|
QObject {
|
2024-05-21 10:42:50 +00:00
|
|
|
id: d
|
|
|
|
|
2024-05-06 20:22:43 +00:00
|
|
|
property var currentSessionProposal: null
|
|
|
|
property var acceptedSessionProposal: null
|
2024-05-16 17:57:37 +00:00
|
|
|
|
2024-05-21 10:42:50 +00:00
|
|
|
// TODO #14676: use it to check if already paired
|
|
|
|
function getPairingTopicFromPairingUrl(url)
|
|
|
|
{
|
|
|
|
if (!url.startsWith("wc:"))
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
const atIndex = url.indexOf("@");
|
|
|
|
if (atIndex < 0)
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return url.slice(3, atIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Component.onCompleted: {
|
2024-05-31 09:34:59 +00:00
|
|
|
dappsProvider.updateDapps()
|
|
|
|
}
|
|
|
|
|
2024-05-31 09:58:47 +00:00
|
|
|
DAppsRequestHandler {
|
|
|
|
id: requestHandler
|
|
|
|
|
|
|
|
sdk: root.wcSDK
|
|
|
|
store: root.store
|
|
|
|
walletStore: root.walletStore
|
|
|
|
|
|
|
|
onSessionRequest: (request) => {
|
|
|
|
root.sessionRequest(request)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-31 09:34:59 +00:00
|
|
|
DAppsListProvider {
|
|
|
|
id: dappsProvider
|
|
|
|
|
|
|
|
sdk: root.wcSDK
|
|
|
|
store: root.store
|
2024-05-06 20:22:43 +00:00
|
|
|
}
|
|
|
|
}
|