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:
Stefan 2023-11-24 14:51:36 +02:00 committed by Stefan Dunca
parent a12f96c311
commit 17c7e46917
19 changed files with 1818 additions and 756 deletions

View File

@ -74,6 +74,13 @@ QtObject:
if not self.hasActivePairings.get(false): if not self.hasActivePairings.get(false):
self.hasActivePairings = some(true) 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.} = proc getHasActivePairings*(self: Controller): bool {.slot.} =
if self.hasActivePairings.isNone: if self.hasActivePairings.isNone:
self.hasActivePairings = some(backend.hasActivePairings()) self.hasActivePairings = some(backend.hasActivePairings())

View File

@ -31,6 +31,10 @@ rpc(wCPairSessionProposal, "wallet"):
rpc(wCRecordSuccessfulPairing, "wallet"): rpc(wCRecordSuccessfulPairing, "wallet"):
sessionProposalJson: string sessionProposalJson: string
rpc(wCChangePairingState, "wallet"):
topic: string
active: bool
rpc(wCHasActivePairings, "wallet"): rpc(wCHasActivePairings, "wallet"):
discard discard
@ -39,9 +43,7 @@ rpc(wCSessionRequest, "wallet"):
proc isErrorResponse(rpcResponse: RpcResponse[JsonNode]): bool = proc isErrorResponse(rpcResponse: RpcResponse[JsonNode]): bool =
if not rpcResponse.error.isNil: return not rpcResponse.error.isNil
return true
return false
proc prepareResponse(res: var JsonNode, rpcResponse: RpcResponse[JsonNode]): string = proc prepareResponse(res: var JsonNode, rpcResponse: RpcResponse[JsonNode]): string =
if isErrorResponse(rpcResponse): if isErrorResponse(rpcResponse):
@ -99,6 +101,14 @@ proc recordSuccessfulPairing*(sessionProposalJson: string): bool =
warn e.msg warn e.msg
return false 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 = proc hasActivePairings*(): bool =
try: try:
let response = wCHasActivePairings() let response = wCHasActivePairings()

View File

@ -34,9 +34,46 @@ Item {
controller: WalletConnectController { controller: WalletConnectController {
pairSessionProposal: function(sessionProposalJson) { 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) { sessionRequest: function(sessionRequestJson, password) {
const signedJson = "0x1234567890" const signedJson = "0x1234567890"
this.respondSessionRequest(sessionRequestJson, signedJson, respondError.checked) this.respondSessionRequest(sessionRequestJson, signedJson, respondError.checked)
@ -74,6 +111,7 @@ Item {
checked: wc.sdk.webEngineLoader.active checked: wc.sdk.webEngineLoader.active
enabled: false enabled: false
} }
RowLayout { RowLayout {
id: optionsHeader id: optionsHeader
@ -95,14 +133,64 @@ Item {
checked: false 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 // spacer
ColumnLayout {} ColumnLayout {}
} }
} }
Settings { Settings {
id: settings id: settings
property bool hasActivePairings: hasActivePairingsCheckBox.checked 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);
});
} }
} }

View File

@ -10,6 +10,10 @@ Item {
// function pairSessionProposal(/*string*/ sessionProposalJson) // function pairSessionProposal(/*string*/ sessionProposalJson)
required property var pairSessionProposal 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) signal respondSessionRequest(string sessionRequestJson, string signedJson, bool error)

View File

@ -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-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 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/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-20231114210825-6c2d15b5dc57 h1:AuJFXERIFVzUjf9rrTb8vamFubB6Ks/e8aUasDr4pOM=
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/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.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 h1:Khwjb59NzniloUr5i9s9AtkEyqBbQFt1lkoAu66sAu0=
github.com/status-im/migrate/v4 v4.6.2-status.3/go.mod h1:c/kc90n47GZu/58nnz1OMLTf7uE4Da4gZP5qmU+A/v8= github.com/status-im/migrate/v4 v4.6.2-status.3/go.mod h1:c/kc90n47GZu/58nnz1OMLTf7uE4Da4gZP5qmU+A/v8=

View File

