feat(wallet) Wallet Connect: process delete_session
Requires the specific status-go changes that brings WCChangePairingState Process delete session and update internal pairing history state Updated testing while fighting for the issue of not deleting the session Found out that the client requests a different topic in the delete session request. Also: - update debugging UX to support session events - update storybook to support mocking session events - fix go test utility to account for refactoring Updates #12858
This commit is contained in:
parent
a12f96c311
commit
17c7e46917
|
@ -74,6 +74,13 @@ QtObject:
|
|||
if not self.hasActivePairings.get(false):
|
||||
self.hasActivePairings = some(true)
|
||||
|
||||
proc deletePairing(self: Controller, topic: string) {.slot.} =
|
||||
if backend.deletePairing(topic):
|
||||
if self.hasActivePairings.get(false):
|
||||
self.hasActivePairings = some(backend.hasActivePairings())
|
||||
else:
|
||||
error "Failed to delete pairing"
|
||||
|
||||
proc getHasActivePairings*(self: Controller): bool {.slot.} =
|
||||
if self.hasActivePairings.isNone:
|
||||
self.hasActivePairings = some(backend.hasActivePairings())
|
||||
|
|
|
@ -31,6 +31,10 @@ rpc(wCPairSessionProposal, "wallet"):
|
|||
rpc(wCRecordSuccessfulPairing, "wallet"):
|
||||
sessionProposalJson: string
|
||||
|
||||
rpc(wCChangePairingState, "wallet"):
|
||||
topic: string
|
||||
active: bool
|
||||
|
||||
rpc(wCHasActivePairings, "wallet"):
|
||||
discard
|
||||
|
||||
|
@ -39,9 +43,7 @@ rpc(wCSessionRequest, "wallet"):
|
|||
|
||||
|
||||
proc isErrorResponse(rpcResponse: RpcResponse[JsonNode]): bool =
|
||||
if not rpcResponse.error.isNil:
|
||||
return true
|
||||
return false
|
||||
return not rpcResponse.error.isNil
|
||||
|
||||
proc prepareResponse(res: var JsonNode, rpcResponse: RpcResponse[JsonNode]): string =
|
||||
if isErrorResponse(rpcResponse):
|
||||
|
@ -99,6 +101,14 @@ proc recordSuccessfulPairing*(sessionProposalJson: string): bool =
|
|||
warn e.msg
|
||||
return false
|
||||
|
||||
proc deletePairing*(topic: string): bool =
|
||||
try:
|
||||
let response = wCChangePairingState(topic, false)
|
||||
return not isErrorResponse(response)
|
||||
except Exception as e:
|
||||
warn e.msg
|
||||
return false
|
||||
|
||||
proc hasActivePairings*(): bool =
|
||||
try:
|
||||
let response = wCHasActivePairings()
|
||||
|
|
|
@ -34,9 +34,46 @@ Item {
|
|||
|
||||
controller: WalletConnectController {
|
||||
pairSessionProposal: function(sessionProposalJson) {
|
||||
proposeUserPair(sessionProposalJson, `{"eip155":{"methods":["eth_sendTransaction","personal_sign"],"chains":["eip155:5"],"events":["accountsChanged","chainChanged"],"accounts":["eip155:5:0x53780d79E83876dAA21beB8AFa87fd64CC29990b","eip155:5:0xBd54A96c0Ae19a220C8E1234f54c940DFAB34639","eip155:5:0x5D7905390b77A937Ae8c444aA8BF7Fa9a6A7DBA0"]}}`)
|
||||
proposeUserPair(sessionProposalJson, `{"eip155":{"methods":[
|
||||
"personal_sign",
|
||||
"eth_sendTransaction",
|
||||
"eth_signTransaction",
|
||||
"eth_sign",
|
||||
"eth_signTypedData",
|
||||
"eth_signTypedData_v4"
|
||||
],
|
||||
"chains":["eip155:5"],
|
||||
"events":[
|
||||
"chainChanged",
|
||||
"accountsChanged"
|
||||
],
|
||||
"accounts":["eip155:5:0xBd54A96c0Ae19a220C8E1234f54c940DFAB34639"]}}`)
|
||||
}
|
||||
|
||||
recordSuccessfulPairing: function(sessionProposalJson) {
|
||||
const sessionProposal = JSON.parse(sessionProposalJson)
|
||||
|
||||
pairingsModel.append({
|
||||
topic: sessionProposal.params.pairingTopic,
|
||||
expiry: sessionProposal.params.expiry,
|
||||
active: true,
|
||||
})
|
||||
root.saveListModel(pairingsModel)
|
||||
}
|
||||
deletePairing: function(pairingTopic) {
|
||||
var found = false
|
||||
for (var i = 0; i < pairingsModel.count; i++) {
|
||||
if (pairingsModel.get(i).topic === pairingTopic) {
|
||||
pairingsModel.get.active = false
|
||||
found = true
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
console.error("Mock Controller: pairing not found", pairingTopic)
|
||||
}
|
||||
root.saveListModel(pairingsModel)
|
||||
}
|
||||
sessionRequest: function(sessionRequestJson, password) {
|
||||
const signedJson = "0x1234567890"
|
||||
this.respondSessionRequest(sessionRequestJson, signedJson, respondError.checked)
|
||||
|
@ -74,6 +111,7 @@ Item {
|
|||
checked: wc.sdk.webEngineLoader.active
|
||||
enabled: false
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: optionsHeader
|
||||
|
||||
|
@ -95,14 +133,64 @@ Item {
|
|||
checked: false
|
||||
}
|
||||
|
||||
StatusBaseText { text: "Pairings History"; font.bold: true }
|
||||
StatusButton {
|
||||
text: "Clear"
|
||||
onClicked: { pairingsModel.clear(); root.saveListModel(pairingsModel); }
|
||||
}
|
||||
Pairings {
|
||||
id: pairingsView
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: count > 0 ? 400 : 0
|
||||
Layout.preferredHeight: contentHeight
|
||||
Layout.maximumHeight: 300
|
||||
|
||||
onDisconnect: function(pairingTopic) {
|
||||
wc.sdk.disconnectPairing(pairingTopic)
|
||||
}
|
||||
|
||||
model: ListModel {
|
||||
id: pairingsModel
|
||||
}
|
||||
clip: true
|
||||
}
|
||||
|
||||
// spacer
|
||||
ColumnLayout {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Settings {
|
||||
id: settings
|
||||
|
||||
property bool hasActivePairings: hasActivePairingsCheckBox.checked
|
||||
property string pairingsHistory: ""
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
loadListModel(pairingsModel)
|
||||
}
|
||||
|
||||
function saveListModel(model) {
|
||||
var listArray = [];
|
||||
for (var i = 0; i < model.count; i++) {
|
||||
listArray.push(model.get(i));
|
||||
}
|
||||
settings.pairingsHistory = JSON.stringify(listArray);
|
||||
}
|
||||
|
||||
function loadListModel(model) {
|
||||
pairingsModel.clear();
|
||||
if (!settings.pairingsHistory) {
|
||||
return;
|
||||
}
|
||||
var listArray = JSON.parse(settings.pairingsHistory);
|
||||
listArray.forEach(function(entry) {
|
||||
pairingsModel.append(entry);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,10 @@ Item {
|
|||
|
||||
// function pairSessionProposal(/*string*/ sessionProposalJson)
|
||||
required property var pairSessionProposal
|
||||
// function pairSessionRequest(/*string*/ sessionRequestJson)
|
||||
required property var recordSuccessfulPairing
|
||||
// function deletePairing(/*string*/ topic)
|
||||
required property var deletePairing
|
||||
|
||||
signal respondSessionRequest(string sessionRequestJson, string signedJson, bool error)
|
||||
|
||||
|
|
|
@ -1988,8 +1988,8 @@ github.com/status-im/gomoji v1.1.3-0.20220213022530-e5ac4a8732d4/go.mod h1:hmpnZ
|
|||
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
|
||||
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 h1:Oo2KZNP70KE0+IUJSidPj/BFS/RXNHmKIJOdckzml2E=
|
||||
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
|
||||
github.com/status-im/markdown v0.0.0-20230314100416-26c6f74522d5 h1:Mie/nQtRrI/+qqyV4j5ydesjoPh6v6KF583NOPLKFQY=
|
||||
github.com/status-im/markdown v0.0.0-20230314100416-26c6f74522d5/go.mod h1:5rjPyv3KffPNVbFjnsVy0NGj9+JeW40WvXLdxH1VKuE=
|
||||
github.com/status-im/markdown v0.0.0-20231114210825-6c2d15b5dc57 h1:AuJFXERIFVzUjf9rrTb8vamFubB6Ks/e8aUasDr4pOM=
|
||||
github.com/status-im/markdown v0.0.0-20231114210825-6c2d15b5dc57/go.mod h1:5rjPyv3KffPNVbFjnsVy0NGj9+JeW40WvXLdxH1VKuE=
|
||||
github.com/status-im/migrate/v4 v4.6.2-status.2/go.mod h1:c/kc90n47GZu/58nnz1OMLTf7uE4Da4gZP5qmU+A/v8=
|
||||
github.com/status-im/migrate/v4 v4.6.2-status.3 h1:Khwjb59NzniloUr5i9s9AtkEyqBbQFt1lkoAu66sAu0=
|
||||
github.com/status-im/migrate/v4 v4.6.2-status.3/go.mod h1:c/kc90n47GZu/58nnz1OMLTf7uE4Da4gZP5qmU+A/v8=
|
||||
|
|
|
@ -91,8 +91,9 @@ func callPrivateMethod(method string, params []interface{}) string {
|
|||
}
|
||||
|
||||
type Config struct {
|
||||
HashedPassword string `json:"hashedPassword"`
|
||||
NodeConfigFile string `json:"nodeConfigFile"`
|
||||
HashedPassword string `json:"hashedPassword"`
|
||||
NodeConfigFile string `json:"nodeConfigFile"`
|
||||
DataDir *string `json:"dataDir,omitempty"`
|
||||
}
|
||||
|
||||
func processConfigArgs() (config *Config, nodeConfigJson string, userFolder string, err error) {
|
||||
|
@ -128,6 +129,11 @@ func processConfigArgs() (config *Config, nodeConfigJson string, userFolder stri
|
|||
if err == nil {
|
||||
nodeConfigJson = string(nodeConfigData)
|
||||
}
|
||||
|
||||
if config.DataDir != nil {
|
||||
userFolder = *config.DataDir
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
<div id="log"></div>
|
||||
<script src="bundle.js" type="module"></script>
|
||||
<script>
|
||||
// Helper functions
|
||||
//
|
||||
function goEcho(message) {
|
||||
window.echo(message);
|
||||
}
|
||||
|
@ -47,39 +49,158 @@
|
|||
return addHtmlEntry(`${componentHtml}${statusHtml}`, null, entry);
|
||||
}
|
||||
|
||||
// SDK initialization
|
||||
//
|
||||
const statusGoEntry = logComponentStatusChange("status-go", "Initializing...");
|
||||
var initEventCount = 0;
|
||||
var eventCount = 0;
|
||||
const readyToPairEventName = "readyToPair";
|
||||
async function initializeSDK() {
|
||||
try {
|
||||
const sdkEntry = logComponentStatusChange("SDK", "Initializing...");
|
||||
const conf = await window.getConfiguration();
|
||||
const wc = await window.wc.init(conf.projectId);
|
||||
await window.wc.init(conf.projectId);
|
||||
logComponentStatusChange("SDK", "Initialized", "green", sdkEntry);
|
||||
eventCount++;
|
||||
initEventCount++;
|
||||
} catch (error) {
|
||||
logComponentStatusChange("SDK", "FAIL initializing ${error.message}", "red", sdkEntry);
|
||||
goEcho(`SDK init error: ${error}`);
|
||||
logComponentStatusChange("SDK", "FAIL initializing ${error}", "red", sdkEntry);
|
||||
}
|
||||
}
|
||||
|
||||
// Simulate statusObject
|
||||
window.statusq = {
|
||||
channel: {
|
||||
objects: {
|
||||
statusObject: {
|
||||
sdkInitialized: function (error) {
|
||||
window.statusObject_sdkInitialized(error);
|
||||
},
|
||||
onSessionProposal: function (sessionProposal) {
|
||||
window.statusObject_onSessionProposal(JSON.stringify(sessionProposal)).then((success) => {
|
||||
if (!success) {
|
||||
goEcho(`statusObject: onSessionProposal call failed ${sessionProposal.id}`);
|
||||
return;
|
||||
}
|
||||
});
|
||||
},
|
||||
onSessionRequest: function (sessionRequest) {
|
||||
eventCount++;
|
||||
|
||||
logComponentStatusChange("SDK", `received "session_request" event`, "green");
|
||||
addLogEntry(`Data: ${JSON.stringify(sessionRequest)}`);
|
||||
|
||||
addHtmlEntry(
|
||||
`<button id="acceptSessionButton${eventCount}">Accept</button> <button id="rejectSessionButton${eventCount}">Reject</button>`
|
||||
);
|
||||
|
||||
const acceptSessionButton = document.getElementById(`acceptSessionButton${eventCount}`);
|
||||
const rejectSessionButton = document.getElementById(`rejectSessionButton${eventCount}`);
|
||||
acceptSessionButton.addEventListener("click", function () {
|
||||
const sessionReqEntry = logComponentStatusChange("status-go", `sessionRequest called`, "orange");
|
||||
window.sessionRequest(JSON.stringify(sessionRequest), hashedPasswordInput.value).then((success) => {
|
||||
acceptSessionButton.disabled = true;
|
||||
rejectSessionButton.disabled = true;
|
||||
|
||||
if (success) {
|
||||
logComponentStatusChange("status-go", `sessionRequest OK`, "green", sessionReqEntry);
|
||||
// waiting for "sessionRequestResult" event
|
||||
} else {
|
||||
logComponentStatusChange(
|
||||
"status-go",
|
||||
`sessionRequest call failed for topic ${sessionRequest.topic}`,
|
||||
"red",
|
||||
sessionReqEntry
|
||||
);
|
||||
window.wc.rejectSessionRequest(sessionRequest.topic, sessionRequest.id, true);
|
||||
setStatus(`Session ${sessionRequest.id} rejected, internal error`, "purple");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
rejectSessionButton.addEventListener("click", function () {
|
||||
acceptSessionButton.disabled = true;
|
||||
rejectSessionButton.disabled = true;
|
||||
window.wc.rejectSessionRequest(sessionRequest.topic, sessionRequest.id).then(
|
||||
() => {
|
||||
addLogEntry(`Session ${sessionRequest.id} rejected`);
|
||||
},
|
||||
(err) => {
|
||||
addLogEntry(`Session ${sessionRequest.id} reject error: ${err.message}`, "red");
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
onSessionDelete: function (deletePayload) {
|
||||
goEcho(`statusObject: onSessionDelete ${JSON.stringify(deletePayload)}`);
|
||||
},
|
||||
onSessionExpire: function (expirePayload) {
|
||||
goEcho(`statusObject: onSessionExpire ${JSON.stringify(expirePayload)}`);
|
||||
},
|
||||
onSessionUpdate: function (updatePayload) {
|
||||
goEcho(`statusObject: onSessionUpdate ${JSON.stringify(updatePayload)}`);
|
||||
},
|
||||
onSessionExtend: function (extendPayload) {
|
||||
goEcho(`statusObject: onSessionExtend ${JSON.stringify(extendPayload)}`);
|
||||
},
|
||||
onSessionPing: function (pingPayload) {
|
||||
goEcho(`statusObject: onSessionPing ${JSON.stringify(pingPayload)}`);
|
||||
},
|
||||
onSessionEvent: function (eventPayload) {
|
||||
goEcho(`statusObject: onSessionEvent ${JSON.stringify(eventPayload)}`);
|
||||
},
|
||||
onSessionRequest: function (sessionRequestPayload) {
|
||||
goEcho(`statusObject: onSessionRequest ${JSON.stringify(sessionRequestPayload)}`);
|
||||
},
|
||||
onSessionRequestSent: function (sessionRequestSentPayload) {
|
||||
goEcho(`statusObject: onSessionRequestSent ${JSON.stringify(sessionRequestSentPayload)}`);
|
||||
},
|
||||
onProposalExpire: function (proposalExpirePayload) {
|
||||
goEcho(`statusObject: onProposalExpire ${JSON.stringify(proposalExpirePayload)}`);
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
var pairLinkInput = null;
|
||||
var pairButton = null;
|
||||
function newPairWorkflow() {
|
||||
// Remove all the previous entries
|
||||
if (logEntries) {
|
||||
for (let i = 0; i < logEntries.length; i++) {
|
||||
logEntries[i].remove();
|
||||
}
|
||||
}
|
||||
|
||||
logEntries = [];
|
||||
eventCount++;
|
||||
|
||||
// Add session reset and password input
|
||||
addHtmlEntry(`<button id="newSessionButton" style="display: none;">New Session</button>`);
|
||||
newSessionButton = document.getElementById("newSessionButton");
|
||||
newSessionButton.addEventListener("click", function () {
|
||||
newPairWorkflow();
|
||||
});
|
||||
addHtmlEntry(
|
||||
`<input type="text" id="hashedPasswordInput" placeholder="Insert hashed password" value="0x38301fb0b5fcf3aaa4b97c4771bb6c75546e313b4ce7057c51a8cc6a3ace9d7e"/>`
|
||||
);
|
||||
hashedPasswordInput = document.getElementById(`hashedPasswordInput`);
|
||||
|
||||
addHtmlEntry(
|
||||
`<input type="text" id="pairLinkInput" placeholder="Insert pair link" /><button id="pairButton" disabled>Pair</button>`
|
||||
);
|
||||
|
||||
// List existing pairing sessions
|
||||
const pairings = window.wc.getPairings();
|
||||
const pairingsRes = window.wc.getPairings();
|
||||
let pairings = [];
|
||||
if (pairingsRes) {
|
||||
if (!!pairingsRes.error) {
|
||||
goEcho(`getPairings() error: ${pairingsRes.error}`);
|
||||
return;
|
||||
} else if (pairingsRes.result) {
|
||||
pairings = pairingsRes.result;
|
||||
}
|
||||
}
|
||||
if (pairings.length > 0) {
|
||||
addHtmlEntry(`Existing pairings:`, "fuchsia");
|
||||
}
|
||||
|
@ -88,24 +209,23 @@
|
|||
const disconnectEntry = addHtmlEntry(
|
||||
`[${i + 1}] <span style="color: ${p.active ? "green" : "orange"};">${
|
||||
p.active ? "ACTIVE" : "INACTIVE"
|
||||
}</span> <span class="elide-text">${
|
||||
p.topic
|
||||
}</span>; Expires: ${timestampToStr(p.expiry)} <button id="unpairButton${i}">Disconnect</button>`
|
||||
}</span> <span class="elide-text">${p.topic}</span>; Expires: ${timestampToStr(
|
||||
p.expiry
|
||||
)} <button id="unpairButton${i}">Disconnect</button>`
|
||||
);
|
||||
const unpairButton = document.getElementById(`unpairButton${i}`);
|
||||
unpairButton.addEventListener("click", function () {
|
||||
window.wc.disconnect(p.topic).then(
|
||||
() => {
|
||||
addLogEntry(`Pairing ${p.topic} disconnected`, "green", disconnectEntry);
|
||||
unpairButton.remove();
|
||||
},
|
||||
(err) => {
|
||||
addLogEntry(`Pairing ${p.topic} disconnect error: ${err.message}`, "red", disconnectEntry);
|
||||
}
|
||||
);
|
||||
const res = window.wc.disconnect(p.topic);
|
||||
if (res && !!res.error) {
|
||||
addLogEntry(`Pairing ${p.topic} disconnect error: ${err.message}`, "red", disconnectEntry);
|
||||
return;
|
||||
}
|
||||
addLogEntry(`Pairing ${p.topic} disconnected`, "green", disconnectEntry);
|
||||
unpairButton.remove();
|
||||
});
|
||||
}
|
||||
|
||||
// Add pairing options
|
||||
pairLinkInput = document.getElementById(`pairLinkInput`);
|
||||
pairButton = document.getElementById(`pairButton`);
|
||||
pairLinkInput.addEventListener("input", function () {
|
||||
|
@ -117,139 +237,73 @@
|
|||
pairLinkInput.disabled = true;
|
||||
|
||||
const sdkEntry = logComponentStatusChange("SDK", "Pairing...");
|
||||
window.wc
|
||||
.pair(pairLinkInput.value)
|
||||
.then((sessionProposal) => {
|
||||
logComponentStatusChange("SDK", "got Pair session proposal", "green", sdkEntry);
|
||||
addLogEntry(`Pair ID: ${sessionProposal.id} ; Topic: ${sessionProposal.params.pairingTopic}`);
|
||||
const goSession = logComponentStatusChange("GO.pairSessionProposal", "waiting status-go", "pink");
|
||||
const result = window.wc.pair(pairLinkInput.value);
|
||||
if (result && !!result.error) {
|
||||
goEcho("pair() error: ", result.error);
|
||||
logComponentStatusChange("SDK", `Pairing error ${error.message}`, "red", sdkEntry);
|
||||
return;
|
||||
}
|
||||
|
||||
document.addEventListener(`proposeUserPair`, function (event) {
|
||||
pairProposalEntry = logComponentStatusChange(
|
||||
"GO.proposeUserPair",
|
||||
`received "proposeUserPair"`,
|
||||
"green"
|
||||
);
|
||||
addLogEntry(JSON.stringify(event.detail.supportedNamespaces));
|
||||
addHtmlEntry(
|
||||
`<button id="acceptPairButton">Accept</button><button id="rejectPairButton">Reject</button>`
|
||||
);
|
||||
const acceptPairButton = document.getElementById(`acceptPairButton`);
|
||||
const rejectPairButton = document.getElementById(`rejectPairButton`);
|
||||
acceptPairButton.addEventListener("click", function () {
|
||||
window.wc.approvePairSession(sessionProposal, event.detail.supportedNamespaces).then(
|
||||
() => {
|
||||
logComponentStatusChange(
|
||||
"GO.pairSessionProposal",
|
||||
`Pair session ${sessionProposal.id} approved`,
|
||||
"green",
|
||||
pairProposalEntry
|
||||
);
|
||||
acceptPairButton.remove();
|
||||
rejectPairButton.remove();
|
||||
},
|
||||
(err) => {
|
||||
logComponentStatusChange(
|
||||
"GO.pairSessionProposal",
|
||||
`Pair session ${sessionProposal.id} approve error: ${err.message}`,
|
||||
"red",
|
||||
pairProposalEntry
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
rejectPairButton.addEventListener("click", function () {
|
||||
window.wc.rejectPairSession(sessionProposal.id).then(
|
||||
() => {
|
||||
logComponentStatusChange(
|
||||
"GO.pairSessionProposal",
|
||||
`Pair session ${sessionProposal.id} rejected`,
|
||||
"green",
|
||||
pairProposalEntry
|
||||
);
|
||||
acceptPairButton.remove();
|
||||
rejectPairButton.remove();
|
||||
},
|
||||
(err) => {
|
||||
logComponentStatusChange(
|
||||
"GO.pairSessionProposal",
|
||||
`Pair session ${sessionProposal.id} reject error: ${err.message}`,
|
||||
"red",
|
||||
pairProposalEntry
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
window.pairSessionProposal(JSON.stringify(sessionProposal)).then((success) => {
|
||||
if (!success) {
|
||||
logComponentStatusChange(
|
||||
"GO.pairSessionProposal",
|
||||
`call failed ${sessionProposal.id}`,
|
||||
"red",
|
||||
goSession
|
||||
);
|
||||
return;
|
||||
}
|
||||
logComponentStatusChange("GO.pairSessionProposal", `waiting for "proposeUserPair"`, "black", goSession);
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
logComponentStatusChange("SDK", `Pairing error ${error.message}`, "red", sdkEntry);
|
||||
});
|
||||
logComponentStatusChange("SDK", "got Pair session proposal", "green", sdkEntry);
|
||||
const goSessionEntry = logComponentStatusChange("GO.pairSessionProposal", "waiting status-go", "pink");
|
||||
});
|
||||
}
|
||||
|
||||
function sdkReady() {
|
||||
window.wc.registerForSessionRequest((event) => {
|
||||
eventCount++;
|
||||
|
||||
logComponentStatusChange("SDK", `received "session_request" event`, "green");
|
||||
addLogEntry(`Event: ${JSON.stringify(event)}`);
|
||||
|
||||
addHtmlEntry(
|
||||
`<button id="acceptSessionButton${eventCount}">Accept</button> <button id="rejectSessionButton${eventCount}">Reject</button>`
|
||||
);
|
||||
|
||||
const acceptSessionButton = document.getElementById(`acceptSessionButton${eventCount}`);
|
||||
const rejectSessionButton = document.getElementById(`rejectSessionButton${eventCount}`);
|
||||
acceptSessionButton.addEventListener("click", function () {
|
||||
const sessionReqEntry = logComponentStatusChange("status-go", `sessionRequest called`, "orange");
|
||||
window.sessionRequest(JSON.stringify(event), hashedPasswordInput.value).then((success) => {
|
||||
acceptSessionButton.disabled = true;
|
||||
rejectSessionButton.disabled = true;
|
||||
|
||||
if (success) {
|
||||
logComponentStatusChange("status-go", `sessionRequest OK`, "green", sessionReqEntry);
|
||||
// waiting for "sessionRequestResult" event
|
||||
} else {
|
||||
logComponentStatusChange(
|
||||
"status-go",
|
||||
`sessionRequest call failed for topic ${event.topic}`,
|
||||
"red",
|
||||
sessionReqEntry
|
||||
);
|
||||
window.wc.rejectSessionRequest(event.topic, event.id, true);
|
||||
setStatus(`Session ${event.id} rejected, internal error`, "purple");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
rejectSessionButton.addEventListener("click", function () {
|
||||
acceptSessionButton.disabled = true;
|
||||
rejectSessionButton.disabled = true;
|
||||
window.wc.rejectSessionRequest(event.topic, event.id).then(
|
||||
() => {
|
||||
addLogEntry(`Session ${event.id} rejected`);
|
||||
},
|
||||
(err) => {
|
||||
addLogEntry(`Session ${event.id} reject error: ${err.message}`, "red");
|
||||
}
|
||||
document.addEventListener(`proposeUserPair`, function (event) {
|
||||
logComponentStatusChange("GO.proposeUserPair", `received "proposeUserPair"`, "green");
|
||||
addLogEntry(JSON.stringify(event.detail.supportedNamespaces));
|
||||
if (!document.getElementById(`acceptPairButton`)) {
|
||||
addHtmlEntry(`<button id="acceptPairButton">Accept</button><button id="rejectPairButton">Reject</button>`);
|
||||
}
|
||||
const acceptPairButton = document.getElementById(`acceptPairButton`);
|
||||
const rejectPairButton = document.getElementById(`rejectPairButton`);
|
||||
const sessionProposal = event.detail.sessionProposal;
|
||||
acceptPairButton.addEventListener("click", function () {
|
||||
const result = window.wc.approvePairSession(sessionProposal, event.detail.supportedNamespaces);
|
||||
if (result && !!result.error) {
|
||||
logComponentStatusChange(
|
||||
"GO.pairSessionProposal",
|
||||
`Pair session ${sessionProposal.id} approve error: ${result.error}`,
|
||||
"red",
|
||||
goSessionEntry
|
||||
);
|
||||
});
|
||||
return;
|
||||
}
|
||||
acceptPairButton.remove();
|
||||
rejectPairButton.remove();
|
||||
|
||||
root.controller_recordSuccessfulPairing(JSON.stringify(sessionProposal));
|
||||
|
||||
logComponentStatusChange(
|
||||
"GO.pairSessionProposal",
|
||||
`Pair session ${sessionProposal.id} approved`,
|
||||
"green",
|
||||
goSessionEntry
|
||||
);
|
||||
});
|
||||
}
|
||||
rejectPairButton.addEventListener("click", function () {
|
||||
const result = window.wc.rejectPairSession(sessionProposal.id);
|
||||
if (result && !!result.error) {
|
||||
logComponentStatusChange(
|
||||
"GO.pairSessionProposal",
|
||||
`Pair session ${sessionProposal.id} reject error: ${result.error}`,
|
||||
"red",
|
||||
goSessionEntry
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
acceptPairButton.remove();
|
||||
rejectPairButton.remove();
|
||||
|
||||
logComponentStatusChange(
|
||||
"GO.pairSessionProposal",
|
||||
`Pair session ${sessionProposal.id} rejected`,
|
||||
"green",
|
||||
goSessionEntry
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener("sessionRequestResult", function (event) {
|
||||
let req = event.detail.sessionRequest;
|
||||
|
@ -262,16 +316,6 @@
|
|||
|
||||
// Add start from scratch option
|
||||
document.addEventListener(readyToPairEventName, function () {
|
||||
addHtmlEntry(`<button id="newSessionButton" style="display: none;">New Session</button>`);
|
||||
newSessionButton = document.getElementById("newSessionButton");
|
||||
newSessionButton.addEventListener("click", function () {
|
||||
newPairWorkflow();
|
||||
});
|
||||
addHtmlEntry(
|
||||
`<input type="text" id="hashedPasswordInput" placeholder="Insert hashed password" value="0x38301fb0b5fcf3aaa4b97c4771bb6c75546e313b4ce7057c51a8cc6a3ace9d7e"/>`
|
||||
);
|
||||
hashedPasswordInput = document.getElementById(`hashedPasswordInput`);
|
||||
sdkReady();
|
||||
newPairWorkflow();
|
||||
});
|
||||
|
||||
|
@ -282,12 +326,12 @@
|
|||
switch (event.name) {
|
||||
case "nodeReady":
|
||||
logComponentStatusChange("status-go", "Ready", "green", statusGoEntry);
|
||||
eventCount++;
|
||||
initEventCount++;
|
||||
break;
|
||||
default:
|
||||
// Handle status-go and SDK bootstrap events
|
||||
if (eventCount == 2) {
|
||||
eventCount++;
|
||||
if (initEventCount == 2) {
|
||||
initEventCount++;
|
||||
document.dispatchEvent(new CustomEvent(readyToPairEventName, {}));
|
||||
} else if (event.name != "") {
|
||||
goEcho(`GO event: ${event.name}`);
|
||||
|
@ -315,7 +359,7 @@
|
|||
const readableDate = date.toLocaleDateString();
|
||||
const readableTime = date.toLocaleTimeString();
|
||||
|
||||
return `${readableDate} - ${readableTime}`
|
||||
return `${readableDate} - ${readableTime}`;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -63,9 +63,9 @@ func signalHandler(jsonEvent string) {
|
|||
return
|
||||
}
|
||||
// TODO: continue from here
|
||||
if walletEvent.Type == "WalletConnectProposeUserPair" {
|
||||
eventQueue <- GoEvent{Name: "proposeUserPair", Payload: walletEvent.Message}
|
||||
}
|
||||
// if walletEvent.Type == "WalletConnectProposeUserPair" {
|
||||
// eventQueue <- GoEvent{Name: "proposeUserPair", Payload: walletEvent.Message}
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,30 +91,31 @@ func main() {
|
|||
w.SetTitle("WC status-go test")
|
||||
w.SetSize(1280, 1024, webview.HintNone)
|
||||
|
||||
w.Bind("pairSessionProposal", func(sessionProposalJson string) bool {
|
||||
sessionProposalRes := callPrivateMethod("wallet_wCPairSessionProposal", []interface{}{sessionProposalJson})
|
||||
var apiResponse wc.PairSessionResponse
|
||||
err = getRPCAPIResponse(sessionProposalRes, &apiResponse)
|
||||
if err != nil {
|
||||
l.Error("Error parsing the API response", "error", err)
|
||||
return false
|
||||
}
|
||||
|
||||
go func() {
|
||||
eventQueue <- GoEvent{Name: "proposeUserPair", Payload: apiResponse}
|
||||
}()
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
w.Bind("sessionRequest", func(sessionRequestJson, hashedPassword string) bool {
|
||||
sessionReqRes := callPrivateMethod("wallet_wCSessionRequest", []interface{}{sessionRequestJson, hashedPassword})
|
||||
fmt.Println("sessionRequestJson:", sessionRequestJson)
|
||||
sessionReqRes := callPrivateMethod("wallet_wCSessionRequest", []interface{}{sessionRequestJson})
|
||||
fmt.Println("sessionReqRes:", sessionReqRes)
|
||||
var apiResponse wc.SessionRequestResponse
|
||||
err = getRPCAPIResponse(sessionReqRes, &apiResponse)
|
||||
if err != nil {
|
||||
l.Error("Error parsing the API response", "error", err)
|
||||
l.Error("Error parsing wallet_wCSessionRequest response", "error", err)
|
||||
return false
|
||||
}
|
||||
if apiResponse.SignOnKeycard {
|
||||
l.Error("SignOnKeycard is not supported in this test")
|
||||
return false
|
||||
}
|
||||
|
||||
sessionReqRes = callPrivateMethod("wallet_wCSignMessage", []interface{}{apiResponse.MessageToSign, apiResponse.Address, hashedPassword})
|
||||
fmt.Println("sessionReqRes:", sessionReqRes)
|
||||
var signature string
|
||||
err = getRPCAPIResponse(sessionReqRes, &signature)
|
||||
if err != nil {
|
||||
l.Error("Error parsing wallet_wCSignMessage response", "error", err)
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO: process the request type ...
|
||||
|
||||
go func() {
|
||||
eventQueue <- GoEvent{Name: "sessionRequestResult", Payload: apiResponse}
|
||||
|
@ -146,6 +147,9 @@ func main() {
|
|||
}
|
||||
})
|
||||
|
||||
mockStatusObject(w)
|
||||
mockController(w)
|
||||
|
||||
// Start a local server to serve the files
|
||||
http.HandleFunc("/bundle.js", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0")
|
||||
|
@ -162,3 +166,64 @@ func main() {
|
|||
w.Navigate("http://localhost:8080")
|
||||
w.Run()
|
||||
}
|
||||
|
||||
func mockController(w webview.WebView) {
|
||||
w.Bind("controller_recordSuccessfulPairing", func(sessionProposalJson string) {
|
||||
fmt.Println("controller_recordSuccessfulPairing:", sessionProposalJson)
|
||||
sessionProposalRes := callPrivateMethod("wallet_wCRecordSuccessfulPairing", []interface{}{sessionProposalJson})
|
||||
var apiResponse wc.PairSessionResponse
|
||||
err := getRPCAPIResponse(sessionProposalRes, &apiResponse)
|
||||
if err != nil {
|
||||
l.Error("Error parsing the API response", "error", err)
|
||||
}
|
||||
})
|
||||
|
||||
w.Bind("controller_changePairingState", func(topic string, active bool) {
|
||||
sessionProposalRes := callPrivateMethod("wallet_wCChangePairingState", []interface{}{topic, active})
|
||||
var apiResponse wc.PairSessionResponse
|
||||
err := getRPCAPIResponse(sessionProposalRes, &apiResponse)
|
||||
if err != nil {
|
||||
l.Error("Error parsing the API response", "error", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func mockStatusObject(w webview.WebView) {
|
||||
w.Bind("statusObject_sdkInitialized", func(error string) {
|
||||
// All OK here
|
||||
})
|
||||
w.Bind("statusObject_onSessionProposal", func(sessionProposalJson string) bool {
|
||||
sessionProposalRes := callPrivateMethod("wallet_wCPairSessionProposal", []interface{}{sessionProposalJson})
|
||||
var apiResponse wc.PairSessionResponse
|
||||
err := getRPCAPIResponse(sessionProposalRes, &apiResponse)
|
||||
if err != nil {
|
||||
l.Error("Error parsing the API response", "error", err)
|
||||
return false
|
||||
}
|
||||
|
||||
go func() {
|
||||
eventQueue <- GoEvent{Name: "proposeUserPair", Payload: apiResponse}
|
||||
}()
|
||||
|
||||
return true
|
||||
})
|
||||
w.Bind("statusObject_onSessionRequest", func(sessionRequestJson string) bool {
|
||||
sessionReqRes := callPrivateMethod("wallet_wCSessionRequest", []interface{}{sessionRequestJson})
|
||||
var apiResponse wc.SessionRequestResponse
|
||||
err := getRPCAPIResponse(sessionReqRes, &apiResponse)
|
||||
if err != nil {
|
||||
l.Error("Error parsing the API response", "error", err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// function onSessionUpdate(details)
|
||||
// function onSessionExtend(details)
|
||||
// function onSessionPing(details)
|
||||
// function onSessionDelete(details)
|
||||
// function onSessionExpire(details)
|
||||
// function onSessionRequestSent(details)
|
||||
// function onSessionEvent(details)
|
||||
// function onProposalExpire(details)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
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)
|
||||
|
||||
delegate: Item {
|
||||
implicitWidth: delegateLayout.implicitWidth
|
||||
implicitHeight: delegateLayout.implicitHeight
|
||||
|
||||
RowLayout {
|
||||
id: delegateLayout
|
||||
width: root.width
|
||||
|
||||
StatusBaseText {
|
||||
text: `${SQUtils.Utils.elideText(model.topic, 6, 6)}\n${new Date(model.expiry * 1000).toLocaleString()}`
|
||||
color: model.active ? "green" : "orange"
|
||||
}
|
||||
StatusButton {
|
||||
text: "Disconnect"
|
||||
|
||||
visible: model.active
|
||||
|
||||
onClicked: {
|
||||
root.disconnect(model.topic)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,5 +28,8 @@ Item {
|
|||
onSessionRequestEvent: (details) => {
|
||||
modal.openWithSessionRequestEvent(details)
|
||||
}
|
||||
onSessionDelete: (deletePayload) => {
|
||||
root.controller.deletePairing(deletePayload.topic)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,14 +4,13 @@ import QtQuick.Layouts 1.15
|
|||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Utils 0.1 as SQUtils
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
Popup {
|
||||
id: root
|
||||
|
||||
implicitWidth: Math.min(mainLayout.implicitWidth, 400)
|
||||
implicitHeight: Math.min(mainLayout.implicitHeight, 700)
|
||||
implicitWidth: 500
|
||||
implicitHeight: Math.min(mainLayout.implicitHeight * 2, 700)
|
||||
|
||||
required property WalletConnectSDK sdk
|
||||
|
||||
|
@ -38,89 +37,87 @@ Popup {
|
|||
|
||||
anchors.fill: parent
|
||||
|
||||
contentWidth: mainLayout.width
|
||||
contentHeight: mainLayout.height
|
||||
contentWidth: mainLayout.implicitWidth
|
||||
contentHeight: mainLayout.implicitHeight
|
||||
|
||||
interactive: contentHeight > height || contentWidth > width
|
||||
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
id: mainLayout
|
||||
|
||||
StatusBaseText {
|
||||
text: qsTr("Debugging UX until design is ready")
|
||||
}
|
||||
|
||||
StatusInput {
|
||||
id: pairLinkInput
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
placeholderText: "Insert pair link"
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
StatusButton {
|
||||
text: "Pair"
|
||||
onClicked: {
|
||||
statusText.text = "Pairing..."
|
||||
sdk.pair(pairLinkInput.text)
|
||||
}
|
||||
enabled: pairLinkInput.text.length > 0 && sdk.sdkReady
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Auth"
|
||||
onClicked: {
|
||||
statusText.text = "Authenticating..."
|
||||
sdk.auth()
|
||||
}
|
||||
enabled: false && pairLinkInput.text.length > 0 && sdk.sdkReady
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Accept"
|
||||
onClicked: {
|
||||
sdk.approvePairSession(d.sessionProposal, d.supportedNamespaces)
|
||||
}
|
||||
visible: d.state === d.waitingPairState
|
||||
}
|
||||
StatusButton {
|
||||
text: "Reject"
|
||||
onClicked: {
|
||||
sdk.rejectPairSession(d.sessionProposal.id)
|
||||
}
|
||||
visible: d.state === d.waitingPairState
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
StatusBaseText {
|
||||
id: statusText
|
||||
text: "-"
|
||||
text: qsTr("Debugging UX until design is ready")
|
||||
}
|
||||
StatusBaseText {
|
||||
text: "Pairings"
|
||||
visible: sdk.pairingsModel.count > 0
|
||||
}
|
||||
StatusListView {
|
||||
|
||||
StatusInput {
|
||||
id: pairLinkInput
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: contentHeight
|
||||
Layout.maximumHeight: 200
|
||||
|
||||
model: sdk.pairingsModel
|
||||
placeholderText: "Insert pair link"
|
||||
}
|
||||
|
||||
delegate: StatusBaseText {
|
||||
text: `${SQUtils.Utils.elideText(topic, 6, 6)} - ${new Date(expiry * 1000).toLocaleString()}`
|
||||
color: active ? "green" : "orange"
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
StatusButton {
|
||||
text: "Pair"
|
||||
|
||||
onClicked: {
|
||||
statusText.text = "Pairing..."
|
||||
sdk.pair(pairLinkInput.text)
|
||||
}
|
||||
enabled: pairLinkInput.text.length > 0 && sdk.sdkReady
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Auth"
|
||||
onClicked: {
|
||||
statusText.text = "Authenticating..."
|
||||
sdk.auth()
|
||||
}
|
||||
enabled: false && pairLinkInput.text.length > 0 && sdk.sdkReady
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Accept"
|
||||
onClicked: {
|
||||
sdk.approvePairSession(d.sessionProposal, d.supportedNamespaces)
|
||||
// Will trigger an onPairAcceptedResult if successful
|
||||
}
|
||||
visible: d.state === d.waitingPairState
|
||||
}
|
||||
StatusButton {
|
||||
text: "Reject"
|
||||
onClicked: {
|
||||
sdk.rejectPairSession(d.sessionProposal.id)
|
||||
}
|
||||
visible: d.state === d.waitingPairState
|
||||
}
|
||||
}
|
||||
Flickable {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 200
|
||||
Layout.maximumHeight: 400
|
||||
|
||||
contentWidth: detailsText.width
|
||||
contentHeight: detailsText.height
|
||||
ColumnLayout {
|
||||
StatusBaseText {
|
||||
id: statusText
|
||||
text: "-"
|
||||
}
|
||||
StatusBaseText {
|
||||
text: "Pairings"
|
||||
visible: sdk.pairingsModel.count > 0
|
||||
}
|
||||
|
||||
Pairings {
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: count > 0 ? 400 : 0
|
||||
Layout.preferredHeight: contentHeight
|
||||
Layout.maximumHeight: 300
|
||||
|
||||
model: sdk.pairingsModel
|
||||
|
||||
onDisconnect: function (topic) {
|
||||
sdk.disconnectPairing(topic)
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: detailsText
|
||||
|
@ -130,42 +127,37 @@ Popup {
|
|||
color: "#FF00FF"
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
RowLayout {
|
||||
StatusButton {
|
||||
text: "Accept"
|
||||
onClicked: {
|
||||
root.controller.sessionRequest(JSON.stringify(d.sessionRequest), passwordInput.text)
|
||||
}
|
||||
visible: d.state === d.waitingUserResponseToSessionRequest
|
||||
}
|
||||
StatusButton {
|
||||
text: "Reject"
|
||||
onClicked: {
|
||||
sdk.rejectSessionRequest(d.sessionRequest.topic, d.sessionRequest.id, false)
|
||||
}
|
||||
visible: d.state === d.waitingUserResponseToSessionRequest
|
||||
}
|
||||
StatusInput {
|
||||
id: passwordInput
|
||||
|
||||
clip: true
|
||||
text: "1234567890"
|
||||
placeholderText: "Insert account password"
|
||||
visible: d.state === d.waitingUserResponseToSessionRequest
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout { /* spacer */ }
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
StatusButton {
|
||||
text: "Accept"
|
||||
onClicked: {
|
||||
root.controller.sessionRequest(JSON.stringify(d.sessionRequest), passwordInput.text)
|
||||
}
|
||||
visible: d.state === d.waitingUserResponseToSessionRequest
|
||||
}
|
||||
StatusButton {
|
||||
text: "Reject"
|
||||
onClicked: {
|
||||
sdk.rejectSessionRequest(d.sessionRequest.topic, d.sessionRequest.id, false)
|
||||
}
|
||||
visible: d.state === d.waitingUserResponseToSessionRequest
|
||||
}
|
||||
StatusInput {
|
||||
id: passwordInput
|
||||
|
||||
text: "1234567890"
|
||||
placeholderText: "Insert account password"
|
||||
visible: d.state === d.waitingUserResponseToSessionRequest
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout { /* spacer */ }
|
||||
// Separator
|
||||
ColumnLayout {}
|
||||
}
|
||||
|
||||
// Separator
|
||||
ColumnLayout {}
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
|
||||
clip: true
|
||||
|
@ -190,7 +182,7 @@ Popup {
|
|||
if (success) {
|
||||
d.setStatusText("Pair ID: " + sessionProposal.id + "; Topic: " + sessionProposal.params.pairingTopic)
|
||||
root.controller.pairSessionProposal(JSON.stringify(sessionProposal))
|
||||
// Expecting signal onProposeUserPair from controller
|
||||
// Expecting signal onProposeUserPair(..., true, ...) from controller
|
||||
} else {
|
||||
d.setStatusText("Pairing error", "red")
|
||||
}
|
||||
|
|
|
@ -31,11 +31,18 @@ Item {
|
|||
signal sessionRequestEvent(var sessionRequest)
|
||||
signal sessionRequestUserAnswerResult(bool accept, string error)
|
||||
|
||||
signal sessionDelete(var deletePayload)
|
||||
|
||||
function pair(pairLink)
|
||||
{
|
||||
wcCalls.pair(pairLink)
|
||||
}
|
||||
|
||||
function disconnectPairing(topic)
|
||||
{
|
||||
wcCalls.disconnectPairing(topic)
|
||||
}
|
||||
|
||||
function approvePairSession(sessionProposal, supportedNamespaces)
|
||||
{
|
||||
wcCalls.approvePairSession(sessionProposal, supportedNamespaces)
|
||||
|
@ -108,7 +115,7 @@ Item {
|
|||
function init() {
|
||||
console.debug(`WC WalletConnectSDK.wcCall.init; root.projectId: ${root.projectId}`)
|
||||
|
||||
d.engine.runJavaScript(`wc.init("${root.projectId}")`, function(result) {
|
||||
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)}`)
|
||||
|
||||
|
@ -252,6 +259,22 @@ Item {
|
|||
d.resetPairingsModel()
|
||||
})
|
||||
}
|
||||
|
||||
function disconnectPairing(topic) {
|
||||
console.debug(`WC WalletConnectSDK.wcCall.disconnectPairing; topic: "${topic}"`)
|
||||
|
||||
d.engine.runJavaScript(`wc.disconnect("${topic}")`, function(result) {
|
||||
console.debug(`WC WalletConnectSDK.wcCall.disconnect; response: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
if (result) {
|
||||
if (!!result.error) {
|
||||
console.error("disconnect: ", result.error)
|
||||
return
|
||||
}
|
||||
}
|
||||
d.resetPairingsModel()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
|
@ -300,7 +323,8 @@ Item {
|
|||
|
||||
function onSessionDelete(details)
|
||||
{
|
||||
console.debug(`WC TODO WalletConnectSDK.onSessionDelete; details: ${JSON.stringify(details, null, 2)}`)
|
||||
console.debug(`WC WalletConnectSDK.onSessionDelete; details: ${JSON.stringify(details, null, 2)}`)
|
||||
root.sessionDelete(details)
|
||||
}
|
||||
|
||||
function onSessionExpire(details)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
WalletConnect 1.0 WalletConnect.qml
|
||||
WalletConnectModal 1.0 WalletConnectModal.qml
|
||||
WalletConnectSDK 1.0 WalletConnectSDK.qml
|
||||
WalletConnectSDK 1.0 WalletConnectSDK.qml
|
||||
Pairings 1.0 Pairings.qml
|
|
@ -18,7 +18,8 @@ Install dependencies steps by executing commands in this directory:
|
|||
- update the [`package.json`](./package.json) versions and run `npm install`
|
||||
- alternatively
|
||||
- use the command `npm install <package-name>@<version/latest> --save` for individual packages
|
||||
- or to update to the latest run `npm update` in here
|
||||
- or to update to the latest run `ncu -u; npm install` in here
|
||||
- run `npm install -g npm-check-updates` for `ncu` command
|
||||
- these commands will also create or update a `package-lock.json` file and populate the `node_modules` directory
|
||||
- update the [`bundle.js`](./dist/main.js) file by running `npm run build`
|
||||
- the result will be embedded with the app and loaded by [`WalletConnectSDK.qml`](../WalletConnectSDK.qml) component
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"name": "wallet_connect_integration",
|
||||
"version": "0.1.0",
|
||||
"description": "Wallet Connect Integration for status-desktop",
|
||||
"description": "Wallet Connect integration for status-desktop",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"webpack": "^5.88.2",
|
||||
"webpack": "^5.89.0",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-server": "^4.15.1"
|
||||
},
|
||||
|
@ -16,7 +16,6 @@
|
|||
"start": "webpack serve --mode development --open"
|
||||
},
|
||||
"dependencies": {
|
||||
"@walletconnect/auth-client": "^2.1.2",
|
||||
"@walletconnect/web3wallet": "^1.9.2"
|
||||
"@walletconnect/web3wallet": "^1.9.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { Core } from "@walletconnect/core";
|
||||
import { Web3Wallet } from "@walletconnect/web3wallet";
|
||||
|
||||
import AuthClient from '@walletconnect/auth-client'
|
||||
// Disabled for now to debug the issue with wrong pairing topic
|
||||
//import AuthClient from '@walletconnect/auth-client'
|
||||
|
||||
// import the builder util
|
||||
import { buildApprovedNamespaces, getSdkError } from "@walletconnect/utils";
|
||||
|
@ -14,21 +15,24 @@ window.wc = {
|
|||
statusObject: null,
|
||||
|
||||
init: function (projectId) {
|
||||
(async () => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
if (!window.statusq) {
|
||||
console.error('missing window.statusq! Forgot to execute "ui/StatusQ/src/StatusQ/Components/private/qwebchannel/helpers.js" first?');
|
||||
return;
|
||||
const errMsg = 'missing window.statusq! Forgot to execute "ui/StatusQ/src/StatusQ/Components/private/qwebchannel/helpers.js" first?'
|
||||
console.error(errMsg);
|
||||
reject(errMsg);
|
||||
}
|
||||
|
||||
if (window.statusq.error) {
|
||||
console.error("Failed initializing WebChannel: " + window.statusq.error);
|
||||
return;
|
||||
const errMsg = "Failed initializing WebChannel: " + window.statusq.error
|
||||
console.error(errMsg);
|
||||
reject(errMsg);
|
||||
}
|
||||
|
||||
wc.statusObject = window.statusq.channel.objects.statusObject;
|
||||
if (!wc.statusObject) {
|
||||
console.error("Failed initializing WebChannel or initialization not run");
|
||||
return;
|
||||
const errMsg = "Failed initializing WebChannel or initialization not run"
|
||||
console.error(errMsg);
|
||||
reject(errMsg);
|
||||
}
|
||||
|
||||
window.wc.core = new Core({
|
||||
|
@ -45,10 +49,10 @@ window.wc = {
|
|||
},
|
||||
});
|
||||
|
||||
window.wc.authClient = await AuthClient.init({
|
||||
projectId: projectId,
|
||||
metadata: window.wc.web3wallet.metadata,
|
||||
});
|
||||
//window.wc.authClient = await AuthClient.init({
|
||||
// projectId: projectId,
|
||||
// metadata: window.wc.web3wallet.metadata,
|
||||
//});
|
||||
|
||||
// connect session responses https://specs.walletconnect.com/2.0/specs/clients/sign/session-events#events
|
||||
window.wc.web3wallet.on("session_proposal", async (details) => {
|
||||
|
@ -92,9 +96,8 @@ window.wc = {
|
|||
});
|
||||
|
||||
wc.statusObject.sdkInitialized("");
|
||||
})();
|
||||
|
||||
return { result: "ok", error: "" };
|
||||
resolve("");
|
||||
});
|
||||
},
|
||||
|
||||
// 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
|
||||
|
@ -127,6 +130,7 @@ window.wc = {
|
|||
supportedNamespaces: supportedNamespaces,
|
||||
});
|
||||
|
||||
wc.statusObject.bubbleConsoleMessage("debug", `web3wallet.approveSession id: ${id} ${JSON.stringify(approvedNamespaces, null, 2)}`)
|
||||
return {
|
||||
result: window.wc.web3wallet.approveSession({
|
||||
id,
|
||||
|
@ -145,45 +149,45 @@ window.wc = {
|
|||
};
|
||||
},
|
||||
|
||||
auth: function (uri) {
|
||||
return {
|
||||
result: window.wc.authClient.core.pairing.pair({ uri }),
|
||||
error: ""
|
||||
};
|
||||
},
|
||||
// auth: function (uri) {
|
||||
// return {
|
||||
// result: window.wc.authClient.core.pairing.pair({ uri }),
|
||||
// error: ""
|
||||
// };
|
||||
// },
|
||||
|
||||
approveAuth: function (authProposal) {
|
||||
const { id, params } = authProposal;
|
||||
// approveAuth: function (authProposal) {
|
||||
// const { id, params } = authProposal;
|
||||
|
||||
// TODO: source user’s address
|
||||
const iss = `did:pkh:eip155:1:${"0x0123456789"}`;
|
||||
// // TODO: source user’s address
|
||||
// const iss = `did:pkh:eip155:1:${"0x0123456789"}`;
|
||||
|
||||
// format the cacao payload with the user’s address
|
||||
const message = window.wc.authClient.formatMessage(params.cacaoPayload, iss);
|
||||
// // format the cacao payload with the user’s address
|
||||
// const message = window.wc.authClient.formatMessage(params.cacaoPayload, iss);
|
||||
|
||||
// TODO: signature
|
||||
const signature = "0x123456789"
|
||||
// // TODO: signature
|
||||
// const signature = "0x123456789"
|
||||
|
||||
return {
|
||||
result: window.wc.authClient.respond(
|
||||
{
|
||||
id: id,
|
||||
signature: {
|
||||
s: signature,
|
||||
t: "eip191",
|
||||
},
|
||||
},
|
||||
iss),
|
||||
error: ""
|
||||
};
|
||||
},
|
||||
// return {
|
||||
// result: window.wc.authClient.respond(
|
||||
// {
|
||||
// id: id,
|
||||
// signature: {
|
||||
// s: signature,
|
||||
// t: "eip191",
|
||||
// },
|
||||
// },
|
||||
// iss),
|
||||
// error: ""
|
||||
// };
|
||||
// },
|
||||
|
||||
rejectAuth: function (id) {
|
||||
return {
|
||||
result: window.wc.authClient.reject(id),
|
||||
error: ""
|
||||
};
|
||||
},
|
||||
// rejectAuth: function (id) {
|
||||
// return {
|
||||
// result: window.wc.authClient.reject(id),
|
||||
// error: ""
|
||||
// };
|
||||
// },
|
||||
|
||||
respondSessionRequest: function (topic, id, signature) {
|
||||
const response = formatJsonRpcResult(id, signature)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 317ad2f906dfd97b9ad620e6481a72801dde713d
|
||||
Subproject commit c433908834ad2d55e40b67da1cbd88014319315f
|
Loading…
Reference in New Issue