feat(@desktop/wallet): implement unified currency formatting in send/bridge modal

Fixes #8934
This commit is contained in:
Dario Gabriel Lipicar 2023-01-08 19:23:51 -03:00 committed by dlipicar
parent ae55e78faf
commit d11017f7b3
31 changed files with 336 additions and 247 deletions

View File

@ -43,6 +43,9 @@ proc isMnemonicBackedUp*(self: Controller): bool =
proc getCurrencyBalance*(self: Controller): CurrencyAmount = proc getCurrencyBalance*(self: Controller): CurrencyAmount =
return currencyAmountToItem(self.walletAccountService.getTotalCurrencyBalance(), self.currencyService.getCurrencyFormat(self.getCurrency())) return currencyAmountToItem(self.walletAccountService.getTotalCurrencyBalance(), self.currencyService.getCurrencyFormat(self.getCurrency()))
proc getCurrencyAmount*(self: Controller, amount: float64, symbol: string): CurrencyAmount =
return currencyAmountToItem(amount, self.currencyService.getCurrencyFormat(symbol))
proc updateCurrency*(self: Controller, currency: string) = proc updateCurrency*(self: Controller, currency: string) =
self.walletAccountService.updateCurrency(currency) self.walletAccountService.updateCurrency(currency)

View File

@ -1,3 +1,6 @@
import ../../shared_models/currency_amount
export CurrencyAmount
type type
AccessInterface* {.pure inheritable.} = ref object of RootObj AccessInterface* {.pure inheritable.} = ref object of RootObj
## Abstract class for any input/interaction with this module. ## Abstract class for any input/interaction with this module.
@ -23,6 +26,9 @@ method updateCurrency*(self: AccessInterface, currency: string) {.base.} =
method setTotalCurrencyBalance*(self: AccessInterface) {.base.} = method setTotalCurrencyBalance*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method getCurrencyAmount*(self: AccessInterface, amount: float64, symbol: string): CurrencyAmount {.base.} =
raise newException(ValueError, "No implementation available")
# View Delegate Interface # View Delegate Interface
# Delegate for the view must be declared here due to use of QtObject and multi # Delegate for the view must be declared here due to use of QtObject and multi
# inheritance, which is not well supported in Nim. # inheritance, which is not well supported in Nim.

View File

@ -100,6 +100,9 @@ method switchAccountByAddress*(self: Module, address: string) =
method setTotalCurrencyBalance*(self: Module) = method setTotalCurrencyBalance*(self: Module) =
self.view.setTotalCurrencyBalance(self.controller.getCurrencyBalance()) self.view.setTotalCurrencyBalance(self.controller.getCurrencyBalance())
method getCurrencyAmount*(self: Module, amount: float64, symbol: string): CurrencyAmount =
return self.controller.getCurrencyAmount(amount, symbol)
method load*(self: Module) = method load*(self: Module) =
singletonInstance.engine.setRootContextProperty("walletSection", newQVariant(self.view)) singletonInstance.engine.setRootContextProperty("walletSection", newQVariant(self.view))

View File

@ -1,4 +1,4 @@
import NimQml import NimQml, json
import ./io_interface import ./io_interface
import ../../shared_models/currency_amount import ../../shared_models/currency_amount
@ -75,6 +75,13 @@ QtObject:
self.currentCurrency = currency self.currentCurrency = currency
self.currentCurrencyChanged() self.currentCurrencyChanged()
# Returning a QVariant from a slot with parameters other than "self" won't compile
# proc getCurrencyAmount*(self: View, amount: float, symbol: string): QVariant {.slot.} =
# return newQVariant(self.delegate.getCurrencyAmount(amount, symbol))
proc getCurrencyAmountAsJson*(self: View, amount: float, symbol: string): string {.slot.} =
return $self.delegate.getCurrencyAmount(amount, symbol).toJsonNode()
proc setData*(self: View, currency, signingPhrase: string, mnemonicBackedUp: bool) = proc setData*(self: View, currency, signingPhrase: string, mnemonicBackedUp: bool) =
self.currentCurrency = currency self.currentCurrency = currency
self.signingPhrase = signingPhrase self.signingPhrase = signingPhrase

View File

@ -21,6 +21,14 @@ logScope:
include async_tasks include async_tasks
const ETHEREUM_SYMBOL = "ETH"
const CRYPTO_SUB_UNITS_TO_FACTOR = {
"WEI": (ETHEREUM_SYMBOL, 1e-18),
"KWEI": (ETHEREUM_SYMBOL, 1e-15),
"MWEI": (ETHEREUM_SYMBOL, 1e-12),
"GWEI": (ETHEREUM_SYMBOL, 1e-9),
}.toTable()
# Signals which may be emitted by this service: # Signals which may be emitted by this service:
const SIGNAL_TOKEN_HISTORICAL_DATA_LOADED* = "tokenHistoricalDataLoaded" const SIGNAL_TOKEN_HISTORICAL_DATA_LOADED* = "tokenHistoricalDataLoaded"
const SIGNAL_BALANCE_HISTORY_DATA_READY* = "tokenBalanceHistoryDataReady" const SIGNAL_BALANCE_HISTORY_DATA_READY* = "tokenBalanceHistoryDataReady"
@ -130,26 +138,35 @@ QtObject:
proc getTokenPriceCacheKey(crypto: string, fiat: string) : string = proc getTokenPriceCacheKey(crypto: string, fiat: string) : string =
return renameSymbol(crypto) & renameSymbol(fiat) return renameSymbol(crypto) & renameSymbol(fiat)
proc getCryptoKeyAndFactor(crypto: string) : (string, float64) =
let cryptoKey = renameSymbol(crypto)
return CRYPTO_SUB_UNITS_TO_FACTOR.getOrDefault(cryptoKey, (cryptoKey, 1.0))
proc isCachedTokenPriceRecent*(self: Service, crypto: string, fiat: string): bool = proc isCachedTokenPriceRecent*(self: Service, crypto: string, fiat: string): bool =
let cacheKey = getTokenPriceCacheKey(crypto, fiat) let (cryptoKey, _) = getCryptoKeyAndFactor(crypto)
let cacheKey = getTokenPriceCacheKey(cryptoKey, fiat)
return self.priceCache.isCached(cacheKey) return self.priceCache.isCached(cacheKey)
proc getCachedTokenPrice*(self: Service, crypto: string, fiat: string): float64 = proc getCachedTokenPrice*(self: Service, crypto: string, fiat: string): float64 =
let cacheKey = getTokenPriceCacheKey(crypto, fiat) let (cryptoKey, factor) = getCryptoKeyAndFactor(crypto)
let cacheKey = getTokenPriceCacheKey(cryptoKey, fiat)
if self.priceCache.hasKey(cacheKey): if self.priceCache.hasKey(cacheKey):
return self.priceCache.get(cacheKey) return self.priceCache.get(cacheKey) * factor
else: else:
return 0.0 return 0.0
proc getTokenPrice*(self: Service, crypto: string, fiat: string, fetchIfNotAvailable: bool = true): float64 = proc getTokenPrice*(self: Service, crypto: string, fiat: string): float64 =
let cacheKey = getTokenPriceCacheKey(crypto, fiat) let fiatKey = renameSymbol(fiat)
let (cryptoKey, factor) = getCryptoKeyAndFactor(crypto)
let cacheKey = getTokenPriceCacheKey(cryptoKey, fiatKey)
if self.priceCache.isCached(cacheKey): if self.priceCache.isCached(cacheKey):
return self.priceCache.get(cacheKey) return self.priceCache.get(cacheKey) * factor
var prices = initTable[string, Table[string, float]]() var prices = initTable[string, Table[string, float]]()
try: try:
let cryptoKey = renameSymbol(crypto)
let fiatKey = renameSymbol(fiat)
let response = backend.fetchPrices(@[cryptoKey], @[fiatKey]) let response = backend.fetchPrices(@[cryptoKey], @[fiatKey])
for (symbol, pricePerCurrency) in response.result.pairs: for (symbol, pricePerCurrency) in response.result.pairs:
prices[symbol] = initTable[string, float]() prices[symbol] = initTable[string, float]()
@ -157,7 +174,7 @@ QtObject:
prices[symbol][currency] = price.getFloat prices[symbol][currency] = price.getFloat
self.updateCachedTokenPrice(cryptoKey, fiatKey, prices[cryptoKey][fiatKey]) self.updateCachedTokenPrice(cryptoKey, fiatKey, prices[cryptoKey][fiatKey])
return prices[cryptoKey][fiatKey] return prices[cryptoKey][fiatKey] * factor
except Exception as e: except Exception as e:
let errDesription = e.msg let errDesription = e.msg
error "error: ", errDesription error "error: ", errDesription

View File

@ -27,20 +27,28 @@ QtObject {
return num.toLocaleString(locale, 'f', precision) return num.toLocaleString(locale, 'f', precision)
} }
function currencyAmountToLocaleString(currencyAmount, locale) { function numberFromLocaleString(num, locale = null) {
if (!locale) { locale = locale || Qt.locale()
console.log("Unspecified locale for: " + JSON.stringify(currencyAmount))
locale = Qt.locale() return Number.fromLocaleString(locale, num)
}
function currencyAmountToLocaleString(currencyAmount, options = null, locale = null) {
locale = locale || Qt.locale()
if (!currencyAmount) {
return "N/A"
} }
if (typeof(currencyAmount) !== "object") { if (typeof(currencyAmount) !== "object") {
console.log("Wrong type for currencyAmount: " + JSON.stringify(currencyAmount)) console.log("Wrong type for currencyAmount: " + JSON.stringify(currencyAmount))
console.trace()
return NaN return NaN
} }
var amountStr = numberToLocaleString(currencyAmount.amount, currencyAmount.displayDecimals, locale) var amountStr = numberToLocaleString(currencyAmount.amount, currencyAmount.displayDecimals, locale)
if (currencyAmount.stripTrailingZeroes) { if (currencyAmount.stripTrailingZeroes) {
amountStr = stripTrailingZeroes(amountStr, locale) amountStr = stripTrailingZeroes(amountStr, locale)
} }
if (currencyAmount.symbol) { if (currencyAmount.symbol && !(options && options.onlyAmount)) {
amountStr = "%1 %2".arg(amountStr).arg(currencyAmount.symbol) amountStr = "%1 %2".arg(amountStr).arg(currencyAmount.symbol)
} }
return amountStr return amountStr

View File

@ -204,10 +204,12 @@ Popup {
AssetsView { AssetsView {
id: assetsTab id: assetsTab
locale: RootStore.locale
account: WalletStore.dappBrowserAccount account: WalletStore.dappBrowserAccount
} }
HistoryView { HistoryView {
id: historyTab id: historyTab
locale: RootStore.locale
account: WalletStore.dappBrowserAccount account: WalletStore.dappBrowserAccount
} }
} }

View File

@ -46,7 +46,7 @@ Item {
font.pixelSize: 28 font.pixelSize: 28
font.bold: true font.bold: true
color: Theme.palette.baseColor1 color: Theme.palette.baseColor1
text: LocaleUtils.currencyAmountToLocaleString(root.currentAccount.currencyBalance, root.locale) text: LocaleUtils.currencyAmountToLocaleString(root.currentAccount.currencyBalance)
} }
} }

