feat(dapps) implement signing of messages

Implement infrastructure and integration with status-go to support
general session requests

Supported methods:
- personal_sign
- eth_signTypedData_v4

depends on status-go change that exposes the signing methods

Also

- support hex or utf8 encoding for personal_sign
- format the typed data for display in the modal

Tests are disabled for now, as they are crashing on CI

Close: #14927
This commit is contained in:
Stefan 2024-06-07 19:54:19 +03:00 committed by Stefan Dunca
parent 28a7b691cd
commit 758dbc55e5
13 changed files with 198 additions and 92 deletions

View File

@ -38,7 +38,7 @@ QtObject:
self.dappsListReceived(res) self.dappsListReceived(res)
return true return true
proc userAuthenticationResult*(self: Controller, topic: string, id: string, error: bool) {.signal.} proc userAuthenticationResult*(self: Controller, topic: string, id: string, error: bool, password: string, pin: string) {.signal.}
# Beware, it will fail if an authentication is already in progress # Beware, it will fail if an authentication is already in progress
proc authenticateUser*(self: Controller, topic: string, id: string, address: string): bool {.slot.} = proc authenticateUser*(self: Controller, topic: string, id: string, address: string): bool {.slot.} =
@ -46,6 +46,12 @@ QtObject:
if acc.keyUid == "": if acc.keyUid == "":
return false return false
return self.service.authenticateUser(acc.keyUid, proc(success: bool) = return self.service.authenticateUser(acc.keyUid, proc(password: string, pin: string, success: bool) =
self.userAuthenticationResult(topic, id, success) self.userAuthenticationResult(topic, id, success, password, pin)
) )
proc signMessage*(self: Controller, address: string, password: string, message: string): string {.slot.} =
return self.service.signMessage(address, password, message)
proc signTypedDataV4*(self: Controller, address: string, password: string, typedDataJson: string): string {.slot.} =
return self.service.signTypedDataV4(address, password, typedDataJson)

View File

@ -20,7 +20,7 @@ logScope:
const UNIQUE_WALLET_CONNECT_MODULE_IDENTIFIER* = "WalletSection-WCModule" const UNIQUE_WALLET_CONNECT_MODULE_IDENTIFIER* = "WalletSection-WCModule"
type type
AuthenticationResponseFn* = proc(success: bool) AuthenticationResponseFn* = proc(password: string, pin: string, success: bool)
QtObject: QtObject:
type Service* = ref object of QObject type Service* = ref object of QObject
@ -59,10 +59,10 @@ QtObject:
if args.password == "" and args.pin == "": if args.password == "" and args.pin == "":
info "fail to authenticate user" info "fail to authenticate user"
self.authenticationCallback(false) self.authenticationCallback("", "", false)
return return
self.authenticationCallback(true) self.authenticationCallback(args.password, args.pin, true)
proc addSession*(self: Service, session_json: string): bool = proc addSession*(self: Service, session_json: string): bool =
# TODO #14588: call it async # TODO #14588: call it async
@ -86,3 +86,9 @@ QtObject:
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_AUTHENTICATE_USER, data) self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_AUTHENTICATE_USER, data)
return true return true
proc signMessage*(self: Service, address: string, password: string, message: string): string =
return status_go.signMessage(address, password, message)
proc signTypedDataV4*(self: Service, address: string, password: string, typedDataJson: string): string =
return status_go.signTypedData(address, password, typedDataJson)

View File

