chore(walletconnect): improvements identifying pairings and sessions

This commit is contained in:
Sale Djenic 2023-12-08 19:18:58 +01:00 committed by saledjenic
parent f1c090a765
commit d587552c40
7 changed files with 571 additions and 298 deletions

View File

@ -80,17 +80,23 @@ QtObject:
error "Unknown identifier"
# supportedNamespaces is a Namespace as defined in status-go: services/wallet/walletconnect/walletconnect.go
proc proposeUserPair*(self: Controller, sessionProposalJson: string, supportedNamespacesJson: string) {.signal.}
proc respondSessionProposal*(self: Controller, sessionProposalJson: string, supportedNamespacesJson: string, error: string) {.signal.}
proc pairSessionProposal(self: Controller, sessionProposalJson: string) {.slot.} =
var res: JsonNode
let err = backend_wallet_connect.pair(res, sessionProposalJson)
if err.len > 0:
error "Failed to pair session"
return
let sessionProposalJson = if res.hasKey("sessionProposal"): $res["sessionProposal"] else: ""
let supportedNamespacesJson = if res.hasKey("supportedNamespaces"): $res["supportedNamespaces"] else: ""
self.proposeUserPair(sessionProposalJson, supportedNamespacesJson)
proc sessionProposal(self: Controller, sessionProposalJson: string) {.slot.} =
var
supportedNamespacesJson: string
error: string
try:
var res: JsonNode
let err = backend_wallet_connect.pair(res, sessionProposalJson)
if err.len > 0:
raise newException(CatchableError, err)
supportedNamespacesJson = if res.hasKey("supportedNamespaces"): $res["supportedNamespaces"] else: ""
except Exception as e:
error = e.msg
error "pairing", msg=error
self.respondSessionProposal(sessionProposalJson, supportedNamespacesJson, error)
proc recordSuccessfulPairing(self: Controller, sessionProposalJson: string) {.slot.} =
if backend_wallet_connect.recordSuccessfulPairing(sessionProposalJson):

View File

@ -11,6 +11,8 @@ ListView {
signal disconnect(string topic)
spacing: 32
delegate: Item {
implicitWidth: delegateLayout.implicitWidth
implicitHeight: delegateLayout.implicitHeight
@ -19,10 +21,16 @@ ListView {
id: delegateLayout
width: root.width
StatusIcon {
icon: model.peerMetadata.icons.length > 0? model.peerMetadata.icons[0] : ""
visible: !!icon
}
StatusBaseText {
text: `${SQUtils.Utils.elideText(model.topic, 6, 6)}\n${new Date(model.expiry * 1000).toLocaleString()}`
text: `${model.peerMetadata.name}\n${model.peerMetadata.url}\nTopic: ${SQUtils.Utils.elideText(model.topic, 6, 6)}\nExpire: ${new Date(model.expiry * 1000).toLocaleString()}`
color: model.active ? "green" : "orange"
}
StatusButton {
text: "Disconnect"
@ -34,4 +42,4 @@ ListView {
}
}
}
}
}

View File

