feat(@desktop/wallet): Implements auto refresh

fixes #14952
This commit is contained in:
Khushboo Mehta 2024-07-04 00:08:03 +02:00 committed by Khushboo-dev-cpp
parent 3049c6016b
commit 2df35ff0c9
8 changed files with 74 additions and 40 deletions

View File

@ -150,11 +150,7 @@ Item {
// verify loading state was set and no errors currently // verify loading state was set and no errors currently
verify(!root.swapAdaptor.validSwapProposalReceived) verify(!root.swapAdaptor.validSwapProposalReceived)
verify(root.swapAdaptor.swapProposalLoading) verify(root.swapAdaptor.swapProposalLoading)
compare(root.swapAdaptor.swapOutputData.fromTokenAmount, "") compare(root.swapAdaptor.swapOutputData.rawPaths, [])
compare(root.swapAdaptor.swapOutputData.toTokenAmount, "")
compare(root.swapAdaptor.swapOutputData.totalFees, 0)
compare(root.swapAdaptor.swapOutputData.bestRoutes, [])
compare(root.swapAdaptor.swapOutputData.approvalNeeded, false)
compare(root.swapAdaptor.swapOutputData.hasError, false) compare(root.swapAdaptor.swapOutputData.hasError, false)
// verfy input and output panels // verfy input and output panels
@ -589,7 +585,6 @@ Item {
compare(root.swapAdaptor.swapOutputData.fromTokenAmount, "") compare(root.swapAdaptor.swapOutputData.fromTokenAmount, "")
compare(root.swapAdaptor.swapOutputData.toTokenAmount, "") compare(root.swapAdaptor.swapOutputData.toTokenAmount, "")
compare(root.swapAdaptor.swapOutputData.totalFees, 0) compare(root.swapAdaptor.swapOutputData.totalFees, 0)
compare(root.swapAdaptor.swapOutputData.bestRoutes, [])
compare(root.swapAdaptor.swapOutputData.approvalNeeded, false) compare(root.swapAdaptor.swapOutputData.approvalNeeded, false)
compare(root.swapAdaptor.swapOutputData.hasError, true) compare(root.swapAdaptor.swapOutputData.hasError, true)
verify(errorTag.visible) verify(errorTag.visible)
@ -638,7 +633,6 @@ Item {
let totalFees = root.swapAdaptor.currencyStore.getFiatValue(gasTimeEstimate.totalFeesInEth, Constants.ethToken) + totalTokenFeesInFiat let totalFees = root.swapAdaptor.currencyStore.getFiatValue(gasTimeEstimate.totalFeesInEth, Constants.ethToken) + totalTokenFeesInFiat
compare(root.swapAdaptor.swapOutputData.totalFees, totalFees) compare(root.swapAdaptor.swapOutputData.totalFees, totalFees)
compare(root.swapAdaptor.swapOutputData.bestRoutes, txRoutes.suggestedRoutes)
compare(root.swapAdaptor.swapOutputData.approvalNeeded, false) compare(root.swapAdaptor.swapOutputData.approvalNeeded, false)
compare(root.swapAdaptor.swapOutputData.hasError, false) compare(root.swapAdaptor.swapOutputData.hasError, false)
verify(!errorTag.visible) verify(!errorTag.visible)
@ -686,7 +680,6 @@ Item {
totalFees = root.swapAdaptor.currencyStore.getFiatValue(gasTimeEstimate.totalFeesInEth, Constants.ethToken) + totalTokenFeesInFiat totalFees = root.swapAdaptor.currencyStore.getFiatValue(gasTimeEstimate.totalFeesInEth, Constants.ethToken) + totalTokenFeesInFiat
compare(root.swapAdaptor.swapOutputData.totalFees, totalFees) compare(root.swapAdaptor.swapOutputData.totalFees, totalFees)
compare(root.swapAdaptor.swapOutputData.bestRoutes, txRoutes2.suggestedRoutes)
compare(root.swapAdaptor.swapOutputData.approvalNeeded, true) compare(root.swapAdaptor.swapOutputData.approvalNeeded, true)
compare(root.swapAdaptor.swapOutputData.hasError, false) compare(root.swapAdaptor.swapOutputData.hasError, false)
verify(!errorTag.visible) verify(!errorTag.visible)
@ -1333,7 +1326,6 @@ Item {
SQUtils.AmountsArithmetic.fromString(txRoutes.amountToReceive), SQUtils.AmountsArithmetic.fromString(txRoutes.amountToReceive),
SQUtils.AmountsArithmetic.fromNumber(1, root.swapAdaptor.toToken.decimals)).toString()) SQUtils.AmountsArithmetic.fromNumber(1, root.swapAdaptor.toToken.decimals)).toString())
compare(root.swapAdaptor.swapOutputData.totalFees, totalFees) compare(root.swapAdaptor.swapOutputData.totalFees, totalFees)
compare(root.swapAdaptor.swapOutputData.bestRoutes, txRoutes.suggestedRoutes)
compare(root.swapAdaptor.swapOutputData.hasError, false) compare(root.swapAdaptor.swapOutputData.hasError, false)
compare(root.swapAdaptor.swapOutputData.estimatedTime, bestPath.estimatedTime) compare(root.swapAdaptor.swapOutputData.estimatedTime, bestPath.estimatedTime)
compare(root.swapAdaptor.swapOutputData.txProviderName, bestPath.bridgeName) compare(root.swapAdaptor.swapOutputData.txProviderName, bestPath.bridgeName)
@ -1414,7 +1406,7 @@ Item {
let txHasRouteNoApproval = root.dummySwapTransactionRoutes.txHasRouteNoApproval let txHasRouteNoApproval = root.dummySwapTransactionRoutes.txHasRouteNoApproval
txHasRouteNoApproval.uuid = root.swapAdaptor.uuid txHasRouteNoApproval.uuid = root.swapAdaptor.uuid
root.swapStore.suggestedRoutesReady(root.dummySwapTransactionRoutes.txHasRouteNoApproval) root.swapStore.suggestedRoutesReady(txHasRouteNoApproval)
verify(!root.swapAdaptor.approvalPending) verify(!root.swapAdaptor.approvalPending)
verify(!root.swapAdaptor.approvalSuccessful) verify(!root.swapAdaptor.approvalSuccessful)
@ -1571,5 +1563,29 @@ Item {
closeAndVerfyModal() closeAndVerfyModal()
} }
function test_auto_refresh() {
// Asset chosen but no pay value set state -------------------------------------------------------------------------------
root.swapFormData.fromTokenAmount = "0.0001"
root.swapFormData.selectedAccountAddress = "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240"
root.swapFormData.selectedNetworkChainId = 11155111
root.swapFormData.fromTokensKey = "ETH"
// for testing making it 1.5 seconds so as to not make tests running too long
root.swapFormData.autoRefreshTime = 1500
// Launch popup
launchAndVerfyModal()
// check if fetchSuggestedRoutes called
fetchSuggestedRoutesCalled.wait()
// emit routes ready
let txHasRouteNoApproval = root.dummySwapTransactionRoutes.txHasRouteNoApproval
txHasRouteNoApproval.uuid = root.swapAdaptor.uuid
root.swapStore.suggestedRoutesReady(txHasRouteNoApproval)
// check if fetch occurs automatically after 15 seconds
fetchSuggestedRoutesCalled.wait()
}
} }
} }

