chore(dapps) implement service tests and basic workflow tests

Abstract WalletConnectSDK to make it testable
Implement WC service pairing test
Bring back DAppsWorkflow tests back to life and add a pair modal test

Updates: #14927
This commit is contained in:
Stefan 2024-05-31 12:34:59 +03:00 committed by Stefan Dunca
parent e896267874
commit 145053e34f
12 changed files with 528 additions and 79 deletions

View File

@ -53,6 +53,14 @@ Item {
spacing: 8 spacing: 8
wcService: walletConnectService wcService: walletConnectService
onDisplayToastMessage: (message, isErr) => {
if(isErr) {
console.log(`Storybook.displayToastMessage(${message}, "", "warning", false, Constants.ephemeralNotificationType.danger, "")`)
return
}
console.log(`Storybook.displayToastMessage(${message}, "", "checkmark-circle", false, Constants.ephemeralNotificationType.success, "")`)
}
} }
} }
ColumnLayout {} ColumnLayout {}
@ -83,6 +91,15 @@ Item {
// spacer // spacer
ColumnLayout {} ColumnLayout {}
CheckBox {
text: "Enable SDK"
checked: settings.enableSDK
onCheckedChanged: {
settings.enableSDK = checked
}
}
RowLayout { RowLayout {
Text { text: "URI" } Text { text: "URI" }
TextField { TextField {
@ -170,7 +187,7 @@ Item {
id: walletConnectService id: walletConnectService
wcSDK: WalletConnectSDK { wcSDK: WalletConnectSDK {
active: true active: settings.enableSDK
projectId: projectIdText.projectId projectId: projectIdText.projectId
} }
@ -246,6 +263,7 @@ Item {
property int testCase: d.noTestCase property int testCase: d.noTestCase
property string pairUri: "" property string pairUri: ""
property bool testNetworks: false property bool testNetworks: false
property bool enableSDK: true
} }
} }

View File

@ -0,0 +1,134 @@
const requiredEventsJsonString = `["chainChanged", "accountsChanged"]`
const requiredMethodsJsonString = `["eth_sendTransaction","personal_sign"]`
const optionalNamespacesJsonString = `{
"eip155": {
"chains": [
"eip155:1",
"eip155:10"
],
"events": [
"chainChanged",
"accountsChanged",
"message",
"disconnect",
"connect"
],
"methods": [
"eth_sign",
"eth_signTransaction",
"eth_signTypedData",
"eth_signTypedData_v3",
"eth_signTypedData_v4",
"eth_sendTransaction"
],
"rpcMap": {
"1": "https://cloudflare-eth.com",
"10": "https://mainnet.optimism.io/"
}
}
}`
const requiredNamespacesJsonString = `{
"eip155": {
"chains": [
"eip155:1"
],
"events": ${requiredEventsJsonString},
"methods": ${requiredMethodsJsonString},
"rpcMap": {
"1": "https://mainnet.io/123"
}
}
}`
const dappMetadataJsonString = `{
"description": "Test dApp description",
"icons": [
"https://test.com/icon.png"
],
"name": "TestApp",
"url": "https://app.test.org"
}`
function formatSessionProposal() {
return `{
"id": 1715976881734096,
"params": {
"expiryTimestamp": 1715977219,
"id": 1715976881734096,
"optionalNamespaces": ${optionalNamespacesJsonString},
"pairingTopic": "50fba141cdb5c015493c2907c46bacf9f7cbd7c8e3d4e97df891f18dddcff69c",
"proposer": {
"metadata": ${dappMetadataJsonString},
"publicKey": "095d9992ca0eb6081cabed26faf48919162fd70cc66d639f118a60507ae0463d"
},
"relays": [
{
"protocol": "irn"
}
],
"requiredNamespaces": ${requiredNamespacesJsonString}
},
"verifyContext": {
"verified": {
"origin": "https://app.test.org",
"validation": "UNKNOWN",
"verifyUrl": "https://verify.walletconnect.com"
}
}
}`
}
function formatBuildApprovedNamespacesResult(networksArray, accountsArray) {
let requiredChainsStr = networksArray.map(chainId => `"eip155:${chainId}"`).join(',')
let requiredAccountsStr = accountsArray.map(address => networksArray.map(chainId => `"eip155:${chainId}:${address}"`).join(',')).join(',')
return `{
"eip155": {
"chains": [${requiredChainsStr}],
"accounts": [${requiredAccountsStr}],
"events": ${requiredEventsJsonString},
"methods": ${requiredMethodsJsonString}
}
}`
}
function formatApproveSessionResponse(networksArray, accountsArray) {
let chainsStr = networksArray.map(chainId => `"eip155:${chainId}"`).join(',')
let accountsStr = accountsArray.map(address => networksArray.map(chainId => `"eip155:${chainId}:${address}"`).join(',')).join(',')
return `{
"acknowledged": true,
"controller": "da4a87d5f0f54951afe870ebf020cf03f8a3522fbd219398c3fa159a37e16d54",
"expiry": 1716581732,
"namespaces": {
"eip155": {
"accounts": [${accountsStr}],
"chains": [${chainsStr}],
"events": ${requiredEventsJsonString},
"methods": ${requiredMethodsJsonString}
}
},
"optionalNamespaces": ${optionalNamespacesJsonString},
"pairingTopic": "50fba141cdb5c015493c2907c46bacf9f7cbd7c8e3d4e97df891f18dddcff69c",
"peer": {
"metadata": ${dappMetadataJsonString},
"publicKey": "095d9992ca0eb6081cabed26faf48919162fd70cc66d639f118a60507ae0463d"
},
"relay": {
"protocol": "irn"
},
"requiredNamespaces": ${requiredNamespacesJsonString},
"self": {
"metadata": {
"description": "Status Wallet",
"icons": [
"https://status.im/img/status-footer-logo.svg"
],
"name": "Status",
"url": "http://localhost"
},
"publicKey": "da4a87d5f0f54951afe870ebf020cf03f8a3522fbd219398c3fa159a37e16d54"
},
"topic": "e39e1f435a46b5ee6b31484d1751cfbc35be1275653af2ea340974a7592f1a19"
}`
}

View File

@ -2,56 +2,286 @@ import QtQuick 2.15
import QtTest 1.15 import QtTest 1.15
import StatusQ 0.1 // See #10218 import StatusQ 0.1 // See #10218
import StatusQ.Core.Utils 0.1 // See #10218
import QtQuick.Controls 2.15 import QtQuick.Controls 2.15
import Storybook 1.0 import Storybook 1.0
//import AppLayouts.Wallet.panels 1.0
import AppLayouts.Wallet.services.dapps 1.0 import AppLayouts.Wallet.services.dapps 1.0
import AppLayouts.Profile.stores 1.0
import shared.stores 1.0
import QtQml.Models 2.15 import AppLayouts.Wallet.panels 1.0
import "helpers/wallet_connect.js" as Testing
Item { Item {
id: root id: root
width: 600 width: 600
height: 400 height: 400
// TODO: mock WalletConnectSDK
// Component {
// id: componentUnderTest
// DAppsWorkflow {
// }
// }
// TestCase { Component {
// name: "DAppsWorkflow" id: sdkComponent
// when: windowShown
// property DAppsWorkflow controlUnderTest: null WalletConnectSDKBase {
property bool sdkReady: true
// function init() { property int pairCalled: 0
// controlUnderTest = createTemporaryObject(componentUnderTest, root)
// }
// function test_ClickToOpenAndClosePopup() { getActiveSessions: function() {
// verify(!!controlUnderTest) return []
// waitForRendering(controlUnderTest) }
pair: function() {
pairCalled++
}
// mouseClick(controlUnderTest, Qt.LeftButton) property var buildApprovedNamespacesCalls: []
// waitForRendering(controlUnderTest) buildApprovedNamespaces: function(params, supportedNamespaces) {
buildApprovedNamespacesCalls.push({params, supportedNamespaces})
}
// let popup = findChild(controlUnderTest, "dappsPopup") property var approveSessionCalls: []
// verify(!!popup) approveSession: function(sessionProposalJson, approvedNamespaces) {
// verify(popup.opened) approveSessionCalls.push({sessionProposalJson, approvedNamespaces})
}
}
}
// mouseClick(Overlay.overlay, Qt.LeftButton) Component {
// waitForRendering(controlUnderTest) id: serviceComponent
// verify(!popup.opened) WalletConnectService {
// } property var onApproveSessionResultTriggers: []
// } onApproveSessionResult: function(session, error) {
onApproveSessionResultTriggers.push({session, error})
}
property var onDisplayToastMessageTriggers: []
onDisplayToastMessage: function(message, error) {
onDisplayToastMessageTriggers.push({message, error})
}
}
}
Component {
id: dappsStoreComponent
DAppsStore {
signal dappsListReceived(string dappsJson)
// By default, return no dapps in store
function getDapps() {
dappsListReceived('[]')
return true
}
property var addWalletConnectSessionCalls: []
function addWalletConnectSession(sessionJson) {
addWalletConnectSessionCalls.push({sessionJson})
}
}
}
Component {
id: walletStoreComponent
WalletStore {
readonly property ListModel flatNetworks: ListModel {
ListElement { chainId: 1 }
ListElement { chainId: 2 }
}
readonly property ListModel accounts: ListModel {
ListElement { address: "0x1" }
ListElement { address: "0x2" }
}
}
}
TestCase {
id: walletConnectServiceTest
name: "WalletConnectService"
property WalletConnectService service: null
SignalSpy {
id: connectDAppSpy
target: walletConnectServiceTest.service
signalName: "connectDApp"
property var argPos: {
"dappChains": 0,
"sessionProposalJson": 1,
"availableNamespaces": 0
}
}
function init() {
let walletStore = createTemporaryObject(walletStoreComponent, root)
verify(!!walletStore)
let sdk = createTemporaryObject(sdkComponent, root, { projectId: "12ab" })
verify(!!sdk)
let store = createTemporaryObject(dappsStoreComponent, root)
verify(!!store)
service = createTemporaryObject(serviceComponent, root, {wcSDK: sdk, store: store, walletStore: walletStore})
verify(!!service)
}
function cleanup() {
service.destroy()
connectDAppSpy.clear()
}
function test_TestPairing() {
// All calls to SDK are expected as events to be made by the wallet connect SDK
let sdk = service.wcSDK
let walletStore = service.walletStore
let store = service.store
service.pair("wc:12ab@1?bridge=https%3A%2F%2Fbridge.walletconnect.org&key=12ab")
compare(sdk.pairCalled, 1, "expected a call to sdk.pair")
sdk.sessionProposal(JSON.parse(Testing.formatSessionProposal()))
compare(sdk.buildApprovedNamespacesCalls.length, 1, "expected a call to sdk.buildApprovedNamespaces")
var args = sdk.buildApprovedNamespacesCalls[0]
verify(!!args.supportedNamespaces, "expected supportedNamespaces to be set")
let chainsForApproval = args.supportedNamespaces.eip155.chains
let networksArray = ModelUtils.modelToArray(walletStore.flatNetworks).map(entry => entry.chainId)
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
let accountsArray = ModelUtils.modelToArray(walletStore.accounts).map(entry => entry.address)
verify(accountsArray.every(address => allAccountsForApproval.some(eip155Address => eip155Address === `eip155:${networksArray[0]}:${address}`)),
"expect at least all accounts for the first chain to be present"
)
let allApprovedNamespaces = JSON.parse(Testing.formatBuildApprovedNamespacesResult(networksArray, accountsArray))
sdk.buildApprovedNamespacesResult(allApprovedNamespaces, "")
compare(connectDAppSpy.count, 1, "expected a call to service.connectDApp")
let connectArgs = connectDAppSpy.signalArguments[0]
compare(connectArgs[connectDAppSpy.argPos.dappChains], networksArray, "expected all provided networks (walletStore.flatNetworks) for the dappChains")
verify(!!connectArgs[connectDAppSpy.argPos.sessionProposalJson], "expected sessionProposalJson to be set")
verify(!!connectArgs[connectDAppSpy.argPos.availableNamespaces], "expected availableNamespaces to be set")
let selectedAccount = walletStore.accounts.get(1)
service.approvePairSession(connectArgs[connectDAppSpy.argPos.sessionProposalJson], connectArgs[connectDAppSpy.argPos.dappChains], selectedAccount)
compare(sdk.buildApprovedNamespacesCalls.length, 2, "expected a call to sdk.buildApprovedNamespaces")
args = sdk.buildApprovedNamespacesCalls[1]
verify(!!args.supportedNamespaces, "expected supportedNamespaces to be set")
// We test here that only one account for all chains is provided
let accountsForApproval = args.supportedNamespaces.eip155.accounts
compare(accountsForApproval.length, networksArray.length, "expect only one account per chain")
compare(accountsForApproval[0], `eip155:${networksArray[0]}:${selectedAccount.address}`)
compare(accountsForApproval[1], `eip155:${networksArray[1]}:${selectedAccount.address}`)
let approvedNamespaces = JSON.parse(Testing.formatBuildApprovedNamespacesResult(networksArray, [selectedAccount.address]))
sdk.buildApprovedNamespacesResult(approvedNamespaces, "")
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]))
sdk.approveSessionResult(finalApprovedNamespaces, "")
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")
verify(!service.onDisplayToastMessageTriggers[0].error, "expected no error")
verify(service.onDisplayToastMessageTriggers[0].message, "expected message to be set")
}
}
Component {
id: componentUnderTest
DAppsWorkflow {
}
}
TestCase {
id: dappsWorkflowTest
name: "DAppsWorkflow"
when: windowShown
property DAppsWorkflow controlUnderTest: null
SignalSpy {
id: dappsListReadySpy
target: dappsWorkflowTest.controlUnderTest
signalName: "dappsListReady"
}
SignalSpy {
id: pairWCReadySpy
target: dappsWorkflowTest.controlUnderTest
signalName: "pairWCReady"
}
function init() {
let walletStore = createTemporaryObject(walletStoreComponent, root)
verify(!!walletStore)
let sdk = createTemporaryObject(sdkComponent, root, { projectId: "12ab" })
verify(!!sdk)
let store = createTemporaryObject(dappsStoreComponent, root)
verify(!!store)
let service = createTemporaryObject(serviceComponent, root, {wcSDK: sdk, store: store, walletStore: walletStore})
verify(!!service)
controlUnderTest = createTemporaryObject(componentUnderTest, root, {wcService: service})
verify(!!controlUnderTest)
}
function cleanup() {
controlUnderTest.destroy()
dappsListReadySpy.reset()
pairWCReadySpy.reset()
}
function test_OpenAndCloseDappList() {
waitForRendering(controlUnderTest)
compare(dappsListReadySpy.count, 0, "expected NO dappsListReady signal to be emitted")
mouseClick(controlUnderTest, Qt.LeftButton)
waitForRendering(controlUnderTest)
compare(dappsListReadySpy.count, 1, "expected dappsListReady signal to be emitted")
let popup = findChild(controlUnderTest, "dappsPopup")
verify(!!popup)
verify(popup.opened)
mouseClick(Overlay.overlay, Qt.LeftButton)
waitForRendering(controlUnderTest)
verify(!popup.opened)
}
function test_OpenPairModal() {
waitForRendering(controlUnderTest)
mouseClick(controlUnderTest, Qt.LeftButton)
waitForRendering(controlUnderTest)
let popup = findChild(controlUnderTest, "dappsPopup")
verify(!!popup)
verify(popup.opened)
let connectButton = findChild(popup, "connectDappButton")
verify(!!connectButton)
verify(pairWCReadySpy.count === 0, "expected NO pairWCReady signal to be emitted")
mouseClick(connectButton, Qt.LeftButton)
waitForRendering(controlUnderTest)
verify(pairWCReadySpy.count === 1, "expected pairWCReady signal to be emitted")
let pairWCModal = findChild(controlUnderTest, "pairWCModal")
verify(!!pairWCModal)
}
}
TestCase { TestCase {
name: "ServiceHelpers" name: "ServiceHelpers"

View File

@ -8,6 +8,7 @@ import shared.popups.walletconnect 1.0
import AppLayouts.Wallet.services.dapps 1.0 import AppLayouts.Wallet.services.dapps 1.0
import shared.stores 1.0 import shared.stores 1.0
import utils 1.0
ConnectedDappsButton { ConnectedDappsButton {
id: root id: root
@ -16,6 +17,7 @@ ConnectedDappsButton {
signal dappsListReady() signal dappsListReady()
signal pairWCReady() signal pairWCReady()
signal displayToastMessage(string message, bool error)
onClicked: { onClicked: {
dappsListLoader.active = true dappsListLoader.active = true
@ -138,5 +140,9 @@ ConnectedDappsButton {
} }
} }
} }
function onDisplayToastMessage(message, err) {
root.displayToastMessage(message, err)
}
} }
} }

