fix: keycard signing integration into wallet connect flows (#16083)
Fixes: #15957
This commit is contained in:
parent
7dc08731f4
commit
5054d2963d
|
@ -172,7 +172,7 @@ proc newModule*(
|
||||||
result.collectibleDetailsController = collectible_detailsc.newController(int32(backend_collectibles.CollectiblesRequestID.WalletAccount), networkService, events)
|
result.collectibleDetailsController = collectible_detailsc.newController(int32(backend_collectibles.CollectiblesRequestID.WalletAccount), networkService, events)
|
||||||
result.filter = initFilter(result.controller)
|
result.filter = initFilter(result.controller)
|
||||||
|
|
||||||
result.walletConnectService = wc_service.newService(result.events, result.threadpool, settingsService, transactionService)
|
result.walletConnectService = wc_service.newService(result.events, result.threadpool, settingsService, transactionService, keycardService)
|
||||||
result.walletConnectController = wc_controller.newController(result.walletConnectService, walletAccountService)
|
result.walletConnectController = wc_controller.newController(result.walletConnectService, walletAccountService)
|
||||||
|
|
||||||
result.dappsConnectorService = connector_service.newService(result.events)
|
result.dappsConnectorService = connector_service.newService(result.events)
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import NimQml
|
import NimQml
|
||||||
import chronicles, times, json
|
import chronicles, times, json
|
||||||
|
|
||||||
|
import app/global/global_singleton
|
||||||
|
import app_service/common/utils
|
||||||
import app_service/service/wallet_connect/service as wallet_connect_service
|
import app_service/service/wallet_connect/service as wallet_connect_service
|
||||||
import app_service/service/wallet_account/service as wallet_account_service
|
import app_service/service/wallet_account/service as wallet_account_service
|
||||||
|
|
||||||
|
@ -9,6 +11,8 @@ import helpers
|
||||||
logScope:
|
logScope:
|
||||||
topics = "wallet-connect-controller"
|
topics = "wallet-connect-controller"
|
||||||
|
|
||||||
|
type
|
||||||
|
SigningCallbackFn* = proc(topic: string, id: string, keyUid: string, address: string, signature: string)
|
||||||
|
|
||||||
QtObject:
|
QtObject:
|
||||||
type
|
type
|
||||||
|
@ -27,6 +31,10 @@ QtObject:
|
||||||
|
|
||||||
result.QObject.setup
|
result.QObject.setup
|
||||||
|
|
||||||
|
## signals emitted by this controller
|
||||||
|
proc userAuthenticationResult*(self: Controller, topic: string, id: string, error: bool, password: string, pin: string, payload: string) {.signal.}
|
||||||
|
proc signingResultReceived*(self: Controller, topic: string, id: string, data: string) {.signal.}
|
||||||
|
|
||||||
proc addWalletConnectSession*(self: Controller, session_json: string): bool {.slot.} =
|
proc addWalletConnectSession*(self: Controller, session_json: string): bool {.slot.} =
|
||||||
return self.service.addSession(session_json)
|
return self.service.addSession(session_json)
|
||||||
|
|
||||||
|
@ -41,7 +49,7 @@ QtObject:
|
||||||
# Emits signal dappsListReceived with the list of dApps
|
# Emits signal dappsListReceived with the list of dApps
|
||||||
proc getDapps*(self: Controller): bool {.slot.} =
|
proc getDapps*(self: Controller): bool {.slot.} =
|
||||||
let res = self.service.getDapps()
|
let res = self.service.getDapps()
|
||||||
if res == "":
|
if res.len == 0:
|
||||||
return false
|
return false
|
||||||
else:
|
else:
|
||||||
self.dappsListReceived(res)
|
self.dappsListReceived(res)
|
||||||
|
@ -61,32 +69,128 @@ QtObject:
|
||||||
self.activeSessionsReceived(resultStr)
|
self.activeSessionsReceived(resultStr)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
proc userAuthenticationResult*(self: Controller, topic: string, id: string, error: bool, password: string, pin: string, payload: 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, payload: string): bool {.slot.} =
|
proc authenticateUser*(self: Controller, topic: string, id: string, address: string, payload: string): bool {.slot.} =
|
||||||
let acc = self.walletAccountService.getAccountByAddress(address)
|
let keypair = self.walletAccountService.getKeypairByAccountAddress(address)
|
||||||
if acc.keyUid == "":
|
if keypair.isNil:
|
||||||
return false
|
return false
|
||||||
|
var keyUid = singletonInstance.userProfile.getKeyUid()
|
||||||
return self.service.authenticateUser(acc.keyUid, proc(password: string, pin: string, success: bool) =
|
if keypair.migratedToKeycard():
|
||||||
self.userAuthenticationResult(topic, id, success, password, pin, payload)
|
keyUid = keypair.keyUid
|
||||||
|
return self.service.authenticateUser(keyUid, proc(receivedKeyUid: string, password: string, pin: string) =
|
||||||
|
if receivedKeyUid.len == 0 or receivedKeyUid != keyUid or password.len == 0:
|
||||||
|
self.userAuthenticationResult(topic, id, false, "", "", "")
|
||||||
|
return
|
||||||
|
self.userAuthenticationResult(topic, id, true, password, pin, payload)
|
||||||
)
|
)
|
||||||
|
|
||||||
proc signMessageUnsafe*(self: Controller, address: string, password: string, message: string): string {.slot.} =
|
proc signOnKeycard(self: Controller, address: string): bool =
|
||||||
return self.service.signMessageUnsafe(address, password, message)
|
let keypair = self.walletAccountService.getKeypairByAccountAddress(address)
|
||||||
|
if keypair.isNil:
|
||||||
|
raise newException(CatchableError, "cannot resolve keypair for address: " & address)
|
||||||
|
return keypair.migratedToKeycard()
|
||||||
|
|
||||||
proc signMessage*(self: Controller, address: string, password: string, message: string): string {.slot.} =
|
proc preparePassword(self: Controller, password: string): string =
|
||||||
return self.service.signMessage(address, password, message)
|
if singletonInstance.userProfile.getIsKeycardUser():
|
||||||
|
return password
|
||||||
|
return hashPassword(password)
|
||||||
|
|
||||||
proc safeSignTypedData*(self: Controller, address: string, password: string, typedDataJson: string, chainId: int, legacy: bool): string {.slot.} =
|
proc signMessageWithCallback(self: Controller, topic: string, id: string, address: string, message: string, password: string,
|
||||||
return self.service.safeSignTypedData(address, password, typedDataJson, chainId, legacy)
|
pin: string, callback: SigningCallbackFn) =
|
||||||
|
var res = ""
|
||||||
|
try:
|
||||||
|
if message.len == 0:
|
||||||
|
raise newException(CatchableError, "message is empty")
|
||||||
|
if self.signOnKeycard(address):
|
||||||
|
let acc = self.walletAccountService.getAccountByAddress(address)
|
||||||
|
if acc.isNil:
|
||||||
|
raise newException(CatchableError, "cannot resolve account for address: " & address)
|
||||||
|
if not self.service.runSigningOnKeycard(
|
||||||
|
acc.keyUid,
|
||||||
|
acc.path,
|
||||||
|
singletonInstance.utils.removeHexPrefix(message),
|
||||||
|
pin,
|
||||||
|
proc(keyUid: string, signature: string) =
|
||||||
|
if keyUid.len == 0 or keyUid != acc.keyUid or signature.len == 0:
|
||||||
|
raise newException(CatchableError, "keycard signing failed")
|
||||||
|
callback(topic, id, keyUid, address, signature)
|
||||||
|
):
|
||||||
|
raise newException(CatchableError, "runSigningOnKeycard failed")
|
||||||
|
debug "signMessageWithCallback: signing on keycard started successfully"
|
||||||
|
return
|
||||||
|
let finalPassword = self.preparePassword(password)
|
||||||
|
res = self.service.signMessage(address, finalPassword, message)
|
||||||
|
except Exception as e:
|
||||||
|
error "signMessageWithCallback failed: ", msg=e.msg
|
||||||
|
callback(topic, id, "", address, res)
|
||||||
|
|
||||||
proc signTransaction*(self: Controller, address: string, chainId: int, password: string, txJson: string): string {.slot.} =
|
proc signMessage*(self: Controller, topic: string, id: string, address: string, message: string, password: string, pin: string) {.slot.} =
|
||||||
return self.service.signTransaction(address, chainId, password, txJson)
|
var res = ""
|
||||||
|
try:
|
||||||
|
if message.len == 0:
|
||||||
|
raise newException(CatchableError, "message is empty")
|
||||||
|
let hashedMessage = self.service.hashMessageEIP191(message)
|
||||||
|
if hashedMessage.len == 0:
|
||||||
|
raise newException(CatchableError, "hashMessageEIP191 failed")
|
||||||
|
self.signMessageWithCallback(topic, id, address, hashedMessage, password, pin,
|
||||||
|
proc (topic: string, id: string, keyUid: string, address: string, signature: string) =
|
||||||
|
self.signingResultReceived(topic, id, signature)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
error "signMessage failed: ", msg=e.msg
|
||||||
|
self.signingResultReceived(topic, id, res)
|
||||||
|
|
||||||
proc sendTransaction*(self: Controller, address: string, chainId: int, password: string, txJson: string): string {.slot.} =
|
proc signMessageUnsafe*(self: Controller, topic: string, id: string, address: string, message: string, password: string, pin: string) {.slot.} =
|
||||||
return self.service.sendTransaction(address, chainId, password, txJson)
|
self.signMessage(topic, id, address, message, password, pin)
|
||||||
|
|
||||||
|
proc safeSignTypedData*(self: Controller, topic: string, id: string, address: string, typedDataJson: string, chainId: int, legacy: bool,
|
||||||
|
password: string, pin: string): string {.slot.} =
|
||||||
|
var res = ""
|
||||||
|
try:
|
||||||
|
var dataToSign = ""
|
||||||
|
if legacy:
|
||||||
|
dataToSign = self.service.hashTypedData(typedDataJson)
|
||||||
|
else:
|
||||||
|
dataToSign = self.service.hashTypedDataV4(typedDataJson)
|
||||||
|
if dataToSign.len == 0:
|
||||||
|
raise newException(CatchableError, "hashTypedData failed")
|
||||||
|
self.signMessageWithCallback(topic, id, address, dataToSign, password, pin,
|
||||||
|
proc (topic: string, id: string, keyUid: string, address: string, signature: string) =
|
||||||
|
self.signingResultReceived(topic, id, signature)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
error "safeSignTypedData failed: ", msg=e.msg
|
||||||
|
self.signingResultReceived(topic, id, res)
|
||||||
|
|
||||||
|
proc signTransaction*(self: Controller, topic: string, id: string, address: string, chainId: int, txJson: string, password: string, pin: string) {.slot.} =
|
||||||
|
var res = ""
|
||||||
|
try:
|
||||||
|
let (txHash, txData) = self.service.buildTransaction(chainId, txJson)
|
||||||
|
if txHash.len == 0 or txData.isNil:
|
||||||
|
raise newException(CatchableError, "building transaction failed")
|
||||||
|
self.signMessageWithCallback(topic, id, address, txHash, password, pin,
|
||||||
|
proc (topic: string, id: string, keyUid: string, address: string, signature: string) =
|
||||||
|
let rawTx = self.service.buildRawTransaction(chainId, $txData, signature)
|
||||||
|
self.signingResultReceived(topic, id, rawTx)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
error "signTransaction failed: ", msg=e.msg
|
||||||
|
self.signingResultReceived(topic, id, res)
|
||||||
|
|
||||||
|
proc sendTransaction*(self: Controller, topic: string, id: string, address: string, chainId: int, txJson: string, password: string, pin: string) {.slot.} =
|
||||||
|
var res = ""
|
||||||
|
try:
|
||||||
|
let (txHash, txData) = self.service.buildTransaction(chainId, txJson)
|
||||||
|
if txHash.len == 0 or txData.isNil:
|
||||||
|
raise newException(CatchableError, "building transaction failed")
|
||||||
|
self.signMessageWithCallback(topic, id, address, txHash, password, pin,
|
||||||
|
proc (topic: string, id: string, keyUid: string, address: string, signature: string) =
|
||||||
|
let signedTxHash = self.service.sendTransactionWithSignature(chainId, $txData, signature)
|
||||||
|
self.signingResultReceived(topic, id, signedTxHash)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
error "sendTransaction failed: ", msg=e.msg
|
||||||
|
self.signingResultReceived(topic, id, res)
|
||||||
|
|
||||||
proc getEstimatedTime(self: Controller, chainId: int, maxFeePerGasHex: string): int {.slot.} =
|
proc getEstimatedTime(self: Controller, chainId: int, maxFeePerGasHex: string): int {.slot.} =
|
||||||
return self.service.getEstimatedTime(chainId, maxFeePerGasHex).int
|
return self.service.getEstimatedTime(chainId, maxFeePerGasHex).int
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import NimQml, chronicles, times, json
|
import NimQml, chronicles, times, json, uuids
|
||||||
import strutils
|
import strutils
|
||||||
|
|
||||||
import backend/wallet_connect as status_go
|
import backend/wallet_connect as status_go
|
||||||
|
@ -8,6 +8,7 @@ import app_service/service/settings/service as settings_service
|
||||||
import app_service/common/wallet_constants
|
import app_service/common/wallet_constants
|
||||||
from app_service/service/transaction/dto import PendingTransactionTypeDto
|
from app_service/service/transaction/dto import PendingTransactionTypeDto
|
||||||
import app_service/service/transaction/service as tr
|
import app_service/service/transaction/service as tr
|
||||||
|
import app_service/service/keycard/service as keycard_service
|
||||||
|
|
||||||
import app/global/global_singleton
|
import app/global/global_singleton
|
||||||
|
|
||||||
|
@ -25,7 +26,8 @@ logScope:
|
||||||
const UNIQUE_WALLET_CONNECT_MODULE_IDENTIFIER* = "WalletSection-WCModule"
|
const UNIQUE_WALLET_CONNECT_MODULE_IDENTIFIER* = "WalletSection-WCModule"
|
||||||
|
|
||||||
type
|
type
|
||||||
AuthenticationResponseFn* = proc(password: string, pin: string, success: bool)
|
AuthenticationResponseFn* = proc(keyUid: string, password: string, pin: string)
|
||||||
|
SignResponseFn* = proc(keyUid: string, signature: string)
|
||||||
|
|
||||||
QtObject:
|
QtObject:
|
||||||
type Service* = ref object of QObject
|
type Service* = ref object of QObject
|
||||||
|
@ -33,8 +35,11 @@ QtObject:
|
||||||
threadpool: ThreadPool
|
threadpool: ThreadPool
|
||||||
settingsService: settings_service.Service
|
settingsService: settings_service.Service
|
||||||
transactions: tr.Service
|
transactions: tr.Service
|
||||||
|
keycardService: keycard_service.Service
|
||||||
|
|
||||||
|
connectionKeycardResponse: UUID
|
||||||
authenticationCallback: AuthenticationResponseFn
|
authenticationCallback: AuthenticationResponseFn
|
||||||
|
signCallback: SignResponseFn
|
||||||
|
|
||||||
proc delete*(self: Service) =
|
proc delete*(self: Service) =
|
||||||
self.QObject.delete
|
self.QObject.delete
|
||||||
|
@ -44,6 +49,7 @@ QtObject:
|
||||||
threadpool: ThreadPool,
|
threadpool: ThreadPool,
|
||||||
settingsService: settings_service.Service,
|
settingsService: settings_service.Service,
|
||||||
transactions: tr.Service,
|
transactions: tr.Service,
|
||||||
|
keycardService: keycard_service.Service,
|
||||||
): Service =
|
): Service =
|
||||||
new(result, delete)
|
new(result, delete)
|
||||||
result.QObject.setup
|
result.QObject.setup
|
||||||
|
@ -52,25 +58,19 @@ QtObject:
|
||||||
result.threadpool = threadpool
|
result.threadpool = threadpool
|
||||||
result.settingsService = settings_service
|
result.settingsService = settings_service
|
||||||
result.transactions = transactions
|
result.transactions = transactions
|
||||||
|
result.keycardService = keycardService
|
||||||
|
|
||||||
proc init*(self: Service) =
|
proc init*(self: Service) =
|
||||||
self.events.on(SIGNAL_SHARED_KEYCARD_MODULE_USER_AUTHENTICATED) do(e: Args):
|
self.events.on(SIGNAL_SHARED_KEYCARD_MODULE_USER_AUTHENTICATED) do(e: Args):
|
||||||
let args = SharedKeycarModuleArgs(e)
|
let args = SharedKeycarModuleArgs(e)
|
||||||
if args.uniqueIdentifier != UNIQUE_WALLET_CONNECT_MODULE_IDENTIFIER:
|
if args.uniqueIdentifier != UNIQUE_WALLET_CONNECT_MODULE_IDENTIFIER:
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.authenticationCallback == nil:
|
if self.authenticationCallback == nil:
|
||||||
error "unexpected user authenticated event; no callback set"
|
error "unexpected user authenticated event; no callback set"
|
||||||
return
|
return
|
||||||
defer:
|
defer:
|
||||||
self.authenticationCallback = nil
|
self.authenticationCallback = nil
|
||||||
|
self.authenticationCallback(args.keyUid, args.password, args.pin)
|
||||||
if args.password == "" and args.pin == "":
|
|
||||||
info "fail to authenticate user"
|
|
||||||
self.authenticationCallback("", "", false)
|
|
||||||
return
|
|
||||||
|
|
||||||
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
|
||||||
|
@ -114,105 +114,104 @@ QtObject:
|
||||||
let testChains = self.settingsService.areTestNetworksEnabled()
|
let testChains = self.settingsService.areTestNetworksEnabled()
|
||||||
# TODO #14588: call it async
|
# TODO #14588: call it async
|
||||||
return status_go.getDapps(validAtEpoch, testChains)
|
return status_go.getDapps(validAtEpoch, testChains)
|
||||||
|
|
||||||
proc getActiveSessions*(self: Service, validAtTimestamp: int64): JsonNode =
|
proc getActiveSessions*(self: Service, validAtTimestamp: int64): JsonNode =
|
||||||
# TODO #14588: call it async
|
# TODO #14588: call it async
|
||||||
return status_go.getActiveSessions(validAtTimestamp)
|
return status_go.getActiveSessions(validAtTimestamp)
|
||||||
|
|
||||||
|
|
||||||
# Will fail if another authentication is in progress
|
# Will fail if another authentication is in progress
|
||||||
proc authenticateUser*(self: Service, keyUid: string, callback: AuthenticationResponseFn): bool =
|
proc authenticateUser*(self: Service, keyUid: string, callback: AuthenticationResponseFn): bool =
|
||||||
if self.authenticationCallback != nil:
|
if self.authenticationCallback != nil:
|
||||||
return false
|
return false
|
||||||
self.authenticationCallback = callback
|
self.authenticationCallback = callback
|
||||||
|
|
||||||
let data = SharedKeycarModuleAuthenticationArgs(
|
let data = SharedKeycarModuleAuthenticationArgs(
|
||||||
uniqueIdentifier: UNIQUE_WALLET_CONNECT_MODULE_IDENTIFIER,
|
uniqueIdentifier: UNIQUE_WALLET_CONNECT_MODULE_IDENTIFIER,
|
||||||
keyUid: keyUid)
|
keyUid: keyUid)
|
||||||
|
|
||||||
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 signMessageUnsafe*(self: Service, address: string, password: string, message: string): string =
|
proc hashMessageEIP191*(self: Service, message: string): string =
|
||||||
return status_go.signMessageUnsafe(address, password, message)
|
let hashRes = hashMessageEIP191("0x" & toHex(message))
|
||||||
|
if not hashRes.error.isNil:
|
||||||
|
error "hashMessageEIP191 failed: ", msg=hashRes.error.message
|
||||||
|
return ""
|
||||||
|
return hashRes.result.getStr()
|
||||||
|
|
||||||
proc signMessage*(self: Service, address: string, password: string, message: string): string =
|
proc signMessage*(self: Service, address: string, hashedPassword: string, hashedMessage: string): string =
|
||||||
return status_go.signMessage(address, password, message)
|
var signMsgRes: JsonNode
|
||||||
|
let err = wallet.signMessage(signMsgRes,
|
||||||
|
hashedMessage,
|
||||||
|
address,
|
||||||
|
hashedPassword)
|
||||||
|
if err.len > 0:
|
||||||
|
error "status-go - wallet_signMessage failed", err=err
|
||||||
|
return signMsgRes.getStr
|
||||||
|
|
||||||
proc safeSignTypedData*(self: Service, address: string, password: string, typedDataJson: string, chainId: int, legacy: bool): string =
|
proc buildTransaction*(self: Service, chainId: int, txJson: string): tuple[txToSign: string, txData: JsonNode] =
|
||||||
return status_go.safeSignTypedData(address, password, typedDataJson, chainId, legacy)
|
|
||||||
|
|
||||||
proc signTransaction*(self: Service, address: string, chainId: int, password: string, txJson: string): string =
|
|
||||||
var buildTxResponse: JsonNode
|
var buildTxResponse: JsonNode
|
||||||
var err = wallet.buildTransaction(buildTxResponse, chainId, txJson)
|
var err = wallet.buildTransaction(buildTxResponse, chainId, txJson)
|
||||||
if err.len > 0:
|
if err.len > 0:
|
||||||
error "status-go - wallet_buildTransaction failed", err=err
|
error "status-go - wallet_buildTransaction failed", err=err
|
||||||
return ""
|
return
|
||||||
if buildTxResponse.isNil or buildTxResponse.kind != JsonNodeKind.JObject or
|
if buildTxResponse.isNil or buildTxResponse.kind != JsonNodeKind.JObject or
|
||||||
not buildTxResponse.hasKey("txArgs") or not buildTxResponse.hasKey("messageToSign"):
|
not buildTxResponse.hasKey("txArgs") or not buildTxResponse.hasKey("messageToSign"):
|
||||||
error "unexpected wallet_buildTransaction response"
|
error "unexpected wallet_buildTransaction response"
|
||||||
return ""
|
return
|
||||||
var txToBeSigned = buildTxResponse["messageToSign"].getStr
|
result.txToSign = buildTxResponse["messageToSign"].getStr
|
||||||
if txToBeSigned.len != wallet_constants.TX_HASH_LEN_WITH_PREFIX:
|
if result.txToSign.len != wallet_constants.TX_HASH_LEN_WITH_PREFIX:
|
||||||
error "unexpected tx hash length"
|
error "unexpected tx hash length"
|
||||||
return ""
|
return
|
||||||
|
result.txData = buildTxResponse["txArgs"]
|
||||||
var signMsgRes: JsonNode
|
|
||||||
err = wallet.signMessage(signMsgRes,
|
|
||||||
txToBeSigned,
|
|
||||||
address,
|
|
||||||
hashPassword(password))
|
|
||||||
if err.len > 0:
|
|
||||||
error "status-go - wallet_signMessage failed", err=err
|
|
||||||
let signature = singletonInstance.utils.removeHexPrefix(signMsgRes.getStr)
|
|
||||||
|
|
||||||
|
proc buildRawTransaction*(self: Service, chainId: int, txData: string, signature: string): string =
|
||||||
var txResponse: JsonNode
|
var txResponse: JsonNode
|
||||||
err = wallet.buildRawTransaction(txResponse, chainId, $buildTxResponse["txArgs"], signature)
|
var err = wallet.buildRawTransaction(txResponse, chainId, txData, signature)
|
||||||
if err.len > 0:
|
if err.len > 0:
|
||||||
error "status-go - wallet_buildRawTransaction failed", err=err
|
error "status-go - wallet_buildRawTransaction failed", err=err
|
||||||
return ""
|
return
|
||||||
if txResponse.isNil or txResponse.kind != JsonNodeKind.JObject or not txResponse.hasKey("rawTx"):
|
if txResponse.isNil or txResponse.kind != JsonNodeKind.JObject or not txResponse.hasKey("rawTx"):
|
||||||
error "unexpected buildRawTransaction response"
|
error "unexpected wallet_buildRawTransaction response"
|
||||||
return ""
|
return
|
||||||
|
|
||||||
return txResponse["rawTx"].getStr
|
return txResponse["rawTx"].getStr
|
||||||
|
|
||||||
proc sendTransaction*(self: Service, address: string, chainId: int, password: string, txJson: string): string =
|
proc sendTransactionWithSignature*(self: Service, chainId: int, txData: string, signature: string): string =
|
||||||
var buildTxResponse: JsonNode
|
|
||||||
var err = wallet.buildTransaction(buildTxResponse, chainId, txJson)
|
|
||||||
if err.len > 0:
|
|
||||||
error "status-go - wallet_buildTransaction failed", err=err
|
|
||||||
return ""
|
|
||||||
if buildTxResponse.isNil or buildTxResponse.kind != JsonNodeKind.JObject or
|
|
||||||
not buildTxResponse.hasKey("txArgs") or not buildTxResponse.hasKey("messageToSign"):
|
|
||||||
error "unexpected wallet_buildTransaction response"
|
|
||||||
return ""
|
|
||||||
var txToBeSigned = buildTxResponse["messageToSign"].getStr
|
|
||||||
if txToBeSigned.len != wallet_constants.TX_HASH_LEN_WITH_PREFIX:
|
|
||||||
error "unexpected tx hash length"
|
|
||||||
return ""
|
|
||||||
|
|
||||||
var signMsgRes: JsonNode
|
|
||||||
err = wallet.signMessage(signMsgRes,
|
|
||||||
txToBeSigned,
|
|
||||||
address,
|
|
||||||
hashPassword(password))
|
|
||||||
if err.len > 0:
|
|
||||||
error "status-go - wallet_signMessage failed", err=err
|
|
||||||
let signature = singletonInstance.utils.removeHexPrefix(signMsgRes.getStr)
|
|
||||||
|
|
||||||
var txResponse: JsonNode
|
var txResponse: JsonNode
|
||||||
err = wallet.sendTransactionWithSignature(txResponse, chainId,
|
let err = wallet.sendTransactionWithSignature(txResponse,
|
||||||
$PendingTransactionTypeDto.WalletConnectTransfer, $buildTxResponse["txArgs"], signature)
|
chainId,
|
||||||
|
$PendingTransactionTypeDto.WalletConnectTransfer,
|
||||||
|
txData,
|
||||||
|
singletonInstance.utils.removeHexPrefix(signature))
|
||||||
if err.len > 0:
|
if err.len > 0:
|
||||||
error "status-go - sendTransactionWithSignature failed", err=err
|
error "status-go - sendTransactionWithSignature failed", err=err
|
||||||
return ""
|
return ""
|
||||||
if txResponse.isNil or txResponse.kind != JsonNodeKind.JString:
|
if txResponse.isNil or txResponse.kind != JsonNodeKind.JString:
|
||||||
error "unexpected sendTransactionWithSignature response"
|
error "unexpected sendTransactionWithSignature response"
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
return txResponse.getStr
|
return txResponse.getStr
|
||||||
|
|
||||||
|
proc hashTypedData*(self: Service, data: string): string =
|
||||||
|
var response: JsonNode
|
||||||
|
let err = wallet.hashTypedData(response, data)
|
||||||
|
if err.len > 0:
|
||||||
|
error "status-go - hashTypedData failed", err=err
|
||||||
|
return ""
|
||||||
|
if response.isNil or response.kind != JsonNodeKind.JString:
|
||||||
|
error "unexpected hashTypedData response"
|
||||||
|
return ""
|
||||||
|
return response.getStr
|
||||||
|
|
||||||
|
proc hashTypedDataV4*(self: Service, data: string): string =
|
||||||
|
var response: JsonNode
|
||||||
|
let err = wallet.hashTypedDataV4(response, data)
|
||||||
|
if err.len > 0:
|
||||||
|
error "status-go - hashTypedDataV4 failed", err=err
|
||||||
|
return ""
|
||||||
|
if response.isNil or response.kind != JsonNodeKind.JString:
|
||||||
|
error "unexpected hashTypedDataV4 response"
|
||||||
|
return ""
|
||||||
|
return response.getStr
|
||||||
|
|
||||||
# empty maxFeePerGasHex will fetch the current chain's maxFeePerGas
|
# empty maxFeePerGasHex will fetch the current chain's maxFeePerGas
|
||||||
proc getEstimatedTime*(self: Service, chainId: int, maxFeePerGasHex: string): EstimatedTime =
|
proc getEstimatedTime*(self: Service, chainId: int, maxFeePerGasHex: string): EstimatedTime =
|
||||||
var maxFeePerGas: float64
|
var maxFeePerGas: float64
|
||||||
|
@ -237,4 +236,41 @@ QtObject:
|
||||||
return self.transactions.getEstimatedTime(chainId, $(maxFeePerGas))
|
return self.transactions.getEstimatedTime(chainId, $(maxFeePerGas))
|
||||||
|
|
||||||
proc getSuggestedFees*(self: Service, chainId: int): SuggestedFeesDto =
|
proc getSuggestedFees*(self: Service, chainId: int): SuggestedFeesDto =
|
||||||
return self.transactions.suggestedFees(chainId)
|
return self.transactions.suggestedFees(chainId)
|
||||||
|
|
||||||
|
proc disconnectKeycardReponseSignal(self: Service) =
|
||||||
|
self.events.disconnect(self.connectionKeycardResponse)
|
||||||
|
|
||||||
|
proc connectKeycardReponseSignal(self: Service) =
|
||||||
|
self.connectionKeycardResponse = self.events.onWithUUID(SIGNAL_KEYCARD_RESPONSE) do(e: Args):
|
||||||
|
let args = KeycardLibArgs(e)
|
||||||
|
self.disconnectKeycardReponseSignal()
|
||||||
|
if self.signCallback == nil:
|
||||||
|
error "unexpected user authenticated event; no callback set"
|
||||||
|
return
|
||||||
|
defer:
|
||||||
|
self.signCallback = nil
|
||||||
|
let currentFlow = self.keycardService.getCurrentFlow()
|
||||||
|
if currentFlow != KCSFlowType.Sign:
|
||||||
|
error "unexpected keycard flow type: ", currentFlow
|
||||||
|
self.signCallback("", "")
|
||||||
|
return
|
||||||
|
let signature = "0x" &
|
||||||
|
singletonInstance.utils.removeHexPrefix(args.flowEvent.txSignature.r) &
|
||||||
|
singletonInstance.utils.removeHexPrefix(args.flowEvent.txSignature.s) &
|
||||||
|
singletonInstance.utils.removeHexPrefix(args.flowEvent.txSignature.v)
|
||||||
|
self.signCallback(args.flowEvent.keyUid, signature)
|
||||||
|
|
||||||
|
proc cancelCurrentFlow*(self: Service) =
|
||||||
|
self.keycardService.cancelCurrentFlow()
|
||||||
|
|
||||||
|
proc runSigningOnKeycard*(self: Service, keyUid: string, path: string, hashedMessageToSign: string, pin: string, callback: SignResponseFn): bool =
|
||||||
|
if pin.len == 0:
|
||||||
|
return false
|
||||||
|
if self.signCallback != nil:
|
||||||
|
return false
|
||||||
|
self.signCallback = callback
|
||||||
|
self.cancelCurrentFlow()
|
||||||
|
self.connectKeycardReponseSignal()
|
||||||
|
self.keycardService.startSignFlow(path, hashedMessageToSign, pin)
|
||||||
|
return true
|
|
@ -1,7 +1,9 @@
|
||||||
import json, logging
|
import json, json_serialization, logging
|
||||||
import core, response_type
|
import core, response_type
|
||||||
from ./gen import rpc
|
from ./gen import rpc
|
||||||
|
|
||||||
|
import status_go
|
||||||
|
|
||||||
rpc(signMessage, "wallet"):
|
rpc(signMessage, "wallet"):
|
||||||
message: string
|
message: string
|
||||||
address: string
|
address: string
|
||||||
|
@ -92,3 +94,21 @@ proc sendTransactionWithSignature*(resultOut: var JsonNode, chainId: int, txType
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
warn e.msg
|
warn e.msg
|
||||||
return e.msg
|
return e.msg
|
||||||
|
|
||||||
|
proc hashTypedData*(resultOut: var JsonNode, data: string): string =
|
||||||
|
try:
|
||||||
|
let rawResponse = status_go.hashTypedData(data)
|
||||||
|
var response = Json.decode(rawResponse, RpcResponse[JsonNode])
|
||||||
|
return prepareResponse(resultOut, response)
|
||||||
|
except Exception as e:
|
||||||
|
warn e.msg
|
||||||
|
return e.msg
|
||||||
|
|
||||||
|
proc hashTypedDataV4*(resultOut: var JsonNode, data: string): string =
|
||||||
|
try:
|
||||||
|
let rawResponse = status_go.hashTypedDataV4(data)
|
||||||
|
var response = Json.decode(rawResponse, RpcResponse[JsonNode])
|
||||||
|
return prepareResponse(resultOut, response)
|
||||||
|
except Exception as e:
|
||||||
|
warn e.msg
|
||||||
|
return e.msg
|
|
@ -1,15 +1,8 @@
|
||||||
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/wallet
|
|
||||||
|
|
||||||
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
|
||||||
|
@ -23,13 +16,6 @@ rpc(getWalletConnectActiveSessions, "wallet"):
|
||||||
rpc(hashMessageEIP191, "wallet"):
|
rpc(hashMessageEIP191, "wallet"):
|
||||||
message: string
|
message: string
|
||||||
|
|
||||||
rpc(safeSignTypedDataForDApps, "wallet"):
|
|
||||||
typedJson: string
|
|
||||||
address: string
|
|
||||||
password: string
|
|
||||||
chainId: int
|
|
||||||
legacy: bool
|
|
||||||
|
|
||||||
proc isSuccessResponse(rpcResponse: RpcResponse[JsonNode]): bool =
|
proc isSuccessResponse(rpcResponse: RpcResponse[JsonNode]): bool =
|
||||||
return rpcResponse.error.isNil
|
return rpcResponse.error.isNil
|
||||||
|
|
||||||
|
@ -53,7 +39,7 @@ proc disconnectSession*(topic: string): bool =
|
||||||
proc getActiveSessions*(validAtTimestamp: int64): JsonNode =
|
proc getActiveSessions*(validAtTimestamp: int64): JsonNode =
|
||||||
try:
|
try:
|
||||||
let rpcRes = getWalletConnectActiveSessions(validAtTimestamp)
|
let rpcRes = getWalletConnectActiveSessions(validAtTimestamp)
|
||||||
|
|
||||||
if(not isSuccessResponse(rpcRes)):
|
if(not isSuccessResponse(rpcRes)):
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
@ -83,47 +69,4 @@ proc getDapps*(validAtEpoch: int64, testChains: bool): string =
|
||||||
return if jsonArray != "null": jsonArray else: "[]"
|
return if jsonArray != "null": jsonArray else: "[]"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error "GetWalletConnectDapps failed: ", "msg", e.msg
|
error "GetWalletConnectDapps failed: ", "msg", e.msg
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
proc signMessageUnsafe*(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:
|
|
||||||
error "status_go.signMessage failed: ", "msg", e.msg
|
|
||||||
return ""
|
|
||||||
|
|
||||||
proc signMessage*(address: string, password: string, message: string): string =
|
|
||||||
try:
|
|
||||||
let hashRes = hashMessageEIP191("0x" & toHex(message))
|
|
||||||
if not isSuccessResponse(hashRes):
|
|
||||||
error "wallet_hashMessageEIP191 failed: ", "msg", hashRes.error.message
|
|
||||||
return ""
|
|
||||||
|
|
||||||
let safeHash = hashRes.result.getStr()
|
|
||||||
let signRes = wallet.signMessage(safeHash, address, hashPassword(password))
|
|
||||||
if not isSuccessResponse(signRes):
|
|
||||||
error "wallet_signMessage failed: ", "msg", signRes.error.message
|
|
||||||
return ""
|
|
||||||
|
|
||||||
return signRes.result.getStr()
|
|
||||||
except Exception as e:
|
|
||||||
error "signMessageForDApps failed: ", "msg", e.msg
|
|
||||||
return ""
|
|
||||||
|
|
||||||
proc safeSignTypedData*(address: string, password: string, typedDataJson: string, chainId: int, legacy: bool): string =
|
|
||||||
try:
|
|
||||||
let rpcRes = safeSignTypedDataForDApps(typedDataJson, address, hashPassword(password), chainId, legacy)
|
|
||||||
if not isSuccessResponse(rpcRes):
|
|
||||||
return ""
|
|
||||||
|
|
||||||
return rpcRes.result.getStr()
|
|
||||||
except Exception as e:
|
|
||||||
error (if legacy: "wallet_safeSignTypedDataForDApps" else: "wallet_signTypedDataV4") & " failed: ", "msg", e.msg
|
|
||||||
return ""
|
|
|
@ -274,7 +274,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, "password", "")
|
store.userAuthenticated(td.topic, td.request.id, "hello world", "")
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,22 @@ SQUtils.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 onSigningResult(topic, id, data) {
|
||||||
|
let isSuccessful = (data != "")
|
||||||
|
if (isSuccessful) {
|
||||||
|
// acceptSessionRequest will trigger an sdk.sessionRequestUserAnswerResult signal
|
||||||
|
sdk.acceptSessionRequest(topic, id, data)
|
||||||
|
} else {
|
||||||
|
console.error("signing error")
|
||||||
|
var request = requests.findRequest(topic, id)
|
||||||
|
if (request === null) {
|
||||||
|
console.error("Error finding event for topic", topic, "id", id)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
root.sessionRequestResult(request, isSuccessful)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SQUtils.QObject {
|
SQUtils.QObject {
|
||||||
|
@ -359,64 +375,75 @@ SQUtils.QObject {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (password !== "") {
|
if (password === "") {
|
||||||
let actionResult = ""
|
console.error("No password provided to sign message")
|
||||||
if (request.method === SessionRequest.methods.sign.name) {
|
return
|
||||||
actionResult = store.signMessageUnsafe(request.topic, request.id,
|
}
|
||||||
request.account.address, password,
|
|
||||||
SessionRequest.methods.personalSign.getMessageFromData(request.data))
|
if (request.method === SessionRequest.methods.sign.name) {
|
||||||
} else if (request.method === SessionRequest.methods.personalSign.name) {
|
store.signMessageUnsafe(request.topic,
|
||||||
actionResult = store.signMessage(request.topic, request.id,
|
request.id,
|
||||||
request.account.address, password,
|
request.account.address,
|
||||||
SessionRequest.methods.personalSign.getMessageFromData(request.data))
|
SessionRequest.methods.personalSign.getMessageFromData(request.data),
|
||||||
} else if (request.method === SessionRequest.methods.signTypedData_v4.name ||
|
password,
|
||||||
request.method === SessionRequest.methods.signTypedData.name)
|
pin)
|
||||||
{
|
} else if (request.method === SessionRequest.methods.personalSign.name) {
|
||||||
let legacy = request.method === SessionRequest.methods.signTypedData.name
|
store.signMessage(request.topic,
|
||||||
actionResult = store.safeSignTypedData(request.topic, request.id,
|
request.id,
|
||||||
request.account.address, password,
|
request.account.address,
|
||||||
|
SessionRequest.methods.personalSign.getMessageFromData(request.data),
|
||||||
|
password,
|
||||||
|
pin)
|
||||||
|
} else if (request.method === SessionRequest.methods.signTypedData_v4.name ||
|
||||||
|
request.method === SessionRequest.methods.signTypedData.name)
|
||||||
|
{
|
||||||
|
let legacy = request.method === SessionRequest.methods.signTypedData.name
|
||||||
|
store.safeSignTypedData(request.topic,
|
||||||
|
request.id,
|
||||||
|
request.account.address,
|
||||||
SessionRequest.methods.signTypedData.getMessageFromData(request.data),
|
SessionRequest.methods.signTypedData.getMessageFromData(request.data),
|
||||||
request.network.chainId, legacy)
|
request.network.chainId,
|
||||||
} else if (d.isTransactionMethod(request.method)) {
|
legacy,
|
||||||
let txObj = d.getTxObject(request.method, request.data)
|
password,
|
||||||
if (!!payload) {
|
pin)
|
||||||
let feesInfoJson = payload
|
} else if (d.isTransactionMethod(request.method)) {
|
||||||
let hexFeesJson = root.store.convertFeesInfoToHex(feesInfoJson)
|
let txObj = d.getTxObject(request.method, request.data)
|
||||||
if (!!hexFeesJson) {
|
if (!!payload) {
|
||||||
let feesInfo = JSON.parse(hexFeesJson)
|
let feesInfoJson = payload
|
||||||
if (feesInfo.maxFeePerGas) {
|
let hexFeesJson = root.store.convertFeesInfoToHex(feesInfoJson)
|
||||||
txObj.maxFeePerGas = feesInfo.maxFeePerGas
|
if (!!hexFeesJson) {
|
||||||
}
|
let feesInfo = JSON.parse(hexFeesJson)
|
||||||
if (feesInfo.maxPriorityFeePerGas) {
|
if (feesInfo.maxFeePerGas) {
|
||||||
txObj.maxPriorityFeePerGas = feesInfo.maxPriorityFeePerGas
|
txObj.maxFeePerGas = feesInfo.maxFeePerGas
|
||||||
}
|
}
|
||||||
|
if (feesInfo.maxPriorityFeePerGas) {
|
||||||
|
txObj.maxPriorityFeePerGas = feesInfo.maxPriorityFeePerGas
|
||||||
}
|
}
|
||||||
delete txObj.gasLimit
|
|
||||||
delete txObj.gasPrice
|
|
||||||
}
|
|
||||||
// Remove nonce from txObj to be auto-filled by the wallet
|
|
||||||
delete txObj.nonce
|
|
||||||
|
|
||||||
if (request.method === SessionRequest.methods.signTransaction.name) {
|
|
||||||
actionResult = store.signTransaction(request.topic, request.id,
|
|
||||||
request.account.address, request.network.chainId, password, txObj)
|
|
||||||
} else if (request.method === SessionRequest.methods.sendTransaction.name) {
|
|
||||||
actionResult = store.sendTransaction(request.topic, request.id,
|
|
||||||
request.account.address, request.network.chainId, password, txObj)
|
|
||||||
}
|
}
|
||||||
|
delete txObj.gasLimit
|
||||||
|
delete txObj.gasPrice
|
||||||
}
|
}
|
||||||
|
// Remove nonce from txObj to be auto-filled by the wallet
|
||||||
|
delete txObj.nonce
|
||||||
|
|
||||||
let isSuccessful = (actionResult != "")
|
if (request.method === SessionRequest.methods.signTransaction.name) {
|
||||||
if (isSuccessful) {
|
store.signTransaction(request.topic,
|
||||||
// acceptSessionRequest will trigger an sdk.sessionRequestUserAnswerResult signal
|
request.id,
|
||||||
sdk.acceptSessionRequest(request.topic, request.id, actionResult)
|
request.account.address,
|
||||||
} else {
|
request.network.chainId,
|
||||||
root.sessionRequestResult(request, isSuccessful)
|
txObj,
|
||||||
|
password,
|
||||||
|
pin)
|
||||||
|
} else if (request.method === SessionRequest.methods.sendTransaction.name) {
|
||||||
|
store.sendTransaction(
|
||||||
|
request.topic,
|
||||||
|
request.id,
|
||||||
|
request.account.address,
|
||||||
|
request.network.chainId,
|
||||||
|
txObj,
|
||||||
|
password,
|
||||||
|
pin)
|
||||||
}
|
}
|
||||||
} else if (pin !== "") {
|
|
||||||
console.debug("TODO #15097 sign message using keycard: ", request.data)
|
|
||||||
} else {
|
|
||||||
console.error("No password or pin provided to sign message")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -240,48 +240,59 @@ WalletConnectSDKBase {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (password !== "") {
|
if (password === "") {
|
||||||
var actionResult = ""
|
console.error("No password provided to sign message")
|
||||||
if (request.method === SessionRequest.methods.sign.name) {
|
return
|
||||||
actionResult = store.signMessageUnsafe(request.topic, request.id,
|
}
|
||||||
request.account.address, password,
|
|
||||||
SessionRequest.methods.personalSign.getMessageFromData(request.data))
|
if (request.method === SessionRequest.methods.sign.name) {
|
||||||
} else if (request.method === SessionRequest.methods.personalSign.name) {
|
store.signMessageUnsafe(request.topic,
|
||||||
actionResult = store.signMessage(request.topic, request.id,
|
request.id,
|
||||||
request.account.address, password,
|
request.account.address,
|
||||||
SessionRequest.methods.personalSign.getMessageFromData(request.data))
|
SessionRequest.methods.personalSign.getMessageFromData(request.data),
|
||||||
} else if (request.method === SessionRequest.methods.signTypedData_v4.name ||
|
password,
|
||||||
request.method === SessionRequest.methods.signTypedData.name)
|
pin)
|
||||||
{
|
} else if (request.method === SessionRequest.methods.personalSign.name) {
|
||||||
let legacy = request.method === SessionRequest.methods.signTypedData.name
|
store.signMessage(request.topic,
|
||||||
actionResult = store.safeSignTypedData(request.topic, request.id,
|
request.id,
|
||||||
request.account.address, password,
|
request.account.address,
|
||||||
|
SessionRequest.methods.personalSign.getMessageFromData(request.data),
|
||||||
|
password,
|
||||||
|
pin)
|
||||||
|
} else if (request.method === SessionRequest.methods.signTypedData_v4.name ||
|
||||||
|
request.method === SessionRequest.methods.signTypedData.name)
|
||||||
|
{
|
||||||
|
let legacy = request.method === SessionRequest.methods.signTypedData.name
|
||||||
|
store.safeSignTypedData(request.topic,
|
||||||
|
request.id,
|
||||||
|
request.account.address,
|
||||||
SessionRequest.methods.signTypedData.getMessageFromData(request.data),
|
SessionRequest.methods.signTypedData.getMessageFromData(request.data),
|
||||||
request.network.chainId, legacy)
|
request.network.chainId,
|
||||||
} else if (request.method === SessionRequest.methods.signTransaction.name) {
|
legacy,
|
||||||
let txObj = SessionRequest.methods.signTransaction.getTxObjFromData(request.data)
|
password,
|
||||||
actionResult = store.signTransaction(request.topic, request.id,
|
pin)
|
||||||
request.account.address, request.network.chainId, password, txObj)
|
} else if (request.method === SessionRequest.methods.signTransaction.name) {
|
||||||
} else if (request.method === SessionRequest.methods.sendTransaction.name) {
|
let txObj = SessionRequest.methods.signTransaction.getTxObjFromData(request.data)
|
||||||
let txObj = SessionRequest.methods.sendTransaction.getTxObjFromData(request.data)
|
store.signTransaction(request.topic,
|
||||||
actionResult = store.sendTransaction(request.topic, request.id,
|
request.id,
|
||||||
request.account.address, request.network.chainId, password, txObj)
|
request.account.address,
|
||||||
}
|
request.network.chainId,
|
||||||
let isSuccessful = (actionResult != "")
|
txObj,
|
||||||
if (isSuccessful) {
|
password,
|
||||||
// acceptSessionRequest will trigger an sdk.sessionRequestUserAnswerResult signal
|
pin)
|
||||||
acceptSessionRequest(request.topic, request.method, request.id, actionResult)
|
} else if (request.method === SessionRequest.methods.sendTransaction.name) {
|
||||||
} else {
|
let txObj = SessionRequest.methods.sendTransaction.getTxObjFromData(request.data)
|
||||||
root.sessionRequestResult(request, isSuccessful)
|
store.sendTransaction(request.topic,
|
||||||
}
|
request.id,
|
||||||
} else if (pin !== "") {
|
request.account.address,
|
||||||
console.debug("TODO #15097 sign message using keycard: ", request.data)
|
request.network.chainId,
|
||||||
} else {
|
txObj,
|
||||||
console.error("No password or pin provided to sign message")
|
password,
|
||||||
|
pin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function acceptSessionRequest(topic, method, id, signature) {
|
function acceptSessionRequest(topic, id, signature) {
|
||||||
console.debug(`Connector DappsConnectorSDK.acceptSessionRequest; requestId: ${root.requestId}, signature: "${signature}"`)
|
console.debug(`Connector DappsConnectorSDK.acceptSessionRequest; requestId: ${root.requestId}, signature: "${signature}"`)
|
||||||
|
|
||||||
sessionRequestLoader.active = false
|
sessionRequestLoader.active = false
|
||||||
|
@ -348,6 +359,16 @@ WalletConnectSDKBase {
|
||||||
root.displayToastMessage(qsTr("Failed to authenticate %1").arg(session.peer.metadata.url), true)
|
root.displayToastMessage(qsTr("Failed to authenticate %1").arg(session.peer.metadata.url), true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onSigningResult(topic, id, data) {
|
||||||
|
let isSuccessful = (data != "")
|
||||||
|
if (isSuccessful) {
|
||||||
|
// acceptSessionRequest will trigger an sdk.sessionRequestUserAnswerResult signal
|
||||||
|
d.acceptSessionRequest(topic, id, data)
|
||||||
|
} else {
|
||||||
|
console.error("signing error")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
|
|
|
@ -252,10 +252,6 @@ QObject {
|
||||||
|
|
||||||
readonly property var supportedAccountsModel: SortFilterProxyModel {
|
readonly property var supportedAccountsModel: SortFilterProxyModel {
|
||||||
sourceModel: root.walletRootStore.nonWatchAccounts
|
sourceModel: root.walletRootStore.nonWatchAccounts
|
||||||
filters: ValueFilter {
|
|
||||||
roleName: "keycardAccount"
|
|
||||||
value: false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
property var currentSessionProposal: null
|
property var currentSessionProposal: null
|
||||||
|
|
|
@ -12,6 +12,8 @@ QObject {
|
||||||
signal userAuthenticated(string topic, string id, string password, string pin, string payload)
|
signal userAuthenticated(string topic, string id, string password, string pin, string payload)
|
||||||
signal userAuthenticationFailed(string topic, string id)
|
signal userAuthenticationFailed(string topic, string id)
|
||||||
|
|
||||||
|
signal signingResult(string topic, string id, string data)
|
||||||
|
|
||||||
function addWalletConnectSession(sessionJson) {
|
function addWalletConnectSession(sessionJson) {
|
||||||
return controller.addWalletConnectSession(sessionJson)
|
return controller.addWalletConnectSession(sessionJson)
|
||||||
}
|
}
|
||||||
|
@ -31,19 +33,16 @@ QObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the hex encoded signature of the message or empty string if error
|
function signMessageUnsafe(topic, id, address, message, password, pin = "") {
|
||||||
function signMessageUnsafe(topic, id, address, password, message) {
|
controller.signMessageUnsafe(topic, id, address, message, password, pin)
|
||||||
return controller.signMessageUnsafe(address, password, message)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the hex encoded signature of the message or empty string if error
|
function signMessage(topic, id, address, message, password, pin = "") {
|
||||||
function signMessage(topic, id, address, password, message) {
|
controller.signMessage(topic, id, address, message, password, pin)
|
||||||
return controller.signMessage(address, password, message)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the hex encoded signature of the typedDataJson or empty string if error
|
function safeSignTypedData(topic, id, address, typedDataJson, chainId, legacy, password, pin = "") {
|
||||||
function safeSignTypedData(topic, id, address, password, typedDataJson, chainId, legacy) {
|
controller.safeSignTypedData(topic, id, address, typedDataJson, chainId, legacy, password, pin)
|
||||||
return controller.safeSignTypedData(address, password, typedDataJson, chainId, legacy)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove leading zeros from hex number as expected by status-go
|
// Remove leading zeros from hex number as expected by status-go
|
||||||
|
@ -91,16 +90,14 @@ QObject {
|
||||||
return JSON.parse(controller.getSuggestedFeesJson(chainId))
|
return JSON.parse(controller.getSuggestedFeesJson(chainId))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the hex encoded signature of the transaction or empty string if error
|
|
||||||
function signTransaction(topic, id, address, chainId, password, txObj) {
|
function signTransaction(topic, id, address, chainId, password, txObj) {
|
||||||
let tx = prepareTxForStatusGo(txObj)
|
let tx = prepareTxForStatusGo(txObj)
|
||||||
return controller.signTransaction(address, chainId, password, JSON.stringify(tx))
|
controller.signTransaction(topic, id, address, chainId, JSON.stringify(tx), password, pin)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the hash of the transaction or empty string if error
|
function sendTransaction(topic, id, address, chainId, txObj, password, pin = "") {
|
||||||
function sendTransaction(topic, id, address, chainId, password, txObj) {
|
|
||||||
let tx = prepareTxForStatusGo(txObj)
|
let tx = prepareTxForStatusGo(txObj)
|
||||||
return controller.sendTransaction(address, chainId, password, JSON.stringify(tx))
|
controller.sendTransaction(topic, id, address, chainId, JSON.stringify(tx), password, pin)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \c getDapps triggers an async response to \c dappsListReceived
|
/// \c getDapps triggers an async response to \c dappsListReceived
|
||||||
|
@ -149,5 +146,9 @@ QObject {
|
||||||
root.userAuthenticationFailed(topic, id)
|
root.userAuthenticationFailed(topic, id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onSigningResultReceived(topic, id, data) {
|
||||||
|
root.signingResult(topic, id, data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 5546ffaea2b2135e7a3da58845e230d8e26fe709
|
Subproject commit 8923d70ec0348c7b238ce6d5d86ebe6682577ba4
|
Loading…
Reference in New Issue