feat(dapp) disconnect wallet connect dapps

Closes: #15189
This commit is contained in:
Stefan 2024-06-25 00:26:53 +03:00 committed by Stefan Dunca
parent fecbd4005e
commit 94dc7b04a5
10 changed files with 248 additions and 153 deletions

View File

@ -27,6 +27,9 @@ QtObject:
proc addWalletConnectSession*(self: Controller, session_json: string): bool {.slot.} =
return self.service.addSession(session_json)
proc deactivateWalletConnectSession*(self: Controller, topic: string): bool {.slot.} =
return self.service.deactivateSession(topic)
proc dappsListReceived*(self: Controller, dappsJson: string) {.signal.}
# Emits signal dappsListReceived with the list of dApps

View File

@ -71,6 +71,10 @@ QtObject:
# TODO #14588: call it async
return status_go.addSession(session_json)
proc addSession*(self: Service, topic: string): bool =
# TODO #14588: call it async
return status_go.deactivateSession(topic)
proc getDapps*(self: Service): string =
let validAtEpoch = now().toTime().toUnix()
let testChains = self.settingsService.areTestNetworksEnabled()

View File

@ -108,8 +108,11 @@ Item {
color: "grey"
}
StatusBaseText { text: "Requests Queue" }
ListView {
Layout.fillWidth: true
Layout.preferredHeight: Math.min(50, contentHeight)
model: walletConnectService.requestHandler.requestsModel
delegate: RowLayout {
StatusBaseText {
@ -119,6 +122,35 @@ Item {
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: "grey"
}
StatusBaseText { text: "Persisted Sessions" }
ListView {
Layout.fillWidth: true
Layout.preferredHeight: Math.min(100, contentHeight)
model: sessionsModel
delegate: RowLayout {
StatusBaseText {
text: SQUtils.Utils.elideAndFormatWalletAddress(model.topic, 6, 4)
Layout.fillWidth: true
}
}
}
StatusButton {
text: qsTr("Clear Persistance")
visible: sessionsModel.count > 0
onClicked: {
settings.persistedSessions = "[]"
d.updateSessionsModelAndAddNewIfNotNull(null)
}
}
// spacer
ColumnLayout {}
@ -268,19 +300,26 @@ Item {
console.info("Persist Session", sessionJson)
let session = JSON.parse(sessionJson)
d.updateSessionsModelAndAddNewIfNotNull(session)
let firstIconUrl = session.peer.metadata.icons.length > 0 ? session.peer.metadata.icons[0] : ""
let persistedDapp = {
"name": session.peer.metadata.name,
"url": session.peer.metadata.url,
"iconUrl": firstIconUrl
}
d.persistedDapps.push(persistedDapp)
return true
}
function deactivateWalletConnectSession(topic) {
console.info("Deactivate Persisted Session", topic)
let sessions = JSON.parse(settings.persistedSessions)
let newSessions = sessions.filter(function(session) {
return session.topic !== topic
})
settings.persistedSessions = JSON.stringify(newSessions)
d.updateSessionsModelAndAddNewIfNotNull(null)
return true
}
function getDapps() {
this.dappsListReceived(JSON.stringify(d.persistedDapps))
let dappsJson = JSON.stringify(d.persistedDapps)
this.dappsListReceived(dappsJson)
return true
}
@ -323,7 +362,7 @@ Item {
}
property var accounts: customAccountsModel.count > 0 ? customAccountsModel : defaultAccountsModel
readonly property ListModel nonWatchAccounts: accounts
function getNetworkShortNames(chainIds) {
return "eth:oeth:arb"
}
@ -355,15 +394,43 @@ Item {
readonly property int openDappsTestCase: 1
readonly property int openPairTestCase: 2
property var persistedDapps: [
{"name":"Test dApp 1", "url":"https://dapp.test/1","iconUrl":"https://se-sdk-dapp.vercel.app/assets/eip155:1.png"},
{"name":"Test dApp 2", "url":"https://dapp.test/2","iconUrl":"https://react-app.walletconnect.com/assets/eip155-1.png"},
{"name":"Test dApp 3", "url":"https://dapp.test/3","iconUrl":"https://react-app.walletconnect.com/assets/eip155-1.png"},
{"name":"Test dApp 4 - very long name !!!!!!!!!!!!!!!!", "url":"https://dapp.test/4","iconUrl":"https://react-app.walletconnect.com/assets/eip155-1.png"},
{"name":"Test dApp 5 - very long url", "url":"https://dapp.test/very_long/url/unusual","iconUrl":"https://react-app.walletconnect.com/assets/eip155-1.png"},
{"name":"Test dApp 6", "url":"https://dapp.test/6","iconUrl":"https://react-app.walletconnect.com/assets/eip155-1.png"}
]
ListModel {
id: sessionsModel
}
function updateSessionsModelAndAddNewIfNotNull(newSession) {
var sessions = JSON.parse(settings.persistedSessions)
if (!!newSession) {
sessions.push(newSession)
settings.persistedSessions = JSON.stringify(sessions)
}
sessionsModel.clear()
d.persistedDapps = []
sessions.forEach(function(session) {
sessionsModel.append(session)
let firstIconUrl = session.peer.metadata.icons.length > 0 ? session.peer.metadata.icons[0] : ""
let persistedDapp = {
"name": session.peer.metadata.name,
"url": session.peer.metadata.url,
"iconUrl": firstIconUrl,
"topic": session.topic
}
var found = false
for (var i = 0; i < d.persistedDapps.length; i++) {
if (d.persistedDapps[i].url == persistedDapp.url) {
found = true
break
}
}
if (!found) {
d.persistedDapps.push(persistedDapp)
}
})
}
property var persistedDapps: []
ListModel {
id: customAccountsModel
}
@ -387,6 +454,11 @@ Item {
property bool enableSDK: true
property bool pending : false
property string customAccounts: ""
property string persistedSessions: "[]"
}
Component.onCompleted: {
d.updateSessionsModelAndAddNewIfNotNull(null)
}
}

View File

@ -19,6 +19,7 @@ ComboBox {
signal dappsListReady
signal pairDapp
signal disconnectDapp(string dappUrl)
implicitHeight: 38
implicitWidth: 38
@ -54,11 +55,15 @@ ComboBox {
delegate: DAppDelegate {
width: ListView.view.width
onDisconnectDapp: (dappUrl) => {
root.disconnectDapp(dappUrl)
}
}
popup: DAppsListPopup {
objectName: "dappsListPopup"
x: root.width - width
y: root.height + 4

View File

@ -27,6 +27,10 @@ DappsComboBox {
pairWCLoader.active = true
}
onDisconnectDapp: (dappUrl) => {
root.wcService.disconnectDapp(dappUrl)
}
Loader {
id: pairWCLoader
@ -94,7 +98,7 @@ DappsComboBox {
onDisconnect: {
connectDappLoader.active = false
root.wcService.disconnectDapp(sessionTopic)
root.wcService.disconnectSession(sessionTopic)
}
}
}

View File

@ -45,11 +45,6 @@ QObject {
root.store.dappsListReceived.disconnect(dappsListReceivedFn);
}
// TODO DEV: check if still holds true
// Reasons to postpone `getDapps` call:
// - the first recent made session will always have `active` prop set to false
// - expiration date won't be the correct one, but one used in session proposal
// - the list of dapps will display successfully made pairing as inactive
getActiveSessionsFn = () => {
sdk.getActiveSessions((sessions) => {
root.store.dappsListReceived.disconnect(dappsListReceivedFn);

View File

@ -99,7 +99,7 @@ WalletConnectSDKBase {
d.engine.runJavaScript(`wc.init("${root.projectId}").catch((error) => {wc.statusObject.sdkInitialized("SDK init error: "+error);})`, function(result) {
console.debug(`WC WalletConnectSDK.wcCall.init; response: ${JSON.stringify(result, null, 2)}`)
console.debug(`WC WalletConnectSDK.wcCall.init; response: ${JSON.stringify(result)}`)
if (result && !!result.error)
{
@ -113,7 +113,7 @@ WalletConnectSDKBase {
if (d.engine) {
d.engine.runJavaScript(`wc.getPairings()`, function(result) {
console.debug(`WC WalletConnectSDK.wcCall.getPairings; result: ${JSON.stringify(result, null, 2)}`)
console.debug(`WC WalletConnectSDK.wcCall.getPairings; result: ${JSON.stringify(result)}`)
if (callback && result) {
callback(result)
@ -127,12 +127,6 @@ WalletConnectSDKBase {
if (d.engine) {
d.engine.runJavaScript(`wc.getActiveSessions()`, function(result) {
var allSessions = ""
for (var key of Object.keys(result)) {
allSessions += `\nsessionTopic: ${key} relatedPairingTopic: ${result[key].pairingTopic}`;
}
console.debug(`WC WalletConnectSDK.wcCall.getActiveSessions; result: ${allSessions}`)
if (callback && result) {
callback(result)
}
@ -294,7 +288,7 @@ WalletConnectSDKBase {
console.debug(`WC WalletConnectSDK.wcCall.auth; cacaoPayload: ${JSON.stringify(cacaoPayload)}, address: ${address}`)
d.engine.runJavaScript(`wc.formatAuthMessage(${JSON.stringify(cacaoPayload)}, "${address}")`, function(result) {
console.debug(`WC WalletConnectSDK.wcCall.formatAuthMessage; response: ${JSON.stringify(result, null, 2)}`)
console.debug(`WC WalletConnectSDK.wcCall.formatAuthMessage; response: ${JSON.stringify(result)}`)
root.authMessageFormated(result, address)
})
@ -373,12 +367,12 @@ WalletConnectSDKBase {
}
function onBuildApprovedNamespacesResponse(approvedNamespaces, error) {
console.debug(`WC WalletConnectSDK.onBuildApprovedNamespacesResponse; approvedNamespaces: ${approvedNamespaces ? JSON.stringify(approvedNamespaces, null, 2) : "-"}, error: ${error}`)
console.debug(`WC WalletConnectSDK.onBuildApprovedNamespacesResponse; approvedNamespaces: ${approvedNamespaces ? JSON.stringify(approvedNamespaces) : "-"}, error: ${error}`)
root.buildApprovedNamespacesResult(approvedNamespaces, error)
}
function onApproveSessionResponse(session, error) {
console.debug(`WC WalletConnectSDK.onApproveSessionResponse; sessionTopic: ${JSON.stringify(session, null, 2)}, error: ${error}`)
console.debug(`WC WalletConnectSDK.onApproveSessionResponse; sessionTopic: ${JSON.stringify(session)}, error: ${error}`)
root.approveSessionResult(session, error)
}
@ -400,51 +394,51 @@ WalletConnectSDKBase {
}
function onSessionProposal(details) {
console.debug(`WC WalletConnectSDK.onSessionProposal; details: ${JSON.stringify(details, null, 2)}`)
console.debug(`WC WalletConnectSDK.onSessionProposal; details: ${JSON.stringify(details)}`)
root.sessionProposal(details)
}
function onSessionUpdate(details) {
console.debug(`WC TODO WalletConnectSDK.onSessionUpdate; details: ${JSON.stringify(details, null, 2)}`)
console.debug(`WC TODO WalletConnectSDK.onSessionUpdate; details: ${JSON.stringify(details)}`)
}
function onSessionExtend(details) {
console.debug(`WC TODO WalletConnectSDK.onSessionExtend; details: ${JSON.stringify(details, null, 2)}`)
console.debug(`WC TODO WalletConnectSDK.onSessionExtend; details: ${JSON.stringify(details)}`)
}
function onSessionPing(details) {
console.debug(`WC TODO WalletConnectSDK.onSessionPing; details: ${JSON.stringify(details, null, 2)}`)
console.debug(`WC TODO WalletConnectSDK.onSessionPing; details: ${JSON.stringify(details)}`)
}
function onSessionDelete(details) {
console.debug(`WC WalletConnectSDK.onSessionDelete; details: ${JSON.stringify(details, null, 2)}`)
console.debug(`WC WalletConnectSDK.onSessionDelete; details: ${JSON.stringify(details)}`)
root.sessionDelete(details.topic, "")
}
function onSessionExpire(details) {
console.debug(`WC TODO WalletConnectSDK.onSessionExpire; details: ${JSON.stringify(details, null, 2)}`)
console.debug(`WC TODO WalletConnectSDK.onSessionExpire; details: ${JSON.stringify(details)}`)
}
function onSessionRequest(details) {
console.debug(`WC WalletConnectSDK.onSessionRequest; details: ${JSON.stringify(details, null, 2)}`)
console.debug(`WC WalletConnectSDK.onSessionRequest; details: ${JSON.stringify(details)}`)
root.sessionRequestEvent(details)
}
function onSessionRequestSent(details) {
console.debug(`WC TODO WalletConnectSDK.onSessionRequestSent; details: ${JSON.stringify(details, null, 2)}`)
console.debug(`WC TODO WalletConnectSDK.onSessionRequestSent; details: ${JSON.stringify(details)}`)
}
function onSessionEvent(details) {
console.debug(`WC TODO WalletConnectSDK.onSessionEvent; details: ${JSON.stringify(details, null, 2)}`)
console.debug(`WC TODO WalletConnectSDK.onSessionEvent; details: ${JSON.stringify(details)}`)
}
function onProposalExpire(details) {
console.debug(`WC WalletConnectSDK.onProposalExpire; details: ${JSON.stringify(details, null, 2)}`)
console.debug(`WC WalletConnectSDK.onProposalExpire; details: ${JSON.stringify(details)}`)
root.sessionProposalExpired()
}
function onAuthRequest(details) {
console.debug(`WC WalletConnectSDK.onAuthRequest; details: ${JSON.stringify(details, null, 2)}`)
console.debug(`WC WalletConnectSDK.onAuthRequest; details: ${JSON.stringify(details)}`)
root.authRequest(details)
}

View File

@ -64,10 +64,22 @@ QObject {
wcSDK.rejectSession(id)
}
function disconnectDapp(sessionTopic) {
function disconnectSession(sessionTopic) {
wcSDK.disconnectSession(sessionTopic)
}
function disconnectDapp(url) {
wcSDK.getActiveSessions((sessions) => {
for (let key in sessions) {
let dapp = sessions[key].peer.metadata
let topic = sessions[key].topic
if (dapp.url == url) {
wcSDK.disconnectSession(topic)
}
}
});
}
signal connectDApp(var dappChains, var sessionProposal, var approvedNamespaces)
signal approveSessionResult(var session, var error)
signal sessionRequest(SessionRequestResolved request)
@ -133,6 +145,9 @@ QObject {
}
function onSessionDelete(topic, err) {
store.deactivateWalletConnectSession(topic)
dappsProvider.updateDapps()
const app_url = d.currentSessionProposal ? d.currentSessionProposal.params.proposer.metadata.url : "-"
const app_domain = StringUtils.extractDomainFromLink(app_url)
if(err) {

View File

@ -1,106 +1,105 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtGraphicalEffects 1.15
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
MouseArea {
id: root
implicitHeight: 50
hoverEnabled: true
required property string name
required property string url
required property string iconUrl
signal disconnectDapp()
RowLayout {
anchors.fill: parent
anchors.margins: 8
Item {
Layout.preferredWidth: 32
Layout.preferredHeight: 32
StatusImage {
id: iconImage
anchors.fill: parent
source: root.iconUrl
visible: !fallbackImage.visible
}
StatusIcon {
id: fallbackImage
anchors.fill: parent
icon: "dapp"
color: Theme.palette.baseColor1
visible: iconImage.isLoading || iconImage.isError || !root.iconUrl
}
layer.enabled: true
layer.effect: OpacityMask {
maskSource: Rectangle {
width: iconImage.width
height: iconImage.height
radius: width / 2
visible: false
}
}
}
ColumnLayout {
Layout.leftMargin: 12
Layout.rightMargin: 12
StatusBaseText {
text: root.name
Layout.fillWidth: true
font.pixelSize: 13
font.bold: true
elide: Text.ElideRight
clip: true
}
StatusBaseText {
text: root.url
Layout.fillWidth: true
font.pixelSize: 12
color: Theme.palette.baseColor1
elide: Text.ElideRight
clip: true
}
}
StatusFlatButton {
size: StatusBaseButton.Size.Large
asset.color: root.containsMouse ? Theme.palette.directColor1
: Theme.palette.baseColor1
icon.name: "disconnect"
tooltip.text: qsTr("Disconnect dApp")
onClicked: {
console.debug(`TODO #14755 - Disconnect ${root.name}`)
// root.disconnectDapp()
}
}
}
}
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtGraphicalEffects 1.15
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
MouseArea {
id: root
implicitHeight: 50
hoverEnabled: true
required property string name
required property string url
required property string iconUrl
signal disconnectDapp(string dappUrl)
RowLayout {
anchors.fill: parent
anchors.margins: 8
Item {
Layout.preferredWidth: 32
Layout.preferredHeight: 32
StatusImage {
id: iconImage
anchors.fill: parent
source: root.iconUrl
visible: !fallbackImage.visible
}
StatusIcon {
id: fallbackImage
anchors.fill: parent
icon: "dapp"
color: Theme.palette.baseColor1
visible: iconImage.isLoading || iconImage.isError || !root.iconUrl
}
layer.enabled: true
layer.effect: OpacityMask {
maskSource: Rectangle {
width: iconImage.width
height: iconImage.height
radius: width / 2
visible: false
}
}
}
ColumnLayout {
Layout.leftMargin: 12
Layout.rightMargin: 12
StatusBaseText {
text: root.name
Layout.fillWidth: true
font.pixelSize: 13
font.bold: true
elide: Text.ElideRight
clip: true
}
StatusBaseText {
text: root.url
Layout.fillWidth: true
font.pixelSize: 12
color: Theme.palette.baseColor1
elide: Text.ElideRight
clip: true
}
}
StatusFlatButton {
size: StatusBaseButton.Size.Large
asset.color: root.containsMouse ? Theme.palette.directColor1
: Theme.palette.baseColor1
icon.name: "disconnect"
tooltip.text: qsTr("Disconnect dApp")
onClicked: {
root.disconnectDapp(root.url)
}
}
}
}

View File

@ -16,6 +16,10 @@ QObject {
return controller.addWalletConnectSession(sessionJson)
}
function deactivateWalletConnectSession(topic) {
return controller.deactivateWalletConnectSession(topic)
}
function authenticateUser(topic, id, address) {
let ok = controller.authenticateUser(topic, id, address)
if(!ok) {