diff --git a/src/app/modules/shared_modules/wallet_connect/controller.nim b/src/app/modules/shared_modules/wallet_connect/controller.nim index 7dd28f1d5e..d81e509c49 100644 --- a/src/app/modules/shared_modules/wallet_connect/controller.nim +++ b/src/app/modules/shared_modules/wallet_connect/controller.nim @@ -4,9 +4,12 @@ import chronicles import app_service/service/wallet_connect/service as wallet_connect_service import app_service/service/wallet_account/service as wallet_account_service +import helpers + logScope: topics = "wallet-connect-controller" + QtObject: type Controller* = ref object of QObject @@ -44,16 +47,16 @@ QtObject: self.dappsListReceived(res) return true - proc userAuthenticationResult*(self: Controller, topic: string, id: string, error: bool, password: string, pin: string) {.signal.} + 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 - proc authenticateUser*(self: Controller, topic: string, id: string, address: string): bool {.slot.} = + proc authenticateUser*(self: Controller, topic: string, id: string, address: string, payload: string): bool {.slot.} = let acc = self.walletAccountService.getAccountByAddress(address) if acc.keyUid == "": return false return self.service.authenticateUser(acc.keyUid, proc(password: string, pin: string, success: bool) = - self.userAuthenticationResult(topic, id, success, password, pin) + self.userAuthenticationResult(topic, id, success, password, pin, payload) ) proc signMessageUnsafe*(self: Controller, address: string, password: string, message: string): string {.slot.} = @@ -73,3 +76,22 @@ QtObject: proc getEstimatedTime(self: Controller, chainId: int, maxFeePerGasHex: string): int {.slot.} = return self.service.getEstimatedTime(chainId, maxFeePerGasHex).int + + proc getSuggestedFeesJson(self: Controller, chainId: int): string {.slot.} = + let dto = self.service.getSuggestedFees(chainId) + return dto.toJson() + + proc hexToDecBigString*(self: Controller, hex: string): string {.slot.} = + try: + return hexToDec(hex) + except Exception as e: + error "Failed to convert hex big int: ", hex=hex, ex=e.msg + return "" + + # Convert from float gwei to hex wei + proc convertFeesInfoToHex*(self: Controller, feesInfoJson: string): string {.slot.} = + try: + return convertFeesInfoToHex(feesInfoJson) + except Exception as e: + error "Failed to convert fees info to hex: ", feesInfoJson=feesInfoJson, ex=e.msg + return "" diff --git a/src/app/modules/shared_modules/wallet_connect/helpers.nim b/src/app/modules/shared_modules/wallet_connect/helpers.nim new file mode 100644 index 0000000000..6927b26a4d --- /dev/null +++ b/src/app/modules/shared_modules/wallet_connect/helpers.nim @@ -0,0 +1,21 @@ +import stint, json, strutils + +proc hexToDec*(hex: string): string = + return stint.parse(hex, UInt256, 16).toString() + +proc convertFeesInfoToHex*(feesInfoJson: string): string = + let parsedJson = parseJson(feesInfoJson) + + let maxFeeFloat = parsedJson["maxFeePerGas"].getFloat() + let maxFeeWei = int64(maxFeeFloat * 1e9) + + let maxPriorityFeeFloat = parsedJson["maxPriorityFeePerGas"].getFloat() + let maxPriorityFeeWei = int64(maxPriorityFeeFloat * 1e9) + + # Assemble the JSON and return it + var resultJson = %* { + "maxFeePerGas": "0x" & toHex(maxFeeWei).strip(chars = {'0'}, trailing = false), + "maxPriorityFeePerGas": "0x" & toHex(maxPriorityFeeWei).strip(chars = {'0'}, trailing = false) + } + return $resultJson + diff --git a/src/app_service/service/wallet_connect/service.nim b/src/app_service/service/wallet_connect/service.nim index d2d47dae96..879f92311e 100644 --- a/src/app_service/service/wallet_connect/service.nim +++ b/src/app_service/service/wallet_connect/service.nim @@ -225,3 +225,6 @@ QtObject: let maxFeePerGasInt = parseHexInt(maxFeePerGasHex) maxFeePerGas = maxFeePerGasInt.float return self.transactions.getEstimatedTime(chainId, $(maxFeePerGas)) + +proc getSuggestedFees*(self: Service, chainId: int): SuggestedFeesDto = + return self.transactions.suggestedFees(chainId) \ No newline at end of file diff --git a/storybook/pages/DAppsWorkflowPage.qml b/storybook/pages/DAppsWorkflowPage.qml index 79705e9ec9..2e9f9d73a9 100644 --- a/storybook/pages/DAppsWorkflowPage.qml +++ b/storybook/pages/DAppsWorkflowPage.qml @@ -377,6 +377,13 @@ Item { function getEstimatedTime(chainId, maxFeePerGas) { return Constants.TransactionEstimatedTime.LessThanThreeMins } + + function hexToDec(hex) { + if (hex.length > "0xfffffffffffff".length) { + console.warn(`Beware of possible loss of precision converting ${hex}`) + } + return parseInt(hex, 16).toString() + } } walletRootStore: QObject { @@ -390,6 +397,7 @@ Item { function getNetworkShortNames(chainIds) { return "eth:oeth:arb" } + readonly property CurrenciesStore currencyStore: CurrenciesStore {} } onDisplayToastMessage: (message, isErr) => { diff --git a/storybook/qmlTests/tests/tst_DAppsWorkflow.qml b/storybook/qmlTests/tests/tst_DAppsWorkflow.qml index 491469240a..ca3b3eae6f 100644 --- a/storybook/qmlTests/tests/tst_DAppsWorkflow.qml +++ b/storybook/qmlTests/tests/tst_DAppsWorkflow.qml @@ -155,6 +155,7 @@ Item { id: dappsRequestHandlerComponent DAppsRequestHandler { + currenciesStore: CurrenciesStore {} } } diff --git a/test/nim/wallet_connect_tests.nim b/test/nim/wallet_connect_tests.nim index ea47cda27f..8e7dfbe04d 100644 --- a/test/nim/wallet_connect_tests.nim +++ b/test/nim/wallet_connect_tests.nim @@ -2,8 +2,19 @@ import unittest import app/modules/main/wallet_section/poc_wallet_connect/helpers +import app/modules/shared_modules/wallet_connect/helpers + suite "wallet connect": + test "hexToDec": + check(hexToDec("0x3") == "3") + check(hexToDec("f") == "15") + + test "convertFeesInfoToHex": + const feesInfoJson = "{\"maxFees\":\"24528.282681\",\"maxFeePerGas\":1.168013461,\"maxPriorityFeePerGas\":0.036572351,\"gasPrice\":\"1.168013461\"}" + + check(convertFeesInfoToHex(feesInfoJson) == """{"maxFeePerGas":"0x459E7895","maxPriorityFeePerGas":"0x22E0CBF"}""") + test "parse deep link url": const testUrl = "https://status.app/wc?uri=wc%3Aa4f32854428af0f5b6635fb7a3cb2cfe174eaad63b9d10d52ef1c686f8eab862%402%3Frelay-protocol%3Dirn%26symKey%3D4ccbae2b4c81c26fbf4a6acee9de2771705d467de9a1d24c80240e8be59de6be" diff --git a/ui/app/AppLayouts/Wallet/panels/DAppsWorkflow.qml b/ui/app/AppLayouts/Wallet/panels/DAppsWorkflow.qml index f2de3de5b1..0ec1e2c4ec 100644 --- a/ui/app/AppLayouts/Wallet/panels/DAppsWorkflow.qml +++ b/ui/app/AppLayouts/Wallet/panels/DAppsWorkflow.qml @@ -3,6 +3,7 @@ import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import StatusQ 0.1 +import StatusQ.Core.Utils 0.1 as SQUtils import SortFilterProxyModel 0.2 import AppLayouts.Wallet 1.0 @@ -159,6 +160,8 @@ DappsComboBox { loginType: request.account.migragedToKeycard ? Constants.LoginType.Keycard : root.loginType visible: true + property var feesInfo: null + dappUrl: request.dappUrl dappIcon: request.dappIcon dappName: request.dappName @@ -180,7 +183,7 @@ DappsComboBox { enoughFundsForTransaction: request.enoughFunds enoughFundsForFees: request.enoughFunds - signingTransaction: request.method === SessionRequest.methods.signTransaction.name || request.method === SessionRequest.methods.sendTransaction.name + signingTransaction: !!request.method && (request.method === SessionRequest.methods.signTransaction.name || request.method === SessionRequest.methods.sendTransaction.name) requestPayload: { switch(request.method) { case SessionRequest.methods.personalSign.name: @@ -219,8 +222,9 @@ DappsComboBox { console.error("Error signing: request is null") return } + requestHandled = true - root.wcService.requestHandler.authenticate(request) + root.wcService.requestHandler.authenticate(request, JSON.stringify(feesInfo)) } onRejected: { @@ -240,22 +244,18 @@ DappsComboBox { Connections { target: root.wcService.requestHandler - function onMaxFeesUpdated(maxFees, maxFeesWei, haveEnoughFunds, symbol) { - fiatFees = maxFees - currentCurrency = symbol - - var ethStr = "?" - try { - ethStr = globalUtils.wei2Eth(maxFeesWei, 9) - } catch (e) { - // ignore error in case of tests and storybook where we don't have access to globalUtils + function onMaxFeesUpdated(fiatMaxFees, ethMaxFees, haveEnoughFunds, haveEnoughFees, symbol, feesInfo) { + dappRequestModal.hasFees = !!ethMaxFees + dappRequestModal.feesLoading = !dappRequestModal.hasFees + if (!hasFees) { + return } - - cryptoFees = ethStr - enoughFundsForTransaction = haveEnoughFunds - enoughFundsForFees = haveEnoughFunds - feesLoading = false - hasFees = !!maxFees + dappRequestModal.fiatFees = fiatMaxFees.toString() + dappRequestModal.cryptoFees = ethMaxFees.toString() + dappRequestModal.currentCurrency = symbol + dappRequestModal.enoughFundsForTransaction = haveEnoughFunds + dappRequestModal.enoughFundsForFees = haveEnoughFees + dappRequestModal.feesInfo = feesInfo } function onEstimatedTimeUpdated(estimatedTimeEnum) { @@ -273,6 +273,8 @@ DappsComboBox { sessionRequestLoader.active = false } else { // TODO #14762 handle the error case + let userRejected = false + root.wcService.requestHandler.rejectSessionRequest(request, userRejected) } } } diff --git a/ui/app/AppLayouts/Wallet/services/dapps/DAppsRequestHandler.qml b/ui/app/AppLayouts/Wallet/services/dapps/DAppsRequestHandler.qml index e645c18cbd..a404f905e0 100644 --- a/ui/app/AppLayouts/Wallet/services/dapps/DAppsRequestHandler.qml +++ b/ui/app/AppLayouts/Wallet/services/dapps/DAppsRequestHandler.qml @@ -3,20 +3,21 @@ import QtQuick 2.15 import AppLayouts.Wallet.services.dapps 1.0 import AppLayouts.Wallet.services.dapps.types 1.0 -import StatusQ.Core.Utils 0.1 +import StatusQ.Core.Utils 0.1 as SQUtils import shared.stores 1.0 import utils 1.0 import "types" -QObject { +SQUtils.QObject { id: root required property WalletConnectSDKBase sdk required property DAppsStore store required property var accountsModel required property var networksModel + required property CurrenciesStore currenciesStore property alias requestsModel: requests @@ -26,14 +27,14 @@ QObject { } /// Beware, it will fail if called multiple times before getting an answer - function authenticate(request) { - return store.authenticateUser(request.topic, request.id, request.account.address) + function authenticate(request, payload) { + return store.authenticateUser(request.topic, request.id, request.account.address, payload) } signal sessionRequest(SessionRequestResolved request) signal displayToastMessage(string message, bool error) signal sessionRequestResult(/*model entry of SessionRequestResolved*/ var request, bool isSuccess) - signal maxFeesUpdated(real maxFees, int maxFeesWei, bool haveEnoughFunds, string symbol) + signal maxFeesUpdated(real fiatMaxFees, var /* Big */ ethMaxFees, bool haveEnoughFunds, bool haveEnoughFees, string symbol, var feesInfo) // Reports Constants.TransactionEstimatedTime values signal estimatedTimeUpdated(int estimatedTimeEnum) @@ -51,7 +52,7 @@ QObject { } function onSessionRequestUserAnswerResult(topic, id, accept, error) { - var request = requests.findRequest(topic, id) + let request = requests.findRequest(topic, id) if (request === null) { console.error("Error finding event for topic", topic, "id", id) return @@ -85,17 +86,17 @@ QObject { Connections { target: root.store - function onUserAuthenticated(topic, id, password, pin) { + function onUserAuthenticated(topic, id, password, pin, payload) { var request = requests.findRequest(topic, id) if (request === null) { console.error("Error finding event for topic", topic, "id", id) return } - d.executeSessionRequest(request, password, pin) + d.executeSessionRequest(request, password, pin, payload) } function onUserAuthenticationFailed(topic, id) { - var request = requests.findRequest(topic, id) + let request = requests.findRequest(topic, id) let methodStr = SessionRequest.methodToUserString(request.method) if (request === null || !methodStr) { return @@ -108,7 +109,7 @@ QObject { } } - QObject { + SQUtils.QObject { id: d function resolveAsync(event) { @@ -128,6 +129,7 @@ QObject { console.error("Error in event data lookup", JSON.stringify(event)) return null } + let enoughFunds = !d.isTransactionMethod(method) let obj = sessionRequestComponent.createObject(null, { event, topic: event.topic, @@ -138,7 +140,7 @@ QObject { data, maxFeesText: "?", maxFeesEthText: "?", - enoughFunds: false, + enoughFunds: enoughFunds, }) if (obj === null) { console.error("Error creating SessionRequestResolved for event") @@ -159,20 +161,16 @@ QObject { obj.resolveDappInfoFromSession(session) root.sessionRequest(obj) - let estimatedTimeEnum = getEstimatedTimeInterval(data, method, obj.network.chainId) - root.estimatedTimeUpdated(estimatedTimeEnum) - - // TODO #15192: update maxFees - if (!event.params.request.params[0].gasLimit || !event.params.request.params[0].gasPrice) { - root.maxFeesUpdated(0, 0, true, "") + if (!d.isTransactionMethod(method)) { return } - let gasLimit = parseFloat(parseInt(event.params.request.params[0].gasLimit, 16)); - let gasPrice = parseFloat(parseInt(event.params.request.params[0].gasPrice, 16)); - let maxFees = gasLimit * gasPrice - root.maxFeesUpdated(maxFees/1000000000, maxFees, true, "Gwei") + let estimatedTimeEnum = getEstimatedTimeInterval(data, method, obj.network.chainId) + root.estimatedTimeUpdated(estimatedTimeEnum) + let st = getEstimatedFeesStatus(data, method, obj.network.chainId) + + root.maxFeesUpdated(st.fiatMaxFees, st.maxFeesEth, st.haveEnoughFunds, st.haveEnoughFees, st.symbol, st.feesInfo) }) return obj @@ -180,7 +178,7 @@ QObject { /// Returns null if the account is not found function lookupAccountFromEvent(event, method) { - var address = "" + let address = "" if (method === SessionRequest.methods.personalSign.name) { if (event.params.request.params.length < 2) { return null @@ -198,14 +196,13 @@ QObject { return null } address = event.params.request.params[0] - } else if (method === SessionRequest.methods.signTransaction.name - || method === SessionRequest.methods.sendTransaction.name) { + } else if (d.isTransactionMethod(method)) { if (event.params.request.params.length == 0) { return null } address = event.params.request.params[0].from } - return ModelUtils.getFirstModelEntryIf(root.accountsModel, (account) => { + return SQUtils.ModelUtils.getFirstModelEntryIf(root.accountsModel, (account) => { return account.address.toLowerCase() === address.toLowerCase(); }) } @@ -216,7 +213,7 @@ QObject { return null } let chainId = Helpers.chainIdFromEip155(event.params.chainId) - return ModelUtils.getByKey(root.networksModel, "chainId", chainId) + return SQUtils.ModelUtils.getByKey(root.networksModel, "chainId", chainId) } function extractMethodData(event, method) { @@ -226,7 +223,7 @@ QObject { if (event.params.request.params.length < 1) { return null } - var message = "" + let message = "" let messageIndex = (method === SessionRequest.methods.personalSign.name ? 0 : 1) let messageParam = event.params.request.params[messageIndex] // There is no standard on how data is encoded. Therefore we support hex or utf8 @@ -275,14 +272,14 @@ QObject { }) } - function executeSessionRequest(request, password, pin) { + function executeSessionRequest(request, password, pin, payload) { if (!SessionRequest.getSupportedMethods().includes(request.method)) { console.error("Unsupported method to execute: ", request.method) return } if (password !== "") { - var actionResult = "" + let actionResult = "" if (request.method === SessionRequest.methods.sign.name) { actionResult = store.signMessageUnsafe(request.topic, request.id, request.account.address, password, @@ -299,15 +296,36 @@ QObject { request.account.address, password, SessionRequest.methods.signTypedData.getMessageFromData(request.data), request.network.chainId, legacy) - } else if (request.method === SessionRequest.methods.signTransaction.name) { - let txObj = SessionRequest.methods.signTransaction.getTxObjFromData(request.data) - actionResult = store.signTransaction(request.topic, request.id, - request.account.address, request.network.chainId, password, txObj) - } else if (request.method === SessionRequest.methods.sendTransaction.name) { - let txObj = SessionRequest.methods.sendTransaction.getTxObjFromData(request.data) - actionResult = store.sendTransaction(request.topic, request.id, - request.account.address, request.network.chainId, password, txObj) + } else if (d.isTransactionMethod(request.method)) { + let txObj = d.getTxObject(request.method, request.data) + if (!!payload) { + let feesInfoJson = payload + let hexFeesJson = root.store.convertFeesInfoToHex(feesInfoJson) + if (!!hexFeesJson) { + let feesInfo = JSON.parse(hexFeesJson) + if (feesInfo.maxFeePerGas) { + 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) { + let txObj = SessionRequest.methods.sendTransaction.getTxObjFromData(request.data) + actionResult = store.sendTransaction(request.topic, request.id, + request.account.address, request.network.chainId, password, txObj) + } } + let isSuccessful = (actionResult != "") if (isSuccessful) { // acceptSessionRequest will trigger an sdk.sessionRequestUserAnswerResult signal @@ -324,28 +342,110 @@ QObject { // Returns Constants.TransactionEstimatedTime function getEstimatedTimeInterval(data, method, chainId) { - if (method != SessionRequest.methods.signTransaction.name - && method != SessionRequest.methods.sendTransaction.name) - { - return "" + let tx = {} + let maxFeePerGas = "" + if (d.isTransactionMethod(method)) { + tx = d.getTxObject(method, data) + // Empty string instructs getEstimatedTime to fetch the blockchain value + if (!!tx.maxFeePerGas) { + maxFeePerGas = tx.maxFeePerGas + } else if (!!tx.gasPrice) { + maxFeePerGas = tx.gasPrice + } } - var tx = {} + return root.store.getEstimatedTime(chainId, maxFeePerGas) + } + + // Returns { + // maxFees -> Big number in Gwei + // maxFeePerGas + // maxPriorityFeePerGas + // gasPrice + // } + function getEstimatedMaxFees(data, method, chainId) { + let tx = {} + if (d.isTransactionMethod(method)) { + tx = d.getTxObject(method, data) + } + + let Math = SQUtils.AmountsArithmetic + let gasLimit = Math.fromString("21000") + let gasPrice, maxFeePerGas, maxPriorityFeePerGas + // Beware, the tx values are standard blockchain hex big number values; the fees values are nim's float64 values, hence the complex conversions + if (!!tx.maxFeePerGas && !!tx.maxPriorityFeePerGas) { + let maxFeePerGasDec = root.store.hexToDec(tx.maxFeePerGas) + gasPrice = Math.fromString(maxFeePerGasDec) + // Source fees info from the incoming transaction for when we process it + maxFeePerGas = maxFeePerGasDec + let maxPriorityFeePerGasDec = root.store.hexToDec(tx.maxPriorityFeePerGas) + maxPriorityFeePerGas = maxPriorityFeePerGasDec + } else { + let fees = root.store.getSuggestedFees(chainId) + maxPriorityFeePerGas = fees.maxPriorityFeePerGas + if (fees.eip1559Enabled) { + if (!!fees.maxFeePerGasM) { + gasPrice = Math.fromString(fees.maxFeePerGasM) + maxFeePerGas = fees.maxFeePerGasM + } else if(!!tx.maxFeePerGas) { + let maxFeePerGasDec = root.store.hexToDec(tx.maxFeePerGas) + gasPrice = Math.fromString(maxFeePerGasDec) + maxFeePerGas = maxFeePerGasDec + } else { + console.error("Error fetching maxFeePerGas from fees or tx objects") + return + } + } else { + if (!!fees.gasPrice) { + gasPrice = Math.fromString(fees.gasPrice) + } else { + console.error("Error fetching suggested fees") + return + } + } + gasPrice = Math.sum(gasPrice, Math.fromString(fees.l1GasFee)) + } + + let maxFees = Math.times(gasLimit, gasPrice) + return {maxFees, maxFeePerGas, maxPriorityFeePerGas, gasPrice} + } + + function getEstimatedFeesStatus(data, method, chainId) { + let Math = SQUtils.AmountsArithmetic + + let feesInfo = getEstimatedMaxFees(data, method, chainId) + + let maxFeesEth = Math.div(feesInfo.maxFees, Math.fromString("1000000000")) + + // TODO #15192: extract account.balance + //let accountFundsEth = account.balance + //let haveEnoughFees = Math.cmp(accountFundsEth, maxFeesEth) >= 0 + let haveEnoughFees = true + + let maxFeesEthStr = maxFeesEth.toString() + let fiatMaxFees = root.currenciesStore.getFiatValue(maxFeesEthStr, Constants.ethToken) + let symbol = root.currenciesStore.currentCurrency + + // We don't process the transaction so we don't have this information yet + let haveEnoughFunds = true + return {fiatMaxFees, maxFeesEth, haveEnoughFunds, haveEnoughFees, symbol, feesInfo} + } + + function isTransactionMethod(method) { + return method === SessionRequest.methods.signTransaction.name + || method === SessionRequest.methods.sendTransaction.name + } + + function getTxObject(method, data) { + let tx if (method === SessionRequest.methods.signTransaction.name) { tx = SessionRequest.methods.signTransaction.getTxObjFromData(data) } else if (method === SessionRequest.methods.sendTransaction.name) { tx = SessionRequest.methods.sendTransaction.getTxObjFromData(data) + } else { + console.error("Not a transaction method") } - - // Empty string instructs getEstimatedTime to fetch the blockchain value - var maxFeePerGas = "" - if (!!tx.maxFeePerGas) { - maxFeePerGas = tx.maxFeePerGas - } else if (!!tx.gasPrice) { - maxFeePerGas = tx.gasPrice - } - - return root.store.getEstimatedTime(chainId, maxFeePerGas) + return tx } } diff --git a/ui/app/AppLayouts/Wallet/services/dapps/WalletConnectService.qml b/ui/app/AppLayouts/Wallet/services/dapps/WalletConnectService.qml index 851faceb36..5c1da37440 100644 --- a/ui/app/AppLayouts/Wallet/services/dapps/WalletConnectService.qml +++ b/ui/app/AppLayouts/Wallet/services/dapps/WalletConnectService.qml @@ -238,6 +238,7 @@ QObject { store: root.store accountsModel: root.validAccounts networksModel: root.flatNetworks + currenciesStore: root.walletRootStore.currencyStore onSessionRequest: (request) => { timeoutTimer.stop() diff --git a/ui/app/AppLayouts/Wallet/services/dapps/helpers.js b/ui/app/AppLayouts/Wallet/services/dapps/helpers.js index 7925d235d4..a7c2db0590 100644 --- a/ui/app/AppLayouts/Wallet/services/dapps/helpers.js +++ b/ui/app/AppLayouts/Wallet/services/dapps/helpers.js @@ -99,4 +99,4 @@ function extractInfoFromPairUri(uri) { } } return { topic, expiry } -} \ No newline at end of file +} diff --git a/ui/app/AppLayouts/Wallet/services/dapps/types/SessionRequestResolved.qml b/ui/app/AppLayouts/Wallet/services/dapps/types/SessionRequestResolved.qml index d7ebecf1cc..d6fb10a04c 100644 --- a/ui/app/AppLayouts/Wallet/services/dapps/types/SessionRequestResolved.qml +++ b/ui/app/AppLayouts/Wallet/services/dapps/types/SessionRequestResolved.qml @@ -28,9 +28,9 @@ QObject { readonly property alias dappUrl: d.dappUrl readonly property alias dappIcon: d.dappIcon - readonly property string maxFeesText: "" - readonly property string maxFeesEthText: "" - readonly property bool enoughFunds: false + property string maxFeesText: "" + property string maxFeesEthText: "" + property bool enoughFunds: false function resolveDappInfoFromSession(session) { let meta = session.peer.metadata diff --git a/ui/imports/shared/stores/DAppsStore.qml b/ui/imports/shared/stores/DAppsStore.qml index d2a3bb977a..4c87413205 100644 --- a/ui/imports/shared/stores/DAppsStore.qml +++ b/ui/imports/shared/stores/DAppsStore.qml @@ -8,7 +8,7 @@ QObject { required property var controller /// \c dappsJson serialized from status-go.wallet.GetDapps signal dappsListReceived(string dappsJson) - signal userAuthenticated(string topic, string id, string password, string pin) + signal userAuthenticated(string topic, string id, string password, string pin, string payload) signal userAuthenticationFailed(string topic, string id) function addWalletConnectSession(sessionJson) { @@ -23,8 +23,8 @@ QObject { return controller.updateSessionsMarkedAsActive(activeTopicsJson) } - function authenticateUser(topic, id, address) { - let ok = controller.authenticateUser(topic, id, address) + function authenticateUser(topic, id, address, payload) { + let ok = controller.authenticateUser(topic, id, address, payload) if(!ok) { root.userAuthenticationFailed() } @@ -70,6 +70,12 @@ QObject { return controller.getEstimatedTime(chainId, maxFeePerGasHex) } + // Returns nim's SuggestedFeesDto; see src/app_service/service/transaction/dto.nim + // Returns all value initialized to 0 if error + function getSuggestedFees(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) { let tx = prepareTxForStatusGo(txObj) @@ -87,6 +93,15 @@ QObject { return controller.getDapps() } + function hexToDec(hex) { + return controller.hexToDecBigString(hex) + } + + // Return just the modified fields { "maxFeePerGas": "0x<...>", "maxPriorityFeePerGas": "0x<...>" } + function convertFeesInfoToHex(feesInfoJson) { + return controller.convertFeesInfoToHex(feesInfoJson) + } + // Handle async response from controller Connections { target: controller @@ -95,9 +110,9 @@ QObject { root.dappsListReceived(dappsJson) } - function onUserAuthenticationResult(topic, id, success, password, pin) { + function onUserAuthenticationResult(topic, id, success, password, pin, payload) { if (success) { - root.userAuthenticated(topic, id, password, pin) + root.userAuthenticated(topic, id, password, pin, payload) } else { root.userAuthenticationFailed(topic, id) }