@ -1,20 +1,32 @@
import options, logging import options, logging
import json, json_serialization import json, json_serialization
import core, response_type import core, response_type
import strutils
from gen import rpc from gen import rpc
import backend import backend
import status_go
import app_service/service/community/dto/sign_params
import app_service/common/utils
rpc(addWalletConnectSession, "wallet"): rpc(addWalletConnectSession, "wallet"):
sessionJson: string sessionJson: string
proc isErrorResponse(rpcResponse: RpcResponse[JsonNode]): bool = rpc(signTypedDataV4, "wallet"):
return not rpcResponse.error.isNil typedJson: string
address: string
password: string
proc isSuccessResponse(rpcResponse: RpcResponse[JsonNode]): bool =
return rpcResponse.error.isNil
proc addSession*(sessionJson: string): bool = proc addSession*(sessionJson: string): bool =
try: try:
let rpcRes = addWalletConnectSession(sessionJson) let rpcRes = addWalletConnectSession(sessionJson)
return isErrorResponse(rpcRes): return isSuccessResponse(rpcRes):
except Exception as e: except Exception as e:
warn "AddWalletConnectSession failed: ", "msg", e.msg warn "AddWalletConnectSession failed: ", "msg", e.msg
return false return false
@ -33,3 +45,29 @@ proc getDapps*(validAtEpoch: int64, testChains: bool): string =
except Exception as e: except Exception as e:
warn "GetWalletConnectDapps failed: ", "msg", e.msg warn "GetWalletConnectDapps failed: ", "msg", e.msg
return "" return ""
proc signMessage*(address: string, password: string, message: string): string =
try:
let signParams = SignParamsDto(address: address, password: hashPassword(password), data: "0x" & toHex(message))
let paramsStr = $toJson(signParams)
let rpcResRaw = status_go.signMessage(paramsStr)
let rpcRes = Json.decode(rpcResRaw, RpcResponse[JsonNode])
if(not rpcRes.error.isNil):
return ""
return rpcRes.result.getStr()
except Exception as e:
warn "status_go.signMessage failed: ", "msg", e.msg
return ""
proc signTypedData*(address: string, password: string, typedDataJson: string): string =
try:
let rpcRes = signTypedDataV4(typedDataJson, address, hashPassword(password))
if not isSuccessResponse(rpcRes):
return ""
return rpcRes.result.getStr()
except Exception as e:
warn "wallet_signTypedDataV4 failed: ", "msg", e.msg
return ""

View File

@ -50,7 +50,8 @@ Item {
dappName: settings.dappName dappName: settings.dappName
dappUrl: settings.dappUrl dappUrl: settings.dappUrl
dappIcon: settings.dappIcon dappIcon: settings.dappIcon
signContent: JSON.stringify(d.signTestContent, null, 2) signContent: d.signTestContent
method: "eth_signTypedData_v4"
maxFeesText: "1.82 EUR" maxFeesText: "1.82 EUR"
estimatedTimeText: "3-5 mins" estimatedTimeText: "3-5 mins"
@ -128,36 +129,7 @@ Item {
readonly property var selectedNetwork: NetworksModel.flatNetworks.get(0) readonly property var selectedNetwork: NetworksModel.flatNetworks.get(0)
readonly property var signTestContent: { readonly property var signTestContent: "{\"types\":{\"EIP712Domain\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"chainId\",\"type\":\"uint256\"},{\"name\":\"verifyingContract\",\"type\":\"address\"}],\"Person\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"wallet\",\"type\":\"address\"}],\"Mail\":[{\"name\":\"from\",\"type\":\"Person\"},{\"name\":\"to\",\"type\":\"Person\"},{\"name\":\"contents\",\"type\":\"string\"}]},\"primaryType\":\"Mail\",\"domain\":{\"name\":\"Ether Mail\",\"version\":\"1\",\"chainId\":1,\"verifyingContract\":\"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC\"},\"message\":{\"from\":{\"name\":\"Cow\",\"wallet\":\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\"},\"to\":{\"name\":\"Bob\",\"wallet\":\"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB\"},\"contents\":\"Hello, Bob!\"}}"
"id": 1714038548266495,
"params": {
"chainld": "eip155:11155111",
"request": {
"expiryTimestamp": 1714038848,
"method": "eth_signTransaction",
"params": [
{
"data": "0x",
"from": "0xE2d622C817878dA5143bBE06866ca8E35273Ba8",
"gasLimit": "0x5208",
"gasPrice": "0xa677ef31",
"nonce": "0x27",
"to": "0xE2d622C817878dA5143bBE06866ca8E35273Ba8a",
"value": "0x00"
}
]
}
},
"topic": "a0f85b23a1f3a540d85760a523963165fb92169d57320c",
"verifyContext": {
"verified": {
"isScam": false,
"origin": "https://react-app.walletconnect.com/",
"validation": "VALID",
"verifyUrl": "https://verify.walletconnect.com/"
}
}
}
} }
} }

