From 8ece500dde1005421b5701d9859b7f14b42cc669 Mon Sep 17 00:00:00 2001 From: Khushboo Mehta Date: Fri, 20 Dec 2024 11:30:24 +0100 Subject: [PATCH] feat(@desktop/wallet): Implements and handles errors in the new simple send modal fies #17000 --- storybook/pages/SimpleSendModalPage.qml | 17 +++++++-- ui/app/AppLayouts/Wallet/WalletUtils.qml | 5 ++- .../popups/simpleSend/SimpleSendModal.qml | 37 +++++++++++++++++++ ui/app/mainui/AppMain.qml | 11 ++++++ ui/app/mainui/SendModalHandler.qml | 25 +++++++++++-- 5 files changed, 86 insertions(+), 9 deletions(-) diff --git a/storybook/pages/SimpleSendModalPage.qml b/storybook/pages/SimpleSendModalPage.qml index 40acf0a9a1..7600c88ebe 100644 --- a/storybook/pages/SimpleSendModalPage.qml +++ b/storybook/pages/SimpleSendModalPage.qml @@ -66,7 +66,19 @@ SplitView { simpleSend.estimatedTime = "~60s" simpleSend.estimatedFiatFees = "1.45 EUR" simpleSend.estimatedCryptoFees = "0.0007 ETH" + simpleSend.routerErrorCode = Constants.routerErrorCodes.router.errNotEnoughNativeBalance + simpleSend.routerError = qsTr("Not enough ETH to pay gas fees") + simpleSend.routerErrorDetails = "" }) + + function resetRouterValues() { + simpleSend.estimatedCryptoFees = "" + simpleSend.estimatedFiatFees = "" + simpleSend.estimatedTime = "" + simpleSend.routerErrorCode = "" + simpleSend.routerError = "" + simpleSend.routerErrorDetails = "" + } } PopupBackground { @@ -123,9 +135,7 @@ SplitView { }) onFormChanged: { - estimatedCryptoFees = "" - estimatedFiatFees = "" - estimatedTime = "" + d.resetRouterValues() if(allValuesFilledCorrectly()) { console.log("Fetch fees...") routesLoading = true @@ -134,6 +144,7 @@ SplitView { } onReviewSendClicked: console.log("Review send clicked") + onLaunchBuyFlow: console.log("launch buy flow clicked") Binding on selectedAccountAddress { value: accountsCombobox.currentValue ?? "" diff --git a/ui/app/AppLayouts/Wallet/WalletUtils.qml b/ui/app/AppLayouts/Wallet/WalletUtils.qml index 4087465cff..7a658a79d0 100644 --- a/ui/app/AppLayouts/Wallet/WalletUtils.qml +++ b/ui/app/AppLayouts/Wallet/WalletUtils.qml @@ -142,7 +142,7 @@ QtObject { case Constants.routerErrorCodes.router.errNotEnoughTokenBalance: return qsTr("not enough token balance") case Constants.routerErrorCodes.router.errNotEnoughNativeBalance: - return qsTr("not enough ETH") + return qsTr("Not enough ETH to pay gas fees") case Constants.routerErrorCodes.router.errLowAmountInForHopBridge: return qsTr("amount in too low") case Constants.routerErrorCodes.router.errNoPositiveBalance: @@ -278,7 +278,6 @@ QtObject { case Constants.routerErrorCodes.router.errCannotCheckLockedAmounts: return qsTr("cannot check locked amounts") case Constants.routerErrorCodes.router.errNotEnoughTokenBalance: - case Constants.routerErrorCodes.router.errNotEnoughNativeBalance: try { const jsonObj = JSON.parse(details) @@ -299,6 +298,8 @@ QtObject { catch (e) { return "" } + case Constants.routerErrorCodes.router.errNotEnoughNativeBalance: + return details case Constants.routerErrorCodes.router.errLowAmountInForHopBridge: return qsTr("bonder fee greater than estimated received, a higher amount is needed to cover fees") case Constants.routerErrorCodes.router.errNoPositiveBalance: diff --git a/ui/app/AppLayouts/Wallet/popups/simpleSend/SimpleSendModal.qml b/ui/app/AppLayouts/Wallet/popups/simpleSend/SimpleSendModal.qml index 7fe8d8c50d..31305c7ef0 100644 --- a/ui/app/AppLayouts/Wallet/popups/simpleSend/SimpleSendModal.qml +++ b/ui/app/AppLayouts/Wallet/popups/simpleSend/SimpleSendModal.qml @@ -1,5 +1,6 @@ import QtQuick 2.15 import QtQuick.Layouts 1.14 +import QtQml.Models 2.15 import StatusQ 0.1 import StatusQ.Core 0.1 @@ -90,6 +91,12 @@ StatusDialog { property string estimatedFiatFees /** input property to set estimated fees in crypto **/ property string estimatedCryptoFees + /** input property to set router error title **/ + property string routerError: "" + /** input property to set router error details **/ + property string routerErrorDetails: "" + /** input property to set router error code **/ + property string routerErrorCode /** property to set currently selected send type **/ property string sendType: Constants.SendType.Transfer @@ -122,6 +129,8 @@ StatusDialog { signal reviewSendClicked() /** Output signal to inform that the forms been updated **/ signal formChanged() + /** Output signal to launch buy flow **/ + signal launchBuyFlow() /** function exposed to check if the form is filled correctly **/ function allValuesFilledCorrectly() { @@ -229,6 +238,8 @@ StatusDialog { root.selectedRecipientAddress, root.selectedAmount] onCombinedPropertyChangedHandlerChanged: Qt.callLater(() => root.formChanged()) + + readonly property bool errNotEnoughGas: root.routerErrorCode === Constants.routerErrorCodes.router.errNotEnoughNativeBalance } width: 556 @@ -467,6 +478,7 @@ StatusDialog { cryptoFees: root.estimatedCryptoFees fiatFees: root.estimatedFiatFees loading: root.routesLoading && root.allValuesFilledCorrectly() + error: d.errNotEnoughGas } visible: root.allValuesFilledCorrectly() } @@ -480,8 +492,33 @@ StatusDialog { estimateTime: root.estimatedTime estimatedFees: root.estimatedFiatFees + error: d.errNotEnoughGas + errorTags: amountToSend.markAsInvalid || !!root.routerErrorCode ? + errorTagsModel: null + loading: root.routesLoading && root.allValuesFilledCorrectly() onReviewSendClicked: root.reviewSendClicked() } + + ObjectModel { + id: errorTagsModel + RouterErrorTag { + errorTitle: qsTr("Insufficient funds for send transaction") + buttonText: qsTr("Add assets") + onButtonClicked: root.launchBuyFlow() + + visible: amountToSend.markAsInvalid + } + RouterErrorTag { + errorTitle: root.routerError + errorDetails: !d.errNotEnoughGas ? + root.routerErrorDetails: "" + buttonText: qsTr("Add ETH") + expandable: !d.errNotEnoughGas + onButtonClicked: root.launchBuyFlow() + + visible: !!root.routerErrorCode + } + } } diff --git a/ui/app/mainui/AppMain.qml b/ui/app/mainui/AppMain.qml index 16efffd2f8..55e9904167 100644 --- a/ui/app/mainui/AppMain.qml +++ b/ui/app/mainui/AppMain.qml @@ -44,6 +44,7 @@ import AppLayouts.Communities.stores 1.0 import AppLayouts.Profile.stores 1.0 as ProfileStores import AppLayouts.Wallet.popups 1.0 as WalletPopups import AppLayouts.Wallet.popups.dapps 1.0 as DAppsPopups +import AppLayouts.Wallet.popups.buy 1.0 import AppLayouts.Wallet.stores 1.0 as WalletStores import AppLayouts.stores 1.0 as AppStores @@ -601,6 +602,9 @@ Item { } return username } + + // TODO: Remove this and adapt new mechanism to launch BuyModal as done for SendModal + property BuyCryptoParamsForm buyFormData: BuyCryptoParamsForm {} } Settings { @@ -683,6 +687,13 @@ Item { savedAddressesModel: WalletStores.RootStore.savedAddresses recentRecipientsModel: appMain.transactionStore.tempActivityController1Model + onLaunchBuyFlowRequested: { + d.buyFormData.selectedWalletAddress = accountAddress + d.buyFormData.selectedNetworkChainId = chainId + d.buyFormData.selectedTokenKey = tokenKey + Global.openBuyCryptoModalRequested(d.buyFormData) + } + Component.onCompleted: { // It's requested from many nested places, so as a workaround we use // Global to shorten the path via global signal. diff --git a/ui/app/mainui/SendModalHandler.qml b/ui/app/mainui/SendModalHandler.qml index 4255e299f2..d44c2fe887 100644 --- a/ui/app/mainui/SendModalHandler.qml +++ b/ui/app/mainui/SendModalHandler.qml @@ -107,6 +107,8 @@ QtObject { /** required signal to receive resolved ens name address **/ signal ensNameResolved(string resolvedPubKey, string resolvedAddress, string uuid) + signal launchBuyFlowRequested(string accountAddress, string chainId, string tokenKey) + function openSend(params = {}) { // TODO remove once simple send is feature complete let sendModalCmp = root.simpleSendEnabled ? simpleSendModalComponent: sendModalComponent @@ -250,9 +252,7 @@ QtObject { } onFormChanged: { - estimatedCryptoFees = "" - estimatedFiatFees = "" - estimatedTime = "" + backendHandler.resetRouterValues() if(allValuesFilledCorrectly()) { backendHandler.uuid = Utils.uuid() simpleSendModal.routesLoading = true @@ -268,7 +268,11 @@ QtObject { // TODO: this should be called from the Reiew and Sign Modal instead onReviewSendClicked: { - root.transactionStoreNew.authenticateAndTransfer(uuid, selectedAccountAddress) + root.transactionStoreNew.authenticateAndTransfer(backendHandler.uuid, selectedAccountAddress) + } + + onLaunchBuyFlow: { + root.launchBuyFlowRequested(selectedAccountAddress, selectedChainId, selectedTokenKey) } readonly property var backendHandler: QtObject { @@ -286,6 +290,10 @@ QtObject { // Suggested routes for a different fetch, ignore return } + simpleSendModal.routerErrorCode = errCode + simpleSendModal.routerError = WalletUtils.getRouterErrorBasedOnCode(errCode) + simpleSendModal.routerErrorDetails = "%1 - %2".arg(errCode).arg( + WalletUtils.getRouterErrorDetailsOnCode(errCode, errDescription)) fetchedPathModel = pathModel // TODO: Handle errors here } @@ -377,6 +385,15 @@ QtObject { root.transactionStoreNew.suggestedRoutesReady.connect(routesFetched) root.transactionStoreNew.transactionSent.connect(transactionSent) } + + function resetRouterValues() { + simpleSendModal.estimatedCryptoFees = "" + simpleSendModal.estimatedFiatFees = "" + simpleSendModal.estimatedTime = "" + simpleSendModal.routerErrorCode = "" + simpleSendModal.routerError = "" + simpleSendModal.routerErrorDetails = "" + } } } }