diff --git a/src/app/modules/main/wallet_section/activity/entry.nim b/src/app/modules/main/wallet_section/activity/entry.nim index e6247dda50..ee1a766a3b 100644 --- a/src/app/modules/main/wallet_section/activity/entry.nim +++ b/src/app/modules/main/wallet_section/activity/entry.nim @@ -197,6 +197,15 @@ QtObject: QtProperty[QVariant] totalFees: read = getTotalFees + proc getMaxTotalFees*(self: ActivityEntry): QVariant {.slot.} = + if self.transaction == nil: + error "getMaxTotalFees: ActivityEntry is not an transaction.Item" + return newQVariant(newCurrencyAmount()) + return newQVariant(self.transaction[].getMaxTotalFees()) + + QtProperty[QVariant] maxTotalFees: + read = getMaxTotalFees + proc getInput*(self: ActivityEntry): string {.slot.} = if self.transaction == nil: error "getInput: ActivityEntry is not an transaction.Item" diff --git a/src/app/modules/main/wallet_section/transactions/module.nim b/src/app/modules/main/wallet_section/transactions/module.nim index 0b31dc0fb8..a0d174c473 100644 --- a/src/app/modules/main/wallet_section/transactions/module.nim +++ b/src/app/modules/main/wallet_section/transactions/module.nim @@ -56,6 +56,8 @@ proc getResolvedSymbol*(self: Module, transaction: TransactionDto): string = let contractSymbol = self.controller.findTokenSymbolByAddress(transaction.contract) if contractSymbol != "": result = contractSymbol + elif transaction.typeValue == "erc20": + result = "" else: result = "ETH" diff --git a/ui/app/AppLayouts/Wallet/views/TransactionDetailView.qml b/ui/app/AppLayouts/Wallet/views/TransactionDetailView.qml index d376ed8fbe..cb2fc41235 100644 --- a/ui/app/AppLayouts/Wallet/views/TransactionDetailView.qml +++ b/ui/app/AppLayouts/Wallet/views/TransactionDetailView.qml @@ -51,12 +51,30 @@ Item { readonly property string inSymbol: isTransactionValid ? transaction.inSymbol : "" readonly property string outSymbol: isTransactionValid ? transaction.outSymbol : "" readonly property var multichainNetworks: [] // TODO fill icon for networks for multichain - readonly property string fiatValueFormatted: root.isTransactionValid && !transactionHeader.isMultiTransaction ? RootStore.formatCurrencyAmount(transactionHeader.fiatValue, RootStore.currentCurrency) : "" - readonly property string cryptoValueFormatted: root.isTransactionValid && !transactionHeader.isMultiTransaction ? RootStore.formatCurrencyAmount(transaction.amount, transaction.symbol) : "" - readonly property string outFiatValueFormatted: root.isTransactionValid && transactionHeader.isMultiTransaction ? RootStore.formatCurrencyAmount(transactionHeader.outFiatValue, RootStore.currentCurrency) : "" - readonly property string outCryptoValueFormatted: root.isTransactionValid && transactionHeader.isMultiTransaction ? RootStore.formatCurrencyAmount(transaction.outAmount, transaction.outSymbol) : "" + readonly property string fiatValueFormatted: { + if (!root.isTransactionValid || transactionHeader.isMultiTransaction || !symbol) + return "" + return RootStore.formatCurrencyAmount(transactionHeader.fiatValue, RootStore.currentCurrency) + } + readonly property string cryptoValueFormatted: { + if (!root.isTransactionValid || transactionHeader.isMultiTransaction) + return "" + const formatted = RootStore.formatCurrencyAmount(transaction.amount, transaction.symbol) + return symbol || !transaction.contract ? formatted : "%1 (%2)".arg(formatted).arg(Utils.compactAddress(transaction.contract, 4)) + } + readonly property string outFiatValueFormatted: { + if (!root.isTransactionValid || !transactionHeader.isMultiTransaction || !outSymbol) + return "" + return RootStore.formatCurrencyAmount(transactionHeader.outFiatValue, RootStore.currentCurrency) + } + readonly property string outCryptoValueFormatted: { + if (!root.isTransactionValid || !transactionHeader.isMultiTransaction) + return "" + const formatted = RootStore.formatCurrencyAmount(transaction.outAmount, transaction.outSymbol) + return outSymbol || !transaction.contract ? formatted : "%1 (%2)".arg(formatted).arg(Utils.compactAddress(transaction.contract, 4)) + } readonly property real feeEthValue: root.isTransactionValid ? RootStore.getGasEthValue(transaction.totalFees.amount, 1) : 0 // TODO use directly? - readonly property real feeFiatValue: root.isTransactionValid ? RootStore.getFiatValue(d.feeEthValue, "ETH", RootStore.currentCurrency) : 0 // TODO use directly? + readonly property real feeFiatValue: root.isTransactionValid ? RootStore.getFiatValue(d.feeEthValue, Constants.ethToken, RootStore.currentCurrency) : 0 // TODO use directly? readonly property int transactionType: root.isTransactionValid ? transaction.txType : Constants.TransactionType.Send readonly property string toNetworkName: "" // TODO fill network name for bridge @@ -294,7 +312,11 @@ Item { TransactionContractTile { // Used to display contract address for any network address: root.isTransactionValid ? transaction.contract : "" - symbol: root.isTransactionValid ? d.symbol : "" + symbol: { + if (!root.isTransactionValid) + return "" + return d.symbol ? d.symbol : "(%1)".arg(Utils.compactAddress(transaction.contract, 4)) + } networkName: transactionHeader.networkName shortNetworkName: d.networkShortName } @@ -553,10 +575,15 @@ Item { } TransactionDataTile { width: parent.width - title: qsTr("Fees") + title: d.symbol ? qsTr("Fees") : qsTr("Estimated max fee") subTitle: { if (!root.isTransactionValid || transactionHeader.isNFT) return "" + if (!d.symbol) { + const maxFeeEth = RootStore.getGasEthValue(transaction.maxTotalFees.amount, 1) + return RootStore.formatCurrencyAmount(maxFeeEth, Constants.ethToken) + } + switch(d.transactionType) { case Constants.TransactionType.Send: case Constants.TransactionType.Swap: @@ -566,7 +593,18 @@ Item { return "" } } - tertiaryTitle: !!subTitle ? RootStore.formatCurrencyAmount(d.feeFiatValue, RootStore.currentCurrency) : "" + tertiaryTitle: { + if (!subTitle) + return "" + let fiatValue + if (!d.symbol) { + const maxFeeEth = RootStore.getGasEthValue(transaction.maxTotalFees.amount, 1) + fiatValue = RootStore.getFiatValue(maxFeeEth, Constants.ethToken, RootStore.currentCurrency) + } else { + fiatValue = d.feeFiatValue + } + return RootStore.formatCurrencyAmount(fiatValue, RootStore.currentCurrency) + } visible: !!subTitle } TransactionDataTile { @@ -574,19 +612,19 @@ Item { // Using fees in this tile because of same higlight and color settings as Total title: d.transactionType === Constants.TransactionType.Destroy || transactionHeader.isNFT ? qsTr("Fees") : qsTr("Total") subTitle: { - if (transactionHeader.isNFT && d.isIncoming) + if ((transactionHeader.isNFT && d.isIncoming) || !d.symbol) return "" const type = d.transactionType if (type === Constants.TransactionType.Destroy || transactionHeader.isNFT) { - return RootStore.formatCurrencyAmount(d.feeEthValue, "ETH") + return RootStore.formatCurrencyAmount(d.feeEthValue, Constants.ethToken) } else if (type === Constants.TransactionType.Receive || (type === Constants.TransactionType.Buy && progressBlock.isLayer1)) { return d.cryptoValueFormatted } const cryptoValue = transactionHeader.isMultiTransaction ? d.outCryptoValueFormatted : d.cryptoValueFormatted - return "%1 + %2".arg(cryptoValue).arg(RootStore.formatCurrencyAmount(d.feeEthValue, "ETH")) + return "%1 + %2".arg(cryptoValue).arg(RootStore.formatCurrencyAmount(d.feeEthValue, Constants.ethToken)) } tertiaryTitle: { - if (transactionHeader.isNFT && d.isIncoming) + if ((transactionHeader.isNFT && d.isIncoming) || !d.symbol) return "" const type = d.transactionType if (type === Constants.TransactionType.Destroy || transactionHeader.isNFT) { diff --git a/ui/imports/shared/controls/TransactionDelegate.qml b/ui/imports/shared/controls/TransactionDelegate.qml index b5bbeb77aa..78bb2ab116 100644 --- a/ui/imports/shared/controls/TransactionDelegate.qml +++ b/ui/imports/shared/controls/TransactionDelegate.qml @@ -68,7 +68,10 @@ StatusListItem { return qsTr("N/A") } else if (root.isNFT) { return modelData.nftName ? modelData.nftName : "#" + modelData.tokenID + } else if (!modelData.symbol) { + return "%1 (%2)".arg(root.rootStore.formatCurrencyAmount(cryptoValue, "")).arg(Utils.compactAddress(modelData.contract, 4)) } + return root.rootStore.formatCurrencyAmount(cryptoValue, modelData.symbol) } @@ -273,7 +276,8 @@ StatusListItem { details += protocolFromContractAddress + endl2 } if (!!modelData.contract) { - details += qsTr("%1 %2 contract address").arg(root.networkName).arg(modelData.symbol) + endl + let symbol = !!modelData.symbol || !modelData.contract ? modelData.symbol : "(%1)".arg(Utils.compactAddress(modelData.contract, 4)) + details += qsTr("%1 %2 contract address").arg(root.networkName).arg(symbol) + endl details += modelData.contract + endl2 } const protocolToContractAddress = "" // TODO fill protocol contract address for 'to' network for Bridge @@ -376,8 +380,8 @@ StatusListItem { details += valuesString + endl2 } - // Remove locale specific number separator - details = details.replace(/\ /, ' ') + // Remove unicode characters + details = details.replace(/[^\x00-\x7F]/g, " "); // Remove empty new lines at the end return details.replace(/[\r\n\s]*$/, '') } @@ -602,7 +606,7 @@ StatusListItem { text: { if (root.loading) { return "dummy text" - } else if (!root.isModelDataValid || root.isNFT) { + } else if (!root.isModelDataValid || root.isNFT || !modelData.symbol) { return "" } diff --git a/ui/imports/utils/Constants.qml b/ui/imports/utils/Constants.qml index 5fb43dd69a..e986768b19 100644 --- a/ui/imports/utils/Constants.qml +++ b/ui/imports/utils/Constants.qml @@ -822,6 +822,8 @@ QtObject { readonly property string networkMainnet: "Mainnet" readonly property string networkRopsten: "Ropsten" + readonly property string ethToken: "ETH" + readonly property QtObject networkShortChainNames: QtObject { readonly property string mainnet: "eth" readonly property string arbiscan: "arb"