@ -91,8 +91,9 @@ func callPrivateMethod(method string, params []interface{}) string {
} }
type Config struct { type Config struct {
HashedPassword string `json:"hashedPassword"` HashedPassword string `json:"hashedPassword"`
NodeConfigFile string `json:"nodeConfigFile"` NodeConfigFile string `json:"nodeConfigFile"`
DataDir *string `json:"dataDir,omitempty"`
} }
func processConfigArgs() (config *Config, nodeConfigJson string, userFolder string, err error) { 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 { if err == nil {
nodeConfigJson = string(nodeConfigData) nodeConfigJson = string(nodeConfigData)
} }
if config.DataDir != nil {
userFolder = *config.DataDir
}
return return
} }

View File

@ -9,6 +9,8 @@
<div id="log"></div> <div id="log"></div>
<script src="bundle.js" type="module"></script> <script src="bundle.js" type="module"></script>
<script> <script>
// Helper functions
//
function goEcho(message) { function goEcho(message) {
window.echo(message); window.echo(message);
} }
@ -47,39 +49,158 @@
return addHtmlEntry(`${componentHtml}${statusHtml}`, null, entry); return addHtmlEntry(`${componentHtml}${statusHtml}`, null, entry);
} }
// SDK initialization
//
const statusGoEntry = logComponentStatusChange("status-go", "Initializing..."); const statusGoEntry = logComponentStatusChange("status-go", "Initializing...");
var initEventCount = 0;
var eventCount = 0; var eventCount = 0;
const readyToPairEventName = "readyToPair"; const readyToPairEventName = "readyToPair";
async function initializeSDK() { async function initializeSDK() {
try { try {
const sdkEntry = logComponentStatusChange("SDK", "Initializing..."); const sdkEntry = logComponentStatusChange("SDK", "Initializing...");
const conf = await window.getConfiguration(); const conf = await window.getConfiguration();
const wc = await window.wc.init(conf.projectId); await window.wc.init(conf.projectId);
logComponentStatusChange("SDK", "Initialized", "green", sdkEntry); logComponentStatusChange("SDK", "Initialized", "green", sdkEntry);
eventCount++; initEventCount++;
} catch (error) { } 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 pairLinkInput = null;
var pairButton = null; var pairButton = null;
function newPairWorkflow() { function newPairWorkflow() {
// Remove all the previous entries
if (logEntries) { if (logEntries) {
for (let i = 0; i < logEntries.length; i++) { for (let i = 0; i < logEntries.length; i++) {
logEntries[i].remove(); logEntries[i].remove();
} }
} }
logEntries = []; logEntries = [];
eventCount++; 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( addHtmlEntry(
`<input type="text" id="pairLinkInput" placeholder="Insert pair link" /><button id="pairButton" disabled>Pair</button>` `<input type="text" id="pairLinkInput" placeholder="Insert pair link" /><button id="pairButton" disabled>Pair</button>`
); );
// List existing pairing sessions // 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) { if (pairings.length > 0) {
addHtmlEntry(`Existing pairings:`, "fuchsia"); addHtmlEntry(`Existing pairings:`, "fuchsia");
} }
@ -88,24 +209,23 @@
const disconnectEntry = addHtmlEntry( const disconnectEntry = addHtmlEntry(
`[${i + 1}] <span style="color: ${p.active ? "green" : "orange"};">${ `[${i + 1}] <span style="color: ${p.active ? "green" : "orange"};">${
p.active ? "ACTIVE" : "INACTIVE" p.active ? "ACTIVE" : "INACTIVE"
}</span> <span class="elide-text">${ }</span> <span class="elide-text">${p.topic}</span>; Expires: ${timestampToStr(
p.topic p.expiry
}</span>; Expires: ${timestampToStr(p.expiry)} <button id="unpairButton${i}">Disconnect</button>` )} <button id="unpairButton${i}">Disconnect</button>`
); );
const unpairButton = document.getElementById(`unpairButton${i}`); const unpairButton = document.getElementById(`unpairButton${i}`);
unpairButton.addEventListener("click", function () { unpairButton.addEventListener("click", function () {
window.wc.disconnect(p.topic).then( const res = window.wc.disconnect(p.topic);
() => { if (res && !!res.error) {
addLogEntry(`Pairing ${p.topic} disconnected`, "green", disconnectEntry); addLogEntry(`Pairing ${p.topic} disconnect error: ${err.message}`, "red", disconnectEntry);
unpairButton.remove(); return;
}, }
(err) => { addLogEntry(`Pairing ${p.topic} disconnected`, "green", disconnectEntry);
addLogEntry(`Pairing ${p.topic} disconnect error: ${err.message}`, "red", disconnectEntry); unpairButton.remove();
}
);
}); });
} }
// Add pairing options
pairLinkInput = document.getElementById(`pairLinkInput`); pairLinkInput = document.getElementById(`pairLinkInput`);
pairButton = document.getElementById(`pairButton`); pairButton = document.getElementById(`pairButton`);
pairLinkInput.addEventListener("input", function () { pairLinkInput.addEventListener("input", function () {
@ -117,139 +237,73 @@
pairLinkInput.disabled = true; pairLinkInput.disabled = true;
const sdkEntry = logComponentStatusChange("SDK", "Pairing..."); const sdkEntry = logComponentStatusChange("SDK", "Pairing...");
window.wc const result = window.wc.pair(pairLinkInput.value);
.pair(pairLinkInput.value) if (result && !!result.error) {
.then((sessionProposal) => { goEcho("pair() error: ", result.error);
logComponentStatusChange("SDK", "got Pair session proposal", "green", sdkEntry); logComponentStatusChange("SDK", `Pairing error ${error.message}`, "red", sdkEntry);
addLogEntry(`Pair ID: ${sessionProposal.id} ; Topic: ${sessionProposal.params.pairingTopic}`); return;
const goSession = logComponentStatusChange("GO.pairSessionProposal", "waiting status-go", "pink"); }
document.addEventListener(`proposeUserPair`, function (event) { logComponentStatusChange("SDK", "got Pair session proposal", "green", sdkEntry);
pairProposalEntry = logComponentStatusChange( const goSessionEntry = logComponentStatusChange("GO.pairSessionProposal", "waiting status-go", "pink");
"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);
});
}); });
} }
function sdkReady() { document.addEventListener(`proposeUserPair`, function (event) {
window.wc.registerForSessionRequest((event) => { logComponentStatusChange("GO.proposeUserPair", `received "proposeUserPair"`, "green");
eventCount++; addLogEntry(JSON.stringify(event.detail.supportedNamespaces));
if (!document.getElementById(`acceptPairButton`)) {
logComponentStatusChange("SDK", `received "session_request" event`, "green"); addHtmlEntry(`<button id="acceptPairButton">Accept</button><button id="rejectPairButton">Reject</button>`);
addLogEntry(`Event: ${JSON.stringify(event)}`); }
const acceptPairButton = document.getElementById(`acceptPairButton`);
addHtmlEntry( const rejectPairButton = document.getElementById(`rejectPairButton`);
`<button id="acceptSessionButton${eventCount}">Accept</button> <button id="rejectSessionButton${eventCount}">Reject</button>` const sessionProposal = event.detail.sessionProposal;
); acceptPairButton.addEventListener("click", function () {
const result = window.wc.approvePairSession(sessionProposal, event.detail.supportedNamespaces);
const acceptSessionButton = document.getElementById(`acceptSessionButton${eventCount}`); if (result && !!result.error) {
const rejectSessionButton = document.getElementById(`rejectSessionButton${eventCount}`); logComponentStatusChange(
acceptSessionButton.addEventListener("click", function () { "GO.pairSessionProposal",
const sessionReqEntry = logComponentStatusChange("status-go", `sessionRequest called`, "orange"); `Pair session ${sessionProposal.id} approve error: ${result.error}`,
window.sessionRequest(JSON.stringify(event), hashedPasswordInput.value).then((success) => { "red",
acceptSessionButton.disabled = true; goSessionEntry
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");
}
); );
}); 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) { document.addEventListener("sessionRequestResult", function (event) {
let req = event.detail.sessionRequest; let req = event.detail.sessionRequest;
@ -262,16 +316,6 @@
// Add start from scratch option // Add start from scratch option
document.addEventListener(readyToPairEventName, function () { 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(); newPairWorkflow();
}); });
@ -282,12 +326,12 @@
switch (event.name) { switch (event.name) {
case "nodeReady": case "nodeReady":
logComponentStatusChange("status-go", "Ready", "green", statusGoEntry); logComponentStatusChange("status-go", "Ready", "green", statusGoEntry);
eventCount++; initEventCount++;
break; break;
default: default:
// Handle status-go and SDK bootstrap events // Handle status-go and SDK bootstrap events
if (eventCount == 2) { if (initEventCount == 2) {
eventCount++; initEventCount++;
document.dispatchEvent(new CustomEvent(readyToPairEventName, {})); document.dispatchEvent(new CustomEvent(readyToPairEventName, {}));
} else if (event.name != "") { } else if (event.name != "") {
goEcho(`GO event: ${event.name}`); goEcho(`GO event: ${event.name}`);
@ -315,7 +359,7 @@
const readableDate = date.toLocaleDateString(); const readableDate = date.toLocaleDateString();
const readableTime = date.toLocaleTimeString(); const readableTime = date.toLocaleTimeString();
return `${readableDate} - ${readableTime}` return `${readableDate} - ${readableTime}`;
} }
</script> </script>
</body> </body>

View File

@ -63,9 +63,9 @@ func signalHandler(jsonEvent string) {
return return
} }
// TODO: continue from here // TODO: continue from here
if walletEvent.Type == "WalletConnectProposeUserPair" { // if walletEvent.Type == "WalletConnectProposeUserPair" {
eventQueue <- GoEvent{Name: "proposeUserPair", Payload: walletEvent.Message} // eventQueue <- GoEvent{Name: "proposeUserPair", Payload: walletEvent.Message}
} // }
} }
} }
@ -91,30 +91,31 @@ func main() {
w.SetTitle("WC status-go test") w.SetTitle("WC status-go test")
w.SetSize(1280, 1024, webview.HintNone) 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 { 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 var apiResponse wc.SessionRequestResponse
err = getRPCAPIResponse(sessionReqRes, &apiResponse) err = getRPCAPIResponse(sessionReqRes, &apiResponse)
if err != nil { if err != nil {
l.Error("Error parsing the API response", "error", err) l.Error("Error parsing wallet_wCSessionRequest response", "error", err)
return false 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() { go func() {
eventQueue <- GoEvent{Name: "sessionRequestResult", Payload: apiResponse} eventQueue <- GoEvent{Name: "sessionRequestResult", Payload: apiResponse}
@ -146,6 +147,9 @@ func main() {
} }
}) })
mockStatusObject(w)
mockController(w)
// Start a local server to serve the files // Start a local server to serve the files
http.HandleFunc("/bundle.js", func(w http.ResponseWriter, r *http.Request) { 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") 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.Navigate("http://localhost:8080")
w.Run() 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)
}

View File

@ -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)
}
}
}
}
}

View File

@ -28,5 +28,8 @@ Item {
onSessionRequestEvent: (details) => { onSessionRequestEvent: (details) => {
modal.openWithSessionRequestEvent(details) modal.openWithSessionRequestEvent(details)
} }
onSessionDelete: (deletePayload) => {
root.controller.deletePairing(deletePayload.topic)
}
} }
} }