View File

@ -83,6 +83,16 @@ Item {
enabled: !!Global.walletConnectService enabled: !!Global.walletConnectService
wcService: Global.walletConnectService wcService: Global.walletConnectService
onDisplayToastMessage: (message, isErr) => {
if (isErr) {
Global.displayToastMessage(message, "", "warning", false,
Constants.ephemeralNotificationType.danger, "")
} else {
Global.displayToastMessage(message, "", "checkmark-circle", false,
Constants.ephemeralNotificationType.success, "")
}
}
} }
StatusButton { StatusButton {

View File

@ -9,7 +9,7 @@ import utils 1.0
QObject { QObject {
id: root id: root
required property WalletConnectSDK sdk required property WalletConnectSDKBase sdk
required property DAppsStore store required property DAppsStore store
readonly property alias dappsModel: d.dappsModel readonly property alias dappsModel: d.dappsModel

View File

@ -8,10 +8,9 @@ import QtWebChannel 1.15
import StatusQ.Core.Utils 0.1 as SQUtils import StatusQ.Core.Utils 0.1 as SQUtils
import StatusQ.Components 0.1 import StatusQ.Components 0.1
Item { WalletConnectSDKBase {
id: root id: root
required property string projectId
readonly property alias sdkReady: d.sdkReady readonly property alias sdkReady: d.sdkReady
readonly property alias webEngineLoader: loader readonly property alias webEngineLoader: loader
@ -21,66 +20,49 @@ Item {
implicitWidth: 1 implicitWidth: 1
implicitHeight: 1 implicitHeight: 1
signal statusChanged(string message)
signal sdkInit(bool success, var result)
signal pairResponse(bool success)
signal sessionProposal(var sessionProposal)
signal sessionProposalExpired()
signal buildApprovedNamespacesResult(var session, string error)
signal approveSessionResult(var approvedNamespaces, string error)
signal rejectSessionResult(string error)
signal sessionRequestEvent(var sessionRequest)
signal sessionRequestUserAnswerResult(bool accept, string error)
signal authRequest(var request)
signal authMessageFormated(string formatedMessage, string address)
signal authRequestUserAnswerResult(bool accept, string error)
signal sessionDelete(var topic, string error)
/// Generates \c pairResponse signal and expects to receive /// Generates \c pairResponse signal and expects to receive
/// a \c sessionProposal signal with the sessionProposal object /// a \c sessionProposal signal with the sessionProposal object
function pair(pairLink) { pair: function(pairLink) {
wcCalls.pair(pairLink) wcCalls.pair(pairLink)
} }
function getPairings(callback) { getPairings: function(callback) {
wcCalls.getPairings(callback) wcCalls.getPairings(callback)
} }
function getActiveSessions(callback) { getActiveSessions: function(callback) {
wcCalls.getActiveSessions(callback) wcCalls.getActiveSessions(callback)
} }
function disconnectSession(topic) { disconnectSession: function(topic) {
wcCalls.disconnectSession(topic) wcCalls.disconnectSession(topic)
} }
function disconnectPairing(topic) { disconnectPairing: function(topic) {
wcCalls.disconnectPairing(topic) wcCalls.disconnectPairing(topic)
} }
function ping(topic) { ping: function(topic) {
wcCalls.ping(topic) wcCalls.ping(topic)
} }
function buildApprovedNamespaces(params, supportedNamespaces) { buildApprovedNamespaces: function(params, supportedNamespaces) {
wcCalls.buildApprovedNamespaces(params, supportedNamespaces) wcCalls.buildApprovedNamespaces(params, supportedNamespaces)
} }
function approveSession(sessionProposal, supportedNamespaces) { approveSession: function(sessionProposal, supportedNamespaces) {
wcCalls.approveSession(sessionProposal, supportedNamespaces) wcCalls.approveSession(sessionProposal, supportedNamespaces)
} }
function rejectSession(id) { rejectSession: function(id) {
wcCalls.rejectSession(id) wcCalls.rejectSession(id)
} }
function acceptSessionRequest(topic, id, signature) { acceptSessionRequest: function(topic, id, signature) {
wcCalls.acceptSessionRequest(topic, id, signature) wcCalls.acceptSessionRequest(topic, id, signature)
} }
function rejectSessionRequest(topic, id, error) { rejectSessionRequest: function(topic, id, error) {
wcCalls.rejectSessionRequest(topic, id, error) wcCalls.rejectSessionRequest(topic, id, error)
} }

View File

@ -0,0 +1,62 @@
import QtQuick 2.15
/// SDK requires a visible parent to embed WebEngineView
Item {
required property string projectId
signal statusChanged(string message)
signal sdkInit(bool success, var result)
signal pairResponse(bool success)
signal sessionProposal(var sessionProposal)
signal sessionProposalExpired()
signal buildApprovedNamespacesResult(var session, string error)
signal approveSessionResult(var approvedNamespaces, string error)
signal rejectSessionResult(string error)
signal sessionRequestEvent(var sessionRequest)
signal sessionRequestUserAnswerResult(bool accept, string error)
signal authRequest(var request)
signal authMessageFormated(string formatedMessage, string address)
signal authRequestUserAnswerResult(bool accept, string error)
signal sessionDelete(var topic, string error)
property var pair: function(pairLink) {
console.error("pair not implemented")
}
property var getPairings: function(callback) {
console.error("getPairings not implemented")
}
property var getActiveSessions: function(callback) {
console.error("getActiveSessions not implemented")
}
property var disconnectSession: function(topic) {
console.error("disconnectSession not implemented")
}
property var disconnectPairing: function(topic) {
console.error("disconnectPairing not implemented")
}
property var ping: function(topic) {
console.error("ping not implemented")
}
property var buildApprovedNamespaces: function(params, supportedNamespaces) {
console.error("buildApprovedNamespaces not implemented")
}
property var approveSession: function(sessionProposal, supportedNamespaces) {
console.error("approveSession not implemented")
}
property var rejectSession: function(id) {
console.error("rejectSession not implemented")
}
property var acceptSessionRequest: function(topic, id, signature) {
console.error("acceptSessionRequest not implemented")
}
property var rejectSessionRequest: function(topic, id, error) {
console.error("rejectSessionRequest not implemented")
}
}

View File

@ -14,11 +14,11 @@ import utils 1.0
QObject { QObject {
id: root id: root
required property WalletConnectSDK wcSDK required property WalletConnectSDKBase wcSDK
required property DAppsStore store required property DAppsStore store
required property WalletStore walletStore required property WalletStore walletStore
readonly property alias dappsModel: d.dappsProvider.dappsModel readonly property alias dappsModel: dappsProvider.dappsModel
readonly property var validAccounts: SortFilterProxyModel { readonly property var validAccounts: SortFilterProxyModel {
sourceModel: walletStore.accounts sourceModel: walletStore.accounts
@ -51,6 +51,7 @@ QObject {
signal connectDApp(var dappChains, var sessionProposal, var approvedNamespaces) signal connectDApp(var dappChains, var sessionProposal, var approvedNamespaces)
signal approveSessionResult(var session, var error) signal approveSessionResult(var session, var error)
signal displayToastMessage(string message, bool error)
readonly property Connections sdkConnections: Connections { readonly property Connections sdkConnections: Connections {
target: wcSDK target: wcSDK
@ -78,9 +79,6 @@ QObject {
} }
function onApproveSessionResult(session, err) { function onApproveSessionResult(session, err) {
// Notify client
root.approveSessionResult(session, err)
if (err) { if (err) {
// TODO #14676: handle the error // TODO #14676: handle the error
console.error("Failed to approve session", err) console.error("Failed to approve session", err)
@ -89,44 +87,42 @@ QObject {
// TODO #14754: implement custom dApp notification // TODO #14754: implement custom dApp notification
let app_url = d.currentSessionProposal ? d.currentSessionProposal.params.proposer.metadata.url : "-" let app_url = d.currentSessionProposal ? d.currentSessionProposal.params.proposer.metadata.url : "-"
Global.displayToastMessage(qsTr("Connected to %1 via WalletConnect").arg(app_url), "", "checkmark-circle", false, Constants.ephemeralNotificationType.success, "") root.displayToastMessage(qsTr("Connected to %1 via WalletConnect").arg(app_url), false)
// Persist session // Persist session
store.addWalletConnectSession(JSON.stringify(session)) store.addWalletConnectSession(JSON.stringify(session))
d.dappsProvider.updateDapps() // Notify client
root.approveSessionResult(session, err)
dappsProvider.updateDapps()
} }
function onRejectSessionResult(err) { function onRejectSessionResult(err) {
let app_url = d.currentSessionProposal ? d.currentSessionProposal.params.proposer.metadata.url : "-" let app_url = d.currentSessionProposal ? d.currentSessionProposal.params.proposer.metadata.url : "-"
if(err) { if(err) {
Global.displayToastMessage(qsTr("Failed to reject connection request for %1").arg(app_url), "", "warning", false, Constants.ephemeralNotificationType.danger, "") root.displayToastMessage(qsTr("Failed to reject connection request for %1").arg(app_url), true)
} else { } else {
Global.displayToastMessage(qsTr("Connection request for %1 was rejected").arg(app_url), "", "checkmark-circle", false, Constants.ephemeralNotificationType.success, "") root.displayToastMessage(qsTr("Connection request for %1 was rejected").arg(app_url), false)
} }
} }
function onSessionDelete(topic, err) { function onSessionDelete(topic, err) {
let app_url = d.currentSessionProposal ? d.currentSessionProposal.params.proposer.metadata.url : "-" let app_url = d.currentSessionProposal ? d.currentSessionProposal.params.proposer.metadata.url : "-"
if(err) { if(err) {
Global.displayToastMessage(qsTr("Failed to disconnect from %1").arg(app_url), "", "warning", false, Constants.ephemeralNotificationType.danger, "") root.displayToastMessage(qsTr("Failed to disconnect from %1").arg(app_url), true)
} else { } else {
Global.displayToastMessage(qsTr("Disconnected from %1").arg(app_url), "", "checkmark-circle", false, Constants.ephemeralNotificationType.success, "") root.displayToastMessage(qsTr("Disconnected from %1").arg(app_url), false)
} }
} }
} }
QtObject { QObject {
id: d id: d
property var currentSessionProposal: null property var currentSessionProposal: null
property var acceptedSessionProposal: null property var acceptedSessionProposal: null
readonly property DAppsListProvider dappsProvider: DAppsListProvider {
sdk: root.wcSDK
store: root.store
}
// TODO #14676: use it to check if already paired // TODO #14676: use it to check if already paired
function getPairingTopicFromPairingUrl(url) function getPairingTopicFromPairingUrl(url)
{ {
@ -146,6 +142,13 @@ QObject {
} }
Component.onCompleted: { Component.onCompleted: {
d.dappsProvider.updateDapps() dappsProvider.updateDapps()
}
DAppsListProvider {
id: dappsProvider
sdk: root.wcSDK
store: root.store
} }
} }

View File

@ -1,3 +1,4 @@
WalletConnectSDKBase 1.0 WalletConnectSDKBase.qml
WalletConnectSDK 1.0 WalletConnectSDK.qml WalletConnectSDK 1.0 WalletConnectSDK.qml
WalletConnectService 1.0 WalletConnectService.qml WalletConnectService 1.0 WalletConnectService.qml
DAppsListProvider 1.0 DAppsListProvider.qml DAppsListProvider 1.0 DAppsListProvider.qml

View File

@ -95,6 +95,7 @@ Popup {
} }
StatusButton { StatusButton {
objectName: "connectDappButton"
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: implicitHeight Layout.preferredHeight: implicitHeight

View File

@ -14,6 +14,8 @@ import "PairWCModal"
StatusDialog { StatusDialog {
id: root id: root
objectName: "pairWCModal"
width: 480 width: 480
implicitHeight: 633 implicitHeight: 633