diff --git a/ui/app/AppLayouts/Wallet/popups/swap/SwapInputParamsForm.qml b/ui/app/AppLayouts/Wallet/popups/swap/SwapInputParamsForm.qml index fdd9da578a..844a4673a6 100644 --- a/ui/app/AppLayouts/Wallet/popups/swap/SwapInputParamsForm.qml +++ b/ui/app/AppLayouts/Wallet/popups/swap/SwapInputParamsForm.qml @@ -20,7 +20,7 @@ QtObject { // default token key property string defaultToTokenKey: "" // 15 seconds - property int autoRefreshTime: 15000 + property int expirationTime: 15000 onSelectedAccountAddressChanged: root.formValuesChanged() onSelectedNetworkChainIdChanged: root.formValuesChanged() diff --git a/ui/app/AppLayouts/Wallet/popups/swap/SwapModal.qml b/ui/app/AppLayouts/Wallet/popups/swap/SwapModal.qml index e871fa41c4..848d0462f2 100644 --- a/ui/app/AppLayouts/Wallet/popups/swap/SwapModal.qml +++ b/ui/app/AppLayouts/Wallet/popups/swap/SwapModal.qml @@ -40,13 +40,7 @@ StatusDialog { }) function fetchSuggestedRoutes() { - if (root.swapInputParamsForm.isFormFilledCorrectly()) { - root.swapAdaptor.swapProposalLoading = true - } - root.swapAdaptor.validSwapProposalReceived = false - root.swapAdaptor.approvalPending = false - root.swapAdaptor.approvalSuccessful = false - root.swapAdaptor.swapOutputData.resetPathInfoAndError() + root.swapAdaptor.prepareFetchSuggestedRoutes() debounceFetchSuggestedRoutes() } @@ -61,6 +55,26 @@ StatusDialog { function addMetricsEvent(subEventName) { Global.addCentralizedMetricIfEnabled("swap", {subEvent: subEventName}) } + + property bool isReviewingApproveTx: false + property bool isReviewingSwapTx: false + readonly property bool hasStartedTxProcess: root.swapAdaptor.approvalPending || root.swapAdaptor.approvalSuccessful + readonly property bool canRefreshSwapProposal: !isReviewingApproveTx && !isReviewingSwapTx && !hasStartedTxProcess + + function checkSwapProposalAutoRefresh() { + // Refresh the swap proposal if it has expired and: + // - the user isn't reviewing/signing a transaction + // - the user hasn't placed an approval or swap tx + if (root.swapAdaptor.swapProposalExpired && d.canRefreshSwapProposal) { + d.fetchSuggestedRoutes() + } + } + + onCanRefreshSwapProposalChanged: { + if (canRefreshSwapProposal) { + d.checkSwapProposalAutoRefresh() + } + } } Connections { @@ -80,6 +94,16 @@ StatusDialog { } } + Connections { + target: root.swapAdaptor + + function onSwapProposalExpiredChanged() { + if (root.swapAdaptor.swapProposalExpired) { + d.checkSwapProposalAutoRefresh() + } + } + } + // needed as the first time the value not loaded correctly without this Binding Binding { target: root.swapAdaptor @@ -440,9 +464,7 @@ StatusDialog { feesLoading: root.swapAdaptor.swapProposalLoading fromTokenSymbol: root.swapAdaptor.fromToken.symbol - fromTokenAmount: SQUtils.AmountsArithmetic.div( - SQUtils.AmountsArithmetic.fromString(root.swapAdaptor.swapOutputData.approvalAmountRequired), - SQUtils.AmountsArithmetic.fromNumber(1, root.swapAdaptor.fromToken.decimals ?? 18)).toFixed() + fromTokenAmount: root.swapInputParamsForm.fromTokenAmount fromTokenContractAddress: SQUtils.ModelUtils.getByKey(root.swapAdaptor.fromToken.addressPerChain, "chainId", root.swapInputParamsForm.selectedNetworkChainId, "address") @@ -477,6 +499,10 @@ StatusDialog { d.addMetricsEvent("send approve tx") root.swapAdaptor.sendApproveTx() } + + onVisibleChanged: { + d.isReviewingApproveTx = visible + } } } @@ -533,6 +559,10 @@ StatusDialog { root.swapAdaptor.sendSwapTx() root.close() } + + onVisibleChanged: { + d.isReviewingSwapTx = visible + } } } } diff --git a/ui/app/AppLayouts/Wallet/popups/swap/SwapModalAdaptor.qml b/ui/app/AppLayouts/Wallet/popups/swap/SwapModalAdaptor.qml index 2d72b88b99..d3c9ace398 100644 --- a/ui/app/AppLayouts/Wallet/popups/swap/SwapModalAdaptor.qml +++ b/ui/app/AppLayouts/Wallet/popups/swap/SwapModalAdaptor.qml @@ -19,9 +19,10 @@ QObject { required property SwapInputParamsForm swapFormData required property SwapOutputData swapOutputData - // the below 2 properties holds the state of finding a swap proposal + // the below 3 properties holds the state of finding a swap proposal property bool validSwapProposalReceived: false property bool swapProposalLoading: false + property bool swapProposalExpired: false // We consider a swap proposal "expired" some time after it was received // the below 2 properties holds the state of finding a swap proposal property bool approvalPending: false @@ -193,6 +194,15 @@ QObject { } return "" } + + property Timer swapProposalExpiredTimer: Timer { + interval: root.swapFormData.expirationTime + running: false + repeat: false + onTriggered: { + root.swapProposalExpired = true + } + } } ModelEntry { @@ -246,6 +256,9 @@ QObject { root.swapOutputData.approvalContractAddress = !!bestPath ? bestPath.approvalContractAddress: "" root.swapOutputData.estimatedTime = !!bestPath ? bestPath.estimatedTime: Constants.TransactionEstimatedTime.Unknown root.swapOutputData.txProviderName = !!bestPath ? bestPath.bridgeName: "" + if (!root.swapProposalExpired) { + d.swapProposalExpiredTimer.start() + } } else { root.swapOutputData.hasError = true } @@ -274,6 +287,7 @@ QObject { } function reset() { + d.uuid = "" root.swapFormData.resetFormData() root.swapOutputData.reset() root.validSwapProposalReceived = false @@ -281,6 +295,8 @@ QObject { root.approvalPending = false root.approvalSuccessful = false d.txHash = "" + root.swapProposalExpired = false + d.swapProposalExpiredTimer.stop() } function formatCurrencyAmount(balance, symbol, options = null, locale = null) { @@ -302,6 +318,19 @@ QObject { return disabledChainIds.join(":") } + function prepareFetchSuggestedRoutes() { + d.uuid = "" + if (root.swapFormData.isFormFilledCorrectly()) { + root.swapProposalLoading = true + } + root.swapProposalExpired = false + d.swapProposalExpiredTimer.stop() + root.validSwapProposalReceived = false + root.approvalPending = false + root.approvalSuccessful = false + root.swapOutputData.resetPathInfoAndError() + } + function fetchSuggestedRoutes(cryptoValueInRaw) { root.swapFormData.toTokenAmount = "" if (root.swapFormData.isFormFilledCorrectly() && !!cryptoValueInRaw) {