@ -0,0 +1,155 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Utils 0.1 as SQUtils
ListView {
id: root
signal disconnect(string topic)
signal ping(string topic)
spacing: 48
delegate: Item {
implicitWidth: delegateLayout.implicitWidth
implicitHeight: delegateLayout.implicitHeight
ListModel {
id: namespacesListModel
}
Component.onCompleted: {
for (var key of Object.keys(model.namespaces)) {
let namespace = model.namespaces[key]
let obj = {
"eip": "",
"chain": "",
"methods": namespace.methods.join(", "),
"events": namespace.events.join(", ")
}
if (namespace.chains.length > 0) {
let data = namespace.chains[0].split(":")
if (data.length === 2) {
obj["eip"] = data[0]
obj["chain"] = data[1]
}
}
namespacesListModel.append(obj)
}
}
ColumnLayout {
id: delegateLayout
width: root.width
spacing: 8
StatusIcon {
icon: model.peer.metadata.icons.length > 0? model.peer.metadata.icons[0] : ""
visible: !!icon
}
StatusBaseText {
text: `Pairing topic:${SQUtils.Utils.elideText(model.pairingTopic, 6, 6)}\n${model.peer.metadata.name}\n${model.peer.metadata.url}`
}
StatusBaseText {
text: `Session topic:${SQUtils.Utils.elideText(model.topic, 6, 6)}\nExpire:${new Date(model.expiry * 1000).toLocaleString()}`
}
Rectangle {
color: "transparent"
border.color: "grey"
border.width: 1
Layout.fillWidth: true
Layout.preferredHeight: allNamespaces.implicitHeight
ColumnLayout {
id: allNamespaces
Repeater {
model: namespacesListModel
delegate: Rectangle {
id: namespaceDelegateRoot
property bool expanded: false
color: "transparent"
border.color: "grey"
border.width: 1
Layout.fillWidth: true
Layout.preferredHeight: namespace.implicitHeight
ColumnLayout {
id: namespace
spacing: 8
RowLayout {
StatusBaseText {
text: `Review ${model.eip} permissions`
}
StatusIcon {
icon: namespaceDelegateRoot.expanded? "chevron-up" : "chevron-down"
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: {
namespaceDelegateRoot.expanded = !namespaceDelegateRoot.expanded
}
}
}
}
StatusBaseText {
Layout.fillWidth: true
visible: namespaceDelegateRoot.expanded
text: `Chain ${model.chain}`
}
StatusBaseText {
Layout.fillWidth: true
visible: namespaceDelegateRoot.expanded
text: `Methods: ${model.methods}\nEvents: ${model.events}`
}
}
}
}
}
}
RowLayout {
StatusButton {
text: "Disconnect"
onClicked: {
root.disconnect(model.topic)
}
}
StatusButton {
text: "Ping"
onClicked: {
root.ping(model.topic)
}
}
}
}
}
}

View File

