diff --git a/src/app/modules/main/networks/model.nim b/src/app/modules/main/networks/model.nim index de4a543d6e..88a83508f9 100644 --- a/src/app/modules/main/networks/model.nim +++ b/src/app/modules/main/networks/model.nim @@ -176,3 +176,9 @@ QtObject: if(item.getShortName() == toLowerAscii(shortName)): return item.getChainId() return 0 + + proc getLayer1Network*(self: Model, testNet: bool): int = + for item in self.items: + if item.getLayer() == 1 and item.getIsTest() == testNet: + return item.getChainId() + return 0 diff --git a/src/app/modules/main/networks/view.nim b/src/app/modules/main/networks/view.nim index bdaed1e477..c969e75801 100644 --- a/src/app/modules/main/networks/view.nim +++ b/src/app/modules/main/networks/view.nim @@ -145,4 +145,7 @@ QtObject: QtProperty[QVariant] layer2Proxy: read = getLayer2Proxy - notify = layer2ProxyChanged \ No newline at end of file + notify = layer2ProxyChanged + + proc getMainnetChainId*(self: View): int {.slot.} = + return self.layer1.getLayer1Network(self.areTestNetworksEnabled) diff --git a/src/app_service/service/transaction/async_tasks.nim b/src/app_service/service/transaction/async_tasks.nim index 5af37887f6..99ac22733a 100644 --- a/src/app_service/service/transaction/async_tasks.nim +++ b/src/app_service/service/transaction/async_tasks.nim @@ -83,6 +83,12 @@ const getSuggestedRoutesTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall let response = eth.suggestedRoutes(arg.account, amountAsHex, arg.token, arg.disabledFromChainIDs, arg.disabledToChainIDs, arg.preferredChainIDs, arg.priority, arg.sendType).result var bestPaths = response["Best"].getElems().map(x => x.toTransactionPathDto()) + + # retry along with unpreferred chains incase no route is possible with preferred chains + if(bestPaths.len == 0 and arg.preferredChainIDs.len > 0): + let response = eth.suggestedRoutes(arg.account, amountAsHex, arg.token, arg.disabledFromChainIDs, arg.disabledToChainIDs, @[], arg.priority, arg.sendType).result + bestPaths = response["Best"].getElems().map(x => x.toTransactionPathDto()) + bestPaths.sort(sortAsc[TransactionPathDto]) let output = %*{ "suggestedRoutes": SuggestedRoutesDto( diff --git a/src/app_service/service/transaction/dto.nim b/src/app_service/service/transaction/dto.nim index d06e4c28a7..ef518b7197 100644 --- a/src/app_service/service/transaction/dto.nim +++ b/src/app_service/service/transaction/dto.nim @@ -162,7 +162,6 @@ type tokenFees*: float bonderFees*: string cost*: float - preferred*: bool estimatedTime*: int proc `$`*(self: TransactionPathDto): string = @@ -177,7 +176,6 @@ proc `$`*(self: TransactionPathDto): string = tokenFees:{self.tokenFees}, bonderFees:{self.bonderFees}, cost:{self.cost}, - preferred:{self.preferred}, estimatedTime:{self.estimatedTime} )""" @@ -195,7 +193,6 @@ proc toTransactionPathDto*(jsonObj: JsonNode): TransactionPathDto = result.amountOut = stint.fromHex(UInt256, jsonObj{"AmountOut"}.getStr) result.estimatedTime = jsonObj{"EstimatedTime"}.getInt discard jsonObj.getProp("GasAmount", result.gasAmount) - discard jsonObj.getProp("Preferred", result.preferred) proc convertToTransactionPathDto*(jsonObj: JsonNode): TransactionPathDto = result = TransactionPathDto() @@ -211,7 +208,6 @@ proc convertToTransactionPathDto*(jsonObj: JsonNode): TransactionPathDto = result.amountOut = stint.u256(jsonObj{"amountOut"}.getStr) result.estimatedTime = jsonObj{"estimatedTime"}.getInt discard jsonObj.getProp("gasAmount", result.gasAmount) - discard jsonObj.getProp("preferred", result.preferred) type Fees* = ref object diff --git a/ui/StatusQ/src/StatusQ/Components/StatusCard.qml b/ui/StatusQ/src/StatusQ/Components/StatusCard.qml index 7c87098bd8..927a26b241 100644 --- a/ui/StatusQ/src/StatusQ/Components/StatusCard.qml +++ b/ui/StatusQ/src/StatusQ/Components/StatusCard.qml @@ -183,7 +183,7 @@ Rectangle { id: basicInput StatusBaseText { id: secondaryLabel - Layout.maximumWidth: root.width - 12 + Layout.maximumWidth: root.width - cardIcon.width - errorIcon.width - 24 elide: Text.ElideRight font.pixelSize: 13 font.weight: Font.Medium diff --git a/ui/imports/shared/popups/SendModal.qml b/ui/imports/shared/popups/SendModal.qml index f98c17d546..42cecd71be 100644 --- a/ui/imports/shared/popups/SendModal.qml +++ b/ui/imports/shared/popups/SendModal.qml @@ -75,7 +75,7 @@ StatusDialog { let amount = parseFloat(amountToSendInput.text) * Math.pow(10, assetSelector.selectedAsset.decimals) popup.store.suggestedRoutes(popup.selectedAccount.address, amount.toString(16), assetSelector.selectedAsset.symbol, store.disabledChainIdsFromList, store.disabledChainIdsToList, - d.preferredChainIds, fees.selectedPriority, popup.sendType) + store.preferredChainIds, fees.selectedPriority, popup.sendType) } }) @@ -102,7 +102,6 @@ StatusDialog { property string resolvedENSAddress readonly property string uuid: Utils.uuid() property bool isPendingTx: false - property var preferredChainIds: [] property bool sendTxError: false property string sendTxErrorString @@ -120,7 +119,7 @@ StatusDialog { } else { let chainColor = popup.store.allNetworks.getNetworkColor(splitWords[i]) if(!!chainColor) { - d.addPreferredChain(popup.store.allNetworks.getNetworkChainId(splitWords[i])) + store.addPreferredChain(popup.store.allNetworks.getNetworkChainId(splitWords[i])) editedText += `%2`.arg(chainColor).arg(splitWords[i])+':' } } @@ -130,16 +129,6 @@ StatusDialog { popup.recalculateRoutesAndFees() } } - - function addPreferredChain(chainID) { - if(!chainID) - return - - if(preferredChainIds.includes(chainID)) - return - - preferredChainIds.push(chainID) - } } width: 556 @@ -153,6 +142,9 @@ StatusDialog { onSelectedAccountChanged: popup.recalculateRoutesAndFees() onOpened: { + store.addPreferredChain(popup.store.getMainnetChainId()) + store.addUnpreferredChainsToDisabledChains() + amountToSendInput.input.edit.forceActiveFocus() if(!!popup.preSelectedAsset) { diff --git a/ui/imports/shared/stores/TransactionStore.qml b/ui/imports/shared/stores/TransactionStore.qml index 8efb18e55b..0bff282f42 100644 --- a/ui/imports/shared/stores/TransactionStore.qml +++ b/ui/imports/shared/stores/TransactionStore.qml @@ -121,4 +121,30 @@ QtObject { function plainText(text) { return globalUtils.plainText(text) } + + property var preferredChainIds: [] + + function addPreferredChain(chainID) { + if(!chainID) + return + + if(preferredChainIds.includes(chainID)) + return + + preferredChainIds.push(chainID) + } + + function getMainnetChainId() { + return networksModule.getMainnetChainId() + } + + function addUnpreferredChainsToDisabledChains() { + let mainnetChainId = getMainnetChainId() + for(var i = 0; i < allNetworks.count; i++) { + let chainId = allNetworks.rowData(i, "chainId") * 1 + if(mainnetChainId !== chainId) { + addRemoveDisabledToChain(chainId, true) + } + } + } } diff --git a/ui/imports/shared/views/NetworkCardsComponent.qml b/ui/imports/shared/views/NetworkCardsComponent.qml index 6b766f7fc0..415c027390 100644 --- a/ui/imports/shared/views/NetworkCardsComponent.qml +++ b/ui/imports/shared/views/NetworkCardsComponent.qml @@ -31,6 +31,7 @@ Item { } } property bool interactive: true + property bool showPreferredChains: false property var weiToEth: function(wei) {} property var reCalculateSuggestedRoute: function() {} @@ -49,16 +50,19 @@ Item { toNetworksRepeater.itemAt(i).routeOnNetwork = 0 } } + + function draw() { + canvas.clear() + canvas.requestPaint() + } } + onVisibleChanged: if(visible) d.draw() + onBestRoutesChanged: d.draw() + width: 410 height: visible ? networkCardsLayout.height : 0 - onBestRoutesChanged: { - canvas.clear() - canvas.requestPaint() - } - RowLayout { id: networkCardsLayout width: parent.width @@ -131,12 +135,12 @@ Item { objectName: model.chainId property int routeOnNetwork: 0 property double amountToReceive: 0 + property bool preferred: store.preferredChainIds.includes(model.chainId) primaryText: model.chainName secondaryText: LocaleUtils.numberToLocaleString(amountToReceive) - tertiaryText: "" - // To-do preferred in not something that is supported yet - state: root.errorMode ? "error" : "default" - // opacity: preferred ? 1 : 0 + tertiaryText: state === "unpreferred" ? qsTr("UNPREFERRED") : "" + state: root.errorMode ? "error" : !preferred ? "unpreferred" : "default" + opacity: preferred || showPreferredChains ? 1 : 0 cardIcon.source: Style.svg(model.iconUrl) disabledText: qsTr("Disabled") advancedMode: root.customMode @@ -150,9 +154,20 @@ Item { root.reCalculateSuggestedRoute() } onVisibleChanged: { - if(visible) + if(visible) { disabled = store.disabledChainIdsToList.includes(model.chainId) + preferred = store.preferredChainIds.includes(model.chainId) + } } + onOpacityChanged: { + if(opacity === 1) { + disabled = store.disabledChainIdsToList.includes(model.chainId) + } else { + if(opacity === 0 && routeOnNetwork > 0) + root.reCalculateSuggestedRoute() + } + } + // To-do needed for custom view // onAdvancedInputTextChanged: { // if(selectedNetwork && selectedNetwork.chainName === model.chainName) @@ -217,11 +232,12 @@ Item { fromN.routeOnNetwork += 1 toN.routeOnNetwork += 1 d.thereIsApossibleRoute = true + let routeColor = toN.preferred ? '#627EEA' : Theme.palette.pinColor1 StatusQUtils.Utils.drawArrow(ctx, fromN.x + fromN.width, fromN.y + fromN.cardIconPosition + yOffsetFrom, toNetworksLayout.x + toN.x, toN.y + toN.cardIconPosition + yOffsetTo, - '#627EEA', xOffset) + routeColor, xOffset) } } } diff --git a/ui/imports/shared/views/NetworksAdvancedCustomRoutingView.qml b/ui/imports/shared/views/NetworksAdvancedCustomRoutingView.qml index 1a9f8a4d94..1750c9788c 100644 --- a/ui/imports/shared/views/NetworksAdvancedCustomRoutingView.qml +++ b/ui/imports/shared/views/NetworksAdvancedCustomRoutingView.qml @@ -50,12 +50,17 @@ ColumnLayout { wrapMode: Text.WordWrap } StatusButton { + id: preferredToggleButton Layout.alignment: Qt.AlignRight Layout.preferredHeight: 22 - verticalPadding: 0 + verticalPadding: -1 + checkable: true size: StatusBaseButton.Size.Small - icon.name: "hide" - text: qsTr("Show Unpreferred Networks") + icon.name: checked ? "show" : "hide" + icon.height: 16 + icon.width: 16 + text: checked ? qsTr("Hide Unpreferred Networks"): qsTr("Show Unpreferred Networks") + onToggled: if(!checked) store.addUnpreferredChainsToDisabledChains() } } StatusBaseText { @@ -90,6 +95,7 @@ ColumnLayout { reCalculateSuggestedRoute: function() { root.reCalculateSuggestedRoute() } + showPreferredChains: preferredToggleButton.checked bestRoutes: root.bestRoutes weiToEth: root.weiToEth interactive: root.interactive