From b555d19a1ad772b6419367705a8ef0d65489f98a Mon Sep 17 00:00:00 2001 From: Alex Jbanca Date: Tue, 19 Nov 2024 14:14:59 +0200 Subject: [PATCH] feat(BC): Implement eth_signTypedData_v4 in BrowserConnect This commit renames the personalSign to Sign in nim and status-go to enable `eth_signTypedData_v4` signing. The sing request coming from the status-go API contains the signing method to be used by the client. Currently we're supporting personal sign and signTypedData_v4. The only difference between these two signing methods is the order of challenge and address in the `params` array. This is handled in the SappsConnectorSDK::buildSignRequest --- .../core/signals/remote_signals/connector.nim | 10 ++-- .../signals/remote_signals/signal_type.nim | 2 +- src/app/core/signals/signals_manager.nim | 2 +- .../shared_modules/connector/controller.nim | 27 +++++----- src/app_service/service/connector/service.nim | 22 ++++---- src/backend/connector.nim | 16 +++--- storybook/pages/DAppsWorkflowPage.qml | 5 +- .../services/dapps/DappsConnectorSDK.qml | 51 +++++++++++-------- .../shared/stores/BrowserConnectStore.qml | 26 +++++----- vendor/status-go | 2 +- 10 files changed, 89 insertions(+), 74 deletions(-) diff --git a/src/app/core/signals/remote_signals/connector.nim b/src/app/core/signals/remote_signals/connector.nim index 1802e9fe73..5cd75c2fbb 100644 --- a/src/app/core/signals/remote_signals/connector.nim +++ b/src/app/core/signals/remote_signals/connector.nim @@ -29,13 +29,14 @@ type ConnectorRevokeDAppPermissionSignal* = ref object of Signal name*: string iconUrl*: string -type ConnectorPersonalSignSignal* = ref object of Signal +type ConnectorSignSignal* = ref object of Signal url*: string name*: string iconUrl*: string requestId*: string challenge*: string address*: string + signMethod*: string proc fromEvent*(T: type ConnectorSendRequestAccountsSignal, event: JsonNode): ConnectorSendRequestAccountsSignal = result = ConnectorSendRequestAccountsSignal() @@ -67,11 +68,12 @@ proc fromEvent*(T: type ConnectorRevokeDAppPermissionSignal, event: JsonNode): C result.name = event["event"]{"name"}.getStr() result.iconUrl = event["event"]{"iconUrl"}.getStr() -proc fromEvent*(T: type ConnectorPersonalSignSignal, event: JsonNode): ConnectorPersonalSignSignal = - result = ConnectorPersonalSignSignal() +proc fromEvent*(T: type ConnectorSignSignal, event: JsonNode): ConnectorSignSignal = + result = ConnectorSignSignal() result.url = event["event"]{"url"}.getStr() result.name = event["event"]{"name"}.getStr() result.iconUrl = event["event"]{"iconUrl"}.getStr() result.requestId = event["event"]{"requestId"}.getStr() result.challenge = event["event"]{"challenge"}.getStr() - result.address = event["event"]{"address"}.getStr() \ No newline at end of file + result.address = event["event"]{"address"}.getStr() + result.signMethod = event["event"]{"method"}.getStr() \ No newline at end of file diff --git a/src/app/core/signals/remote_signals/signal_type.nim b/src/app/core/signals/remote_signals/signal_type.nim index 6ddc0fd0de..0c13b8802b 100644 --- a/src/app/core/signals/remote_signals/signal_type.nim +++ b/src/app/core/signals/remote_signals/signal_type.nim @@ -74,7 +74,7 @@ type SignalType* {.pure.} = enum ConnectorSendTransaction = "connector.sendTransaction" ConnectorGrantDAppPermission = "connector.dAppPermissionGranted" ConnectorRevokeDAppPermission = "connector.dAppPermissionRevoked" - ConnectorPersonalSign = "connector.personalSign" + ConnectorSign = "connector.Sign" Unknown proc event*(self:SignalType):string = diff --git a/src/app/core/signals/signals_manager.nim b/src/app/core/signals/signals_manager.nim index b5ad7a9f70..2d9c6c2964 100644 --- a/src/app/core/signals/signals_manager.nim +++ b/src/app/core/signals/signals_manager.nim @@ -145,7 +145,7 @@ QtObject: of SignalType.ConnectorSendTransaction: ConnectorSendTransactionSignal.fromEvent(jsonSignal) of SignalType.ConnectorGrantDAppPermission: ConnectorGrantDAppPermissionSignal.fromEvent(jsonSignal) of SignalType.ConnectorRevokeDAppPermission: ConnectorRevokeDAppPermissionSignal.fromEvent(jsonSignal) - of SignalType.ConnectorPersonalSign: ConnectorPersonalSignSignal.fromEvent(jsonSignal) + of SignalType.ConnectorSign: ConnectorSignSignal.fromEvent(jsonSignal) else: Signal() result.signalType = signalType diff --git a/src/app/modules/shared_modules/connector/controller.nim b/src/app/modules/shared_modules/connector/controller.nim index f9dcc68429..4d232f926d 100644 --- a/src/app/modules/shared_modules/connector/controller.nim +++ b/src/app/modules/shared_modules/connector/controller.nim @@ -13,7 +13,7 @@ const SIGNAL_CONNECTOR_SEND_REQUEST_ACCOUNTS* = "ConnectorSendRequestAccounts" const SIGNAL_CONNECTOR_EVENT_CONNECTOR_SEND_TRANSACTION* = "ConnectorSendTransaction" const SIGNAL_CONNECTOR_GRANT_DAPP_PERMISSION* = "ConnectorGrantDAppPermission" const SIGNAL_CONNECTOR_REVOKE_DAPP_PERMISSION* = "ConnectorRevokeDAppPermission" -const SIGNAL_CONNECTOR_PERSONAL_SIGN* = "ConnectorPersonalSign" +const SIGNAL_CONNECTOR_SIGN* = "ConnectorSign" logScope: topics = "connector-controller" @@ -32,14 +32,14 @@ QtObject: proc disconnected*(self: Controller, payload: string) {.signal.} proc sendTransaction*(self: Controller, requestId: string, payload: string) {.signal.} - proc personalSign(self: Controller, requestId: string, payload: string) {.signal.} + proc sign(self: Controller, requestId: string, payload: string) {.signal.} proc approveConnectResponse*(self: Controller, payload: string, error: bool) {.signal.} proc rejectConnectResponse*(self: Controller, payload: string, error: bool) {.signal.} proc approveTransactionResponse*(self: Controller, topic: string, requestId: string, error: bool) {.signal.} proc rejectTransactionResponse*(self: Controller, topic: string, requestId: string, error: bool) {.signal.} - proc approvePersonalSignResponse*(self: Controller, topic: string, requestId: string, error: bool) {.signal.} - proc rejectPersonalSignResponse*(self: Controller, topic: string, requestId: string, error: bool) {.signal.} + proc approveSignResponse*(self: Controller, topic: string, requestId: string, error: bool) {.signal.} + proc rejectSignResponse*(self: Controller, topic: string, requestId: string, error: bool) {.signal.} proc newController*(service: connector_service.Service, events: EventEmitter): Controller = new(result, delete) @@ -97,17 +97,18 @@ QtObject: controller.disconnected(dappInfo.toJson()) - result.events.on(SIGNAL_CONNECTOR_PERSONAL_SIGN) do(e: Args): - let params = ConnectorPersonalSignSignal(e) + result.events.on(SIGNAL_CONNECTOR_SIGN) do(e: Args): + let params = ConnectorSignSignal(e) let dappInfo = %*{ "icon": params.iconUrl, "name": params.name, "url": params.url, "challenge": params.challenge, "address": params.address, + "method": params.signMethod, } - controller.personalSign(params.requestId, dappInfo.toJson()) + controller.sign(params.requestId, dappInfo.toJson()) result.QObject.setup @@ -146,11 +147,11 @@ QtObject: proc getDApps*(self: Controller): string {.slot.} = return self.service.getDApps() - proc approvePersonalSigning*(self: Controller, sessionTopic: string, requestId: string, signature: string): bool {.slot.} = - result = self.service.approvePersonalSignRequest(requestId, signature) - self.approvePersonalSignResponse(sessionTopic, requestId, not result) + proc approveSigning*(self: Controller, sessionTopic: string, requestId: string, signature: string): bool {.slot.} = + result = self.service.approveSignRequest(requestId, signature) + self.approveSignResponse(sessionTopic, requestId, not result) - proc rejectPersonalSigning*(self: Controller, sessionTopic: string, requestId: string): bool {.slot.} = - result = self.service.rejectPersonalSigning(requestId) - self.rejectPersonalSignResponse(sessionTopic, requestId, not result) \ No newline at end of file + proc rejectSigning*(self: Controller, sessionTopic: string, requestId: string): bool {.slot.} = + result = self.service.rejectSigning(requestId) + self.rejectSignResponse(sessionTopic, requestId, not result) \ No newline at end of file diff --git a/src/app_service/service/connector/service.nim b/src/app_service/service/connector/service.nim index d617e30d89..4455e4305d 100644 --- a/src/app_service/service/connector/service.nim +++ b/src/app_service/service/connector/service.nim @@ -16,7 +16,7 @@ const SIGNAL_CONNECTOR_SEND_REQUEST_ACCOUNTS* = "ConnectorSendRequestAccounts" const SIGNAL_CONNECTOR_EVENT_CONNECTOR_SEND_TRANSACTION* = "ConnectorSendTransaction" const SIGNAL_CONNECTOR_GRANT_DAPP_PERMISSION* = "ConnectorGrantDAppPermission" const SIGNAL_CONNECTOR_REVOKE_DAPP_PERMISSION* = "ConnectorRevokeDAppPermission" -const SIGNAL_CONNECTOR_EVENT_CONNECTOR_PERSONAL_SIGN* = "ConnectorPersonalSign" +const SIGNAL_CONNECTOR_EVENT_CONNECTOR_SIGN* = "ConnectorSign" # Enum with events type Event* = enum @@ -84,17 +84,17 @@ QtObject: self.events.emit(SIGNAL_CONNECTOR_REVOKE_DAPP_PERMISSION, data) ) - self.events.on(SignalType.ConnectorPersonalSign.event, proc(e: Args) = + self.events.on(SignalType.ConnectorSign.event, proc(e: Args) = if self.eventHandler == nil: return - var data = ConnectorPersonalSignSignal(e) + var data = ConnectorSignSignal(e) if not data.requestId.len() == 0: - error "ConnectorPersonalSignSignal failed, requestId is empty" + error "ConnectorSignSignal failed, requestId is empty" return - self.events.emit(SIGNAL_CONNECTOR_EVENT_CONNECTOR_PERSONAL_SIGN, data) + self.events.emit(SIGNAL_CONNECTOR_EVENT_CONNECTOR_SIGN, data) ) proc registerEventsHandler*(self: Service, handler: EventHandlerFn) = @@ -165,17 +165,17 @@ QtObject: error "getDApps failed: ", err=e.msg return "[]" - proc approvePersonalSignRequest*(self: Service, requestId: string, signature: string): bool = + proc approveSignRequest*(self: Service, requestId: string, signature: string): bool = try: - var args = PersonalSignAcceptedArgs() + var args = SignAcceptedArgs() args.requestId = requestId args.signature = signature - return status_go.sendPersonalSignAcceptedFinishedRpc(args) + return status_go.sendSignAcceptedFinishedRpc(args) except Exception as e: - error "sendPersonalSigAcceptedFinishedRpc failed: ", err=e.msg + error "sendSigAcceptedFinishedRpc failed: ", err=e.msg return false - proc rejectPersonalSigning*(self: Service, requestId: string): bool = - rejectRequest(self, requestId, status_go.sendPersonalSignRejectedFinishedRpc, "sendPersonalSignRejectedFinishedRpc failed: ") \ No newline at end of file + proc rejectSigning*(self: Service, requestId: string): bool = + rejectRequest(self, requestId, status_go.sendSignRejectedFinishedRpc, "sendSignRejectedFinishedRpc failed: ") \ No newline at end of file diff --git a/src/backend/connector.nim b/src/backend/connector.nim index 4f084aa24f..64c097bd5c 100644 --- a/src/backend/connector.nim +++ b/src/backend/connector.nim @@ -23,7 +23,7 @@ type RejectedArgs* = ref object of RootObj type RecallDAppPermissionArgs* = ref object of RootObj dAppUrl* {.serializedFieldName("dAppUrl").}: string -type PersonalSignAcceptedArgs* = ref object of RootObj +type SignAcceptedArgs* = ref object of RootObj requestId* {.serializedFieldName("requestId").}: string signature* {.serializedFieldName("signature").}: string @@ -45,10 +45,10 @@ rpc(recallDAppPermission, "connector"): rpc(getPermittedDAppsList, "connector"): discard -rpc(personalSignAccepted, "connector"): - args: PersonalSignAcceptedArgs +rpc(signAccepted, "connector"): + args: SignAcceptedArgs -rpc(personalSignRejected, "connector"): +rpc(signRejected, "connector"): args: RejectedArgs proc isSuccessResponse(rpcResponse: RpcResponse[JsonNode]): bool = @@ -69,8 +69,8 @@ proc sendTransactionRejectedFinishedRpc*(args: RejectedArgs): bool = proc recallDAppPermissionFinishedRpc*(dAppUrl: string): bool = return isSuccessResponse(recallDAppPermission(dAppUrl)) -proc sendPersonalSignAcceptedFinishedRpc*(args: PersonalSignAcceptedArgs): bool = - return isSuccessResponse(personalSignAccepted(args)) +proc sendSignAcceptedFinishedRpc*(args: SignAcceptedArgs): bool = + return isSuccessResponse(signAccepted(args)) -proc sendPersonalSignRejectedFinishedRpc*(args: RejectedArgs): bool = - return isSuccessResponse(personalSignRejected(args)) \ No newline at end of file +proc sendSignRejectedFinishedRpc*(args: RejectedArgs): bool = + return isSuccessResponse(signRejected(args)) \ No newline at end of file diff --git a/storybook/pages/DAppsWorkflowPage.qml b/storybook/pages/DAppsWorkflowPage.qml index d0b9af6592..f2b7df9d61 100644 --- a/storybook/pages/DAppsWorkflowPage.qml +++ b/storybook/pages/DAppsWorkflowPage.qml @@ -378,7 +378,8 @@ Item { accountsModel: dappModule.accountsModel store: SharedStores.BrowserConnectStore { signal connectRequested(string requestId, string dappJson) - signal signRequested(string requestId, string requestJson) + signal sendTransaction(string requestId, string requestJson) + signal sign(string requestId, string dappJson) signal connected(string dappJson) signal disconnected(string dappJson) @@ -389,6 +390,8 @@ Item { signal approveTransactionResponse(string topic, string requestId, bool error) signal rejectTransactionResponse(string topic, string requestId, bool error) + signal approveSignResponse(string topic, string requestId, bool error) + signal rejectSignResponse(string topic, string requestId, bool error) } } store: SharedStores.DAppsStore { diff --git a/ui/app/AppLayouts/Wallet/services/dapps/DappsConnectorSDK.qml b/ui/app/AppLayouts/Wallet/services/dapps/DappsConnectorSDK.qml index 16ea4f89aa..4be459eed4 100644 --- a/ui/app/AppLayouts/Wallet/services/dapps/DappsConnectorSDK.qml +++ b/ui/app/AppLayouts/Wallet/services/dapps/DappsConnectorSDK.qml @@ -53,22 +53,22 @@ WalletConnectSDKBase { } } - function onPersonalSign(requestId, dappInfoString) { + function onSign(requestId, dappInfoString) { try { const dappInfo = JSON.parse(dappInfoString) const mainNet = SQUtils.ModelUtils.getByKey(root.networksModel, "layer", 1) if (!mainNet) { - root.store.rejectPersonalSign(requestId) - console.error("Mainnet not found - personal sign failed") + root.store.rejectSign(requestId) + console.error("Mainnet not found - sign failed") return } - const event = d.buildSignRequest(requestId, dappInfo.url, mainNet.chainId, dappInfo.challenge, dappInfo.address) + const event = d.buildSignRequest(requestId, dappInfo.url, mainNet.chainId, dappInfo.challenge, dappInfo.address, dappInfo.method) d.sessionRequests.set(requestId, event) root.sessionRequestEvent(event) } catch (e) { d.sessionRequests.delete(requestId) - root.store.rejectPersonalSign("", requestId) + root.store.rejectSign("", requestId) console.error("Failed to parse dappInfo for session request", e) } } @@ -111,21 +111,21 @@ WalletConnectSDKBase { } } - function onApprovePersonalSignResponse(topic, requestId, error) { + function onApproveSignResponse(topic, requestId, error) { try { - const errorStr = error ? "Faled to approve personal sign" : "" + const errorStr = error ? "Faled to approve sign" : "" root.sessionRequestUserAnswerResult(topic, requestId, true, errorStr) } catch (e) { - console.error("Failed to approve personal sign response", e) + console.error("Failed to approve sign response", e) } } - function onRejectPersonalSignResponse(topic, requestId, error) { + function onRejectSignResponse(topic, requestId, error) { try { - const errorStr = error ? "Faled to reject personal sign" : "" + const errorStr = error ? "Faled to reject sign" : "" root.sessionRequestUserAnswerResult(topic, requestId, false, errorStr) } catch (e) { - console.error("Failed to reject personal sign response", e) + console.error("Failed to reject sign response", e) } } } @@ -165,8 +165,9 @@ WalletConnectSDKBase { const event = d.sessionRequests.get(requestId) if (event.params.request.method === SessionRequest.methods.sendTransaction.name) { root.store.approveTransaction(topic, requestId, signature) - } else if (event.params.request.method === SessionRequest.methods.personalSign.name) { - root.store.approvePersonalSign(topic, requestId, signature) + } else if (event.params.request.method === SessionRequest.methods.personalSign.name || + event.params.request.method === SessionRequest.methods.signTypedData_v4.name) { + root.store.approveSign(topic, requestId, signature) } else { root.sessionRequestUserAnswerResult(topic, requestId, false, "Unknown request method") console.error("Unknown request method", event.params.request.method) @@ -182,8 +183,9 @@ WalletConnectSDKBase { const event = d.sessionRequests.get(requestId) if (event.params.request.method === SessionRequest.methods.sendTransaction.name) { root.store.rejectTransaction(topic, requestId, error) - } else if (event.params.request.method === SessionRequest.methods.personalSign.name) { - root.store.rejectPersonalSign(topic, requestId) + } else if (event.params.request.method === SessionRequest.methods.personalSign.name || + event.params.request.method === SessionRequest.methods.signTypedData_v4.name) { + root.store.rejectSign(topic, requestId) } else { root.sessionRequestUserAnswerResult(topic, requestId, false, "Unknown request method") console.error("Unknown request method", event.params.request.method) @@ -292,18 +294,25 @@ WalletConnectSDKBase { } } - function buildSignRequest(requestId, topic, chainId, challenge, address) { + function buildSignRequest(requestId, topic, chainId, challenge, address, method) { + let params = [] + if (method == SessionRequest.methods.personalSign.name) { + params = [challenge, address] + } else if (method == SessionRequest.methods.signTypedData_v4.name) { + params = [address, challenge] + } else { + console.error("Unknown sign method", method) + return + } + return { id: requestId, topic, params: { chainId: `eip155:${chainId}`, request: { - method: SessionRequest.methods.personalSign.name, - params: [ - challenge, - address - ] + method, + params } } } diff --git a/ui/imports/shared/stores/BrowserConnectStore.qml b/ui/imports/shared/stores/BrowserConnectStore.qml index 61f586a324..a527477af3 100644 --- a/ui/imports/shared/stores/BrowserConnectStore.qml +++ b/ui/imports/shared/stores/BrowserConnectStore.qml @@ -10,7 +10,7 @@ SQUtils.QObject { // Signals driven by the dApp signal connectRequested(string requestId, string dappJson) signal sendTransaction(string requestId, string requestJson) - signal personalSign(string requestId, string dappJson) + signal sign(string requestId, string dappJson) signal connected(string dappJson) signal disconnected(string dappJson) @@ -21,8 +21,8 @@ SQUtils.QObject { signal approveTransactionResponse(string topic, string requestId, bool error) signal rejectTransactionResponse(string topic, string requestId, bool error) - signal approvePersonalSignResponse(string topic, string requestId, bool error) - signal rejectPersonalSignResponse(string topic, string requestId, bool error) + signal approveSignResponse(string topic, string requestId, bool error) + signal rejectSignResponse(string topic, string requestId, bool error) function approveConnection(id, account, chainId) { return controller.approveConnection(id, account, chainId) @@ -48,12 +48,12 @@ SQUtils.QObject { return controller.getDApps() } - function approvePersonalSign(topic, requestId, signature) { - return controller.approvePersonalSigning(topic, requestId, signature) + function approveSign(topic, requestId, signature) { + return controller.approveSigning(topic, requestId, signature) } - function rejectPersonalSign(topic, requestId) { - return controller.rejectPersonalSigning(topic, requestId) + function rejectSign(topic, requestId) { + return controller.rejectSigning(topic, requestId) } Connections { @@ -67,8 +67,8 @@ SQUtils.QObject { root.sendTransaction(requestId, requestJson) } - function onPersonalSign(requestId, dappJson) { - root.personalSign(requestId, dappJson) + function onSign(requestId, dappJson) { + root.sign(requestId, dappJson) } function onConnected(dappJson) { @@ -95,12 +95,12 @@ SQUtils.QObject { root.rejectTransactionResponse(topic, requestId, error) } - function onApprovePersonalSignResponse(topic, requestId, error) { - root.approvePersonalSignResponse(topic, requestId, error) + function onApproveSignResponse(topic, requestId, error) { + root.approveSignResponse(topic, requestId, error) } - function onRejectPersonalSignResponse(topic, requestId, error) { - root.rejectPersonalSignResponse(topic, requestId, error) + function onRejectSignResponse(topic, requestId, error) { + root.rejectSignResponse(topic, requestId, error) } } } \ No newline at end of file diff --git a/vendor/status-go b/vendor/status-go index ed36d60540..c5dede93b0 160000 --- a/vendor/status-go +++ b/vendor/status-go @@ -1 +1 @@ -Subproject commit ed36d60540f4cc96101ca47bacdf841e38e40bfd +Subproject commit c5dede93b082532af770c47ed43f726af09a2576