View File

@ -87,13 +87,16 @@ QtObject {
The obtained amount can be multiplied or compared. The obtained amount can be multiplied or compared.
Provided number is assumed to be an amount in basic units, an integer. Provided number is assumed to be an amount in basic units, an integer.
returns NaN in case the conversion fails.
*/ */
function fromString(numStr) { function fromString(numStr) {
console.assert(typeof numStr === "string") console.assert(typeof numStr === "string")
const amount = new Big.Big(numStr) try {
// TODO: restore assert when permissions handled as bigints return new Big.Big(numStr)
//console.assert(amount.eq(amount.round())) } catch(e) {
return amount return NaN
}
} }
/*! /*!

View File

@ -63,6 +63,10 @@ Control {
property int swapExchangeButtonWidth: 44 property int swapExchangeButtonWidth: 44
property string caption: swapSide === SwapInputPanel.SwapSide.Pay ? qsTr("Pay") : qsTr("Receive") property string caption: swapSide === SwapInputPanel.SwapSide.Pay ? qsTr("Pay") : qsTr("Receive")
function forceActiveFocus() {
amountToSendInput.input.forceActiveFocus()
}
enum SwapSide { enum SwapSide {
Pay = 0, Pay = 0,
Receive = 1 Receive = 1

View File

@ -19,6 +19,8 @@ QtObject {
// default token key // default token key
property string defaultToTokenKey: "" property string defaultToTokenKey: ""
// 15 seconds
property int autoRefreshTime: 15000
onSelectedAccountAddressChanged: root.formValuesChanged() onSelectedAccountAddressChanged: root.formValuesChanged()
onSelectedNetworkChainIdChanged: root.formValuesChanged() onSelectedNetworkChainIdChanged: root.formValuesChanged()
@ -50,15 +52,13 @@ QtObject {
} }
function isFormFilledCorrectly() { function isFormFilledCorrectly() {
let bigIntNumber = SQUtils.AmountsArithmetic.fromString(root.fromTokenAmount)
return !!root.selectedAccountAddress && return !!root.selectedAccountAddress &&
root.selectedNetworkChainId !== -1 && root.selectedNetworkChainId !== -1 &&
!!root.fromTokensKey && !!root.toTokenKey && !!root.fromTokensKey && !!root.toTokenKey &&
((!!root.fromTokenAmount && (!!root.fromTokenAmount &&
!isNaN(SQUtils.AmountsArithmetic.fromString(root.fromTokenAmount)) && !isNaN(bigIntNumber) &&
SQUtils.AmountsArithmetic.fromString(root.fromTokenAmount) > 0) || SQUtils.AmountsArithmetic.cmp(bigIntNumber, 0) === 1) &&
(!!root.toTokenAmount &&
!isNaN(SQUtils.AmountsArithmetic.fromString(root.toTokenAmount)) &&
SQUtils.AmountsArithmetic.fromString(root.toTokenAmount) > 0 )) &&
root.selectedSlippage > 0 root.selectedSlippage > 0
} }
} }

View File

@ -36,13 +36,20 @@ StatusDialog {
root.swapAdaptor.fetchSuggestedRoutes(payPanel.rawValue) root.swapAdaptor.fetchSuggestedRoutes(payPanel.rawValue)
}) })
property Timer autoRefreshTimer: Timer {
interval: root.swapInputParamsForm.autoRefreshTime
running: false
repeat: false
onTriggered: d.fetchSuggestedRoutes()
}
function fetchSuggestedRoutes() { function fetchSuggestedRoutes() {
if (payPanel.valueValid && root.swapInputParamsForm.isFormFilledCorrectly()) { if (payPanel.valueValid && root.swapInputParamsForm.isFormFilledCorrectly()) {
root.swapAdaptor.validSwapProposalReceived = false root.swapAdaptor.validSwapProposalReceived = false
root.swapAdaptor.swapProposalLoading = true root.swapAdaptor.swapProposalLoading = true
root.swapAdaptor.approvalPending = false root.swapAdaptor.approvalPending = false
root.swapAdaptor.approvalSuccessful = false root.swapAdaptor.approvalSuccessful = false
root.swapAdaptor.swapOutputData.resetAllButReceivedTokenValuesForSwap() root.swapAdaptor.swapOutputData.resetPathInfoAndError()
debounceFetchSuggestedRoutes() debounceFetchSuggestedRoutes()
} }
} }
@ -71,6 +78,10 @@ StatusDialog {
d.fetchSuggestedRoutes() d.fetchSuggestedRoutes()
} }
} }
function onSuggestedRoutesReady() {
if(!root.swapAdaptor.swapProposalLoading)
d.autoRefreshTimer.restart()
}
} }
Behavior on implicitHeight { Behavior on implicitHeight {
@ -257,6 +268,7 @@ StatusDialog {
root.swapInputParamsForm.fromTokenAmount = !!root.swapAdaptor.swapOutputData.toTokenAmount ? root.swapAdaptor.swapOutputData.toTokenAmount : root.swapInputParamsForm.toTokenAmount root.swapInputParamsForm.fromTokenAmount = !!root.swapAdaptor.swapOutputData.toTokenAmount ? root.swapAdaptor.swapOutputData.toTokenAmount : root.swapInputParamsForm.toTokenAmount
root.swapInputParamsForm.toTokenKey = tempPayToken root.swapInputParamsForm.toTokenKey = tempPayToken
root.swapInputParamsForm.toTokenAmount = tempPayAmount root.swapInputParamsForm.toTokenAmount = tempPayAmount
payPanel.forceActiveFocus()
} }
} }
} }

View File

@ -76,6 +76,8 @@ QObject {
filters: ValueFilter { roleName: "isTest"; value: root.swapStore.areTestNetworksEnabled } filters: ValueFilter { roleName: "isTest"; value: root.swapStore.areTestNetworksEnabled }
} }
signal suggestedRoutesReady()
QtObject { QtObject {
id: d id: d
@ -163,7 +165,6 @@ QObject {
// if valid route was found // if valid route was found
if(txRoutes.suggestedRoutes.count === 1) { if(txRoutes.suggestedRoutes.count === 1) {
root.validSwapProposalReceived = true root.validSwapProposalReceived = true
root.swapOutputData.bestRoutes = txRoutes.suggestedRoutes
root.swapOutputData.toTokenAmount = AmountsArithmetic.div(AmountsArithmetic.fromString(txRoutes.amountToReceive), AmountsArithmetic.fromNumber(1, root.toToken.decimals)).toString() root.swapOutputData.toTokenAmount = AmountsArithmetic.div(AmountsArithmetic.fromString(txRoutes.amountToReceive), AmountsArithmetic.fromNumber(1, root.toToken.decimals)).toString()
let gasTimeEstimate = txRoutes.gasTimeEstimate let gasTimeEstimate = txRoutes.gasTimeEstimate
@ -171,7 +172,7 @@ QObject {
if (!!root.fromToken && !!root.fromToken.marketDetails && !!root.fromToken.marketDetails.currencyPrice) if (!!root.fromToken && !!root.fromToken.marketDetails && !!root.fromToken.marketDetails.currencyPrice)
totalTokenFeesInFiat = gasTimeEstimate.totalTokenFees * root.fromToken.marketDetails.currencyPrice.amount totalTokenFeesInFiat = gasTimeEstimate.totalTokenFees * root.fromToken.marketDetails.currencyPrice.amount
root.swapOutputData.totalFees = root.currencyStore.getFiatValue(gasTimeEstimate.totalFeesInEth, Constants.ethToken) + totalTokenFeesInFiat root.swapOutputData.totalFees = root.currencyStore.getFiatValue(gasTimeEstimate.totalFeesInEth, Constants.ethToken) + totalTokenFeesInFiat
let bestPath = ModelUtils.get(root.swapOutputData.bestRoutes, 0, "route") let bestPath = ModelUtils.get(txRoutes.suggestedRoutes, 0, "route")
root.swapOutputData.approvalNeeded = !!bestPath ? bestPath.approvalRequired: false root.swapOutputData.approvalNeeded = !!bestPath ? bestPath.approvalRequired: false
root.swapOutputData.approvalGasFees = !!bestPath ? bestPath.approvalGasFees.toString() : "" root.swapOutputData.approvalGasFees = !!bestPath ? bestPath.approvalGasFees.toString() : ""
root.swapOutputData.approvalAmountRequired = !!bestPath ? bestPath.approvalAmountRequired: "" root.swapOutputData.approvalAmountRequired = !!bestPath ? bestPath.approvalAmountRequired: ""
@ -182,6 +183,7 @@ QObject {
else { else {
root.swapOutputData.hasError = true root.swapOutputData.hasError = true
} }
root.suggestedRoutesReady()
} }
function onTransactionSent(chainId, txHash, uuid, error) { function onTransactionSent(chainId, txHash, uuid, error) {
@ -247,12 +249,12 @@ QObject {
} }
function fetchSuggestedRoutes(cryptoValueInRaw) { function fetchSuggestedRoutes(cryptoValueInRaw) {
root.swapFormData.toTokenAmount = ""
if (root.swapFormData.isFormFilledCorrectly() && !!cryptoValueInRaw) { if (root.swapFormData.isFormFilledCorrectly() && !!cryptoValueInRaw) {
// Identify new swap with a different uuid // Identify new swap with a different uuid
d.uuid = Utils.uuid() d.uuid = Utils.uuid()
root.swapProposalLoading = true root.swapProposalLoading = true
root.swapOutputData.reset()
let account = selectedAccountEntry.item let account = selectedAccountEntry.item
let accountAddress = account.address let accountAddress = account.address
@ -263,6 +265,7 @@ QObject {
disabledChainIds, disabledChainIds, Constants.SendType.Swap, "") disabledChainIds, disabledChainIds, Constants.SendType.Swap, "")
} else { } else {
root.swapProposalLoading = false root.swapProposalLoading = false
root.swapOutputData.reset()
} }
} }

View File

@ -11,7 +11,6 @@ QtObject {
property string toTokenAmount: "" property string toTokenAmount: ""
// TODO: this should be string but backend gas_estimate_item.nim passes this as float // TODO: this should be string but backend gas_estimate_item.nim passes this as float
property real totalFees: 0 property real totalFees: 0
property var bestRoutes: []
property bool hasError property bool hasError
property var rawPaths: [] property var rawPaths: []
// need to check how this is done in new router v2, right now it is Enum type // need to check how this is done in new router v2, right now it is Enum type
@ -22,24 +21,22 @@ QtObject {
property string approvalAmountRequired property string approvalAmountRequired
property string approvalContractAddress property string approvalContractAddress
function resetPathInfoAndError() {
root.hasError = false
root.rawPaths = []
}
function reset() { function reset() {
root.fromTokenAmount = "" root.fromTokenAmount = ""
root.toTokenAmount = "" root.toTokenAmount = ""
root.resetAllButReceivedTokenValuesForSwap() root.txProviderName = ""
}
function resetAllButReceivedTokenValuesForSwap() {
root.totalFees = 0
root.bestRoutes = []
root.approvalNeeded = false
root.hasError = false
root.rawPaths = []
root.estimatedTime = Constants.TransactionEstimatedTime.Unknown root.estimatedTime = Constants.TransactionEstimatedTime.Unknown
txProviderName = "" root.totalFees = 0
approvalNeeded = false root.approvalNeeded = false
approvalGasFees = "" root.approvalGasFees = ""
approvalAmountRequired = "" root.approvalAmountRequired = ""
approvalContractAddress = "" root.approvalContractAddress = ""
resetPathInfoAndError()
} }
} }

View File

@ -351,7 +351,6 @@ StatusDialog {
Layout.maximumWidth: 60 Layout.maximumWidth: 60
titleText: qsTr("Max slippage:") titleText: qsTr("Max slippage:")
infoText: "%1%".arg(LocaleUtils.numberToLocaleString(root.swapSignApproveInputForm.selectedSlippage)) infoText: "%1%".arg(LocaleUtils.numberToLocaleString(root.swapSignApproveInputForm.selectedSlippage))
loading: root.loading
visible: !d.isApproveTx visible: !d.isApproveTx
} }
} }