View File

@ -82,7 +82,7 @@ Rectangle {
objectName: "walletLeftListAmountValue" objectName: "walletLeftListAmountValue"
color: Style.current.textColor color: Style.current.textColor
text: { text: {
LocaleUtils.currencyAmountToLocaleString(RootStore.totalCurrencyBalance, RootStore.currencyStore.locale) LocaleUtils.currencyAmountToLocaleString(RootStore.totalCurrencyBalance)
} }
selectByMouse: true selectByMouse: true
cursorVisible: true cursorVisible: true
@ -117,7 +117,7 @@ Rectangle {
width: ListView.view.width width: ListView.view.width
highlighted: RootStore.currentAccount.name === model.name highlighted: RootStore.currentAccount.name === model.name
title: model.name title: model.name
subTitle: LocaleUtils.currencyAmountToLocaleString(model.currencyBalance, RootStore.currencyStore.locale) subTitle: LocaleUtils.currencyAmountToLocaleString(model.currencyBalance)
asset.emoji: !!model.emoji ? model.emoji: "" asset.emoji: !!model.emoji ? model.emoji: ""
asset.color: model.color asset.color: model.color
asset.name: !model.emoji ? "filled-account": "" asset.name: !model.emoji ? "filled-account": ""

View File

@ -104,6 +104,7 @@ Item {
} }
} }
HistoryView { HistoryView {
locale: RootStore.locale
account: RootStore.currentAccount account: RootStore.currentAccount
onLaunchTransactionDetail: { onLaunchTransactionDetail: {
transactionDetailView.transaction = transaction transactionDetailView.transaction = transaction
@ -127,6 +128,7 @@ Item {
} }
TransactionDetailView { TransactionDetailView {
id: transactionDetailView id: transactionDetailView
locale: RootStore.locale
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
sendModal: root.sendModal sendModal: root.sendModal

View File

@ -54,7 +54,7 @@ Item {
anchors.leftMargin: Style.current.smallPadding anchors.leftMargin: Style.current.smallPadding
font.pixelSize: 15 font.pixelSize: 15
color: Style.current.secondaryText color: Style.current.secondaryText
text: LocaleUtils.currencyAmountToLocaleString(enabledNetworkBalance, root.locale) text: LocaleUtils.currencyAmountToLocaleString(enabledNetworkBalance)
} }
StyledText { StyledText {
@ -65,6 +65,6 @@ Item {
anchors.rightMargin: 0 anchors.rightMargin: 0
font.pixelSize: 15 font.pixelSize: 15
font.strikeout: false font.strikeout: false
text: LocaleUtils.currencyAmountToLocaleString(enabledNetworkCurrencyBalance, root.locale) text: LocaleUtils.currencyAmountToLocaleString(enabledNetworkCurrencyBalance)
} }
} }

View File

@ -16,11 +16,12 @@ Item {
property string selectedTokenSymbol property string selectedTokenSymbol
property string currentCurrency property string currentCurrency
property string currentCurrencySymbol
property var bestRoutes: [] property var bestRoutes: []
property var getGasEthValue: function () {} property var getGasEthValue: function () {}
property var getFiatValue: function () {} property var getFiatValue: function () {}
property var getCurrencyAmount: function () {}
property var locale
width: parent.width width: parent.width
height: visible ? advancedGasSelector.height + Style.current.halfPadding : 0 height: visible ? advancedGasSelector.height + Style.current.halfPadding : 0
@ -48,19 +49,20 @@ Item {
statusListItemIcon.active: true statusListItemIcon.active: true
statusListItemIcon.opacity: modelData.isFirstSimpleTx statusListItemIcon.opacity: modelData.isFirstSimpleTx
title: qsTr("%1 transaction fee").arg(modelData.fromNetwork.chainName) title: qsTr("%1 transaction fee").arg(modelData.fromNetwork.chainName)
subTitle: "%1 eth".arg(LocaleUtils.numberToLocaleString(parseFloat(totalGasAmount))) subTitle: LocaleUtils.currencyAmountToLocaleString(totalGasAmountEth)
property string totalGasAmount : { property var totalGasAmountEth: {
let maxFees = modelData.gasFees.maxFeePerGasM let maxFees = modelData.gasFees.maxFeePerGasM
let gasPrice = modelData.gasFees.eip1559Enabled ? maxFees : modelData.gasFees.gasPrice let gasPrice = modelData.gasFees.eip1559Enabled ? maxFees : modelData.gasFees.gasPrice
return root.getGasEthValue(gasPrice , modelData.gasAmount) return root.getGasEthValue(gasPrice , modelData.gasAmount)
} }
property var totalGasAmountFiat: root.getFiatValue(totalGasAmountEth.amount, "ETH", root.currentCurrency)
statusListItemSubTitle.width: listItem.width/2 - Style.current.smallPadding statusListItemSubTitle.width: listItem.width/2 - Style.current.smallPadding
statusListItemSubTitle.elide: Text.ElideMiddle statusListItemSubTitle.elide: Text.ElideMiddle
statusListItemSubTitle.wrapMode: Text.NoWrap statusListItemSubTitle.wrapMode: Text.NoWrap
components: [ components: [
StatusBaseText { StatusBaseText {
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
text: "%1%2".arg(currentCurrencySymbol).arg(LocaleUtils.numberToLocaleString(parseFloat(root.getFiatValue(totalGasAmount, "ETH", root.currentCurrency)))) text: LocaleUtils.currencyAmountToLocaleString(totalGasAmountFiat)
font.pixelSize: 15 font.pixelSize: 15
color: Theme.palette.baseColor1 color: Theme.palette.baseColor1
width: listItem.width/2 - Style.current.padding width: listItem.width/2 - Style.current.padding
@ -82,7 +84,9 @@ Item {
statusListItemIcon.active: true statusListItemIcon.active: true
statusListItemIcon.opacity: modelData.isFirstSimpleTx statusListItemIcon.opacity: modelData.isFirstSimpleTx
title: qsTr("Approve %1 %2 Bridge").arg(modelData.fromNetwork.chainName).arg(root.selectedTokenSymbol) title: qsTr("Approve %1 %2 Bridge").arg(modelData.fromNetwork.chainName).arg(root.selectedTokenSymbol)
subTitle: "%1 eth".arg(LocaleUtils.numberToLocaleString(modelData.approvalGasFees)) property var approvalGasFees: root.getCurrencyAmount(modelData.approvalGasFees, "ETH")
property var approvalGasFeesFiat: root.getFiatValue(approvalGasFees.amount, "ETH", root.currentCurrency)
subTitle: LocaleUtils.currencyAmountToLocaleString(approvalGasFees)
statusListItemSubTitle.width: listItem.width/2 - Style.current.smallPadding statusListItemSubTitle.width: listItem.width/2 - Style.current.smallPadding
statusListItemSubTitle.elide: Text.ElideMiddle statusListItemSubTitle.elide: Text.ElideMiddle
statusListItemSubTitle.wrapMode: Text.NoWrap statusListItemSubTitle.wrapMode: Text.NoWrap
@ -90,7 +94,7 @@ Item {
components: [ components: [
StatusBaseText { StatusBaseText {
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
text: "%1%2".arg(currentCurrencySymbol).arg(LocaleUtils.numberToLocaleString(parseFloat(root.getFiatValue(modelData.approvalGasFees, "ETH", root.currentCurrency)))) text: LocaleUtils.currencyAmountToLocaleString(approvalGasFeesFiat)
font.pixelSize: 15 font.pixelSize: 15
color: Theme.palette.baseColor1 color: Theme.palette.baseColor1
width: listItem.width/2 - Style.current.padding width: listItem.width/2 - Style.current.padding
@ -113,14 +117,16 @@ Item {
statusListItemIcon.active: true statusListItemIcon.active: true
statusListItemIcon.opacity: modelData.isFirstBridgeTx statusListItemIcon.opacity: modelData.isFirstBridgeTx
title: qsTr("%1 -> %2 bridge").arg(modelData.fromNetwork.chainName).arg(modelData.toNetwork.chainName) title: qsTr("%1 -> %2 bridge").arg(modelData.fromNetwork.chainName).arg(modelData.toNetwork.chainName)
subTitle: "%1 %2".arg(LocaleUtils.numberToLocaleString(modelData.tokenFees)).arg(root.selectedTokenSymbol) property var tokenFees: root.getCurrencyAmount(modelData.tokenFees, root.selectedTokenSymbol)
property var tokenFeesFiat: root.getFiatValue(tokenFees.amount, root.selectedTokenSymbol, root.currentCurrency)
subTitle: LocaleUtils.currencyAmountToLocaleString(tokenFees)
visible: modelData.bridgeName !== "Simple" visible: modelData.bridgeName !== "Simple"
statusListItemSubTitle.width: 100 statusListItemSubTitle.width: 100
statusListItemSubTitle.elide: Text.ElideMiddle statusListItemSubTitle.elide: Text.ElideMiddle
components: [ components: [
StatusBaseText { StatusBaseText {
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
text: "%1%2".arg(currentCurrencySymbol).arg(LocaleUtils.numberToLocaleString(parseFloat(root.getFiatValue(modelData.tokenFees, root.selectedTokenSymbol, root.currentCurrency)))) text: LocaleUtils.currencyAmountToLocaleString(tokenFeesFiat)
font.pixelSize: 15 font.pixelSize: 15
color: Theme.palette.baseColor1 color: Theme.palette.baseColor1
width: listItem2.width/2 - Style.current.padding width: listItem2.width/2 - Style.current.padding

View File

@ -16,7 +16,7 @@ StatusListItem {
signal tokenSelected(var selectedToken) signal tokenSelected(var selectedToken)
title: name title: name
label: LocaleUtils.currencyAmountToLocaleString(enabledNetworkCurrencyBalance, root.locale) label: LocaleUtils.currencyAmountToLocaleString(enabledNetworkCurrencyBalance)
asset.name: symbol ? Style.png("tokens/" + symbol) : "" asset.name: symbol ? Style.png("tokens/" + symbol) : ""
asset.isImage: true asset.isImage: true
asset.width: 32 asset.width: 32
@ -42,7 +42,7 @@ StatusListItem {
id: expandedItem id: expandedItem
StatusListItemTag { StatusListItemTag {
height: 16 height: 16
title: LocaleUtils.currencyAmountToLocaleString(balance, root.locale) title: LocaleUtils.currencyAmountToLocaleString(balance)
titleText.font.pixelSize: 12 titleText.font.pixelSize: 12
closeButtonVisible: false closeButtonVisible: false
bgColor: "transparent" bgColor: "transparent"

View File

@ -12,7 +12,7 @@ StatusListItem {
id: root id: root
property var locale property var locale
title: name title: name
subTitle: LocaleUtils.currencyAmountToLocaleString(enabledNetworkBalance, root.locale) subTitle: LocaleUtils.currencyAmountToLocaleString(enabledNetworkBalance)
asset.name: symbol ? Style.png("tokens/" + symbol) : "" asset.name: symbol ? Style.png("tokens/" + symbol) : ""
asset.isImage: true asset.isImage: true
components: [ components: [
@ -25,7 +25,7 @@ StatusListItem {
anchors.right: parent.right anchors.right: parent.right
font.pixelSize: 15 font.pixelSize: 15
font.strikeout: false font.strikeout: false
text: LocaleUtils.currencyAmountToLocaleString(enabledNetworkCurrencyBalance, root.locale) text: LocaleUtils.currencyAmountToLocaleString(enabledNetworkCurrencyBalance)
} }
Row { Row {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
@ -35,7 +35,7 @@ StatusListItem {
font.pixelSize: 15 font.pixelSize: 15
font.strikeout: false font.strikeout: false
color: valueColumn.textColor color: valueColumn.textColor
text: LocaleUtils.currencyAmountToLocaleString(currencyPrice, root.locale) text: LocaleUtils.currencyAmountToLocaleString(currencyPrice)
} }
Rectangle { Rectangle {
width: 1 width: 1

View File

@ -11,13 +11,13 @@ import shared 1.0
StatusListItem { StatusListItem {
id: root id: root
property var locale
property var modelData property var modelData
property string symbol property string symbol
property bool isIncoming property bool isIncoming
property int transferStatus property int transferStatus
property string currentCurrency property var cryptoValue
property string cryptoValue property var fiatValue
property string fiatValue
property string networkIcon property string networkIcon
property string networkColor property string networkColor
property string networkName property string networkName
@ -62,13 +62,13 @@ StatusListItem {
} }
StatusBaseText { StatusBaseText {
id: cryptoValueText id: cryptoValueText
text: "%1 %2".arg(cryptoValue).arg(resolvedSymbol) text: LocaleUtils.currencyAmountToLocaleString(cryptoValue)
color: Theme.palette.directColor1 color: Theme.palette.directColor1
} }
} }
StatusBaseText { StatusBaseText {
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
text: "%1 %2".arg(fiatValue).arg(currentCurrency.toUpperCase()) text: LocaleUtils.currencyAmountToLocaleString(fiatValue)
font.pixelSize: 15 font.pixelSize: 15
color: Theme.palette.baseColor1 color: Theme.palette.baseColor1
} }

View File

@ -89,7 +89,7 @@ StatusFloatingButtonsSelector {
popupMenuDelegate: StatusListItem { popupMenuDelegate: StatusListItem {
implicitWidth: 272 implicitWidth: 272
title: name title: name
subTitle: LocaleUtils.currencyAmountToLocaleString(currencyBalance, locale) subTitle: LocaleUtils.currencyAmountToLocaleString(currencyBalance)
asset.emoji: !!emoji ? emoji: "" asset.emoji: !!emoji ? emoji: ""
asset.color: model.color asset.color: model.color
asset.name: !emoji ? "filled-account": "" asset.name: !emoji ? "filled-account": ""

View File

@ -33,6 +33,7 @@ StatusDialog {
property var store: TransactionStore{} property var store: TransactionStore{}
property var contactsStore: store.contactStore property var contactsStore: store.contactStore
property var currencyStore: store.currencyStore
property var selectedAccount: store.currentAccount property var selectedAccount: store.currentAccount
property var bestRoutes property var bestRoutes
property string addressText property string addressText
@ -60,7 +61,7 @@ StatusDialog {
popup.selectedAccount.address, popup.selectedAccount.address,
recipientAddress, recipientAddress,
assetSelector.selectedAsset.symbol, assetSelector.selectedAsset.symbol,
amountToSendInput.cryptoValueToSend, amountToSendInput.cryptoValueToSend.amount,
d.uuid, d.uuid,
JSON.stringify(popup.bestRoutes) JSON.stringify(popup.bestRoutes)
) )
@ -69,7 +70,7 @@ StatusDialog {
property var recalculateRoutesAndFees: Backpressure.debounce(popup, 600, function() { property var recalculateRoutesAndFees: Backpressure.debounce(popup, 600, function() {
if(!!popup.selectedAccount && !!assetSelector.selectedAsset && d.recipientReady && amountToSendInput.input.valid) { if(!!popup.selectedAccount && !!assetSelector.selectedAsset && d.recipientReady && amountToSendInput.input.valid) {
popup.isLoading = true popup.isLoading = true
let amount = Math.round(parseFloat(amountToSendInput.cryptoValueToSend) * Math.pow(10, assetSelector.selectedAsset.decimals)) let amount = Math.round(amountToSendInput.cryptoValueToSend.amount * Math.pow(10, assetSelector.selectedAsset.decimals))
popup.store.suggestedRoutes(popup.selectedAccount.address, amount.toString(16), assetSelector.selectedAsset.symbol, popup.store.suggestedRoutes(popup.selectedAccount.address, amount.toString(16), assetSelector.selectedAsset.symbol,
store.disabledChainIdsFromList, store.disabledChainIdsToList, store.disabledChainIdsFromList, store.disabledChainIdsToList,
store.preferredChainIds, popup.sendType, store.lockedInAmounts) store.preferredChainIds, popup.sendType, store.lockedInAmounts)
@ -81,7 +82,7 @@ StatusDialog {
readonly property int errorType: !amountToSendInput.input.valid ? Constants.SendAmountExceedsBalance : readonly property int errorType: !amountToSendInput.input.valid ? Constants.SendAmountExceedsBalance :
(networkSelector.bestRoutes && networkSelector.bestRoutes.length <= 0 && !!amountToSendInput.input.text && recipientReady && !popup.isLoading) ? (networkSelector.bestRoutes && networkSelector.bestRoutes.length <= 0 && !!amountToSendInput.input.text && recipientReady && !popup.isLoading) ?
Constants.NoRoute : Constants.NoError Constants.NoRoute : Constants.NoError
readonly property var maxFiatBalance: !!assetSelector.selectedAsset ? (amountToSendInput.cryptoFiatFlipped ? readonly property var maxFiatBalance: !!assetSelector.selectedAsset ? (amountToSendInput.inputIsFiat ?
assetSelector.selectedAsset.totalCurrencyBalance : assetSelector.selectedAsset.totalCurrencyBalance :
assetSelector.selectedAsset.totalBalance): undefined assetSelector.selectedAsset.totalBalance): undefined
readonly property bool errorMode: popup.isLoading || !recipientReady ? false : errorType !== Constants.NoError || networkSelector.errorMode || isNaN(amountToSendInput.input.text) readonly property bool errorMode: popup.isLoading || !recipientReady ? false : errorType !== Constants.NoError || networkSelector.errorMode || isNaN(amountToSendInput.input.text)
@ -95,9 +96,9 @@ StatusDialog {
readonly property string uuid: Utils.uuid() readonly property string uuid: Utils.uuid()
property bool isPendingTx: false property bool isPendingTx: false
property string totalTimeEstimate property string totalTimeEstimate
property string totalFeesInEth property var totalFeesInEth
property string totalFeesInFiat property var totalFeesInFiat
property double totalAmountToReceive: 0 property var totalAmountToReceive
property Timer waitTimer: Timer { property Timer waitTimer: Timer {
interval: 1500 interval: 1500
@ -156,6 +157,7 @@ StatusDialog {
header: AccountsModalHeader { header: AccountsModalHeader {
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: -height - 18 anchors.topMargin: -height - 18
locale: popup.store.locale
model: popup.store.accounts model: popup.store.accounts
selectedAccount: popup.selectedAccount selectedAccount: popup.selectedAccount
changeSelectedAccount: function(newAccount, newIndex) { changeSelectedAccount: function(newAccount, newIndex) {
@ -244,7 +246,7 @@ StatusDialog {
StatusListItemTag { StatusListItemTag {
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
Layout.preferredHeight: 22 Layout.preferredHeight: 22
title: d.maxFiatBalance && d.maxFiatBalance.amount > 0 ? qsTr("Max: %1").arg(LocaleUtils.currencyAmountToLocaleString(d.maxFiatBalance, popup.store.locale)) : qsTr("No balances active") title: d.maxFiatBalance && d.maxFiatBalance.amount > 0 ? qsTr("Max: %1").arg(LocaleUtils.currencyAmountToLocaleString(d.maxFiatBalance)) : qsTr("No balances active")
closeButtonVisible: false closeButtonVisible: false
titleText.font.pixelSize: 12 titleText.font.pixelSize: 12
bgColor: amountToSendInput.input.valid ? Theme.palette.primaryColor3 : Theme.palette.dangerColor2 bgColor: amountToSendInput.input.valid ? Theme.palette.primaryColor3 : Theme.palette.dangerColor2
@ -263,10 +265,16 @@ StatusDialog {
maxFiatBalance: d.maxFiatBalance maxFiatBalance: d.maxFiatBalance
currentCurrency: popup.store.currentCurrency currentCurrency: popup.store.currentCurrency
getFiatValue: function(cryptoValue) { getFiatValue: function(cryptoValue) {
return popup.store.getFiatValue(cryptoValue, selectedAsset.symbol, currentCurrency) return selectedAsset ? popup.currencyStore.getFiatValue(cryptoValue, selectedAsset.symbol, currentCurrency) : undefined
} }
getCryptoValue: function(fiatValue) { getCryptoValue: function(fiatValue) {
return popup.store.getFiatValue(fiatValue, selectedAsset.symbol, currentCurrency) return selectedAsset ? popup.currencyStore.getCryptoValue(fiatValue, selectedAsset.symbol, currentCurrency) : undefined
}
getFiatCurrencyAmount: function(fiatValue) {
return popup.currencyStore.getCurrencyAmount(fiatValue, currentCurrency)
}
getCryptoCurrencyAmount: function(cryptoValue) {
return selectedAsset ? popup.currencyStore.getCurrencyAmount(cryptoValue, selectedAsset.symbol) : undefined
} }
onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees() onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees()
} }
@ -280,8 +288,12 @@ StatusDialog {
isLoading: popup.isLoading isLoading: popup.isLoading
selectedAsset: assetSelector.selectedAsset selectedAsset: assetSelector.selectedAsset
isBridgeTx: popup.isBridgeTx isBridgeTx: popup.isBridgeTx
amountToReceive: d.totalAmountToReceive cryptoValueToReceive: d.totalAmountToReceive
cryptoFiatFlipped: amountToSendInput.cryptoFiatFlipped inputIsFiat: amountToSendInput.inputIsFiat
currentCurrency: popup.store.currentCurrency
getFiatValue: function(cryptoValue) {
return popup.currencyStore.getFiatValue(cryptoValue, selectedAsset.symbol, currentCurrency)
}
} }
} }
TokenListView { TokenListView {
@ -416,8 +428,8 @@ StatusDialog {
store: popup.store store: popup.store
interactive: popup.interactive interactive: popup.interactive
selectedAccount: popup.selectedAccount selectedAccount: popup.selectedAccount
amountToSend: isNaN(parseFloat(amountToSendInput.cryptoValueToSend)) ? 0 : parseFloat(amountToSendInput.cryptoValueToSend) amountToSend: amountToSendInput.cryptoValueToSend
requiredGasInEth:d.totalFeesInEth requiredGasInEth: d.totalFeesInEth
selectedAsset: assetSelector.selectedAsset selectedAsset: assetSelector.selectedAsset
onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees() onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees()
visible: d.recipientReady && !!assetSelector.selectedAsset visible: d.recipientReady && !!assetSelector.selectedAsset
@ -449,10 +461,10 @@ StatusDialog {
footer: SendModalFooter { footer: SendModalFooter {
nextButtonText: popup.isBridgeTx ? qsTr("Bridge") : qsTr("Send") nextButtonText: popup.isBridgeTx ? qsTr("Bridge") : qsTr("Send")
maxFiatFees: popup.isLoading ? "..." : "%1 %2".arg(LocaleUtils.numberToLocaleString(d.totalFeesInFiat, -1, popup.store.locale)).arg(popup.store.currentCurrency.toUpperCase()) maxFiatFees: popup.isLoading ? "..." : LocaleUtils.currencyAmountToLocaleString(d.totalFeesInFiat)
totalTimeEstimate: popup.isLoading? "..." : d.totalTimeEstimate totalTimeEstimate: popup.isLoading? "..." : d.totalTimeEstimate
pending: d.isPendingTx || popup.isLoading pending: d.isPendingTx || popup.isLoading
visible: d.recipientReady && !isNaN(amountToSendInput.cryptoValueToSend) && !d.errorMode visible: d.recipientReady && amountToSendInput.cryptoValueToSend.amount > 0 && !d.errorMode
onNextButtonClicked: popup.sendTransaction() onNextButtonClicked: popup.sendTransaction()
} }
@ -472,10 +484,11 @@ StatusDialog {
popup.bestRoutes = response.suggestedRoutes.best popup.bestRoutes = response.suggestedRoutes.best
let gasTimeEstimate = response.suggestedRoutes.gasTimeEstimate let gasTimeEstimate = response.suggestedRoutes.gasTimeEstimate
d.totalTimeEstimate = popup.store.getLabelForEstimatedTxTime(gasTimeEstimate.totalTime) d.totalTimeEstimate = popup.store.getLabelForEstimatedTxTime(gasTimeEstimate.totalTime)
d.totalFeesInEth = gasTimeEstimate.totalFeesInEth d.totalFeesInEth = popup.currencyStore.getCurrencyAmount(gasTimeEstimate.totalFeesInEth, "ETH")
d.totalFeesInFiat = parseFloat(popup.store.getFiatValue( gasTimeEstimate.totalFeesInEth, "ETH", popup.store.currentCurrency)) + let totalFeesInFiat = popup.currencyStore.getFiatValue( gasTimeEstimate.totalFeesInEth, "ETH", popup.store.currentCurrency).amount +
parseFloat(popup.store.getFiatValue(gasTimeEstimate.totalTokenFees, fees.selectedTokenSymbol, popup.store.currentCurrency)) popup.currencyStore.getFiatValue(gasTimeEstimate.totalTokenFees, fees.selectedTokenSymbol, popup.store.currentCurrency).amount
d.totalAmountToReceive = popup.store.getWei2Eth(response.suggestedRoutes.amountToReceive, assetSelector.selectedAsset.decimals) d.totalFeesInFiat = popup.currencyStore.getCurrencyAmount(totalFeesInFiat, popup.store.currentCurrency)
d.totalAmountToReceive = popup.currencyStore.getCurrencyAmount(popup.store.getWei2Eth(response.suggestedRoutes.amountToReceive, assetSelector.selectedAsset.decimals), fees.selectedTokenSymbol)
networkSelector.toNetworksList = response.suggestedRoutes.toNetworks networkSelector.toNetworksList = response.suggestedRoutes.toNetworks
popup.isLoading = false popup.isLoading = false
} }

View File

@ -1,11 +1,16 @@
import QtQuick 2.13 import QtQuick 2.13
import utils 1.0 import utils 1.0
import "../../../app/AppLayouts/Profile/stores"
QtObject { QtObject {
id: root id: root
property var locale: Qt.locale(localAppSettings.language) property var locale: Qt.locale(localAppSettings.language)
// Some token+currency-related functions are implemented in the profileSectionModule.
// We should probably refactor this and move those functions to some Wallet module.
property ProfileSectionStore profileSectionStore: ProfileSectionStore {}
property string currentCurrency: walletSection.currentCurrency property string currentCurrency: walletSection.currentCurrency
property int currentCurrencyModelIndex: { property int currentCurrencyModelIndex: {
for (var i=0; i<currenciesModel.count; i++) { for (var i=0; i<currenciesModel.count; i++) {
@ -952,4 +957,32 @@ QtObject {
function updateCurrency(newCurrency) { function updateCurrency(newCurrency) {
walletSection.updateCurrency(newCurrency) walletSection.updateCurrency(newCurrency)
} }
function getCurrencyAmount(amount, symbol) {
let obj = JSON.parse((walletSection.getCurrencyAmountAsJson(amount, symbol)))
if (obj.error) {
console.error("Error parsing currency amount json object, amount: ", amount, ", symbol ", symbol, " error: ", obj.error)
return {amount: nan, symbol: symbol}
}
return obj
}
function getFiatValue(balance, cryptoSymbol, fiatSymbol) {
var amount = profileSectionModule.ensUsernamesModule.getFiatValue(balance, cryptoSymbol, fiatSymbol)
return getCurrencyAmount(parseFloat(amount), fiatSymbol)
}
function getCryptoValue(balance, cryptoSymbol, fiatSymbol) {
var amount = profileSectionModule.ensUsernamesModule.getCryptoValue(balance, cryptoSymbol, fiatSymbol)
return getCurrencyAmount(parseFloat(amount), cryptoSymbol)
}
function getGasEthValue(gweiValue, gasLimit) {
var amount = profileSectionModule.ensUsernamesModule.getGasEthValue(gweiValue, gasLimit)
return getCurrencyAmount(parseFloat(amount), "ETH")
}
function formatCurrencyAmount(currencyAmount) {
return LocaleUtils.currencyAmountToLocaleString(currencyAmount)
}
} }

View File

@ -63,10 +63,6 @@ QtObject {
return networksModule.all.getNetworkName(symbol) return networksModule.all.getNetworkName(symbol)
} }
function getFiatValue(balance, cryptoSymbol, fiatSymbol) {
return profileSectionModule.ensUsernamesModule.getFiatValue(balance, cryptoSymbol, fiatSymbol)
}
function hex2Dec(value) { function hex2Dec(value) {
return globalUtils.hex2Dec(value) return globalUtils.hex2Dec(value)
} }
@ -207,8 +203,24 @@ QtObject {
return walletSectionTransactions.getLastTxBlockNumber() return walletSectionTransactions.getLastTxBlockNumber()
} }
function getCurrencyAmount(amount, symbol) {
return currencyStore.getCurrencyAmount(amount, symbol)
}
function getFiatValue(balance, cryptoSymbol, fiatSymbol) {
return currencyStore.getFiatValue(balance, cryptoSymbol, fiatSymbol)
}
function getCryptoValue(balance, cryptoSymbol, fiatSymbol) {
return currencyStore.getCryptoValue(balance, cryptoSymbol, fiatSymbol)
}
function getGasEthValue(gweiValue, gasLimit) { function getGasEthValue(gweiValue, gasLimit) {
return profileSectionModule.ensUsernamesModule.getGasEthValue(gweiValue, gasLimit) return currencyStore.getGasEthValue(gweiValue, gasLimit)
}
function formatCurrencyAmount(currencyAmount) {
return currencyStore.formatCurrencyAmount(currencyAmount)
} }
function getHistoricalDataForToken(symbol, currency) { function getHistoricalDataForToken(symbol, currency) {

View File

@ -61,18 +61,6 @@ QtObject {
globalUtils.copyToClipboard(text) globalUtils.copyToClipboard(text)
} }
function getFiatValue(balance, cryptoSymbol, fiatSymbol) {
return profileSectionStore.ensUsernamesStore.getFiatValue(balance, cryptoSymbol, fiatSymbol)
}
function getCryptoValue(balance, cryptoSymbol, fiatSymbol) {
return profileSectionStore.ensUsernamesStore.getCryptoValue(balance, cryptoSymbol, fiatSymbol)
}
function getGasEthValue(gweiValue, gasLimit) {
return profileSectionStore.ensUsernamesStore.getGasEthValue(gweiValue, gasLimit)
}
function authenticateAndTransfer(from, to, tokenSymbol, amount, uuid, selectedRoutes) { function authenticateAndTransfer(from, to, tokenSymbol, amount, uuid, selectedRoutes) {
walletSectionTransactions.authenticateAndTransfer(from, to, tokenSymbol, amount, uuid, selectedRoutes) walletSectionTransactions.authenticateAndTransfer(from, to, tokenSymbol, amount, uuid, selectedRoutes)
} }
@ -233,7 +221,7 @@ QtObject {
property var lockedInAmounts: [] property var lockedInAmounts: []
function addLockedInAmount(chainID, value, decimals, locked) { function addLockedInAmount(chainID, value, decimals, locked) {
let amount = Number.fromLocaleString(Qt.locale(), value) * Math.pow(10, decimals) let amount = value * Math.pow(10, decimals)
let index = lockedInAmounts.findIndex(lockedItem => lockedItem !== undefined && lockedItem.chainID === chainID) let index = lockedInAmounts.findIndex(lockedItem => lockedItem !== undefined && lockedItem.chainID === chainID)
if(index === -1) { if(index === -1) {
lockedInAmounts.push({"chainID": chainID, "value": amount.toString(16)}) lockedInAmounts.push({"chainID": chainID, "value": amount.toString(16)})
@ -253,18 +241,6 @@ QtObject {
return undefined return undefined
} }
const jsonObj = selectedAccount.getTokenBalanceOnChainAsJson(chainId, tokenSymbol) return JSON.parse(selectedAccount.getTokenBalanceOnChainAsJson(chainId, tokenSymbol))
if (jsonObj === "") {
console.warn("failed to get balance, returned json is empty")
return undefined
}
const obj = JSON.parse(jsonObj)
if (obj.error) {
console.warn("failed to get balance, json parse error: ", obj.error)
return undefined
}
return obj
} }
} }

View File

@ -5,6 +5,7 @@ import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
import utils 1.0 import utils 1.0
import shared.stores 1.0
ColumnLayout { ColumnLayout {
id: root id: root
@ -13,21 +14,24 @@ ColumnLayout {
property var store property var store
property var selectedAsset property var selectedAsset
property bool isLoading: false property bool isLoading: false
property string amountToReceive property var cryptoValueToReceive
property bool isBridgeTx: false property bool isBridgeTx: false
property bool cryptoFiatFlipped: false property bool inputIsFiat: false
property string currentCurrency
property var getFiatValue: function(cryptoValue) {}
QtObject { QtObject {
id: d id: d
function formatValue(value) {
const precision = (value === 0 ? 2 : 0)
return LocaleUtils.numberToLocaleString(value, precision, root.locale)
}
readonly property string fiatValue: { readonly property string fiatValue: {
if(!root.selectedAsset || !amountToReceive) if(!root.selectedAsset || !cryptoValueToReceive)
return formatValue(0) return LocaleUtils.numberToLocaleString(0, 2)
let cryptoValue = root.store.getFiatValue(amountToReceive, root.selectedAsset.symbol, root.store.currentCurrency) let fiatValue = root.getFiatValue(cryptoValueToReceive.amount, root.selectedAsset.symbol, RootStore.currentCurrency)
return formatValue(parseFloat(cryptoValue)) return LocaleUtils.currencyAmountToLocaleString(fiatValue)
}
readonly property string cryptoValue: {
if(!root.selectedAsset || !cryptoValueToReceive)
return LocaleUtils.numberToLocaleString(0, 2)
return LocaleUtils.currencyAmountToLocaleString(cryptoValueToReceive)
} }
} }
@ -45,31 +49,17 @@ ColumnLayout {
StatusBaseText { StatusBaseText {
id: amountToReceiveText id: amountToReceiveText
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
text: isLoading ? "..." : cryptoFiatFlipped ? d.fiatValue: amountToReceive text: isLoading ? "..." : inputIsFiat ? d.fiatValue : d.cryptoValue
font.pixelSize: Utils.getFontSizeBasedOnLetterCount(text) font.pixelSize: Utils.getFontSizeBasedOnLetterCount(text)
color: Theme.palette.directColor1 color: Theme.palette.directColor1
} }
StatusBaseText {
Layout.alignment: Qt.AlignVCenter
text: isLoading ? "..." : root.store.currentCurrency.toUpperCase()
font.pixelSize: amountToReceiveText.font.pixelSize
color: Theme.palette.directColor1
visible: cryptoFiatFlipped
}
} }
RowLayout { RowLayout {
Layout.alignment: Qt.AlignRight | Qt.AlignBottom Layout.alignment: Qt.AlignRight | Qt.AlignBottom
StatusBaseText { StatusBaseText {
id: txtFiatBalance id: txtFiatBalance
Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.alignment: Qt.AlignLeft | Qt.AlignTop
text: isLoading ? "..." : cryptoFiatFlipped ? amountToReceive : d.fiatValue text: isLoading ? "..." : inputIsFiat ? d.cryptoValue : d.fiatValue
font.pixelSize: 13
color: Theme.palette.directColor5
}
StatusBaseText {
Layout.alignment: Qt.AlignTop
Layout.leftMargin: 4
text: isLoading ? "..." : !cryptoFiatFlipped ? root.store.currentCurrency.toUpperCase() : !!root.selectedAsset ? root.selectedAsset.symbol.toUpperCase() : ""
font.pixelSize: 13 font.pixelSize: 13
color: Theme.palette.directColor5 color: Theme.palette.directColor5
} }

View File

@ -12,54 +12,54 @@ import utils 1.0
ColumnLayout { ColumnLayout {
id: root id: root
property alias input: amountToSendInput property alias input: topAmountToSendInput
property var locale property var locale
property var selectedAsset property var selectedAsset
property bool isBridgeTx: false property bool isBridgeTx: false
property bool interactive: false property bool interactive: false
property var maxFiatBalance property var maxFiatBalance
property bool cryptoFiatFlipped: false property bool inputIsFiat: false
property string cryptoValueToSend: !cryptoFiatFlipped ? amountToSendInput.text : txtFiatBalance.text property var cryptoValueToSend
Binding {
target: root
property: "cryptoValueToSend"
value: root.selectedAsset, !inputIsFiat ? getCryptoCurrencyAmount(LocaleUtils.numberFromLocaleString(topAmountToSendInput.text)) : getCryptoValue(fiatValueToSend ? fiatValueToSend.amount : 0.0)
delayed: true
}
property var fiatValueToSend
Binding {
target: root
property: "fiatValueToSend"
value: root.selectedAsset, inputIsFiat ? getFiatCurrencyAmount(LocaleUtils.numberFromLocaleString(topAmountToSendInput.text)) : getFiatValue(cryptoValueToSend ? cryptoValueToSend.amount : 0.0)
delayed: true
}
property string currentCurrency property string currentCurrency
property var getFiatValue: function(cryptoValue) {} property var getFiatValue: function(cryptoValue) {}
property var getCryptoValue: function(fiatValue) {} property var getCryptoValue: function(fiatValue) {}
property var getFiatCurrencyAmount: function(fiatValue) {}
property var getCryptoCurrencyAmount: function(cryptoValue) {}
signal reCalculateSuggestedRoute() signal reCalculateSuggestedRoute()
QtObject { QtObject {
id: d id: d
readonly property string zeroString: formatValue(0, 2) readonly property string zeroString: LocaleUtils.numberToLocaleString(0, 2)
property Timer waitTimer: Timer { property Timer waitTimer: Timer {
interval: 1000 interval: 1000
onTriggered: reCalculateSuggestedRoute() onTriggered: reCalculateSuggestedRoute()
} }
function formatValue(value, precision) {
const precisionVal = !!precision ? precision : (value === 0 ? 2 : 0)
return LocaleUtils.numberToLocaleString(value, precisionVal, root.locale)
}
function getFiatValue(value) {
if(!root.selectedAsset || !value)
return zeroString
let cryptoValue = root.getFiatValue(value)
return formatValue(parseFloat(cryptoValue))
}
function getCryptoValue(value) {
if(!root.selectedAsset || !value)
return zeroString
let cryptoValue = root.getCryptoValue(value)
return formatValue(parseFloat(cryptoValue))
}
}
onSelectedAssetChanged: { function formatValue(value) {
if(!!root.selectedAsset) { if (!value) {
txtFiatBalance.text = !cryptoFiatFlipped ? d.getFiatValue(amountToSendInput.text): d.getCryptoValue(amountToSendInput.text) return zeroString
}
return LocaleUtils.currencyAmountToLocaleString(value)
} }
} }
onMaxFiatBalanceChanged: { onMaxFiatBalanceChanged: {
floatValidator.top = maxFiatBalance.amount floatValidator.top = maxFiatBalance ? maxFiatBalance.amount : 0.0
input.validate() input.validate()
} }
@ -72,9 +72,11 @@ ColumnLayout {
color: Theme.palette.directColor1 color: Theme.palette.directColor1
} }
RowLayout { RowLayout {
id: topItem
property var topAmountToSend: !inputIsFiat ? cryptoValueToSend : fiatValueToSend
Layout.alignment: Qt.AlignLeft Layout.alignment: Qt.AlignLeft
AmountInputWithCursor { AmountInputWithCursor {
id: amountToSendInput id: topAmountToSendInput
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.maximumWidth: 163 Layout.maximumWidth: 163
Layout.preferredWidth: (!!text) ? input.edit.paintedWidth : textMetrics.advanceWidth Layout.preferredWidth: (!!text) ? input.edit.paintedWidth : textMetrics.advanceWidth
@ -91,45 +93,29 @@ ColumnLayout {
] ]
TextMetrics { TextMetrics {
id: textMetrics id: textMetrics
text: amountToSendInput.placeholderText text: topAmountToSendInput.placeholderText
font: amountToSendInput.input.placeholder.font font: topAmountToSendInput.input.placeholder.font
} }
Keys.onReleased: { Keys.onReleased: {
const amount = amountToSendInput.text.trim() const amount = topAmountToSendInput.text.trim()
if (!Utils.containsOnlyDigits(amount) || isNaN(amount)) { if (!Utils.containsOnlyDigits(amount) || isNaN(amount)) {
return return
} }
txtFiatBalance.text = !cryptoFiatFlipped ? d.getFiatValue(amount): d.getCryptoValue(amount)
d.waitTimer.restart() d.waitTimer.restart()
} }
} }
StatusBaseText {
Layout.alignment: Qt.AlignVCenter
text: root.currentCurrency.toUpperCase()
font.pixelSize: amountToSendInput.input.edit.font.pixelSize
color: Theme.palette.baseColor1
visible: cryptoFiatFlipped
}
} }
Item { Item {
id: fiatBalanceLayout id: bottomItem
property var bottomAmountToSend: inputIsFiat ? cryptoValueToSend : fiatValueToSend
Layout.alignment: Qt.AlignLeft | Qt.AlignBottom Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
Layout.preferredWidth: txtFiatBalance.width + currencyText.width Layout.preferredWidth: txtBottom.width
Layout.preferredHeight: txtFiatBalance.height Layout.preferredHeight: txtBottom.height
StatusBaseText { StatusBaseText {
id: txtFiatBalance id: txtBottom
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
text: d.getFiatValue(amountToSendInput.text) text: d.formatValue(bottomItem.bottomAmountToSend)
font.pixelSize: 13
color: Theme.palette.directColor5
}
StatusBaseText {
id: currencyText
anchors.top: parent.top
anchors.left: txtFiatBalance.right
anchors.leftMargin: 4
text: !cryptoFiatFlipped ? root.currentCurrency.toUpperCase() : !!root.selectedAsset ? root.selectedAsset.symbol.toUpperCase() : ""
font.pixelSize: 13 font.pixelSize: 13
color: Theme.palette.directColor5 color: Theme.palette.directColor5
} }
@ -137,13 +123,12 @@ ColumnLayout {
anchors.fill: parent anchors.fill: parent
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
cryptoFiatFlipped = !cryptoFiatFlipped topAmountToSendInput.validate()
amountToSendInput.validate() if(!!topAmountToSendInput.text) {
if(!!amountToSendInput.text) { topAmountToSendInput.text = LocaleUtils.currencyAmountToLocaleString(bottomItem.bottomAmountToSend, {onlyAmount: true})
const tempVal = Number.fromLocaleString(txtFiatBalance.text)
txtFiatBalance.text = !!amountToSendInput.text ? amountToSendInput.text : d.zeroString
amountToSendInput.text = tempVal
} }
inputIsFiat = !inputIsFiat
d.waitTimer.restart()
} }
} }
} }

View File

@ -58,8 +58,8 @@ Item {
asset.name: token && token.symbol ? Style.png("tokens/%1".arg(token.symbol)) : "" asset.name: token && token.symbol ? Style.png("tokens/%1".arg(token.symbol)) : ""
asset.isImage: true asset.isImage: true
primaryText: token ? token.name : "" primaryText: token ? token.name : ""
secondaryText: token ? LocaleUtils.currencyAmountToLocaleString(token.enabledNetworkBalance, RootStore.locale) : "" secondaryText: token ? LocaleUtils.currencyAmountToLocaleString(token.enabledNetworkBalance) : ""
tertiaryText: token ? LocaleUtils.currencyAmountToLocaleString(token.enabledNetworkCurrencyBalance, RootStore.locale) : "" tertiaryText: token ? LocaleUtils.currencyAmountToLocaleString(token.enabledNetworkCurrencyBalance) : ""
balances: token && token.balances ? token.balances : null balances: token && token.balances ? token.balances : null
getNetworkColor: function(chainId){ getNetworkColor: function(chainId){
return RootStore.getNetworkColor(chainId) return RootStore.getNetworkColor(chainId)
@ -68,7 +68,7 @@ Item {
return RootStore.getNetworkIcon(chainId) return RootStore.getNetworkIcon(chainId)
} }
formatBalance: function(balance){ formatBalance: function(balance){
return LocaleUtils.currencyAmountToLocaleString(balance, RootStore.locale) return LocaleUtils.currencyAmountToLocaleString(balance)
} }
} }
@ -228,7 +228,7 @@ Item {
fontColor: (Theme.palette.name === "dark") ? '#909090' : '#939BA1', fontColor: (Theme.palette.name === "dark") ? '#909090' : '#939BA1',
padding: 8, padding: 8,
callback: function(value, index, ticks) { callback: function(value, index, ticks) {
return LocaleUtils.numberToLocaleString(value, -1, RootStore.locale) return LocaleUtils.numberToLocaleString(value)
}, },
} }
}] }]
@ -267,17 +267,17 @@ Item {
InformationTile { InformationTile {
maxWidth: parent.width maxWidth: parent.width
primaryText: qsTr("Market Cap") primaryText: qsTr("Market Cap")
secondaryText: token && token.marketCap ? LocaleUtils.currencyAmountToLocaleString(token.marketCap, RootStore.locale) : "---" secondaryText: token && token.marketCap ? LocaleUtils.currencyAmountToLocaleString(token.marketCap) : "---"
} }
InformationTile { InformationTile {
maxWidth: parent.width maxWidth: parent.width
primaryText: qsTr("Day Low") primaryText: qsTr("Day Low")
secondaryText: token && token.lowDay ? LocaleUtils.currencyAmountToLocaleString(token.lowDay, RootStore.locale) : "---" secondaryText: token && token.lowDay ? LocaleUtils.currencyAmountToLocaleString(token.lowDay) : "---"
} }
InformationTile { InformationTile {
maxWidth: parent.width maxWidth: parent.width
primaryText: qsTr("Day High") primaryText: qsTr("Day High")
secondaryText: token && token.highDay ? LocaleUtils.currencyAmountToLocaleString(token.highDay, RootStore.locale) : "---" secondaryText: token && token.highDay ? LocaleUtils.currencyAmountToLocaleString(token.highDay) : "---"
} }
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true

View File

@ -7,15 +7,18 @@ import StatusQ.Core.Theme 0.1
import utils 1.0 import utils 1.0
import shared.stores 1.0
import "../controls" import "../controls"
Rectangle { Rectangle {
id: root id: root
property string gasFiatAmount property var gasFiatAmount
property bool isLoading: false property bool isLoading: false
property var bestRoutes property var bestRoutes
property var store property var store
property var currencyStore: store.currencyStore
property var selectedTokenSymbol property var selectedTokenSymbol
property int errorType: Constants.NoError property int errorType: Constants.NoError
@ -56,7 +59,7 @@ Rectangle {
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: Style.current.padding anchors.rightMargin: Style.current.padding
id: totalFeesAdvanced id: totalFeesAdvanced
text: root.isLoading ? "..." : root.gasFiatAmount text: root.isLoading ? "..." : LocaleUtils.currencyAmountToLocaleString(root.gasFiatAmount)
font.pixelSize: 15 font.pixelSize: 15
color: Theme.palette.directColor1 color: Theme.palette.directColor1
visible: !!root.bestRoutes && root.bestRoutes !== undefined && root.bestRoutes.length > 0 visible: !!root.bestRoutes && root.bestRoutes !== undefined && root.bestRoutes.length > 0
@ -64,11 +67,12 @@ Rectangle {
} }
GasSelector { GasSelector {
id: gasSelector id: gasSelector
locale: root.store.locale
width: parent.width width: parent.width
getGasEthValue: root.store.getGasEthValue getGasEthValue: root.currencyStore.getGasEthValue
getFiatValue: root.store.getFiatValue getFiatValue: root.currencyStore.getFiatValue
currentCurrency: root.store.currencyStore.currentCurrency getCurrencyAmount: root.currencyStore.getCurrencyAmount
currentCurrencySymbol: root.store.currencyStore.currentCurrencySymbol currentCurrency: root.currencyStore.currentCurrency
visible: root.errorType === Constants.NoError && !root.isLoading visible: root.errorType === Constants.NoError && !root.isLoading
bestRoutes: root.bestRoutes bestRoutes: root.bestRoutes
selectedTokenSymbol: root.selectedTokenSymbol selectedTokenSymbol: root.selectedTokenSymbol

View File

@ -17,6 +17,7 @@ import "../controls"
ColumnLayout { ColumnLayout {
id: historyView id: historyView
property var locale
property var account property var account
property int pageSize: 20 // number of transactions per page property int pageSize: 20 // number of transactions per page
property bool isLoading: false property bool isLoading: false
@ -113,17 +114,18 @@ ColumnLayout {
Component { Component {
id: transactionDelegate id: transactionDelegate
TransactionDelegate { TransactionDelegate {
isIncoming: modelData !== undefined && !!modelData ? modelData.to === account.address: false locale: historyView.locale
currentCurrency: RootStore.currentCurrency property bool modelDataValid: modelData !== undefined && !!modelData
cryptoValue: modelData !== undefined && !!modelData ? RootStore.hex2Eth(modelData.value) : "" isIncoming: modelDataValid ? modelData.to === account.address: false
cryptoValue: modelDataValid ? RootStore.getCurrencyAmount(RootStore.hex2Eth(modelData.value), resolvedSymbol) : ""
fiatValue: RootStore.getFiatValue(cryptoValue, resolvedSymbol, RootStore.currentCurrency) fiatValue: RootStore.getFiatValue(cryptoValue, resolvedSymbol, RootStore.currentCurrency)
networkIcon: modelData !== undefined && !!modelData ? RootStore.getNetworkIcon(modelData.chainId) : "" networkIcon: modelDataValid ? RootStore.getNetworkIcon(modelData.chainId) : ""
networkColor: modelData !== undefined && !!modelData ? RootStore.getNetworkColor(modelData.chainId) : "" networkColor: modelDataValid ? RootStore.getNetworkColor(modelData.chainId) : ""
networkName: modelData !== undefined && !!modelData ? RootStore.getNetworkShortName(modelData.chainId) : "" networkName: modelDataValid ? RootStore.getNetworkShortName(modelData.chainId) : ""
symbol: modelData !== undefined && !!modelData ? !!modelData.symbol ? modelData.symbol : RootStore.findTokenSymbolByAddress(modelData.contract) : "" symbol: modelDataValid ? !!modelData.symbol ? modelData.symbol : RootStore.findTokenSymbolByAddress(modelData.contract) : ""
transferStatus: modelData !== undefined && !!modelData ? RootStore.hex2Dec(modelData.txStatus) : "" transferStatus: modelDataValid ? RootStore.hex2Dec(modelData.txStatus) : ""
shortTimeStamp: modelData !== undefined && !!modelData ? LocaleUtils.formatTime(modelData.timestamp * 1000, Locale.ShortFormat) : "" shortTimeStamp: modelDataValid ? LocaleUtils.formatTime(modelData.timestamp * 1000, Locale.ShortFormat) : ""
savedAddressName: modelData !== undefined && !!modelData ? RootStore.getNameForSavedWalletAddress(modelData.to) : "" savedAddressName: modelDataValid ? RootStore.getNameForSavedWalletAddress(modelData.to) : ""
onClicked: launchTransactionDetail(modelData) onClicked: launchTransactionDetail(modelData)
} }
} }

View File

@ -16,18 +16,20 @@ Item {
id: root id: root
property var store property var store
property var locale
property var bestRoutes property var bestRoutes
property var selectedAccount property var selectedAccount
property var selectedAsset property var selectedAsset
property var allNetworks property var allNetworks
property bool customMode: false property bool customMode: false
property double amountToSend: 0 property var amountToSend
property double requiredGasInEth: 0 property var requiredGasInEth
property bool errorMode: d.customAmountToSend > root.amountToSend property bool errorMode: !root.amountToSend || d.customAmountToSend > root.amountToSend.amount
property bool interactive: true property bool interactive: true
property bool showPreferredChains: false property bool showPreferredChains: false
property var weiToEth: function(wei) {} property var weiToEth: function(wei) {}
property var reCalculateSuggestedRoute: function() {} property var reCalculateSuggestedRoute: function() {}
property var getCryptoCurrencyAmount: function(cryptoValue) {}
property int errorType: Constants.NoError property int errorType: Constants.NoError
property bool isLoading property bool isLoading
@ -50,7 +52,7 @@ Item {
d.customAmountToSend = 0 d.customAmountToSend = 0
for(var i = 0; i<fromNetworksRepeater.count; i++) { for(var i = 0; i<fromNetworksRepeater.count; i++) {
if(fromNetworksRepeater.itemAt(i).locked) { if(fromNetworksRepeater.itemAt(i).locked) {
let amountEntered = parseFloat(fromNetworksRepeater.itemAt(i).advancedInputText) let amountEntered = fromNetworksRepeater.itemAt(i).advancedInputCurrencyAmount.amount
d.customAmountToSend += isNaN(amountEntered) ? 0 : amountEntered d.customAmountToSend += isNaN(amountEntered) ? 0 : amountEntered
} }
} }
@ -91,26 +93,28 @@ Item {
objectName: model.chainId objectName: model.chainId
property double amountToSend: 0 property double amountToSend: 0
property int routeOnNetwork: 0 property int routeOnNetwork: 0
property bool tokenBalanceOnChainValid: selectedAccount && selectedAccount !== undefined && selectedAsset !== undefined property bool selectedAssetValid: selectedAccount && selectedAccount !== undefined && selectedAsset !== undefined
property var tokenBalanceOnChain: tokenBalanceOnChainValid ? root.store.getTokenBalanceOnChain(selectedAccount, model.chainId, selectedAsset.symbol) : undefined property var tokenBalanceOnChain: selectedAssetValid ? root.store.getTokenBalanceOnChain(selectedAccount, model.chainId, selectedAsset.symbol) : undefined
property var hasGas: selectedAccount.hasGas(model.chainId, model.nativeCurrencySymbol, requiredGasInEth) property bool hasGas: selectedAssetValid && requiredGasInEth ? selectedAccount.hasGas(model.chainId, model.nativeCurrencySymbol, requiredGasInEth.amount) : false
property var advancedInputCurrencyAmount: selectedAssetValid ? root.getCryptoCurrencyAmount(LocaleUtils.numberFromLocaleString(advancedInputText)) : undefined
primaryText: model.chainName primaryText: model.chainName
secondaryText: (tokenBalanceOnChain.amount === 0) && root.amountToSend !== 0 ? secondaryText: !tokenBalanceOnChain || (tokenBalanceOnChain.amount === 0 && root.amountToSend && root.amountToSend.amount !== 0) ?
qsTr("No Balance") : !hasGas ? qsTr("No Gas") : advancedInputText qsTr("No Balance") : !hasGas ? qsTr("No Gas") : advancedInputCurrencyAmount ? LocaleUtils.currencyAmountToLocaleString(advancedInputCurrencyAmount) : "N/A"
tertiaryText: root.errorMode && parseFloat(advancedInputText) !== 0 && advancedInput.valid ? qsTr("EXCEEDS SEND AMOUNT"): qsTr("BALANCE: ") + LocaleUtils.currencyAmountToLocaleString(tokenBalanceOnChain, root.store.locale) tertiaryText: root.errorMode && advancedInputCurrencyAmount && advancedInputCurrencyAmount.amount !== 0 && advancedInput.valid ? qsTr("EXCEEDS SEND AMOUNT"): qsTr("BALANCE: ") + LocaleUtils.currencyAmountToLocaleString(tokenBalanceOnChain)
locked: store.lockedInAmounts.findIndex(lockedItem => lockedItem !== undefined && lockedItem.chainID === model.chainId) !== -1 locked: store.lockedInAmounts.findIndex(lockedItem => lockedItem !== undefined && lockedItem.chainID === model.chainId) !== -1
preCalculatedAdvancedText: { preCalculatedAdvancedText: {
let index = store.lockedInAmounts.findIndex(lockedItem => lockedItem!== undefined && lockedItem.chainID === model.chainId) let index = store.lockedInAmounts.findIndex(lockedItem => lockedItem!== undefined && lockedItem.chainID === model.chainId)
if(locked && index !== -1) { if(locked && index !== -1) {
return root.weiToEth(parseInt(store.lockedInAmounts[index].value, 16)) let amount = root.weiToEth(parseInt(store.lockedInAmounts[index].value, 16))
return LocaleUtils.numberToLocaleString(amount.amount)
} }
else return LocaleUtils.numberToLocaleString(fromNetwork.amountToSend) else return LocaleUtils.numberToLocaleString(fromNetwork.amountToSend)
} }
maxAdvancedValue: tokenBalanceOnChain.amount maxAdvancedValue: tokenBalanceOnChain ? tokenBalanceOnChain.amount : 0.0
state: tokenBalanceOnChain.amount === 0 || !hasGas ? state: !tokenBalanceOnChain || tokenBalanceOnChain.amount === 0 || !hasGas ?
"unavailable" : "unavailable" :
(root.errorMode || !advancedInput.valid) && (parseFloat(advancedInputText) !== 0) ? "error" : "default" (root.errorMode || !advancedInput.valid) && (advancedInputCurrencyAmount.amount !== 0) ? "error" : "default"
cardIcon.source: Style.svg(model.iconUrl) cardIcon.source: Style.svg(model.iconUrl)
disabledText: qsTr("Disabled") disabledText: qsTr("Disabled")
disableText: qsTr("Disable") disableText: qsTr("Disable")
@ -130,9 +134,9 @@ Item {
} }
onCardLocked: { onCardLocked: {
store.addLockedInAmount(model.chainId, advancedInputText, root.selectedAsset.decimals, isLocked) store.addLockedInAmount(model.chainId, advancedInputCurrencyAmount.amount, root.selectedAsset.decimals, isLocked)
d.calculateCustomAmounts() d.calculateCustomAmounts()
if(!locked || (d.customAmountToSend <= root.amountToSend && advancedInput.valid)) if(!locked || (d.customAmountToSend <= root.amountToSend.amount && advancedInput.valid))
root.reCalculateSuggestedRoute() root.reCalculateSuggestedRoute()
} }
} }
@ -141,7 +145,7 @@ Item {
BalanceExceeded { BalanceExceeded {
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
amountToSend: root.amountToSend amountToSend: root.amountToSend ? root.amountToSend.amount : 0.0
isLoading: root.isLoading isLoading: root.isLoading
errorType: root.errorType errorType: root.errorType
} }
@ -166,9 +170,10 @@ Item {
property int routeOnNetwork: 0 property int routeOnNetwork: 0
property int bentLine: 0 property int bentLine: 0
property double amountToReceive: 0 property double amountToReceive: 0
property var currencyAmountToReceive: root.getCryptoCurrencyAmount(amountToReceive)
property bool preferred: store.preferredChainIds.includes(model.chainId) property bool preferred: store.preferredChainIds.includes(model.chainId)
primaryText: model.chainName primaryText: model.chainName
secondaryText: LocaleUtils.numberToLocaleString(amountToReceive) secondaryText: LocaleUtils.currencyAmountToLocaleString(currencyAmountToReceive)
tertiaryText: state === "unpreferred" ? qsTr("UNPREFERRED") : "" tertiaryText: state === "unpreferred" ? qsTr("UNPREFERRED") : ""
state: !preferred ? "unpreferred" : "default" state: !preferred ? "unpreferred" : "default"
opacity: preferred || showPreferredChains ? 1 : 0 opacity: preferred || showPreferredChains ? 1 : 0
@ -252,8 +257,8 @@ Item {
xOffset = (fromN.y - toN.y > 0 ? -1 : 1) * toN.bentLine * 16 xOffset = (fromN.y - toN.y > 0 ? -1 : 1) * toN.bentLine * 16
let amountToSend = weiToEth(bestRoutes[i].amountIn) let amountToSend = weiToEth(bestRoutes[i].amountIn)
let amountToReceive = weiToEth(bestRoutes[i].amountOut) let amountToReceive = weiToEth(bestRoutes[i].amountOut)
fromN.amountToSend = amountToSend fromN.amountToSend = amountToSend.amount
toN.amountToReceive += amountToReceive toN.amountToReceive += amountToReceive.amount
fromN.routeOnNetwork += 1 fromN.routeOnNetwork += 1
toN.routeOnNetwork += 1 toN.routeOnNetwork += 1
toN.bentLine = toN.objectName !== fromN.objectName toN.bentLine = toN.objectName !== fromN.objectName

View File

@ -2,6 +2,7 @@
import QtQuick.Layouts 1.13 import QtQuick.Layouts 1.13
import utils 1.0 import utils 1.0
import shared.stores 1.0
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import StatusQ.Popups 0.1 import StatusQ.Popups 0.1
@ -17,10 +18,11 @@ Item {
implicitHeight: visible ? tabBar.height + stackLayout.height + Style.current.xlPadding : 0 implicitHeight: visible ? tabBar.height + stackLayout.height + Style.current.xlPadding : 0
property var store property var store
property var currencyStore : store.currencyStore
property var selectedAccount property var selectedAccount
property var selectedAsset property var selectedAsset
property double amountToSend: 0 property var amountToSend
property double requiredGasInEth: 0 property var requiredGasInEth
property var bestRoutes property var bestRoutes
property bool isLoading: false property bool isLoading: false
property bool advancedOrCustomMode: (tabBar.currentIndex === 1) || (tabBar.currentIndex === 2) property bool advancedOrCustomMode: (tabBar.currentIndex === 1) || (tabBar.currentIndex === 2)
@ -78,13 +80,14 @@ Item {
amountToSend: root.amountToSend amountToSend: root.amountToSend
isLoading: root.isLoading isLoading: root.isLoading
store: root.store store: root.store
locale: root.store.locale
selectedAsset: root.selectedAsset selectedAsset: root.selectedAsset
selectedAccount: root.selectedAccount selectedAccount: root.selectedAccount
errorMode: root.errorMode errorMode: root.errorMode
errorType: root.errorType errorType: root.errorType
toNetworksList: root.toNetworksList toNetworksList: root.toNetworksList
weiToEth: function(wei) { weiToEth: function(wei) {
return "%1 %2".arg(LocaleUtils.numberToLocaleString(parseFloat(store.getWei2Eth(wei, selectedAsset.decimals)))).arg(selectedAsset.symbol) return root.currencyStore.getCurrencyAmount(parseFloat(store.getWei2Eth(wei, selectedAsset.decimals)), selectedAsset.symbol)
} }
reCalculateSuggestedRoute: function() { reCalculateSuggestedRoute: function() {
root.reCalculateSuggestedRoute() root.reCalculateSuggestedRoute()
@ -114,7 +117,10 @@ Item {
isBridgeTx: root.isBridgeTx isBridgeTx: root.isBridgeTx
errorType: root.errorType errorType: root.errorType
weiToEth: function(wei) { weiToEth: function(wei) {
return parseFloat(store.getWei2Eth(wei, selectedAsset.decimals)) return root.currencyStore.getCurrencyAmount(parseFloat(store.getWei2Eth(wei, selectedAsset.decimals)), selectedAsset.symbol)
}
getCryptoCurrencyAmount: function(cryptoValue) {
return selectedAsset ? root.currencyStore.getCurrencyAmount(parseFloat(cryptoValue), selectedAsset.symbol) : undefined
} }
} }
} }

View File

@ -16,14 +16,15 @@ ColumnLayout {
property var store property var store
property var selectedAccount property var selectedAccount
property double amountToSend: 0 property var amountToSend
property double requiredGasInEth: 0 property var requiredGasInEth
property bool customMode: false property bool customMode: false
property var selectedAsset property var selectedAsset
property var bestRoutes property var bestRoutes
property bool isLoading: false property bool isLoading: false
property bool errorMode: networksLoader.item ? networksLoader.item.errorMode : false property bool errorMode: networksLoader.item ? networksLoader.item.errorMode : false
property var weiToEth: function(wei) {} property var weiToEth: function(wei) {}
property var getCryptoCurrencyAmount: function(cryptoValue) {}
property bool interactive: true property bool interactive: true
property bool isBridgeTx: false property bool isBridgeTx: false
property bool showUnpreferredNetworks: preferredToggleButton.checked property bool showUnpreferredNetworks: preferredToggleButton.checked
@ -81,6 +82,7 @@ ColumnLayout {
visible: active visible: active
sourceComponent: NetworkCardsComponent { sourceComponent: NetworkCardsComponent {
store: root.store store: root.store
locale: root.store.locale
selectedAccount: root.selectedAccount selectedAccount: root.selectedAccount
allNetworks: root.store.allNetworks allNetworks: root.store.allNetworks
amountToSend: root.amountToSend amountToSend: root.amountToSend
@ -93,6 +95,7 @@ ColumnLayout {
showPreferredChains: preferredToggleButton.checked showPreferredChains: preferredToggleButton.checked
bestRoutes: root.bestRoutes bestRoutes: root.bestRoutes
weiToEth: root.weiToEth weiToEth: root.weiToEth
getCryptoCurrencyAmount: root.getCryptoCurrencyAmount
interactive: root.interactive interactive: root.interactive
errorType: root.errorType errorType: root.errorType
isLoading: root.isLoading isLoading: root.isLoading

View File

@ -16,8 +16,9 @@ RowLayout {
id: root id: root
property var store property var store
property var locale
property var bestRoutes property var bestRoutes
property double amountToSend: 0 property var amountToSend
property bool isLoading: false property bool isLoading: false
property bool isBridgeTx: false property bool isBridgeTx: false
property var selectedAsset property var selectedAsset
@ -79,7 +80,7 @@ RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.topMargin: Style.current.bigPadding Layout.topMargin: Style.current.bigPadding
amountToSend: root.amountToSend amountToSend: root.amountToSend ? root.amountToSend.amount : 0.0
isLoading: root.isLoading isLoading: root.isLoading
errorType: root.errorType errorType: root.errorType
} }
@ -98,12 +99,14 @@ RowLayout {
implicitWidth: 410 implicitWidth: 410
title: modelData.chainName title: modelData.chainName
subTitle: { subTitle: {
let index = store.lockedInAmounts.findIndex(lockedItem => lockedItem !== undefined && lockedItem.chainID === modelData.chainId) let index = store.lockedInAmounts.findIndex(lockedItem => lockedItem !== undefined && lockedItem.chainID === modelData.chainId)
var amountOut
if(!root.errorMode || index === -1) if(!root.errorMode || index === -1)
return root.weiToEth(modelData.amountOut) amountOut = root.weiToEth(modelData.amountOut)
else { else {
return root.weiToEth(parseInt(store.lockedInAmounts[index].value, 16)) amountOut = root.weiToEth(parseInt(store.lockedInAmounts[index].value, 16))
} }
return LocaleUtils.currencyAmountToLocaleString(amountOut)
} }
statusListItemSubTitle.color: root.errorMode ? Theme.palette.dangerColor1 : Theme.palette.primaryColor1 statusListItemSubTitle.color: root.errorMode ? Theme.palette.dangerColor1 : Theme.palette.primaryColor1
asset.width: 32 asset.width: 32
@ -128,7 +131,7 @@ RowLayout {
title: chainName title: chainName
property bool tokenBalanceOnChainValid: selectedAccount && selectedAccount !== undefined && selectedAsset !== undefined property bool tokenBalanceOnChainValid: selectedAccount && selectedAccount !== undefined && selectedAsset !== undefined
property var tokenBalanceOnChain: tokenBalanceOnChainValid ? root.store.getTokenBalanceOnChain(selectedAccount, chainId, selectedAsset.symbol) : undefined property var tokenBalanceOnChain: tokenBalanceOnChainValid ? root.store.getTokenBalanceOnChain(selectedAccount, chainId, selectedAsset.symbol) : undefined
subTitle: tokenBalanceOnChain ? LocaleUtils.currencyAmountToLocaleString(tokenBalanceOnChain, root.store.locale) : "N/A" subTitle: tokenBalanceOnChain ? LocaleUtils.currencyAmountToLocaleString(tokenBalanceOnChain) : "N/A"
statusListItemSubTitle.color: Theme.palette.primaryColor1 statusListItemSubTitle.color: Theme.palette.primaryColor1
asset.width: 32 asset.width: 32
asset.height: 32 asset.height: 32

View File

@ -153,7 +153,7 @@ Item {
objectName: model.name objectName: model.name
height: visible ? 64 : 0 height: visible ? 64 : 0
title: !!model.name ? model.name : "" title: !!model.name ? model.name : ""
subTitle: LocaleUtils.currencyAmountToLocaleString(model.currencyBalance, root.locale) subTitle: LocaleUtils.currencyAmountToLocaleString(model.currencyBalance)
asset.emoji: !!model.emoji ? model.emoji: "" asset.emoji: !!model.emoji ? model.emoji: ""
asset.color: model.color asset.color: model.color
asset.name: !model.emoji ? "filled-account": "" asset.name: !model.emoji ? "filled-account": ""

View File

@ -18,6 +18,7 @@ import "../controls"
Item { Item {
id: root id: root
property var locale
property var currentAccount: RootStore.currentAccount property var currentAccount: RootStore.currentAccount
property var contactsStore property var contactsStore
property var transaction property var transaction
@ -57,18 +58,19 @@ Item {
objectName: "transactionDetailHeader" objectName: "transactionDetailHeader"
width: parent.width width: parent.width
locale: root.locale
modelData: transaction modelData: transaction
isIncoming: d.isIncoming isIncoming: d.isIncoming
currentCurrency: RootStore.currentCurrency property bool transactionValid: root.transaction !== undefined && !!root.transaction
cryptoValue: root.transaction !== undefined && !!root.transaction ? RootStore.hex2Eth(transaction.value): "" cryptoValue: transactionValid ? RootStore.getCurrencyAmount(RootStore.hex2Eth(transaction.value), resolvedSymbol): undefined
fiatValue: root.transaction !== undefined && !!root.transaction ? RootStore.getFiatValue(cryptoValue, resolvedSymbol, RootStore.currentCurrency): "" fiatValue: transactionValid ? RootStore.getFiatValue(cryptoValue, resolvedSymbol, RootStore.currentCurrency): ""
networkIcon: root.transaction !== undefined && !!root.transaction ? RootStore.getNetworkIcon(transaction.chainId): "" networkIcon: transactionValid ? RootStore.getNetworkIcon(transaction.chainId): ""
networkColor: root.transaction !== undefined && !!root.transaction ? RootStore.getNetworkColor(transaction.chainId): "" networkColor: transactionValid ? RootStore.getNetworkColor(transaction.chainId): ""
networkName: root.transaction !== undefined && !!root.transaction ? RootStore.getNetworkShortName(transaction.chainId): "" networkName: transactionValid ? RootStore.getNetworkShortName(transaction.chainId): ""
symbol: root.transaction !== undefined && !!root.transaction ? RootStore.findTokenSymbolByAddress(transaction.contract): "" symbol: transactionValid ? RootStore.findTokenSymbolByAddress(transaction.contract): ""
transferStatus: root.transaction !== undefined && !!root.transaction ? RootStore.hex2Dec(transaction.txStatus): "" transferStatus: transactionValid ? RootStore.hex2Dec(transaction.txStatus): ""
shortTimeStamp: root.transaction !== undefined && !!root.transaction ? LocaleUtils.formatTime(transaction.timestamp * 1000, Locale.ShortFormat): "" shortTimeStamp: transactionValid ? LocaleUtils.formatTime(transaction.timestamp * 1000, Locale.ShortFormat): ""
savedAddressName: root.transaction !== undefined && !!root.transaction ? RootStore.getNameForSavedWalletAddress(transaction.to): "" savedAddressName: transactionValid ? RootStore.getNameForSavedWalletAddress(transaction.to): ""
title: d.isIncoming ? qsTr("Received %1 %2 from %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.from) : title: d.isIncoming ? qsTr("Received %1 %2 from %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.from) :
qsTr("Sent %1 %2 to %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.to) qsTr("Sent %1 %2 to %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.to)
sensor.enabled: false sensor.enabled: false
@ -154,18 +156,19 @@ Item {
spacing: 8 spacing: 8
TransactionDelegate { TransactionDelegate {
width: parent.width width: parent.width
locale: root.locale
modelData: transaction modelData: transaction
isIncoming: d.isIncoming isIncoming: d.isIncoming
currentCurrency: RootStore.currentCurrency property bool transactionValid: root.transaction !== undefined && !!root.transaction
cryptoValue: root.transaction !== undefined && !!root.transaction ? RootStore.hex2Eth(transaction.value): "" cryptoValue: transactionValid ? RootStore.getCurrencyAmount(RootStore.hex2Eth(transaction.value), resolvedSymbol): ""
fiatValue: RootStore.getFiatValue(cryptoValue, resolvedSymbol, RootStore.currentCurrency) fiatValue: RootStore.getFiatValue(cryptoValue, resolvedSymbol, RootStore.currentCurrency)
networkIcon: root.transaction !== undefined && !!root.transaction ? RootStore.getNetworkIcon(transaction.chainId) : "" networkIcon: transactionValid ? RootStore.getNetworkIcon(transaction.chainId) : ""
networkColor: root.transaction !== undefined && !!root.transaction ? RootStore.getNetworkColor(transaction.chainId): "" networkColor: transactionValid ? RootStore.getNetworkColor(transaction.chainId): ""
networkName: root.transaction !== undefined && !!root.transaction ? RootStore.getNetworkShortName(transaction.chainId): "" networkName: transactionValid ? RootStore.getNetworkShortName(transaction.chainId): ""
symbol: root.transaction !== undefined && !!root.transaction ? RootStore.findTokenSymbolByAddress(transaction.contract): "" symbol: transactionValid ? RootStore.findTokenSymbolByAddress(transaction.contract): ""
transferStatus: root.transaction !== undefined && !!root.transaction ? RootStore.hex2Dec(transaction.txStatus): "" transferStatus: transactionValid ? RootStore.hex2Dec(transaction.txStatus): ""
shortTimeStamp: root.transaction !== undefined && !!root.transaction ? LocaleUtils.formatTime(transaction.timestamp * 1000, Locale.ShortFormat): "" shortTimeStamp: transactionValid ? LocaleUtils.formatTime(transaction.timestamp * 1000, Locale.ShortFormat): ""
savedAddressName: root.transaction !== undefined && !!root.transaction ? RootStore.getNameForSavedWalletAddress(transaction.to): "" savedAddressName: transactionValid ? RootStore.getNameForSavedWalletAddress(transaction.to): ""
title: d.isIncoming ? qsTr("Received %1 %2 from %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.from) : title: d.isIncoming ? qsTr("Received %1 %2 from %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.from) :
qsTr("Sent %1 %2 to %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.to) qsTr("Sent %1 %2 to %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.to)
sensor.enabled: false sensor.enabled: false