View File

@ -241,7 +241,7 @@ Item {
StatusButton { StatusButton {
text: qsTr("Authenticate") text: qsTr("Authenticate")
onClicked: { onClicked: {
walletConnectService.store.userAuthenticated(authMockDialog.topic, authMockDialog.id) walletConnectService.store.userAuthenticated(authMockDialog.topic, authMockDialog.id, "0x1234567890", "123")
authMockDialog.close() authMockDialog.close()
} }
} }
@ -260,9 +260,8 @@ Item {
store: DAppsStore { store: DAppsStore {
signal dappsListReceived(string dappsJson) signal dappsListReceived(string dappsJson)
signal userAuthenticated(string topic, string id) signal userAuthenticated(string topic, string id, string password, string pin)
signal userAuthenticationFailed(string topic, string id) signal userAuthenticationFailed(string topic, string id)
signal sessionRequestExecuted(var payload, bool success)
function addWalletConnectSession(sessionJson) { function addWalletConnectSession(sessionJson) {
console.info("Persist Session", sessionJson) console.info("Persist Session", sessionJson)
@ -276,6 +275,7 @@ Item {
"iconUrl": firstIconUrl "iconUrl": firstIconUrl
} }
d.persistedDapps.push(persistedDapp) d.persistedDapps.push(persistedDapp)
return true
} }
function getDapps() { function getDapps() {
@ -289,6 +289,16 @@ Item {
authMockDialog.open() authMockDialog.open()
return true return true
} }
// hardcoded for https://react-app.walletconnect.com/
function signMessage(topic, id, address, password, message) {
return "0x0b083acc1b3b612dd38e8e725b28ce9b2dd4936b4cf7922da4e4a3c6f44f7f4f6d3050ccb41455a2b85093f1bfadb10fc6a75d83bb590b2eb70e3447653459701c"
}
// hardcoded for https://react-app.walletconnect.com/
function signTypedDataV4(topic, id, address, password, typedDataJson) {
return "0xf8ceb3468319cc215523b67c24c4504b3addd9bf8de31c278038d7478c9b6de554f7d8a516cd5d6a066b7d48b81f03d9d6bb7d5d754513c08325674ebcc7efbc1b"
}
} }
walletStore: WalletStore { walletStore: WalletStore {

View File

@ -25,6 +25,7 @@ Item {
width: 600 width: 600
height: 400 height: 400
// TODO #15151 fix CI crash and re-enable tests
// Component { // Component {
// id: sdkComponent // id: sdkComponent
@ -79,9 +80,8 @@ Item {
// DAppsStore { // DAppsStore {
// signal dappsListReceived(string dappsJson) // signal dappsListReceived(string dappsJson)
// signal userAuthenticated(string topic, string id) // signal userAuthenticated(string topic, string id, string password, string pin)
// signal userAuthenticationFailed(string topic, string id) // signal userAuthenticationFailed(string topic, string id)
// signal sessionRequestExecuted(var payload, bool success)
// // By default, return no dapps in store // // By default, return no dapps in store
// function getDapps() { // function getDapps() {
@ -100,8 +100,12 @@ Item {
// } // }
// property var signMessageCalls: [] // property var signMessageCalls: []
// function signMessage(message) { // function signMessage(topic, id, address, password, message) {
// signMessageCalls.push({message}) // signMessageCalls.push({topic, id, address, password, message})
// }
// property var signTypedDataV4Calls: []
// function signTypedDataV4(topic, id, address, password, message) {
// signTypedDataV4Calls.push({topic, id, address, password, message})
// } // }
// } // }
// } // }
@ -173,7 +177,7 @@ Item {
// compare(handler.store.authenticateUserCalls.length, 1, "expected a call to store.authenticateUser") // compare(handler.store.authenticateUserCalls.length, 1, "expected a call to store.authenticateUser")
// let store = handler.store // let store = handler.store
// store.userAuthenticated(td.topic, td.request.id) // store.userAuthenticated(td.topic, td.request.id, "password", "")
// compare(store.signMessageCalls.length, 1, "expected a call to store.signMessage") // compare(store.signMessageCalls.length, 1, "expected a call to store.signMessage")
// compare(store.signMessageCalls[0].message, td.request.data) // compare(store.signMessageCalls[0].message, td.request.data)
// } // }
@ -414,7 +418,7 @@ Item {
// } // }
// } // }
// // Beware this TestCase should be last; I had it before ServiceHelpers and it was not run with `when: windowShown` // TODO #15151: this TestCase if placed before ServiceHelpers was not run with `when: windowShown`. Check if related to the CI crash
// TestCase { // TestCase {
// id: dappsWorkflowTest // id: dappsWorkflowTest

View File

@ -129,6 +129,7 @@ ConnectedDappsButton {
dappIcon: request.dappIcon dappIcon: request.dappIcon
signContent: request.data.message signContent: request.data.message
method: request.method
maxFeesText: request.maxFeesText maxFeesText: request.maxFeesText
estimatedTimeText: request.estimatedTimeText estimatedTimeText: request.estimatedTimeText
@ -155,9 +156,12 @@ ConnectedDappsButton {
Connections { Connections {
target: root.wcService ? root.wcService.requestHandler : null target: root.wcService ? root.wcService.requestHandler : null
function onSessionRequestResult(payload, isSuccess) { function onSessionRequestResult(request, payload, isSuccess) {
// TODO #14927 handle this properly if (isSuccess) {
sessionRequestLoader.active = false sessionRequestLoader.active = false
} else {
// TODO #14762 handle the error case
}
} }
} }

View File

@ -30,7 +30,7 @@ QObject {
signal sessionRequest(SessionRequestResolved request) signal sessionRequest(SessionRequestResolved request)
signal displayToastMessage(string message, bool error) signal displayToastMessage(string message, bool error)
signal sessionRequestResult(var payload, bool isSuccess) signal sessionRequestResult(/*model entry of SessionRequestResolved*/ var request, var payload, bool isSuccess)
/// Supported methods /// Supported methods
property QtObject methods: QtObject { property QtObject methods: QtObject {
@ -38,11 +38,16 @@ QObject {
readonly property string name: Constants.personal_sign readonly property string name: Constants.personal_sign
readonly property string userString: qsTr("sign") readonly property string userString: qsTr("sign")
} }
readonly property QtObject signTypedData_v4: QtObject {
readonly property string name: "eth_signTypedData_v4"
readonly property string userString: qsTr("sign typed data")
}
readonly property QtObject sendTransaction: QtObject { readonly property QtObject sendTransaction: QtObject {
readonly property string name: "eth_sendTransaction" readonly property string name: "eth_sendTransaction"
readonly property string userString: qsTr("send transaction") readonly property string userString: qsTr("send transaction")
} }
readonly property var all: [personalSign, sendTransaction] readonly property var all: [personalSign, signTypedData_v4, sendTransaction]
} }
function getSupportedMethods() { function getSupportedMethods() {
@ -81,14 +86,17 @@ QObject {
return return
if (error) { if (error) {
root.displayToastMessage(qsTr("Fail to %1 from %2").arg(methodStr).arg(session.peer.metadata.url), true) root.displayToastMessage(qsTr("Fail to %1 from %2").arg(methodStr).arg(session.peer.metadata.url), true)
// TODO #14757 handle SDK error on user accept/reject
root.sessionRequestResult(request, "", false /*isSuccessful*/)
console.error(`Error accepting session request for topic: ${topic}, id: ${id}, accept: ${accept}, error: ${error}`) console.error(`Error accepting session request for topic: ${topic}, id: ${id}, accept: ${accept}, error: ${error}`)
return return
} }
let actionStr = accept ? qsTr("accepted") : qsTr("rejected") let actionStr = accept ? qsTr("accepted") : qsTr("rejected")
root.displayToastMessage("%1 %2 %3".arg(session.peer.metadata.url).arg(methodStr).arg(actionStr), false) root.displayToastMessage("%1 %2 %3".arg(session.peer.metadata.url).arg(methodStr).arg(actionStr), false)
root.sessionRequestApprovalResult()
root.sessionRequestResult(request, "", true /*isSuccessful*/)
}) })
} }
} }
@ -96,13 +104,13 @@ QObject {
Connections { Connections {
target: root.store target: root.store
function onUserAuthenticated(topic, id) { function onUserAuthenticated(topic, id, password, pin) {
var request = requests.findRequest(topic, id) var request = requests.findRequest(topic, id)
if (request === null) { if (request === null) {
console.error("Error finding event for topic", topic, "id", id) console.error("Error finding event for topic", topic, "id", id)
return return
} }
d.executeSessionRequest(request) d.executeSessionRequest(request, password, pin)
} }
function onUserAuthenticationFailed(topic, id) { function onUserAuthenticationFailed(topic, id) {
@ -117,11 +125,6 @@ QObject {
root.displayToastMessage(qsTr("Failed to authenticate %1 from %2").arg(methodStr).arg(session.peer.metadata.url), true) root.displayToastMessage(qsTr("Failed to authenticate %1 from %2").arg(methodStr).arg(session.peer.metadata.url), true)
}) })
} }
function onSessionRequestExecuted(payload, isSuccess) {
// TODO #14927 handle this properly
root.sessionRequestResult(payload, isSuccess)
}
} }
QObject { QObject {
@ -168,24 +171,24 @@ QObject {
/// Returns null if the account is not found /// Returns null if the account is not found
function lookupAccountFromEvent(event, method) { function lookupAccountFromEvent(event, method) {
var address = ""
if (method === root.methods.personalSign.name) { if (method === root.methods.personalSign.name) {
if (event.params.request.params.length < 2) { if (event.params.request.params.length < 2) {
return null return null
} }
var address = event.params.request.params[1] address = event.params.request.params[1]
for (let i = 0; i < walletStore.ownAccounts.count; i++) { } else if(method === root.methods.signTypedData_v4.name) {
let acc = ModelUtils.get(walletStore.ownAccounts, i) if (event.params.request.params.length < 2) {
if (acc.address === address) {
return acc
}
}
}
return null return null
} }
address = event.params.request.params[0]
}
return ModelUtils.getByKey(walletStore.ownAccounts, "address", address)
}
/// Returns null if the network is not found /// Returns null if the network is not found
function lookupNetworkFromEvent(event, method) { function lookupNetworkFromEvent(event, method) {
if (method === root.methods.personalSign.name) { if (method === root.methods.personalSign.name || method === root.methods.signTypedData_v4.name) {
let chainId = Helpers.chainIdFromEip155(event.params.chainId) let chainId = Helpers.chainIdFromEip155(event.params.chainId)
for (let i = 0; i < walletStore.flatNetworks.count; i++) { for (let i = 0; i < walletStore.flatNetworks.count; i++) {
let network = ModelUtils.get(walletStore.flatNetworks, i) let network = ModelUtils.get(walletStore.flatNetworks, i)
@ -202,9 +205,22 @@ QObject {
if (event.params.request.params.length == 0) { if (event.params.request.params.length == 0) {
return null return null
} }
let hexMessage = event.params.request.params[0] var message = ""
let messageParam = event.params.request.params[0]
// There is no standard on how data is encoded. Therefore we support hex or utf8
if (Helpers.isHex(messageParam)) {
message = Helpers.hexToString(messageParam)
} else {
message = messageParam
}
return {message}
} else if (method === root.methods.signTypedData_v4.name) {
if (event.params.request.params.length < 2) {
return null
}
let jsonMessage = event.params.request.params[1]
return { return {
message: Helpers.hexToString(hexMessage) message: jsonMessage
} }
} }
} }
@ -229,10 +245,33 @@ QObject {
}) })
} }
function executeSessionRequest(request) { function executeSessionRequest(request, password, pin) {
if (request.method === root.methods.personalSign.name || request.method === root.methods.signTypedData_v4.name) {
if (password !== "") {
//let originalMessage = request.data.message
// TODO #14756: clarify why prefixing the message fails the test app https://react-app.walletconnect.com/
//let finalMessage = "\x19Ethereum Signed Message:\n" + originalMessage.length + originalMessage
let finalMessage = request.data.message
var signedMessage = ""
if (request.method === root.methods.personalSign.name) { if (request.method === root.methods.personalSign.name) {
store.signMessage(request.data.message) signedMessage = store.signMessage(request.topic, request.id,
console.debug("TODO #14927 sign message: ", request.data.message) request.account.address, password, finalMessage)
} else if (request.method === root.methods.signTypedData_v4.name) {
signedMessage = store.signTypedDataV4(request.topic, request.id,
request.account.address, password, finalMessage)
}
let isSuccessful = signedMessage != ""
if (isSuccessful) {
// acceptSessionRequest will trigger an sdk.sessionRequestUserAnswerResult signal
sdk.acceptSessionRequest(request.topic, request.id, signedMessage)
} else {
root.sessionRequestResult(request, request.data.message, isSuccessful)
}
} else if (pin !== "") {
console.debug("TODO #14927 sign message using keycard: ", request.data.message)
} else {
console.error("No password or pin provided to sign message")
}
} else { } else {
console.error("Unsupported method to execute: ", request.method) console.error("Unsupported method to execute: ", request.method)
} }

View File

@ -127,7 +127,7 @@ WalletConnectSDKBase {
if (d.engine) { if (d.engine) {
d.engine.runJavaScript(`wc.getActiveSessions()`, function(result) { d.engine.runJavaScript(`wc.getActiveSessions()`, function(result) {
let allSessions = "" var allSessions = ""
for (var key of Object.keys(result)) { for (var key of Object.keys(result)) {
allSessions += `\nsessionTopic: ${key} relatedPairingTopic: ${result[key].pairingTopic}`; allSessions += `\nsessionTopic: ${key} relatedPairingTopic: ${result[key].pairingTopic}`;
} }

View File

@ -99,7 +99,9 @@ QObject {
root.displayToastMessage(qsTr("Connected to %1 via WalletConnect").arg(app_url), false) root.displayToastMessage(qsTr("Connected to %1 via WalletConnect").arg(app_url), false)
// Persist session // Persist session
store.addWalletConnectSession(JSON.stringify(session)) if(!store.addWalletConnectSession(JSON.stringify(session))) {
console.error("Failed to persist session")
}
// Notify client // Notify client
root.approveSessionResult(session, err) root.approveSessionResult(session, err)

View File

@ -4,6 +4,10 @@ function chainIdFromEip155(chain) {
return parseInt(chain.split(':').pop().trim(), 10) return parseInt(chain.split(':').pop().trim(), 10)
} }
function isHex(str) {
return str.startsWith('0x') && str.length % 2 === 0 && /^[0-9a-fA-F]*$/.test(str.slice(2))
}
function hexToString(hex) { function hexToString(hex) {
if (hex.startsWith("0x")) { if (hex.startsWith("0x")) {
hex = hex.substring(2); hex = hex.substring(2);

View File

@ -21,6 +21,7 @@ StatusDialog {
required property string dappName required property string dappName
required property string dappUrl required property string dappUrl
required property url dappIcon required property url dappIcon
required property string method
required property string signContent required property string signContent
required property string maxFeesText required property string maxFeesText
required property string estimatedTimeText required property string estimatedTimeText
@ -35,6 +36,10 @@ StatusDialog {
padding: 20 padding: 20
onSignContentChanged: d.updatePayloadToDisplay()
onMethodChanged: d.updatePayloadToDisplay()
Component.onCompleted: d.updatePayloadToDisplay()
contentItem: StatusScrollView { contentItem: StatusScrollView {
id: scrollView id: scrollView
padding: 0 padding: 0
@ -50,7 +55,6 @@ StatusDialog {
dappName: root.dappName dappName: root.dappName
dappIcon: root.dappIcon dappIcon: root.dappIcon
account: root.account account: root.account
signContent: root.signContent
} }
ContentPanel { ContentPanel {
@ -273,7 +277,6 @@ StatusDialog {
required property string dappName required property string dappName
required property url dappIcon required property url dappIcon
required property var account required property var account
required property string signContent
// Icons // Icons
Item { Item {
@ -405,10 +408,24 @@ StatusDialog {
width: contentScrollView.availableWidth width: contentScrollView.availableWidth
text: signContent text: d.payloadToDisplay
wrapMode: Text.WrapAnywhere wrapMode: Text.WrapAnywhere
} }
} }
} }
QtObject {
id: d
property string payloadToDisplay: ""
function updatePayloadToDisplay() {
if (root.method === "eth_signTypedData_v4" && root.signContent) {
payloadToDisplay = JSON.stringify(JSON.parse(root.signContent), null, 2)
return
}
payloadToDisplay = root.signContent
}
}
} }

View File

@ -9,12 +9,11 @@ QObject {
/// \c dappsJson serialized from status-go.wallet.GetDapps /// \c dappsJson serialized from status-go.wallet.GetDapps
signal dappsListReceived(string dappsJson) signal dappsListReceived(string dappsJson)
signal userAuthenticated(string topic, string id) signal userAuthenticated(string topic, string id, string password, string pin)
signal userAuthenticationFailed(string topic, string id) signal userAuthenticationFailed(string topic, string id)
signal sessionRequestExecuted(var payload, bool success)
function addWalletConnectSession(sessionJson) { function addWalletConnectSession(sessionJson) {
controller.addWalletConnectSession(sessionJson) return controller.addWalletConnectSession(sessionJson)
} }
function authenticateUser(topic, id, address) { function authenticateUser(topic, id, address) {
@ -24,9 +23,14 @@ QObject {
} }
} }
function signMessage(message) { // Returns the hex encoded signature of the message or empty string if error
// TODO #14927 implement me function signMessage(topic, id, address, password, message) {
root.sessionRequestExecuted(message, true) return controller.signMessage(address, password, message)
}
// Returns the hex encoded signature of the typedDataJson or empty string if error
function signTypedDataV4(topic, id, address, password, typedDataJson) {
return controller.signTypedDataV4(address, password, typedDataJson)
} }
/// \c getDapps triggers an async response to \c dappsListReceived /// \c getDapps triggers an async response to \c dappsListReceived
@ -42,9 +46,9 @@ QObject {
root.dappsListReceived(dappsJson) root.dappsListReceived(dappsJson)
} }
function onUserAuthenticationResult(topic, id, success) { function onUserAuthenticationResult(topic, id, success, password, pin) {
if (success) { if (success) {
root.userAuthenticated(topic, id) root.userAuthenticated(topic, id, password, pin)
} else { } else {
root.userAuthenticationFailed(topic, id) root.userAuthenticationFailed(topic, id)
} }