diff --git a/src/app/modules/main/wallet_section/activity/controller.nim b/src/app/modules/main/wallet_section/activity/controller.nim
index f7f8dc080f..9480355de8 100644
--- a/src/app/modules/main/wallet_section/activity/controller.nim
+++ b/src/app/modules/main/wallet_section/activity/controller.nim
@@ -21,7 +21,6 @@ import app_service/service/currency/service as currency_service
import app_service/service/transaction/service as transaction_service
import app_service/service/token/service as token_service
-
proc toRef*[T](obj: T): ref T =
new(result)
result[] = obj
diff --git a/src/app/modules/main/wallet_section/activity/entry.nim b/src/app/modules/main/wallet_section/activity/entry.nim
index a6f96a1d07..e6247dda50 100644
--- a/src/app/modules/main/wallet_section/activity/entry.nim
+++ b/src/app/modules/main/wallet_section/activity/entry.nim
@@ -93,38 +93,27 @@ QtObject:
return self.transaction
proc getSender*(self: ActivityEntry): string {.slot.} =
- # TODO: lookup sender's name
if self.isMultiTransaction():
return self.multi_transaction.fromAddress
-
+ if self.transaction == nil:
+ error "getSender: ActivityEntry is not an transaction.Item"
+ return ""
return self.transaction[].getfrom()
QtProperty[string] sender:
read = getSender
proc getRecipient*(self: ActivityEntry): string {.slot.} =
- # TODO: lookup recipient name
if self.isMultiTransaction():
return self.multi_transaction.toAddress
-
+ if self.transaction == nil:
+ error "getRecipient: ActivityEntry is not an transaction.Item"
+ return ""
return self.transaction[].getTo()
QtProperty[string] recipient:
read = getRecipient
- proc getInAmount*(self: ActivityEntry): float {.slot.} =
- return float(self.extradata.inAmount)
-
- QtProperty[float] inAmount:
- read = getInAmount
-
- proc getOutAmount*(self: ActivityEntry): float {.slot.} =
- return float(self.extradata.outAmount)
-
- QtProperty[float] outAmount:
- read = getOutAmount
-
-
proc getInSymbol*(self: ActivityEntry): string {.slot.} =
return self.extradata.inSymbol
@@ -137,9 +126,20 @@ QtObject:
QtProperty[string] outSymbol:
read = getOutSymbol
+ proc getSymbol*(self: ActivityEntry): string {.slot.} =
+ if self.metadata.activityType == backend.ActivityType.Receive:
+ return self.getInSymbol()
+ return self.getOutSymbol()
+
+ QtProperty[string] symbol:
+ read = getSymbol
+
proc getTimestamp*(self: ActivityEntry): int {.slot.} =
if self.isMultiTransaction():
return self.multi_transaction.timestamp
+ if self.transaction == nil:
+ error "getTimestamp: ActivityEntry is not an transaction.Item"
+ return 0
# TODO: should we account for self.transaction[].isTimeStamp?
return self.transaction[].getTimestamp()
@@ -191,7 +191,7 @@ QtObject:
proc getTotalFees*(self: ActivityEntry): QVariant {.slot.} =
if self.transaction == nil:
error "getTotalFees: ActivityEntry is not an transaction.Item"
- return newQVariant(0)
+ return newQVariant(newCurrencyAmount())
return newQVariant(self.transaction[].getTotalFees())
QtProperty[QVariant] totalFees:
@@ -257,47 +257,31 @@ QtObject:
QtProperty[string] nonce:
read = getNonce
-# TODO: Replaced usage of these for in/out versions in the QML modules
- proc getSymbol*(self: ActivityEntry): string {.slot.} =
+ proc getBlockNumber*(self: ActivityEntry): string {.slot.} =
if self.transaction == nil:
- error "getSymbol: ActivityEntry is not an transaction.Item"
+ error "getBlockNumber: ActivityEntry is not an transaction.Item"
return ""
+ return $self.transaction[].getBlockNumber()
- if self.metadata.activityType == backend.ActivityType.Receive:
- return self.getInSymbol()
+ QtProperty[string] blockNumber:
+ read = getBlockNumber
- return self.getOutSymbol()
+ proc getOutAmount*(self: ActivityEntry): float {.slot.} =
+ return float(self.extradata.outAmount)
- QtProperty[string] symbol:
- read = getSymbol
+ QtProperty[float] outAmount:
+ read = getOutAmount
- proc getFromAmount*(self: ActivityEntry): float {.slot.} =
- if self.isMultiTransaction():
- return self.getOutAmount()
- error "getFromAmount: ActivityEntry is not a MultiTransaction"
- return 0.0
+ proc getInAmount*(self: ActivityEntry): float {.slot.} =
+ return float(self.extradata.inAmount)
- QtProperty[float] fromAmount:
- read = getFromAmount
-
- proc getToAmount*(self: ActivityEntry): float {.slot.} =
- if self.isMultiTransaction():
- return self.getInAmount()
- error "getToAmount: ActivityEntry is not a MultiTransaction"
- return 0.0
-
- QtProperty[float] toAmount:
- read = getToAmount
-
- proc getValue*(self: ActivityEntry): float {.slot.} =
- if self.isMultiTransaction():
- error "getToAmount: ActivityEntry is a MultiTransaction"
- return 0.0
+ QtProperty[float] inAmount:
+ read = getInAmount
+ proc getAmount*(self: ActivityEntry): float {.slot.} =
if self.metadata.activityType == backend.ActivityType.Receive:
return self.getInAmount()
-
return self.getOutAmount()
- QtProperty[float] value:
- read = getValue
\ No newline at end of file
+ QtProperty[float] amount:
+ read = getAmount
diff --git a/ui/app/AppLayouts/Wallet/views/TransactionDetailView.qml b/ui/app/AppLayouts/Wallet/views/TransactionDetailView.qml
index 9fc9fb5315..f7987b8af7 100644
--- a/ui/app/AppLayouts/Wallet/views/TransactionDetailView.qml
+++ b/ui/app/AppLayouts/Wallet/views/TransactionDetailView.qml
@@ -39,33 +39,25 @@ Item {
QtObject {
id: d
- readonly property bool isIncoming: root.isTransactionValid ? root.transaction.recipient.toLowerCase() === root.overview.mixedcaseAddress.toLowerCase() : false
- readonly property bool isNFT: root.isTransactionValid ? root.transaction.isNFT : false
- readonly property string savedAddressNameTo: root.isTransactionValid ? d.getNameForSavedWalletAddress(transaction.recipient) : ""
- readonly property string savedAddressNameFrom: root.isTransactionValid ? d.getNameForSavedWalletAddress(transaction.sender): ""
- readonly property string from: root.isTransactionValid ? !!savedAddressNameFrom ? savedAddressNameFrom : Utils.compactAddress(transaction.sender, 4): ""
- readonly property string to: root.isTransactionValid ? !!savedAddressNameTo ? savedAddressNameTo : Utils.compactAddress(transaction.recipient, 4): ""
- readonly property string savedAddressEns: root.isTransactionValid ? RootStore.getEnsForSavedWalletAddress(isIncoming ? transaction.sender : transaction.recipient) : ""
- readonly property string savedAddressChains: root.isTransactionValid ? RootStore.getChainShortNamesForSavedWalletAddress(isIncoming ? transaction.sender : transaction.recipient) : ""
+ readonly property bool isIncoming: transactionType === Constants.TransactionType.Received
readonly property string networkShortName: root.isTransactionValid ? RootStore.getNetworkShortName(transaction.chainId) : ""
- readonly property string networkFullName: root.isTransactionValid ? RootStore.getNetworkFullName(transaction.chainId): ""
- readonly property string networkIcon: root.isTransactionValid ? RootStore.getNetworkIcon(transaction.chainId): ""
+ readonly property string networkIcon: isTransactionValid ? RootStore.getNetworkIcon(transaction.chainId) : ""
readonly property int blockNumber: root.isTransactionValid ? RootStore.hex2Dec(root.transaction.blockNumber) : 0
- readonly property string bridgeNetworkIcon: "" // TODO fill when bridge data is implemented
- readonly property string bridgeNetworkFullname: "" // TODO fill when bridge data is implemented
- readonly property string bridgeNetworkShortName: "" // TODO fill when bridge data is implemented
- readonly property int bridgeBlockNumber: 0 // TODO fill when bridge data is implemented
- readonly property double swapCryptoValue: 0 // TODO fill when swap data is implemented
- readonly property string swapSymbol: "" // TODO fill when swap data is implemented
- readonly property string symbol: root.isTransactionValid ? transaction.symbol : ""
+ readonly property int toBlockNumber: 0 // TODO fill when bridge data is implemented
+ readonly property string toNetworkIcon: "" // TODO fill when bridge data is implemented
+ readonly property string toNetworkShortName: "" // TODO fill when bridge data is implemented
+ readonly property string symbol: isTransactionValid ? transaction.symbol : ""
+ 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 double cryptoValue: root.isTransactionValid ? transaction.value : 0.0
- readonly property double fiatValue: root.isTransactionValid ? RootStore.getFiatValue(cryptoValue, symbol, RootStore.currentCurrency): 0.0
- readonly property string fiatValueFormatted: root.isTransactionValid ? RootStore.formatCurrencyAmount(d.fiatValue, RootStore.currentCurrency) : ""
- readonly property string cryptoValueFormatted: root.isTransactionValid ? RootStore.formatCurrencyAmount(d.cryptoValue, symbol) : ""
- readonly property real feeEthValue: root.isTransactionValid && transaction.totalFees ? RootStore.getGasEthValue(transaction.totalFees.amount, 1) : 0
- readonly property real feeFiatValue: root.isTransactionValid ? RootStore.getFiatValue(d.feeEthValue, "ETH", RootStore.currentCurrency) : 0
+ 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 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 int transactionType: root.isTransactionValid ? transaction.txType : Constants.TransactionType.Send
+ readonly property string toNetworkName: "" // TODO fill network name for bridge
property string decodedInputData: ""
@@ -116,26 +108,15 @@ Item {
objectName: "transactionDetailHeader"
width: parent.width
leftPadding: 0
-
- modelData: transaction
- currentCurrency: RootStore.currentCurrency
- cryptoValue: d.cryptoValue
- fiatValue: d.fiatValue
- networkIcon: d.networkIcon
- networkColor: root.isTransactionValid ? RootStore.getNetworkColor(transaction.chainId): ""
- networkName: d.networkFullName
- swapSymbol: d.swapSymbol
- bridgeNetworkName: d.bridgeNetworkFullname
- symbol: d.symbol
- transactionStatus: root.isTransactionValid ? transaction.status : Constants.TransactionStatus.Pending
- timeStampText: root.isTransactionValid ? qsTr("Signed at %1").arg(LocaleUtils.formatDateTime(transaction.timestamp * 1000, Locale.LongFormat)): ""
- addressNameTo: root.isTransactionValid ? WalletStores.RootStore.getNameForAddress(transaction.recipient): ""
- addressNameFrom: root.isTransactionValid ? WalletStores.RootStore.getNameForAddress(transaction.sender): ""
sensor.enabled: false
- rootStore: RootStore
- walletRootStore: WalletStores.RootStore
color: Theme.palette.transparent
state: "header"
+
+ modelData: transaction
+ timeStampText: root.isTransactionValid ? qsTr("Signed at %1").arg(LocaleUtils.formatDateTime(transaction.timestamp * 1000, Locale.LongFormat)): ""
+ rootStore: RootStore
+ walletRootStore: WalletStores.RootStore
+
onRetryClicked: d.retryTransaction()
}
@@ -148,7 +129,7 @@ Item {
error: transactionHeader.transactionStatus === Constants.TransactionStatus.Failed
isLayer1: root.isTransactionValid && RootStore.getNetworkLayer(root.transaction.chainId) == 1
confirmations: root.isTransactionValid ? Math.abs(WalletStores.RootStore.getLatestBlockNumber(root.transaction.chainId) - d.blockNumber): 0
- chainName: d.networkFullName
+ chainName: transactionHeader.networkName
timeStamp: root.isTransactionValid ? transaction.timestamp: ""
}
@@ -157,7 +138,7 @@ Item {
}
WalletNftPreview {
- visible: root.isTransactionValid && d.isNFT && !!transaction.nftImageUrl
+ visible: root.isTransactionValid && transactionHeader.isNFT && !!transaction.nftImageUrl
width: Math.min(304, progressBlock.width)
nftName: root.isTransactionValid ? transaction.nftName : ""
nftUrl: root.isTransactionValid && !!transaction.nftImageUrl ? transaction.nftImageUrl : ""
@@ -187,8 +168,7 @@ Item {
RowLayout {
spacing: 0
width: parent.width
- height: opacity > 0 ? Math.max(implicitHeight, 85) : 0
- opacity: fromNetworkTile.visible || toNetworkTile.visible ? 1 : 0
+ height: fromNetworkTile.visible || toNetworkTile.visible ? 85 : 0
TransactionDataTile {
id: fromNetworkTile
Layout.fillWidth: true
@@ -197,9 +177,9 @@ Item {
subTitle: {
switch(d.transactionType) {
case Constants.TransactionType.Swap:
- return d.symbol
+ return d.outSymbol
case Constants.TransactionType.Bridge:
- return d.networkFullName
+ return transactionHeader.networkName
default:
return ""
}
@@ -207,7 +187,7 @@ Item {
asset.name: {
switch(d.transactionType) {
case Constants.TransactionType.Swap:
- return !!d.symbol ? Constants.tokenIcon(d.symbol) : ""
+ return !!d.outSymbol ? Constants.tokenIcon(d.outSymbol) : ""
case Constants.TransactionType.Bridge:
return !!d.networkIcon ? Style.svg(d.networkIcon) : ""
default:
@@ -224,9 +204,9 @@ Item {
subTitle: {
switch(d.transactionType) {
case Constants.TransactionType.Swap:
- return d.swapSymbol
+ return d.inSymbol
case Constants.TransactionType.Bridge:
- return d.bridgeNetworkFullname
+ return d.toNetworkName
default:
return ""
}
@@ -234,9 +214,9 @@ Item {
asset.name: {
switch(d.transactionType) {
case Constants.TransactionType.Swap:
- return !!d.swapSymbol ? Constants.tokenIcon(d.swapSymbol) : ""
+ return !!d.inSymbol ? Constants.tokenIcon(d.inSymbol) : ""
case Constants.TransactionType.Bridge:
- return !!d.bridgeNetworkIcon ? Style.svg(d.bridgeNetworkIcon) : ""
+ return !!d.toNetworkIcon ? Style.svg(d.toNetworkIcon) : ""
default:
return ""
}
@@ -262,7 +242,7 @@ Item {
TransactionAddressTile {
width: parent.width
title: qsTr("To")
- addresses: root.isTransactionValid ? [root.transaction.recipient] : []
+ addresses: root.isTransactionValid && visible ? [root.transaction.recipient] : []
contactsStore: root.contactsStore
rootStore: WalletStores.RootStore
onButtonClicked: addressMenu.openReceiverMenu(this, addresses[0], d.networkShortName)
@@ -281,7 +261,7 @@ Item {
}
TransactionDataTile {
width: parent.width
- title: qsTr("%1 Tx hash").arg(d.networkFullName)
+ title: qsTr("%1 Tx hash").arg(transactionHeader.networkName)
subTitle: root.isTransactionValid ? root.transaction.txHash : ""
visible: !!subTitle
buttonIconName: "more"
@@ -289,17 +269,17 @@ Item {
}
TransactionDataTile {
width: parent.width
- title: qsTr("%1 Tx hash").arg(d.bridgeNetworkFullname)
+ title: qsTr("%1 Tx hash").arg(d.toNetworkName)
subTitle: "" // TODO fill tx hash for Bridge
visible: !!subTitle
buttonIconName: "more"
- onButtonClicked: addressMenu.openTxMenu(this, subTitle, d.bridgeNetworkShortName)
+ onButtonClicked: addressMenu.openTxMenu(this, subTitle, d.toNetworkShortName)
}
TransactionContractTile {
// Used for Bridge and Swap to display 'From' network Protocol contract address
address: "" // TODO fill protocol contract address for 'from' network for Bridge and Swap
symbol: "" // TODO fill protocol name for Bridge and Swap
- networkName: d.networkFullName
+ networkName: transactionHeader.networkName
shortNetworkName: d.networkShortName
visible: !!subTitle && (d.transactionType === Constants.TransactionType.Bridge || d.transactionType === Constants.TransactionType.Swap)
}
@@ -307,15 +287,15 @@ Item {
// Used to display contract address for any network
address: root.isTransactionValid ? transaction.contract : ""
symbol: root.isTransactionValid ? d.symbol : ""
- networkName: d.networkFullName
+ networkName: transactionHeader.networkName
shortNetworkName: d.networkShortName
}
TransactionContractTile {
// Used for Bridge to display 'To' network Protocol contract address
address: "" // TODO fill protocol contract address for 'to' network for Bridge
symbol: "" // TODO fill protocol name for Bridge
- networkName: d.bridgeNetworkFullname
- shortNetworkName: d.bridgeNetworkShortName
+ networkName: d.toNetworkName
+ shortNetworkName: d.toNetworkShortName
visible: !!subTitle && d.transactionType === Constants.TransactionType.Bridge
}
TransactionContractTile {
@@ -337,15 +317,15 @@ Item {
return ""
switch(d.transactionType) {
case Constants.TransactionType.Swap:
- return d.swapSymbol
+ return d.inSymbol
case Constants.TransactionType.Bridge:
- return d.symbol
+ return d.outSymbol
default:
return ""
}
}
- networkName: d.bridgeNetworkFullname
- shortNetworkName: d.bridgeNetworkShortName
+ networkName: d.toNetworkName
+ shortNetworkName: d.toNetworkShortName
visible: root.isTransactionValid && !!subTitle
}
}
@@ -393,7 +373,7 @@ Item {
Layout.fillHeight: true
Layout.fillWidth: true
title: qsTr("Network")
- subTitle: d.networkFullName
+ subTitle: transactionHeader.networkName
asset.name: !!d.networkIcon ? Style.svg("%1".arg(d.networkIcon)) : ""
smallIcon: true
visible: d.transactionType !== Constants.TransactionType.Bridge
@@ -446,17 +426,17 @@ Item {
}
TransactionDataTile {
width: parent.width
- title: !!d.networkFullName ? qsTr("Included in Block on %1").arg(d.networkFullName) : qsTr("Included on Block")
+ title: !!transactionHeader.networkName ? qsTr("Included in Block on %1").arg(transactionHeader.networkName) : qsTr("Included on Block")
subTitle: d.blockNumber
tertiaryTitle: root.isTransactionValid ? LocaleUtils.formatDateTime(transaction.timestamp * 1000, Locale.LongFormat) : ""
visible: d.blockNumber > 0
}
TransactionDataTile {
width: parent.width
- title: !!d.bridgeNetworkFullname ? qsTr("Included in Block on %1").arg(d.bridgeNetworkFullname) : qsTr("Included on Block")
- subTitle: d.bridgeBlockNumber
+ title: !!d.toNetworkName ? qsTr("Included in Block on %1").arg(d.toNetworkName) : qsTr("Included on Block")
+ subTitle: d.toBlockNumber
tertiaryTitle: root.isTransactionValid ? LocaleUtils.formatDateTime(transaction.timestamp * 1000, Locale.LongFormat) : ""
- visible: d.bridgeBlockNumber > 0
+ visible: d.toBlockNumber > 0
}
}
}
@@ -464,7 +444,7 @@ Item {
Column {
width: progressBlock.width
spacing: Style.current.smallPadding
- visible: !(d.isNFT && d.isIncoming)
+ visible: !(transactionHeader.isNFT && d.isIncoming)
RowLayout {
width: parent.width
@@ -489,10 +469,10 @@ Item {
TransactionDataTile {
width: parent.width
title: qsTr("Amount sent")
- subTitle: d.cryptoValueFormatted
- tertiaryTitle: d.fiatValueFormatted
+ subTitle: transactionHeader.isMultiTransaction ? d.outCryptoValueFormatted : d.cryptoValueFormatted
+ tertiaryTitle: transactionHeader.isMultiTransaction ? d.outFiatValueFormatted : d.fiatValueFormatted
visible: {
- if (d.isNFT)
+ if (transactionHeader.isNFT)
return false
switch(d.transactionType) {
case Constants.TransactionType.Send:
@@ -508,24 +488,24 @@ Item {
width: parent.width
title: transactionHeader.transactionStatus === Constants.TransactionType.Pending ? qsTr("Amount to receive") : qsTr("Amount received")
subTitle: {
- if (d.isNFT)
+ if (!root.isTransactionValid || transactionHeader.isNFT)
return ""
const type = d.transactionType
if (type === Constants.TransactionType.Swap) {
- return RootStore.formatCurrencyAmount(d.swapCryptoValue, d.swapSymbol)
+ return RootStore.formatCurrencyAmount(transactionHeader.inCryptoValue, d.inSymbol)
} else if (type === Constants.TransactionType.Bridge) {
// Reduce crypto value by fee value
- const valueInCrypto = RootStore.getCryptoValue(d.fiatValue - d.feeFiatValue, d.symbol, RootStore.currentCurrency)
- return RootStore.formatCurrencyAmount(valueInCrypto, d.symbol)
+ const valueInCrypto = RootStore.getCryptoValue(transactionHeader.fiatValue - d.feeFiatValue, d.inSymbol, RootStore.currentCurrency)
+ return RootStore.formatCurrencyAmount(valueInCrypto, d.inSymbol)
}
return ""
}
tertiaryTitle: {
const type = d.transactionType
if (type === Constants.TransactionType.Swap) {
- return RootStore.formatCurrencyAmount(d.swapCryptoValue, d.swapSymbol)
+ return RootStore.formatCurrencyAmount(transactionHeader.inFiatValue, RootStore.currentCurrency)
} else if (type === Constants.TransactionType.Bridge) {
- return RootStore.formatCurrencyAmount(d.fiatValue - d.feeFiatValue, RootStore.currentCurrency)
+ return RootStore.formatCurrencyAmount(transactionHeader.fiatValue - d.feeFiatValue, RootStore.currentCurrency)
}
return ""
}
@@ -535,7 +515,7 @@ Item {
width: parent.width
title: qsTr("Fees")
subTitle: {
- if (!root.isTransactionValid || d.isNFT)
+ if (!root.isTransactionValid || transactionHeader.isNFT)
return ""
switch(d.transactionType) {
case Constants.TransactionType.Send:
@@ -552,28 +532,30 @@ Item {
TransactionDataTile {
width: parent.width
// Using fees in this tile because of same higlight and color settings as Total
- title: d.transactionType === Constants.TransactionType.Destroy || d.isNFT ? qsTr("Fees") : qsTr("Total")
+ title: d.transactionType === Constants.TransactionType.Destroy || transactionHeader.isNFT ? qsTr("Fees") : qsTr("Total")
subTitle: {
- if (d.isNFT && d.isIncoming)
+ if (transactionHeader.isNFT && d.isIncoming)
return ""
const type = d.transactionType
- if (type === Constants.TransactionType.Destroy || d.isNFT) {
+ if (type === Constants.TransactionType.Destroy || transactionHeader.isNFT) {
return RootStore.formatCurrencyAmount(d.feeEthValue, "ETH")
} else if (type === Constants.TransactionType.Receive || (type === Constants.TransactionType.Buy && progressBlock.isLayer1)) {
return d.cryptoValueFormatted
}
- return "%1 + %2".arg(d.cryptoValueFormatted).arg(RootStore.formatCurrencyAmount(d.feeEthValue, "ETH"))
+ const cryptoValue = transactionHeader.isMultiTransaction ? d.outCryptoValueFormatted : d.cryptoValueFormatted
+ return "%1 + %2".arg(cryptoValue).arg(RootStore.formatCurrencyAmount(d.feeEthValue, "ETH"))
}
tertiaryTitle: {
- if (d.isNFT && d.isIncoming)
+ if (transactionHeader.isNFT && d.isIncoming)
return ""
const type = d.transactionType
- if (type === Constants.TransactionType.Destroy || d.isNFT) {
+ if (type === Constants.TransactionType.Destroy || transactionHeader.isNFT) {
return RootStore.formatCurrencyAmount(d.feeFiatValue, RootStore.currentCurrency)
} else if (type === Constants.TransactionType.Receive || (type === Constants.TransactionType.Buy && progressBlock.isLayer1)) {
return d.fiatValueFormatted
}
- return RootStore.formatCurrencyAmount(d.fiatValue + d.feeFiatValue, RootStore.currentCurrency)
+ const fiatValue = transactionHeader.isMultiTransaction ? transactionHeader.outFiatValue : transactionHeader.fiatValue
+ return RootStore.formatCurrencyAmount(fiatValue + d.feeFiatValue, RootStore.currentCurrency)
}
visible: !!subTitle
highlighted: true
@@ -624,7 +606,22 @@ Item {
component DetailsPanel: Item {
width: parent.width
- height: detailsColumn.childrenRect.height
+ height: {
+ // Using childrenRect and transactionvalid properties to refresh this binding
+ if (!isTransactionValid || detailsColumn.childrenRect.height === 0)
+ return 0
+
+ // Height is calculated from visible children because Column doesn't handle
+ // visibility change properly and childrenRect.height gives different values
+ // comparing to manual check
+ var visibleHeight = 0
+ for (var i = 0 ; i < detailsColumn.children.length ; i++) {
+ if (detailsColumn.children[i].visible)
+ visibleHeight += detailsColumn.children[i].height
+ }
+ return visibleHeight
+ }
+
default property alias content: detailsColumn.children
Rectangle {
@@ -659,7 +656,7 @@ Item {
property string address: ""
property string shortNetworkName: ""
width: parent.width
- title: qsTr("%1 %2 contract address").arg(networkName).arg(symbol)
+ title: visible ? qsTr("%1 %2 contract address").arg(networkName).arg(symbol) : ""
subTitle: !!address && !/0x0+$/.test(address) ? address : ""
buttonIconName: "more"
visible: !!subTitle
diff --git a/ui/imports/shared/controls/TransactionAddress.qml b/ui/imports/shared/controls/TransactionAddress.qml
index 8772bb9ef0..1dfc299be8 100644
--- a/ui/imports/shared/controls/TransactionAddress.qml
+++ b/ui/imports/shared/controls/TransactionAddress.qml
@@ -64,7 +64,7 @@ Item {
charactersLen: 2
}
- implicitHeight: Math.max(identicon.height, contentColumn.height) + 12
+ implicitHeight: Math.max(44, contentColumn.height) + 12
QtObject {
id: d
diff --git a/ui/imports/shared/controls/TransactionDataTile.qml b/ui/imports/shared/controls/TransactionDataTile.qml
index 85e441da13..89fcfc42a1 100644
--- a/ui/imports/shared/controls/TransactionDataTile.qml
+++ b/ui/imports/shared/controls/TransactionDataTile.qml
@@ -62,7 +62,7 @@ StatusListItem {
height: visible ? implicitHeight + bottomPadding : 0
radius: 0
sensor.cursorShape: Qt.ArrowCursor
- color: sensor.containsMouse ? Theme.palette.baseColor5 : Style.current.transparent
+ color: sensor.containsMouse || highlighted ? Theme.palette.baseColor5 : Style.current.transparent
// Title
statusListItemTitle.customColor: Theme.palette.directColor5
diff --git a/ui/imports/shared/controls/TransactionDelegate.qml b/ui/imports/shared/controls/TransactionDelegate.qml
index 960d9499c3..b5bbeb77aa 100644
--- a/ui/imports/shared/controls/TransactionDelegate.qml
+++ b/ui/imports/shared/controls/TransactionDelegate.qml
@@ -23,23 +23,10 @@ import shared 1.0
TransactionDelegate {
id: delegate
width: ListView.view.width
- modelData: model
- swapCryptoValue: 0.18
- swapFiatValue: 340
- swapSymbol: "SNT"
- timeStampText: LocaleUtils.formatRelativeTimestamp(modelData.timestamp * 1000)
- cryptoValue: 0.1234
- fiatValue: 123123
- currentCurrency: "USD"
- networkName: "Optimism"
- symbol: "ETH"
- bridgeNetworkName: "Mainnet"
- feeFiatValue: 10.34
- feeCryptoValue: 0.013
- transactionStatus: TransactionDelegate.Pending
- transactionType: TransactionDelegate.Send
+ modelData: model.activityEntry
rootStore: RootStore
- loading: isModelDataValid && modelData.loadingTransaction
+ walletRootStore: WalletStore.RootStore
+ loading: isModelDataValid
}
\endqml
@@ -52,59 +39,53 @@ StatusListItem {
signal retryClicked()
property var modelData
- property string symbol
- property string swapSymbol // TODO fill when swap data is implemented
- property int transactionStatus
- property string currentCurrency
- property double cryptoValue
- property double swapCryptoValue // TODO fill when swap data is implemented
- property double fiatValue
- property double swapFiatValue // TODO fill when swap data is implemented
- property double feeCryptoValue // TODO fill when bridge data is implemented
- property double feeFiatValue // TODO fill when bridge data is implemented
- property string networkIcon
- property string networkColor
- property string networkName
- property string bridgeNetworkName // TODO fill when bridge data is implemented
- property string timeStampText
- property string addressNameTo
- property string addressNameFrom
- property var rootStore
- property var walletRootStore
+ property string timeStampText: isModelDataValid ? LocaleUtils.formatRelativeTimestamp(modelData.timestamp * 1000) : ""
+
+ required property var rootStore
+ required property var walletRootStore
readonly property bool isModelDataValid: modelData !== undefined && !!modelData
+
+ readonly property int transactionStatus: isModelDataValid ? modelData.status : Constants.TransactionStatus.Pending
+ readonly property bool isMultiTransaction: isModelDataValid && modelData.isMultiTransaction
+ readonly property string currentCurrency: rootStore.currentCurrency
+ readonly property double cryptoValue: isModelDataValid && !isMultiTransaction ? modelData.amount : 0.0
+ readonly property double fiatValue: isModelDataValid && !isMultiTransaction ? rootStore.getFiatValue(cryptoValue, modelData.symbol, currentCurrency) : 0.0
+ readonly property double inCryptoValue: isModelDataValid ? modelData.inAmount : 0.0
+ readonly property double inFiatValue: isModelDataValid && isMultiTransaction ? rootStore.getFiatValue(inCryptoValue, modelData.inSymbol, currentCurrency): 0.0
+ readonly property double outCryptoValue: isModelDataValid ? modelData.outAmount : 0.0
+ readonly property double outFiatValue: isModelDataValid && isMultiTransaction ? rootStore.getFiatValue(outCryptoValue, modelData.outSymbol, currentCurrency): 0.0
+ readonly property double feeCryptoValue: 0.0 // TODO fill when bridge data is implemented
+ readonly property double feeFiatValue: 0.0 // TODO fill when bridge data is implemented
+ readonly property string networkColor: isModelDataValid ? rootStore.getNetworkColor(modelData.chainId) : ""
+ readonly property string networkName: isModelDataValid ? rootStore.getNetworkFullName(modelData.chainId) : ""
+ readonly property string addressNameTo: isModelDataValid ? walletRootStore.getNameForAddress(modelData.recipient) : ""
+ readonly property string addressNameFrom: isModelDataValid ? walletRootStore.getNameForAddress(modelData.sender) : ""
readonly property bool isNFT: isModelDataValid && modelData.isNFT
+
readonly property string transactionValue: {
- if (!isModelDataValid)
- return qsTr("N/A")
- if (root.isNFT) {
- return modelData.nftName ? modelData.nftName : "#" + modelData.tokenID
- } else {
- return root.rootStore.formatCurrencyAmount(cryptoValue, symbol)
- }
- }
- readonly property string swapTransactionValue: {
if (!isModelDataValid) {
return qsTr("N/A")
+ } else if (root.isNFT) {
+ return modelData.nftName ? modelData.nftName : "#" + modelData.tokenID
}
- return root.rootStore.formatCurrencyAmount(swapCryptoValue, swapSymbol)
+ return root.rootStore.formatCurrencyAmount(cryptoValue, modelData.symbol)
}
+ readonly property string inTransactionValue: isModelDataValid && isMultiTransaction ? rootStore.formatCurrencyAmount(inCryptoValue, modelData.inSymbol) : qsTr("N/A")
+ readonly property string outTransactionValue: isModelDataValid && isMultiTransaction ? rootStore.formatCurrencyAmount(outCryptoValue, modelData.outSymbol) : qsTr("N/A")
+
readonly property string tokenImage: {
if (!isModelDataValid)
return ""
if (root.isNFT) {
return modelData.nftImageUrl ? modelData.nftImageUrl : ""
} else {
- return Constants.tokenIcon(root.symbol)
+ return Constants.tokenIcon(isMultiTransaction ? modelData.outSymbol : modelData.symbol)
}
}
- readonly property string swapTokenImage: {
- if (!isModelDataValid)
- return ""
- return Constants.tokenIcon(root.swapSymbol)
- }
+ readonly property string inTokenImage: isModelDataValid ? Constants.tokenIcon(modelData.inSymbol) : ""
readonly property string toAddress: !!addressNameTo ?
addressNameTo :
@@ -168,7 +149,7 @@ StatusListItem {
const endl = "\n"
const endl2 = endl + endl
const type = modelData.txType
- const feeEthValue = modelData.totalFees ? rootStore.getGasEthValue(modelData.totalFees.amount, 1) : 0
+ const feeEthValue = rootStore.getGasEthValue(modelData.totalFees.amount, 1)
// TITLE
switch (type) {
@@ -258,20 +239,21 @@ StatusListItem {
}
// SUMMARY ADRESSES
+ const toNetworkName = "" // TODO fill when bridge data is implemented
switch (type) {
case Constants.TransactionType.Swap:
- details += qsTr("From") + endl + root.symbol + endl2
- details += qsTr("To") + endl + root.swapSymbol + endl2
+ details += qsTr("From") + endl + modelData.outSymbol + endl2
+ details += qsTr("To") + endl + modelData.inSymbol + endl2
details += qsTr("In") + endl + root.fromAddress + endl2
break
case Constants.TransactionType.Bridge:
details += qsTr("From") + endl + root.networkName + endl2
- details += qsTr("To") + endl + root.bridgeNetworkName + endl2
+ details += qsTr("To") + endl + toNetworkName + endl2
details += qsTr("In") + endl + modelData.from + endl2
break
default:
- details += qsTr("From") + endl + modelData.from + endl2
- details += qsTr("To") + endl + modelData.to + endl2
+ details += qsTr("From") + endl + modelData.sender + endl2
+ details += qsTr("To") + endl + modelData.recipient + endl2
break
}
const protocolName = "" // TODO fill protocol name for Bridge and Swap
@@ -283,7 +265,7 @@ StatusListItem {
}
const bridgeTxHash = "" // TODO fill tx hash for Bridge
if (!!bridgeTxHash) {
- details += qsTr("%1 Tx hash").arg(root.bridgeNetworkName) + endl + bridgeTxHash + endl2
+ details += qsTr("%1 Tx hash").arg(toNetworkName) + endl + bridgeTxHash + endl2
}
const protocolFromContractAddress = "" // TODO fill protocol contract address for 'from' network for Bridge and Swap
if (!!protocolName && !!protocolFromContractAddress) {
@@ -291,12 +273,12 @@ StatusListItem {
details += protocolFromContractAddress + endl2
}
if (!!modelData.contract) {
- details += qsTr("%1 %2 contract address").arg(root.networkName).arg(root.symbol) + endl
+ details += qsTr("%1 %2 contract address").arg(root.networkName).arg(modelData.symbol) + endl
details += modelData.contract + endl2
}
const protocolToContractAddress = "" // TODO fill protocol contract address for 'to' network for Bridge
if (!!protocolToContractAddress && !!protocolName) {
- details += qsTr("%1 %2 contract address").arg(root.bridgeNetworkName).arg(protocolName) + endl
+ details += qsTr("%1 %2 contract address").arg(toNetworkName).arg(protocolName) + endl
details += protocolToContractAddress + endl2
}
const swapContractAddress = "" // TODO fill swap contract address for Swap
@@ -304,13 +286,13 @@ StatusListItem {
switch (type) {
case Constants.TransactionType.Swap:
if (!!swapContractAddress) {
- details += qsTr("%1 %2 contract address").arg(root.networkName).arg(root.swapSymbol) + endl
+ details += qsTr("%1 %2 contract address").arg(root.networkName).arg(modelData.toSymbol) + endl
details += swapContractAddress + endl2
}
break
case Constants.TransactionType.Bridge:
if (!!bridgeContractAddress) {
- details += qsTr("%1 %2 contract address").arg(root.bridgeNetworkName).arg(root.symbol) + endl
+ details += qsTr("%1 %2 contract address").arg(toNetworkName).arg(modelData.symbol) + endl
details += bridgeContractAddress + endl2
}
break
@@ -327,7 +309,7 @@ StatusListItem {
if (type === Constants.TransactionType.Bridge) {
details += qsTr("Included in Block on %1").arg(networkName) + endl
details += rootStore.hex2Dec(modelData.blockNumber) + endl2
- details += qsTr("Included in Block on %1").arg(bridgeNetworkName) + endl
+ details += qsTr("Included in Block on %1").arg(toNetworkName) + endl
const bridgeBlockNumber = 0 // TODO fill when bridge data is implemented
details += rootStore.hex2Dec(bridgeBlockNumber) + endl2
} else {
@@ -335,27 +317,29 @@ StatusListItem {
}
// VALUES
- const fiatTransactionValue = rootStore.formatCurrencyAmount(root.fiatValue, root.currentCurrency)
+ const fiatTransactionValue = rootStore.formatCurrencyAmount(isMultiTransaction ? root.outFiatValue : root.fiatValue, root.currentCurrency)
const feeFiatValue = rootStore.getFiatValue(feeEthValue, "ETH", root.currentCurrency)
let valuesString = ""
if (!root.isNFT) {
switch(type) {
case Constants.TransactionType.Send:
+ valuesString += qsTr("Amount sent %1 (%2)").arg(root.transactionValue).arg(fiatTransactionValue) + endl2
+ break
case Constants.TransactionType.Swap:
case Constants.TransactionType.Bridge:
- valuesString += qsTr("Amount sent %1 (%2)").arg(root.transactionValue).arg(fiatTransactionValue) + endl2
+ valuesString += qsTr("Amount sent %1 (%2)").arg(root.outTransactionValue).arg(fiatTransactionValue) + endl2
break
default:
break
}
if (type === Constants.TransactionType.Swap) {
- const crypto = rootStore.formatCurrencyAmount(root.swapCryptoValue, root.swapSymbol)
- const fiat = rootStore.formatCurrencyAmount(root.swapCryptoValue, root.swapSymbol)
+ const crypto = rootStore.formatCurrencyAmount(root.inCryptoValue, modelData.inSymbol)
+ const fiat = rootStore.formatCurrencyAmount(root.inCryptoValue, modelData.inSymbol)
valuesString += qsTr("Amount received %1 (%2)").arg(crypto).arg(fiat) + endl2
} else if (type === Constants.TransactionType.Bridge) {
// Reduce crypto value by fee value
- const valueInCrypto = rootStore.getCryptoValue(root.fiatValue - feeFiatValue, root.symbol, root.currentCurrency)
- const crypto = rootStore.formatCurrencyAmount(valueInCrypto, root.symbol)
+ const valueInCrypto = rootStore.getCryptoValue(root.fiatValue - feeFiatValue, modelData.inSymbol, root.currentCurrency)
+ const crypto = rootStore.formatCurrencyAmount(valueInCrypto, modelData.inSymbol)
const fiat = rootStore.formatCurrencyAmount(root.fiatValue - feeFiatValue, root.currentCurrency)
valuesString += qsTr("Amount received %1 (%2)").arg(crypto).arg(fiat) + endl2
}
@@ -381,7 +365,8 @@ StatusListItem {
valuesString += qsTr("Total %1 (%2)").arg(root.transactionValue).arg(fiatTransactionValue) + endl2
} else {
const feeEth = rootStore.formatCurrencyAmount(feeEthValue, "ETH")
- valuesString += qsTr("Total %1 + %2 (%3)").arg(root.transactionValue).arg(feeEth).arg(fiatTransactionValue) + endl2
+ const txValue = isMultiTransaction ? root.inTransactionValue : root.transactionValue
+ valuesString += qsTr("Total %1 + %2 (%3)").arg(txValue).arg(feeEth).arg(fiatTransactionValue) + endl2
}
}
@@ -399,6 +384,7 @@ StatusListItem {
rightPadding: 16
enabled: !loading
+ loading: !isModelDataValid
color: sensor.containsMouse ? Theme.palette.baseColor5 : Style.current.transparent
statusListItemIcon.active: (loading || root.asset.name)
@@ -486,15 +472,15 @@ StatusListItem {
spacing: 8
Row {
visible: !root.loading
- spacing: swapTokenImage.visible ? -tokenImage.width * 0.2 : 0
+ spacing: secondTokenImage.visible ? -tokenImage.width * 0.2 : 0
StatusRoundIcon {
id: tokenImage
anchors.verticalCenter: parent.verticalCenter
asset: root.tokenIconAsset
}
StatusRoundIcon {
- id: swapTokenImage
- visible: root.isModelDataValid && !root.isNFT && !!root.swapTokenImage &&modelData.txType === Constants.TransactionType.Swap
+ id: secondTokenImage
+ visible: root.isModelDataValid && !root.isNFT && !!root.inTokenImage &&modelData.txType === Constants.TransactionType.Swap
anchors.verticalCenter: parent.verticalCenter
asset: StatusAssetSettings {
width: root.tokenIconAsset.width
@@ -505,7 +491,7 @@ StatusListItem {
bgColor: root.color
isImage:root.tokenIconAsset.isImage
color: root.tokenIconAsset.color
- name: root.swapTokenImage
+ name: root.inTokenImage
isLetterIdenticon: root.tokenIconAsset.isLetterIdenticon
}
}
@@ -537,11 +523,12 @@ StatusListItem {
case Constants.TransactionType.Sell:
return qsTr("%1 on %2 via %3").arg(transactionValue).arg(toAddress).arg(networkName)
case Constants.TransactionType.Destroy:
- return qsTr("%1 at %2 via %3").arg(transactionValue).arg(toAddress).arg(networkName)
+ return qsTr("%1 at %2 via %3").arg(inTransactionValue).arg(toAddress).arg(networkName)
case Constants.TransactionType.Swap:
- return qsTr("%1 to %2 via %3").arg(transactionValue).arg(swapTransactionValue).arg(networkName)
+ return qsTr("%1 to %2 via %3").arg(outTransactionValue).arg(inTransactionValue).arg(networkName)
case Constants.TransactionType.Bridge:
- return qsTr("%1 from %2 to %3").arg(transactionValue).arg(bridgeNetworkName).arg(networkName)
+ let toNetworkName = "" // TODO fill when Bridge data is implemented
+ return qsTr("%1 from %2 to %3").arg(inTransactionValue).arg(networkName).arg(toNetworkName)
default:
return qsTr("%1 to %2 via %3").arg(transactionValue).arg(toAddress).arg(networkName)
}
@@ -574,14 +561,18 @@ StatusListItem {
case Constants.TransactionType.Receive:
return "+" + root.transactionValue
case Constants.TransactionType.Swap:
+ let outValue = root.outTransactionValue
+ outValue = outValue.replace('<', '<')
+ let inValue = root.inTransactionValue
+ inValue = inValue.replace('<', '<')
return "-%2 / +%5"
.arg(Theme.palette.directColor1)
- .arg(root.transactionValue)
+ .arg(outValue)
.arg(Theme.palette.baseColor1)
.arg(Theme.palette.successColor1)
- .arg(root.swapTransactionValue)
+ .arg(inValue)
case Constants.TransactionType.Bridge:
- return "−" + root.rootStore.formatCurrencyAmount(feeCryptoValue, root.symbol)
+ return "−" + root.rootStore.formatCurrencyAmount(feeCryptoValue, modelData.symbol)
default:
return ""
}
@@ -623,8 +614,8 @@ StatusListItem {
case Constants.TransactionType.Receive:
return "+" + root.rootStore.formatCurrencyAmount(root.fiatValue, root.currentCurrency)
case Constants.TransactionType.Swap:
- return "-%1 / +%2".arg(root.rootStore.formatCurrencyAmount(root.fiatValue, root.currentCurrency))
- .arg(root.rootStore.formatCurrencyAmount(root.swapFiatValue, root.currentCurrency))
+ return "-%1 / +%2".arg(root.rootStore.formatCurrencyAmount(root.outFiatValue, root.currentCurrency))
+ .arg(root.rootStore.formatCurrencyAmount(root.inFiatValue, root.currentCurrency))
case Constants.TransactionType.Bridge:
return "−" + root.rootStore.formatCurrencyAmount(root.feeFiatValue, root.currentCurrency)
default:
diff --git a/ui/imports/shared/views/HistoryView.qml b/ui/imports/shared/views/HistoryView.qml
index 238dd8b4a3..3c072cccee 100644
--- a/ui/imports/shared/views/HistoryView.qml
+++ b/ui/imports/shared/views/HistoryView.qml
@@ -256,19 +256,11 @@ ColumnLayout {
Component {
id: transactionDelegate
TransactionDelegate {
+ required property var model
+ required property int index
width: ListView.view.width
modelData: model.activityEntry
- currentCurrency: RootStore.currentCurrency
- cryptoValue: isModelDataValid ? modelData.value : 0.0
- fiatValue: isModelDataValid ? RootStore.getFiatValue(cryptoValue, symbol, currentCurrency): 0.0
- networkIcon: isModelDataValid ? RootStore.getNetworkIcon(modelData.chainId) : ""
- networkColor: isModelDataValid ? RootStore.getNetworkColor(modelData.chainId) : ""
- networkName: isModelDataValid ? RootStore.getNetworkFullName(modelData.chainId) : ""
- symbol: isModelDataValid && !!modelData.symbol ? modelData.symbol : ""
- transactionStatus: isModelDataValid ? modelData.status : 0
timeStampText: isModelDataValid ? LocaleUtils.formatRelativeTimestamp(modelData.timestamp * 1000, true) : ""
- addressNameTo: isModelDataValid ? WalletStores.RootStore.getNameForAddress(modelData.recipient) : ""
- addressNameFrom: isModelDataValid ? WalletStores.RootStore.getNameForAddress(modelData.sender) : ""
rootStore: RootStore
walletRootStore: WalletStores.RootStore
onClicked: {
@@ -309,6 +301,8 @@ ColumnLayout {
model: RootStore.historyTransactions.hasMore || d.isInitialLoading ? 10 : 0
TransactionDelegate {
Layout.fillWidth: true
+ rootStore: RootStore
+ walletRootStore: WalletStores.RootStore
loading: true
}
}