View File

@ -4,14 +4,13 @@ import QtQuick.Layouts 1.15
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import StatusQ.Core 0.1 import StatusQ.Core 0.1
import StatusQ.Core.Utils 0.1 as SQUtils
import StatusQ.Popups 0.1 import StatusQ.Popups 0.1
Popup { Popup {
id: root id: root
implicitWidth: Math.min(mainLayout.implicitWidth, 400) implicitWidth: 500
implicitHeight: Math.min(mainLayout.implicitHeight, 700) implicitHeight: Math.min(mainLayout.implicitHeight * 2, 700)
required property WalletConnectSDK sdk required property WalletConnectSDK sdk
@ -38,89 +37,87 @@ Popup {
anchors.fill: parent anchors.fill: parent
contentWidth: mainLayout.width contentWidth: mainLayout.implicitWidth
contentHeight: mainLayout.height contentHeight: mainLayout.implicitHeight
interactive: contentHeight > height || contentWidth > width
ColumnLayout { 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 { StatusBaseText {
id: statusText text: qsTr("Debugging UX until design is ready")
text: "-"
} }
StatusBaseText {
text: "Pairings" StatusInput {
visible: sdk.pairingsModel.count > 0 id: pairLinkInput
}
StatusListView {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: contentHeight
Layout.maximumHeight: 200
model: sdk.pairingsModel placeholderText: "Insert pair link"
}
delegate: StatusBaseText { RowLayout {
text: `${SQUtils.Utils.elideText(topic, 6, 6)} - ${new Date(expiry * 1000).toLocaleString()}` Layout.fillWidth: true
color: active ? "green" : "orange"
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 ColumnLayout {
contentHeight: detailsText.height 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 { StatusBaseText {
id: detailsText id: detailsText
@ -130,42 +127,37 @@ Popup {
color: "#FF00FF" 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 { // Separator
StatusButton { ColumnLayout {}
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 {}
}
ScrollBar.vertical: ScrollBar {} ScrollBar.vertical: ScrollBar {}
clip: true clip: true
@ -190,7 +182,7 @@ Popup {
if (success) { if (success) {
d.setStatusText("Pair ID: " + sessionProposal.id + "; Topic: " + sessionProposal.params.pairingTopic) d.setStatusText("Pair ID: " + sessionProposal.id + "; Topic: " + sessionProposal.params.pairingTopic)
root.controller.pairSessionProposal(JSON.stringify(sessionProposal)) root.controller.pairSessionProposal(JSON.stringify(sessionProposal))
// Expecting signal onProposeUserPair from controller // Expecting signal onProposeUserPair(..., true, ...) from controller
} else { } else {
d.setStatusText("Pairing error", "red") d.setStatusText("Pairing error", "red")
} }

View File

@ -31,11 +31,18 @@ Item {
signal sessionRequestEvent(var sessionRequest) signal sessionRequestEvent(var sessionRequest)
signal sessionRequestUserAnswerResult(bool accept, string error) signal sessionRequestUserAnswerResult(bool accept, string error)
signal sessionDelete(var deletePayload)
function pair(pairLink) function pair(pairLink)
{ {
wcCalls.pair(pairLink) wcCalls.pair(pairLink)
} }
function disconnectPairing(topic)
{
wcCalls.disconnectPairing(topic)
}
function approvePairSession(sessionProposal, supportedNamespaces) function approvePairSession(sessionProposal, supportedNamespaces)
{ {
wcCalls.approvePairSession(sessionProposal, supportedNamespaces) wcCalls.approvePairSession(sessionProposal, supportedNamespaces)
@ -108,7 +115,7 @@ Item {
function init() { function init() {
console.debug(`WC WalletConnectSDK.wcCall.init; root.projectId: ${root.projectId}`) 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)}`) console.debug(`WC WalletConnectSDK.wcCall.init; response: ${JSON.stringify(result, null, 2)}`)
@ -252,6 +259,22 @@ Item {
d.resetPairingsModel() 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 { QtObject {
@ -300,7 +323,8 @@ Item {
function onSessionDelete(details) 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) function onSessionExpire(details)

View File

@ -1,3 +1,4 @@
WalletConnect 1.0 WalletConnect.qml WalletConnect 1.0 WalletConnect.qml
WalletConnectModal 1.0 WalletConnectModal.qml WalletConnectModal 1.0 WalletConnectModal.qml
WalletConnectSDK 1.0 WalletConnectSDK.qml WalletConnectSDK 1.0 WalletConnectSDK.qml
Pairings 1.0 Pairings.qml

View File

@ -18,7 +18,8 @@ Install dependencies steps by executing commands in this directory:
- update the [`package.json`](./package.json) versions and run `npm install` - update the [`package.json`](./package.json) versions and run `npm install`
- alternatively - alternatively
- use the command `npm install <package-name>@<version/latest> --save` for individual packages - 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 - 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` - 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 - 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

View File

@ -1,10 +1,10 @@
{ {
"name": "wallet_connect_integration", "name": "wallet_connect_integration",
"version": "0.1.0", "version": "0.1.0",
"description": "Wallet Connect Integration for status-desktop", "description": "Wallet Connect integration for status-desktop",
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"webpack": "^5.88.2", "webpack": "^5.89.0",
"webpack-cli": "^5.1.4", "webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1" "webpack-dev-server": "^4.15.1"
}, },
@ -16,7 +16,6 @@
"start": "webpack serve --mode development --open" "start": "webpack serve --mode development --open"
}, },
"dependencies": { "dependencies": {
"@walletconnect/auth-client": "^2.1.2", "@walletconnect/web3wallet": "^1.9.4"
"@walletconnect/web3wallet": "^1.9.2"
} }
} }

View File

@ -1,7 +1,8 @@
import { Core } from "@walletconnect/core"; import { Core } from "@walletconnect/core";
import { Web3Wallet } from "@walletconnect/web3wallet"; 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 the builder util
import { buildApprovedNamespaces, getSdkError } from "@walletconnect/utils"; import { buildApprovedNamespaces, getSdkError } from "@walletconnect/utils";
@ -14,21 +15,24 @@ window.wc = {
statusObject: null, statusObject: null,
init: function (projectId) { init: function (projectId) {
(async () => { return new Promise(async (resolve, reject) => {
if (!window.statusq) { if (!window.statusq) {
console.error('missing window.statusq! Forgot to execute "ui/StatusQ/src/StatusQ/Components/private/qwebchannel/helpers.js" first?'); const errMsg = 'missing window.statusq! Forgot to execute "ui/StatusQ/src/StatusQ/Components/private/qwebchannel/helpers.js" first?'
return; console.error(errMsg);
reject(errMsg);
} }
if (window.statusq.error) { if (window.statusq.error) {
console.error("Failed initializing WebChannel: " + window.statusq.error); const errMsg = "Failed initializing WebChannel: " + window.statusq.error
return; console.error(errMsg);
reject(errMsg);
} }
wc.statusObject = window.statusq.channel.objects.statusObject; wc.statusObject = window.statusq.channel.objects.statusObject;
if (!wc.statusObject) { if (!wc.statusObject) {
console.error("Failed initializing WebChannel or initialization not run"); const errMsg = "Failed initializing WebChannel or initialization not run"
return; console.error(errMsg);
reject(errMsg);
} }
window.wc.core = new Core({ window.wc.core = new Core({
@ -45,10 +49,10 @@ window.wc = {
}, },
}); });
window.wc.authClient = await AuthClient.init({ //window.wc.authClient = await AuthClient.init({
projectId: projectId, // projectId: projectId,
metadata: window.wc.web3wallet.metadata, // metadata: window.wc.web3wallet.metadata,
}); //});
// connect session responses https://specs.walletconnect.com/2.0/specs/clients/sign/session-events#events // connect session responses https://specs.walletconnect.com/2.0/specs/clients/sign/session-events#events
window.wc.web3wallet.on("session_proposal", async (details) => { window.wc.web3wallet.on("session_proposal", async (details) => {
@ -92,9 +96,8 @@ window.wc = {
}); });
wc.statusObject.sdkInitialized(""); wc.statusObject.sdkInitialized("");
})(); resolve("");
});
return { result: "ok", error: "" };
}, },
// 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 // 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, supportedNamespaces: supportedNamespaces,
}); });
wc.statusObject.bubbleConsoleMessage("debug", `web3wallet.approveSession id: ${id} ${JSON.stringify(approvedNamespaces, null, 2)}`)
return { return {
result: window.wc.web3wallet.approveSession({ result: window.wc.web3wallet.approveSession({
id, id,
@ -145,45 +149,45 @@ window.wc = {
}; };
}, },
auth: function (uri) { // auth: function (uri) {
return { // return {
result: window.wc.authClient.core.pairing.pair({ uri }), // result: window.wc.authClient.core.pairing.pair({ uri }),
error: "" // error: ""
}; // };
}, // },
approveAuth: function (authProposal) { // approveAuth: function (authProposal) {
const { id, params } = authProposal; // const { id, params } = authProposal;
// TODO: source users address // // TODO: source users address
const iss = `did:pkh:eip155:1:${"0x0123456789"}`; // const iss = `did:pkh:eip155:1:${"0x0123456789"}`;
// format the cacao payload with the users address // // format the cacao payload with the users address
const message = window.wc.authClient.formatMessage(params.cacaoPayload, iss); // const message = window.wc.authClient.formatMessage(params.cacaoPayload, iss);
// TODO: signature // // TODO: signature
const signature = "0x123456789" // const signature = "0x123456789"
return { // return {
result: window.wc.authClient.respond( // result: window.wc.authClient.respond(
{ // {
id: id, // id: id,
signature: { // signature: {
s: signature, // s: signature,
t: "eip191", // t: "eip191",
}, // },
}, // },
iss), // iss),
error: "" // error: ""
}; // };
}, // },
rejectAuth: function (id) { // rejectAuth: function (id) {
return { // return {
result: window.wc.authClient.reject(id), // result: window.wc.authClient.reject(id),
error: "" // error: ""
}; // };
}, // },
respondSessionRequest: function (topic, id, signature) { respondSessionRequest: function (topic, id, signature) {
const response = formatJsonRpcResult(id, signature) const response = formatJsonRpcResult(id, signature)

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit 317ad2f906dfd97b9ad620e6481a72801dde713d Subproject commit c433908834ad2d55e40b67da1cbd88014319315f