mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-22 19:48:52 +00:00
chore(walletconnect): improvements identifying pairings and sessions
This commit is contained in:
parent
f1c090a765
commit
d587552c40
@ -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):
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
155
ui/app/AppLayouts/Wallet/views/walletconnect/Sessions.qml
Normal file
155
ui/app/AppLayouts/Wallet/views/walletconnect/Sessions.qml
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -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
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user