@ -45,104 +45,198 @@ Popup {
ColumnLayout {
id: mainLayout
spacing: 8
StatusBaseText {
text: qsTr("Debugging UX until design is ready")
font.bold: true
}
StatusSwitch {
id: testAuthentication
checkable: true
text: qsTr("Test Authentication")
}
StatusInput {
id: pairLinkInput
StatusTabBar {
id: tabBar
Layout.fillWidth: true
placeholderText: "Insert pair link"
StatusTabButton {
width: implicitWidth
text: qsTr("WalletConnect")
}
StatusTabButton {
width: implicitWidth
text: qsTr("Sessions")
}
StatusTabButton {
width: implicitWidth
text: qsTr("Pairings")
}
}
RowLayout {
StackLayout {
Layout.fillWidth: true
currentIndex: tabBar.currentIndex
StatusButton {
text: testAuthentication.checked? "Authentication" : "Pair"
ColumnLayout {
onClicked: {
if (testAuthentication.checked) {
d.setStatusText("")
d.setDetailsText("")
d.state = ""
accountsModel.clear()
StatusSwitch {
id: testAuthentication
checkable: true
text: qsTr("Test Authentication")
}
statusText.text = "Authenticating..."
root.sdk.auth(pairLinkInput.text)
return
StatusInput {
id: pairLinkInput
Layout.fillWidth: true
placeholderText: "Insert pair link"
}
RowLayout {
Layout.fillWidth: true
StatusButton {
text: testAuthentication.checked? "Authentication" : "Pair"
onClicked: {
d.setStatusText("")
d.setDetailsText("")
d.state = ""
accountsModel.clear()
if (testAuthentication.checked) {
d.setStatusText("Authenticating...")
root.sdk.auth(pairLinkInput.text)
return
}
d.setStatusText("Pairing...")
root.sdk.pair(pairLinkInput.text)
}
enabled: pairLinkInput.text.length > 0 && root.sdk.sdkReady
}
statusText.text = "Pairing..."
root.sdk.pair(pairLinkInput.text)
StatusButton {
text: "Accept"
onClicked: {
root.sdk.approveSession(d.observedData, d.supportedNamespaces)
}
visible: d.state === d.waitingPairState
}
StatusButton {
text: "Reject"
onClicked: {
root.sdk.rejectSession(d.observedData.id)
}
visible: d.state === d.waitingPairState
}
}
ButtonGroup {
id: selAccBtnGroup
}
SelectAccount {
Layout.fillWidth: true
Layout.preferredHeight: contentHeight
model: accountsModel
buttonGroup: selAccBtnGroup
onAccountSelected: {
root.sdk.formatAuthMessage(d.observedData.params.cacaoPayload, address)
}
}
RowLayout {
StatusButton {
text: "Accept"
onClicked: {
if (testAuthentication.checked) {
root.controller.authRequest(d.selectedAddress, d.authMessage, passwordInput.text)
return
}
root.controller.sessionRequest(JSON.stringify(d.sessionRequest), passwordInput.text)
}
visible: d.state === d.waitingUserResponseToSessionRequest ||
d.state === d.waitingUserResponseToAuthRequest
}
StatusButton {
text: "Reject"
onClicked: {
if (testAuthentication.checked) {
root.sdk.authReject(d.observedData.id, d.selectedAddress)
return
}
root.sdk.rejectSessionRequest(d.sessionRequest.topic, d.sessionRequest.id, false)
}
visible: d.state === d.waitingUserResponseToSessionRequest ||
d.state === d.waitingUserResponseToAuthRequest
}
StatusInput {
id: passwordInput
text: "1234567890"
placeholderText: "Insert account password"
visible: d.state === d.waitingUserResponseToSessionRequest ||
d.state === d.waitingUserResponseToAuthRequest
}
}
enabled: pairLinkInput.text.length > 0 && root.sdk.sdkReady
}
StatusButton {
text: "Accept"
onClicked: {
root.sdk.approvePairSession(d.observedData, d.supportedNamespaces)
ColumnLayout {
Layout.fillWidth: true
Sessions {
Layout.fillWidth: true
Layout.preferredHeight: contentHeight
model: root.sdk.sessionsModel
onDisconnect: function (topic) {
root.sdk.disconnectTopic(topic)
}
onPing: function (topic) {
root.sdk.ping(topic)
}
}
visible: d.state === d.waitingPairState
}
StatusButton {
text: "Reject"
onClicked: {
root.sdk.rejectPairSession(d.observedData.id)
ColumnLayout {
Layout.fillWidth: true
Pairings {
Layout.fillWidth: true
Layout.preferredHeight: contentHeight
model: root.sdk.pairingsModel
onDisconnect: function (topic) {
root.sdk.disconnectTopic(topic)
}
}
visible: d.state === d.waitingPairState
}
}
Item {
Layout.fillWidth: true
Layout.preferredHeight: 32
}
ColumnLayout {
StatusBaseText {
text: qsTr("Tracking details...")
font.bold: true
}
StatusBaseText {
id: statusText
text: "-"
}
StatusBaseText {
text: "Pairings"
visible: root.sdk.pairingsModel.count > 0
}
Pairings {
Layout.fillWidth: true
Layout.minimumWidth: count > 0 ? 400 : 0
Layout.preferredHeight: contentHeight
Layout.maximumHeight: 300
model: root.sdk.pairingsModel
onDisconnect: function (topic) {
root.sdk.disconnectPairing(topic)
}
}
ButtonGroup {
id: selAccBtnGroup
}
SelectAccount {
Layout.fillWidth: true
Layout.minimumWidth: count > 0 ? 400 : 0
Layout.preferredHeight: contentHeight
Layout.maximumHeight: 300
model: accountsModel
buttonGroup: selAccBtnGroup
onAccountSelected: {
root.sdk.formatAuthMessage(d.observedData.params.cacaoPayload, address)
}
font.bold: true
}
StatusBaseText {
@ -152,49 +246,7 @@ Popup {
color: "#FF00FF"
}
RowLayout {
StatusButton {
text: "Accept"
onClicked: {
if (testAuthentication.checked) {
root.controller.authRequest(d.selectedAddress, d.authMessage, passwordInput.text)
return
}
root.controller.sessionRequest(JSON.stringify(d.sessionRequest), passwordInput.text)
}
visible: d.state === d.waitingUserResponseToSessionRequest ||
d.state === d.waitingUserResponseToAuthRequest
}
StatusButton {
text: "Reject"
onClicked: {
if (testAuthentication.checked) {
root.sdk.authReject(d.observedData.id, d.selectedAddress)
return
}
root.sdk.rejectSessionRequest(d.sessionRequest.topic, d.sessionRequest.id, false)
}
visible: d.state === d.waitingUserResponseToSessionRequest ||
d.state === d.waitingUserResponseToAuthRequest
}
StatusInput {
id: passwordInput
text: "1234567890"
placeholderText: "Insert account password"
visible: d.state === d.waitingUserResponseToSessionRequest ||
d.state === d.waitingUserResponseToAuthRequest
}
}
ColumnLayout { /* spacer */ }
}
// Separator
ColumnLayout {}
}
ScrollBar.vertical: ScrollBar {}
@ -216,15 +268,15 @@ Popup {
}
}
function onPairSessionProposal(sessionProposal) {
function onSessionProposal(sessionProposal) {
d.setDetailsText(sessionProposal)
d.setStatusText("Pair ID: " + sessionProposal.id + "; Topic: " + sessionProposal.params.pairingTopic)
root.controller.pairSessionProposal(JSON.stringify(sessionProposal))
root.controller.sessionProposal(JSON.stringify(sessionProposal))
}
function onPairAcceptedResult(sessionProposal, success, result) {
d.setDetailsText(result)
if (success) {
function onApproveSessionResult(sessionProposal, error) {
d.setDetailsText("")
if (!error) {
d.setStatusText("Pairing OK")
d.state = d.pairedState
root.controller.recordSuccessfulPairing(JSON.stringify(sessionProposal))
@ -234,10 +286,10 @@ Popup {
}
}
function onPairRejectedResult(success, result) {
d.setDetailsText(result)
function onRejectSessionResult(error) {
d.setDetailsText("")
d.state = d.sdkReadyState
if (success) {
if (!error) {
d.setStatusText("Pairing rejected")
} else {
d.setStatusText("Rejecting pairing error", "red")
@ -257,12 +309,12 @@ Popup {
}
}
function onPairSessionProposalExpired() {
function onSessionProposalExpired() {
d.setStatusText(`Timeout waiting for response. Reusing URI?`, "red")
}
function onStatusChanged(message) {
statusText.text = message
d.setStatusText(message)
}
function onAuthRequest(request) {
@ -352,6 +404,7 @@ Popup {
}
statusText.color = textColor
}
function setDetailsText(message) {
if (message === undefined) {
message = "undefined"
@ -369,7 +422,12 @@ Popup {
Connections {
target: root.controller
function onProposeUserPair(sessionProposalJson, supportedNamespacesJson) {
function onRespondSessionProposal(sessionProposalJson, supportedNamespacesJson, error) {
if (error) {
d.setStatusText(`Error: ${error}`, "red")
d.setDetailsText("")
return
}
d.setStatusText("Waiting user accept")
d.observedData = JSON.parse(sessionProposalJson)

View File

@ -8,12 +8,15 @@ import QtWebChannel 1.15
import StatusQ.Core.Utils 0.1 as SQUtils
import StatusQ.Components 0.1
import utils 1.0
Item {
id: root
required property string projectId
readonly property alias sdkReady: d.sdkReady
readonly property alias pairingsModel: d.pairingsModel
readonly property alias sessionsModel: d.sessionsModel
readonly property alias webEngineLoader: loader
property alias active: loader.active
@ -24,10 +27,10 @@ Item {
signal statusChanged(string message)
signal sdkInit(bool success, var result)
signal pairSessionProposal(var sessionProposal)
signal pairSessionProposalExpired()
signal pairAcceptedResult(var sessionProposal, bool success, var sessionType)
signal pairRejectedResult(bool success, var result)
signal sessionProposal(var sessionProposal)
signal sessionProposalExpired()
signal approveSessionResult(var sessionProposal, string error)
signal rejectSessionResult(string error)
signal sessionRequestEvent(var sessionRequest)
signal sessionRequestUserAnswerResult(bool accept, string error)
@ -41,16 +44,20 @@ Item {
wcCalls.pair(pairLink)
}
function disconnectPairing(topic) {
wcCalls.disconnectPairing(topic)
function disconnectTopic(topic) {
wcCalls.disconnectTopic(topic)
}
function approvePairSession(sessionProposal, supportedNamespaces) {
wcCalls.approvePairSession(sessionProposal, supportedNamespaces)
function ping(topic) {
wcCalls.ping(topic)
}
function rejectPairSession(id) {
wcCalls.rejectPairSession(id)
function approveSession(sessionProposal, supportedNamespaces) {
wcCalls.approveSession(sessionProposal, supportedNamespaces)
}
function rejectSession(id) {
wcCalls.rejectSession(id)
}
function acceptSessionRequest(topic, id, signature) {
@ -82,6 +89,7 @@ Item {
property bool sdkReady: false
property ListModel pairingsModel: pairings
property ListModel sessionsModel: sessions
property WebEngineView engine: loader.instance
@ -89,6 +97,7 @@ Item {
if (sdkReady)
{
d.resetPairingsModel()
d.resetSessionsModel()
}
}
@ -96,18 +105,33 @@ Item {
{
pairings.clear();
wcCalls.getPairings((pairList) => {
for (let i = 0; i < pairList.length; i++) {
pairings.append({
active: pairList[i].active,
topic: pairList[i].topic,
expiry: pairList[i].expiry
});
if (entryCallback) {
entryCallback(pairList[i])
}
}
})
// We have to postpone `getPairings` call, cause otherwise:
// - the last made pairing 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 pairings will display succesfully made pairing as inactive
Backpressure.debounce(this, 250, () => {
wcCalls.getPairings((pairList) => {
for (let i = 0; i < pairList.length; i++) {
pairings.append(pairList[i]);
if (entryCallback) {
entryCallback(pairList[i])
}
}
});
})();
}
function resetSessionsModel() {
sessions.clear();
Backpressure.debounce(this, 250, () => {
wcCalls.getActiveSessions((sessionList) => {
for (var topic of Object.keys(sessionList)) {
sessions.append(sessionList[topic]);
}
});
})();
}
function getPairingTopicFromPairingUrl(url)
@ -116,11 +140,13 @@ Item {
{
return null;
}
const atIndex = url.indexOf("@");
if (atIndex < 0)
{
return null;
}
return url.slice(3, atIndex);
}
}
@ -147,17 +173,19 @@ Item {
d.engine.runJavaScript(`wc.getPairings()`, function(result) {
console.debug(`WC WalletConnectSDK.wcCall.getPairings; response: ${JSON.stringify(result, null, 2)}`)
if (callback && result) {
callback(result)
}
})
}
if (result)
{
if (!!result.error) {
console.error("getPairings: ", result.error)
return
}
function getActiveSessions(callback) {
console.debug(`WC WalletConnectSDK.wcCall.getActiveSessions;`)
callback(result.result)
return
d.engine.runJavaScript(`wc.getActiveSessions()`, function(result) {
if (callback && result) {
callback(result)
}
})
}
@ -165,75 +193,46 @@ Item {
function pair(pairLink) {
console.debug(`WC WalletConnectSDK.wcCall.pair; pairLink: ${pairLink}`)
wcCalls.getPairings((allPairings) => {
console.debug(`WC WalletConnectSDK.wcCall.pair; response: ${JSON.stringify(allPairings, null, 2)}`)
let pairingTopic = d.getPairingTopicFromPairingUrl(pairLink);
// Find pairing by topic
const pairing = allPairings.find((p) => p.topic === pairingTopic);
if (pairing)
{
if (pairing.active) {
console.warn("pair: already paired")
return
}
}
d.engine.runJavaScript(`wc.pair("${pairLink}")`, function(result) {
if (result && !!result.error)
{
console.error("pair: ", result.error)
}
d.engine.runJavaScript(`
wc.pair("${pairLink}")
.then((value) => {
wc.statusObject.onPairResponse("")
})
}
)
.catch((e) => {
wc.statusObject.onPairResponse(e.message)
})
`
)
}
function approvePairSession(sessionProposal, supportedNamespaces) {
console.debug(`WC WalletConnectSDK.wcCall.approvePairSession; sessionProposal: ${JSON.stringify(sessionProposal)}, supportedNamespaces: ${JSON.stringify(supportedNamespaces)}`)
function approveSession(sessionProposal, supportedNamespaces) {
console.debug(`WC WalletConnectSDK.wcCall.approveSession; sessionProposal: ${JSON.stringify(sessionProposal)}, supportedNamespaces: ${JSON.stringify(supportedNamespaces)}`)
d.engine.runJavaScript(`wc.approvePairSession(${JSON.stringify(sessionProposal)}, ${JSON.stringify(supportedNamespaces)})`, function(result) {
console.debug(`WC WalletConnectSDK.wcCall.approvePairSession; response: ${JSON.stringify(result, null, 2)}`)
if (result) {
if (!!result.error)
{
console.error("approvePairSession: ", result.error)
root.pairAcceptedResult(sessionProposal, false, result.error)
return
}
// Update the temporary expiry with the one from the pairing
d.resetPairingsModel((pairing) => {
if (pairing.topic === sessionProposal.params.pairingTopic) {
sessionProposal.params.expiry = pairing.expiry
root.pairAcceptedResult(sessionProposal, true, result.error)
}
})
}
})
d.engine.runJavaScript(`
wc.approveSession(${JSON.stringify(sessionProposal)}, ${JSON.stringify(supportedNamespaces)})
.then((value) => {
wc.statusObject.onApproveSessionResponse(${JSON.stringify(sessionProposal)}, "")
})
.catch((e) => {
wc.statusObject.onApproveSessionResponse(${JSON.stringify(sessionProposal)}, e.message)
})
`
)
}
function rejectPairSession(id) {
console.debug(`WC WalletConnectSDK.wcCall.rejectPairSession; id: ${id}`)
function rejectSession(id) {
console.debug(`WC WalletConnectSDK.wcCall.rejectSession; id: ${id}`)
d.engine.runJavaScript(`wc.rejectPairSession(${id})`, function(result) {
console.debug(`WC WalletConnectSDK.wcCall.rejectPairSession; response: ${JSON.stringify(result, null, 2)}`)
d.resetPairingsModel()
if (result) {
if (!!result.error)
{
console.error("rejectPairSession: ", result.error)
root.pairRejectedResult(false, result.error)
return
}
root.pairRejectedResult(true, result.error)
}
})
d.engine.runJavaScript(`
wc.rejectSession(${id})
.then((value) => {
wc.statusObject.onRejectSessionResponse("")
})
.catch((e) => {
wc.statusObject.onRejectSessionResponse(e.message)
})
`
)
}
function acceptSessionRequest(topic, id, signature) {
@ -241,7 +240,7 @@ Item {
d.engine.runJavaScript(`wc.respondSessionRequest("${topic}", ${id}, "${signature}")`, function(result) {
console.debug(`WC WalletConnectSDK.wcCall.acceptSessionRequest; response: ${JSON.stringify(allPairings, null, 2)}`)
console.debug(`WC WalletConnectSDK.wcCall.acceptSessionRequest; response: ${JSON.stringify(result, null, 2)}`)
if (result) {
if (!!result.error)
@ -252,7 +251,9 @@ Item {
}
root.sessionRequestUserAnswerResult(true, result.error)
}
d.resetPairingsModel()
d.resetSessionsModel()
})
}
@ -263,6 +264,9 @@ Item {
console.debug(`WC WalletConnectSDK.wcCall.rejectSessionRequest; response: ${JSON.stringify(result, null, 2)}`)
d.resetPairingsModel()
d.resetSessionsModel()
if (result) {
if (!!result.error)
{
@ -272,24 +276,37 @@ Item {
}
root.sessionRequestUserAnswerResult(false, result.error)
}
d.resetPairingsModel()
})
}
function disconnectPairing(topic) {
console.debug(`WC WalletConnectSDK.wcCall.disconnectPairing; topic: "${topic}"`)
function disconnectTopic(topic) {
console.debug(`WC WalletConnectSDK.wcCall.disconnectTopic; topic: "${topic}"`)
d.engine.runJavaScript(`wc.disconnect("${topic}")`, function(result) {
console.debug(`WC WalletConnectSDK.wcCall.disconnect; response: ${JSON.stringify(result, null, 2)}`)
d.engine.runJavaScript(`
wc.disconnect("${topic}")
.then((value) => {
wc.statusObject.onDisconnectResponse("")
})
.catch((e) => {
wc.statusObject.onDisconnectResponse(e.message)
})
`
)
}
if (result) {
if (!!result.error) {
console.error("disconnect: ", result.error)
return
}
}
d.resetPairingsModel()
})
function ping(topic) {
console.debug(`WC WalletConnectSDK.wcCall.ping; topic: "${topic}"`)
d.engine.runJavaScript(`
wc.ping("${topic}")
.then((value) => {
wc.statusObject.onPingResponse("")
})
.catch((e) => {
wc.statusObject.onPingResponse(e.message)
})
`
)
}
function auth(authLink) {
@ -378,68 +395,93 @@ Item {
}
}
function sdkInitialized(error)
{
function sdkInitialized(error) {
console.debug(`WC WalletConnectSDK.sdkInitialized; error: ${error}`)
d.sdkReady = !error
root.sdkInit(d.sdkReady, error)
}
function onSessionProposal(details)
{
console.debug(`WC WalletConnectSDK.onSessionProposal; details: ${JSON.stringify(details, null, 2)}`)
root.pairSessionProposal(details)
function onPairResponse(error) {
console.debug(`WC WalletConnectSDK.onPairResponse; error: ${error}`)
}
function onSessionUpdate(details)
{
function onPingResponse(error) {
console.debug(`WC WalletConnectSDK.onPingResponse; error: ${error}`)
}
function onDisconnectResponse(error) {
console.debug(`WC WalletConnectSDK.onDisconnectResponse; error: ${error}`)
d.resetPairingsModel()
d.resetSessionsModel()
}
function onApproveSessionResponse(sessionProposal, error) {
console.debug(`WC WalletConnectSDK.onApproveSessionResponse; sessionProposal: ${JSON.stringify(sessionProposal, null, 2)}, error: ${error}`)
// Update the temporary expiry with the one from the pairing
d.resetPairingsModel((pairing) => {
if (pairing.topic === sessionProposal.params.pairingTopic) {
sessionProposal.params.expiry = pairing.expiry
root.approveSessionResult(sessionProposal, error)
}
})
d.resetSessionsModel()
}
function onRejectSessionResponse(error) {
console.debug(`WC WalletConnectSDK.onRejectSessionResponse; error: ${error}`)
root.rejectSessionResult(error)
d.resetPairingsModel()
d.resetSessionsModel()
}
function onSessionProposal(details) {
console.debug(`WC WalletConnectSDK.onSessionProposal; details: ${JSON.stringify(details, null, 2)}`)
root.sessionProposal(details)
}
function onSessionUpdate(details) {
console.debug(`WC TODO WalletConnectSDK.onSessionUpdate; details: ${JSON.stringify(details, null, 2)}`)
}
function onSessionExtend(details)
{
function onSessionExtend(details) {
console.debug(`WC TODO WalletConnectSDK.onSessionExtend; details: ${JSON.stringify(details, null, 2)}`)
}
function onSessionPing(details)
{
function onSessionPing(details) {
console.debug(`WC TODO WalletConnectSDK.onSessionPing; details: ${JSON.stringify(details, null, 2)}`)
}
function onSessionDelete(details)
{
function onSessionDelete(details) {
console.debug(`WC WalletConnectSDK.onSessionDelete; details: ${JSON.stringify(details, null, 2)}`)
root.sessionDelete(details)
d.resetPairingsModel()
d.resetSessionsModel()
}
function onSessionExpire(details)
{
function onSessionExpire(details) {
console.debug(`WC TODO WalletConnectSDK.onSessionExpire; details: ${JSON.stringify(details, null, 2)}`)
}
function onSessionRequest(details)
{
function onSessionRequest(details) {
console.debug(`WC WalletConnectSDK.onSessionRequest; details: ${JSON.stringify(details, null, 2)}`)
root.sessionRequestEvent(details)
}
function onSessionRequestSent(details)
{
function onSessionRequestSent(details) {
console.debug(`WC TODO WalletConnectSDK.onSessionRequestSent; details: ${JSON.stringify(details, null, 2)}`)
}
function onSessionEvent(details)
{
function onSessionEvent(details) {
console.debug(`WC TODO WalletConnectSDK.onSessionEvent; details: ${JSON.stringify(details, null, 2)}`)
}
function onProposalExpire(details)
{
function onProposalExpire(details) {
console.debug(`WC WalletConnectSDK.onProposalExpire; details: ${JSON.stringify(details, null, 2)}`)
root.pairSessionProposalExpired()
root.sessionProposalExpired()
}
function onAuthRequest(details)
{
function onAuthRequest(details) {
console.debug(`WC WalletConnectSDK.onAuthRequest; details: ${JSON.stringify(details, null, 2)}`)
root.authRequest(details)
}
@ -449,6 +491,10 @@ Item {
id: pairings
}
ListModel {
id: sessions
}
WebEngineLoader {
id: loader

File diff suppressed because one or more lines are too long

View File

@ -104,51 +104,51 @@ window.wc = {
},
// TODO: there is a corner case when attempting to pair with a link that is already paired or was rejected won't trigger any event back
pair: function (uri) {
return {
result: window.wc.web3wallet.pair({ uri }),
error: ""
};
pair: async function (uri) {
await window.wc.web3wallet.pair({ uri });
},
getPairings: function () {
return {
result: window.wc.core.pairing.getPairings(),
error: ""
};
return window.wc.web3wallet.core.pairing.getPairings();
},
disconnect: function (topic) {
return {
result: window.wc.core.pairing.disconnect({ topic: topic }),
error: ""
};
getActiveSessions: function () {
return window.wc.web3wallet.getActiveSessions();
},
approvePairSession: function (sessionProposal, supportedNamespaces) {
disconnect: async function (topic) {
await window.wc.web3wallet.disconnectSession({
topic,
reason: getSdkError('USER_DISCONNECTED')
});
},
ping: async function (topic) {
await window.wc.web3wallet.engine.signClient.ping({ topic });
},
approveSession: async function (sessionProposal, supportedNamespaces) {
const { id, params } = sessionProposal;
const { relays } = params
const approvedNamespaces = buildApprovedNamespaces({
proposal: params,
supportedNamespaces: supportedNamespaces,
});
return {
result: window.wc.web3wallet.approveSession({
await window.wc.web3wallet.approveSession({
id,
relayProtocol: relays[0].protocol,
namespaces: approvedNamespaces,
}),
error: ""
};
});
},
rejectPairSession: function (id) {
return {
result: window.wc.web3wallet.rejectSession({
id: id,
rejectSession: async function (id) {
await window.wc.web3wallet.rejectSession({
id,
reason: getSdkError("USER_REJECTED"), // TODO USER_REJECTED_METHODS, USER_REJECTED_CHAINS, USER_REJECTED_EVENTS
}),
error: ""
};
});
},
auth: function (uri) {