feat: Refactor AmountToSend to use exact amounts for transactions

Closes: #12168
This commit is contained in:
Michał Cieślak 2023-09-15 10:51:06 +02:00 committed by Michał
parent 4b6e9fd70b
commit fb48e7be0b
29 changed files with 245 additions and 121 deletions

View File

@ -33,10 +33,6 @@ QtObject:
proc urlFromUserInput*(self: Utils, input: string): string {.slot.} =
result = url_fromUserInput(input)
proc eth2Wei*(self: Utils, eth: string, decimals: int): string {.slot.} =
let uintValue = conversion.eth2Wei(parseFloat(eth), decimals)
return uintValue.toString()
proc eth2Hex*(self: Utils, eth: float): string {.slot.} =
return "0x" & conversion.eth2Wei(eth, 18).toHex()

View File

@ -181,9 +181,9 @@ QtObject:
self.transactionRoutes = routes
self.suggestedRoutesReady(newQVariant(self.transactionRoutes))
proc suggestedRoutes*(self: View, amount: string, sendType: int): string {.slot.} =
var parsedAmount = stint.u256("0")
var parsedAmount = stint.u256(0)
try:
parsedAmount = fromHex(Stuint[256], amount)
parsedAmount = amount.parse(Uint256)
except Exception as e:
discard

View File

@ -1,4 +1,4 @@
import tables, sequtils, sugar
import tables, sequtils, stint, sugar
import ../shared_models/[balance_item, currency_amount, token_item, token_model, wallet_account_item]
@ -19,6 +19,7 @@ proc currencyAmountToItem*(amount: float64, format: CurrencyFormatDto) : Currenc
proc balanceToItemBalanceItem*(b: BalanceDto, format: CurrencyFormatDto) : balance_item.Item =
return balance_item.initItem(
b.rawBalance,
currencyAmountToItem(b.balance, format),
b.address,
b.chainId
@ -78,6 +79,7 @@ proc walletTokenToItem*(
return token_item.initItem(
t.name,
t.symbol,
t.getRawBalance(chainIds).toString(10),
currencyAmountToItem(t.getBalance(chainIds), tokenFormat),
currencyAmountToItem(t.getCurrencyBalance(chainIds, currency), currencyFormat),
currencyAmountToItem(t.getBalance(enabledChainIds), tokenFormat),

View File

@ -1,18 +1,21 @@
import strformat
import strformat, stint
import ./currency_amount
type
Item* = object
rawBalance*: Uint256
balance*: CurrencyAmount
address*: string
chainId*: int
proc initItem*(
rawBalance: Uint256,
balance: CurrencyAmount,
address: string,
chainId: int,
): Item =
result.rawBalance = rawBalance
result.balance = balance
result.address = address
result.chainId = chainId
@ -24,6 +27,9 @@ proc `$`*(self: Item): string =
chainId: {self.chainId},
]"""
proc getRawBalance*(self: Item): Uint256 =
return self.rawBalance
proc getBalance*(self: Item): CurrencyAmount =
return self.balance

View File

@ -1,4 +1,4 @@
import NimQml, Tables, strutils, strformat, algorithm
import NimQml, Tables, strutils, stint, strformat, algorithm
import balance_item
import ./currency_amount
@ -8,6 +8,7 @@ type
ChainId = UserRole + 1,
Address
Balance
RawBalance
QtObject:
type
@ -46,6 +47,7 @@ QtObject:
ModelRole.ChainId.int:"chainId",
ModelRole.Address.int:"address",
ModelRole.Balance.int:"balance",
ModelRole.RawBalance.int:"rawBalance",
}.toTable
method data(self: BalanceModel, index: QModelIndex, role: int): QVariant =
@ -65,6 +67,8 @@ QtObject:
result = newQVariant(item.address)
of ModelRole.Balance:
result = newQVariant(item.balance)
of ModelRole.RawBalance:
result = newQVariant(item.rawBalance.toString(10))
proc rowData(self: BalanceModel, index: int, column: string): string {.slot.} =
if (index >= self.items.len):
@ -74,6 +78,7 @@ QtObject:
of "chainId": result = $item.chainId
of "address": result = $item.address
of "balance": result = $item.balance
of "rawBalance": result = $item.rawBalance.toString(10)
proc cmpBalances*(x, y: Item): int =

View File

@ -9,6 +9,7 @@ type
Item* = object
name: string
symbol: string
totalRawBalance: string
totalBalance: CurrencyAmount
totalCurrencyBalance: CurrencyAmount
enabledNetworkCurrencyBalance: CurrencyAmount
@ -32,7 +33,7 @@ type
loading: bool
proc initItem*(
name, symbol: string,
name, symbol, totalRawBalance: string,
totalBalance: CurrencyAmount,
totalCurrencyBalance: CurrencyAmount,
enabledNetworkBalance: CurrencyAmount,
@ -57,6 +58,7 @@ proc initItem*(
): Item =
result.name = name
result.symbol = symbol
result.totalRawBalance = totalRawBalance
result.totalBalance = totalBalance
result.totalCurrencyBalance = totalCurrencyBalance
result.enabledNetworkBalance = enabledNetworkBalance
@ -84,6 +86,7 @@ proc `$`*(self: Item): string =
result = fmt"""AllTokensItem(
name: {self.name},
symbol: {self.symbol},
totalRawBalance: {self.totalRawBalance},
totalBalance: {self.totalBalance},
totalCurrencyBalance: {self.totalCurrencyBalance},
enabledNetworkBalance: {self.enabledNetworkBalance},
@ -110,6 +113,7 @@ proc initLoadingItem*(): Item =
return initItem(
name = "",
symbol = "",
totalRawBalance = "0",
totalBalance = newCurrencyAmount(),
totalCurrencyBalance = newCurrencyAmount(),
enabledNetworkBalance = newCurrencyAmount(),
@ -139,6 +143,9 @@ proc getName*(self: Item): string =
proc getSymbol*(self: Item): string =
return self.symbol
proc getTotalRawBalance*(self: Item): string =
return self.totalRawBalance
proc getTotalBalance*(self: Item): CurrencyAmount =
return self.totalBalance

View File

@ -7,6 +7,7 @@ type
ModelRole {.pure.} = enum
Name = UserRole + 1,
Symbol
TotalRawBalance
TotalBalance
TotalCurrencyBalance
EnabledNetworkCurrencyBalance
@ -65,6 +66,7 @@ QtObject:
{
ModelRole.Name.int:"name",
ModelRole.Symbol.int:"symbol",
ModelRole.TotalRawBalance.int:"totalRawBalance",
ModelRole.TotalBalance.int:"totalBalance",
ModelRole.TotalCurrencyBalance.int:"totalCurrencyBalance",
ModelRole.EnabledNetworkCurrencyBalance.int:"enabledNetworkCurrencyBalance",
@ -103,6 +105,8 @@ QtObject:
result = newQVariant(item.getName())
of ModelRole.Symbol:
result = newQVariant(item.getSymbol())
of ModelRole.TotalRawBalance:
result = newQVariant(item.getTotalRawBalance())
of ModelRole.TotalBalance:
result = newQVariant(item.getTotalBalance())
of ModelRole.TotalCurrencyBalance:
@ -153,6 +157,7 @@ QtObject:
case column:
of "name": result = $item.getName()
of "symbol": result = $item.getSymbol()
of "totalRawBalance": result = $item.getTotalRawBalance()
of "totalBalance": result = $item.getTotalBalance().toJsonNode()
of "totalCurrencyBalance": result = $item.getTotalCurrencyBalance().toJsonNode()
of "enabledNetworkCurrencyBalance": result = $item.getEnabledNetworkCurrencyBalance()

View File

@ -261,7 +261,7 @@ QtObject:
) =
try:
var paths: seq[TransactionBridgeDto] = @[]
let amountToSend = conversion.eth2Wei(parseFloat(value), 18)
let amountToSend = value.parse(Uint256)
let toAddress = parseAddress(to_addr)
for route in routes:
@ -320,11 +320,11 @@ QtObject:
if(routes.len > 0):
chainID = routes[0].fromNetwork.chainID
var amountToSend: Stuint[256]
var toAddress: Address
var tokenSym = tokenSymbol
let amountToSend = value.parse(Uint256)
if isERC721Transfer:
amountToSend = value.parse(Stuint[256])
let contract_tokenId = tokenSym.split(":")
if contract_tokenId.len == 2:
toAddress = parseAddress(contract_tokenId[0])
@ -332,7 +332,6 @@ QtObject:
else:
let network = self.networkService.getNetwork(chainID)
let token = self.tokenService.findTokenBySymbol(network.chainId, tokenSym)
amountToSend = conversion.eth2Wei(parseFloat(value), token.decimals)
toAddress = token.address
let transfer = Transfer(

View File

@ -1,8 +1,9 @@
import json, strformat, strutils
import json, strformat, stint, strutils
include app_service/common/json_utils
type BalanceDto* = object
rawBalance*: Uint256
balance*: float64
address*: string
chainId*: int
@ -21,6 +22,7 @@ proc getCurrencyBalance*(self: BalanceDto, currencyPrice: float64): float64 =
proc toBalanceDto*(jsonObj: JsonNode): BalanceDto =
result = BalanceDto()
result.rawBalance = jsonObj{"rawBalance"}.getStr.parse(Uint256)
result.balance = jsonObj{"balance"}.getStr.parseFloat()
discard jsonObj.getProp("address", result.address)
discard jsonObj.getProp("chainId", result.chainId)

View File

@ -1,4 +1,4 @@
import tables, json, strformat, sequtils, sugar, strutils
import tables, json, strformat, sequtils, sugar, stint, strutils
import balance_dto
@ -173,6 +173,13 @@ proc getBalance*(self: WalletTokenDto, chainIds: seq[int]): float64 =
sum += self.balancesPerChain[chainId].balance
return sum
proc getRawBalance*(self: WalletTokenDto, chainIds: seq[int]): UInt256 =
var sum = stint.u256(0)
for chainId in chainIds:
if self.balancesPerChain.hasKey(chainId):
sum += self.balancesPerChain[chainId].rawBalance
return sum
proc getCurrencyBalance*(self: WalletTokenDto, chainIds: seq[int], currency: string): float64 =
var sum = 0.0
let price = if self.marketValuesPerCurrency.hasKey(currency): self.marketValuesPerCurrency[currency].price else: 0.0

View File

@ -1,15 +1,11 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import AppLayouts.Profile.views 1.0
import Storybook 1.0
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import StatusQ.Core 0.1
import shared.popups.send.views 1.0
import utils 1.0
import shared.views 1.0
import Storybook 1.0
SplitView {
id: root
@ -33,7 +29,11 @@ SplitView {
isBridgeTx: false
interactive: true
selectedSymbol: "Crypto"
maxInputBalance: inputIsFiat ? getFiatValue(root.maxCryptoBalance) : root.maxCryptoBalance
inputIsFiat: fiatInput.checked
maxInputBalance: inputIsFiat ? getFiatValue(root.maxCryptoBalance)
: root.maxCryptoBalance
currentCurrency: "Fiat"
getFiatValue: function(cryptoValue) {
return cryptoValue * root.rate
@ -108,8 +108,14 @@ SplitView {
Layout.preferredWidth: 200
text: "6"
}
CheckBox {
id: fiatInput
text: "Fiat input value"
}
}
}
}
// category: Views
// category: Components

View File

@ -8,6 +8,7 @@ import utils 1.0
import shared.popups.send 1.0
import shared.stores 1.0
import shared.stores.send 1.0
import StatusQ.Core.Utils 0.1

View File

@ -3,6 +3,7 @@ import QtQuick 2.15
ListModel {
readonly property var data: [
{
totalRawBalance: "32330",
totalBalance: ({
displayDecimals: true,
stripTrailingZeroes: true,
@ -32,6 +33,7 @@ ListModel {
allChecked: true
},
{
totalRawBalance: "32434330",
totalBalance: ({
displayDecimals: true,
stripTrailingZeroes: true,

View File

@ -1,3 +1,3 @@
CurrenciesStore 1.0 CurrenciesStore.qml
NetworkConnectionStore 1.0 NetworkConnectionStore.qml
TransactionStore 1.0 TransactionStore.qml
singleton RootStore 1.0 RootStore.qml

View File

@ -0,0 +1,3 @@
import QtQuick 2.15
QtObject {}

View File

@ -15,7 +15,7 @@ import shared.panels 1.0
import shared.popups 1.0
import shared.stores 1.0
import shared.views.chat 1.0
import shared.popups.send.stores 1.0
import shared.stores.send 1.0
import utils 1.0
import AppLayouts.Communities.controls 1.0

View File

@ -2,42 +2,42 @@ AddressInput 1.0 AddressInput.qml
AmountInput 1.0 AmountInput.qml
AssetAndAmountInput 1.0 AssetAndAmountInput.qml
AssetDelegate 1.0 AssetDelegate.qml
AssetsDetailsHeader 1.0 AssetsDetailsHeader.qml
ContactSelector 1.0 ContactSelector.qml
ContactsListAndSearch 1.0 ContactsListAndSearch.qml
CopyButton 1.0 CopyButton.qml
CopyToClipBoardButton 1.0 CopyToClipBoardButton.qml
DisabledTooltipButton 1.0 DisabledTooltipButton.qml
EmojiHash 1.0 EmojiHash.qml
ErrorDetails 1.0 ErrorDetails.qml
FormGroup 1.0 FormGroup.qml
GetSyncCodeDesktopInstructions 1.0 GetSyncCodeDesktopInstructions.qml
GetSyncCodeMobileInstructions 1.0 GetSyncCodeMobileInstructions.qml
ImportKeypairInfo 1.0 ImportKeypairInfo.qml
InformationTag 1.0 InformationTag.qml
InformationTile 1.0 InformationTile.qml
Input 1.0 Input.qml
LoadingTokenDelegate 1.0 LoadingTokenDelegate.qml
RadioButtonSelector 1.0 RadioButtonSelector.qml
RecipientSelector 1.0 RecipientSelector.qml
SearchBox 1.0 SearchBox.qml
ShapeRectangle 1.0 ShapeRectangle.qml
SeedPhraseTextArea 1.0 SeedPhraseTextArea.qml
SendToContractWarning 1.0 SendToContractWarning.qml
SettingsRadioButton 1.0 SettingsRadioButton.qml
ShapeRectangle 1.0 ShapeRectangle.qml
SocialLinkPreview 1.0 SocialLinkPreview.qml
StatusSyncCodeInput 1.0 StatusSyncCodeInput.qml
StatusSyncCodeScan 1.0 StatusSyncCodeScan.qml
StatusSyncingInstructions 1.0 StatusSyncingInstructions.qml
StyledButton 1.0 StyledButton.qml
StyledTextArea 1.0 StyledTextArea.qml
StyledTextEdit 1.0 StyledTextEdit.qml
StyledTextEditWithLoadingState 1.0 StyledTextEditWithLoadingState.qml
StyledTextField 1.0 StyledTextField.qml
Timer 1.0 Timer.qml
TransactionDelegate 1.0 TransactionDelegate.qml
TokenDelegate 1.0 TokenDelegate.qml
TransactionAddress 1.0 TransactionAddress.qml
TransactionAddressTile 1.0 TransactionAddressTile.qml
TransactionDataTile 1.0 TransactionDataTile.qml
EmojiHash 1.0 EmojiHash.qml
InformationTile 1.0 InformationTile.qml
SocialLinkPreview 1.0 SocialLinkPreview.qml
AssetsDetailsHeader 1.0 AssetsDetailsHeader.qml
InformationTag 1.0 InformationTag.qml
TransactionDelegate 1.0 TransactionDelegate.qml
TransactionDetailsHeader.qml 1.0 TransactionDetailsHeader.qml
TokenDelegate 1.0 TokenDelegate.qml
StyledTextEditWithLoadingState 1.0 StyledTextEditWithLoadingState.qml
LoadingTokenDelegate 1.0 LoadingTokenDelegate.qml
StatusSyncCodeInput 1.0 StatusSyncCodeInput.qml
StatusSyncCodeScan 1.0 StatusSyncCodeScan.qml
GetSyncCodeMobileInstructions 1.0 GetSyncCodeMobileInstructions.qml
GetSyncCodeDesktopInstructions 1.0 GetSyncCodeDesktopInstructions.qml
ErrorDetails 1.0 ErrorDetails.qml
CopyButton 1.0 CopyButton.qml
DisabledTooltipButton 1.0 DisabledTooltipButton.qml
ImportKeypairInfo 1.0 ImportKeypairInfo.qml

View File

@ -7,6 +7,7 @@ import SortFilterProxyModel 0.2
import utils 1.0
import shared.stores 1.0
import shared.stores.send 1.0
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
@ -19,7 +20,6 @@ import StatusQ.Popups.Dialog 0.1
import "./panels"
import "./controls"
import "./views"
import "./stores"
StatusDialog {
id: popup
@ -34,8 +34,8 @@ StatusDialog {
property alias modalHeader: modalHeader.text
property var store: TransactionStore{}
property var currencyStore: store.currencyStore
property TransactionStore store: TransactionStore {}
property CurrenciesStore currencyStore: store.currencyStore
property var selectedAccount: store.selectedSenderAccount
property var collectiblesModel: store.collectiblesModel
property var nestedCollectiblesModel: store.nestedCollectiblesModel
@ -64,10 +64,12 @@ StatusDialog {
}
property var recalculateRoutesAndFees: Backpressure.debounce(popup, 600, function() {
if(!!popup.selectedAccount && !!d.selectedHolding && recipientLoader.ready && amountToSendInput.inputNumberValid) {
if(!!popup.selectedAccount && !!holdingSelector.selectedItem
&& recipientLoader.ready && amountToSendInput.inputNumberValid) {
popup.isLoading = true
let amount = d.isERC721Transfer ? 1: Math.round(amountToSendInput.cryptoValueToSend * Math.pow(10, d.selectedHolding.decimals))
popup.store.suggestedRoutes(amount.toString(16), popup.sendType)
popup.store.suggestedRoutes(d.isERC721Transfer ? "1" : amountToSendInput.cryptoValueToSend,
popup.sendType)
}
})
@ -242,6 +244,7 @@ StatusDialog {
color: Theme.palette.directColor1
Layout.maximumWidth: contentWidth
}
HoldingSelector {
id: holdingSelector
Layout.fillWidth: true
@ -287,18 +290,26 @@ StatusDialog {
visible: d.isSelectedHoldingValidAsset && !d.isERC721Transfer
AmountToSend {
id: amountToSendInput
Layout.fillWidth:true
Layout.fillWidth: true
isBridgeTx: d.isBridgeTx
interactive: popup.interactive
selectedSymbol: d.selectedSymbol
maxInputBalance: d.maxInputBalance
currentCurrency: popup.currencyStore.currentCurrency
multiplierIndex: holdingSelector.selectedItem
? holdingSelector.selectedItem.decimals
: 0
getFiatValue: function(cryptoValue) {
return selectedSymbol ? popup.currencyStore.getFiatValue(cryptoValue, selectedSymbol, currentCurrency) : 0.0
}
getCryptoValue: function(fiatValue) {
return selectedSymbol ? popup.currencyStore.getCryptoValue(fiatValue, selectedSymbol, currentCurrency) : 0.0
}
formatCurrencyAmount: popup.currencyStore.formatCurrencyAmount
onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees()
}
@ -431,6 +442,7 @@ StatusDialog {
NetworkSelector {
id: networkSelector
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.bigPadding
@ -439,7 +451,7 @@ StatusDialog {
interactive: popup.interactive
selectedAccount: popup.selectedAccount
ensAddressOrEmpty: recipientLoader.isENSValid ? recipientLoader.resolvedENSAddress : ""
amountToSend: amountToSendInput.cryptoValueToSend
amountToSend: amountToSendInput.cryptoValueToSendFloat
minSendCryptoDecimals: amountToSendInput.minSendCryptoDecimals
minReceiveCryptoDecimals: amountToSendInput.minReceiveCryptoDecimals
selectedAsset: d.selectedHolding

View File

@ -13,7 +13,6 @@ import StatusQ.Core.Theme 0.1
ColumnLayout {
id: balancedExceededError
property double amountToSend: 0
property bool isLoading: false
property int errorType: Constants.NoError
@ -40,7 +39,6 @@ ColumnLayout {
visible: !isLoading
}
Loader {
id: loadingComponent
Layout.alignment: Qt.AlignLeft
Layout.preferredHeight: 32
Layout.fillWidth: true

View File

@ -18,17 +18,22 @@ StatusListItem {
QtObject {
id: d
readonly property int indexesThatCanBeShown: Math.floor((root.statusListItemInlineTagsSlot.availableWidth - compactRow.width)/statusListItemInlineTagsSlot.children[0].width)-1
readonly property int indexesThatCanBeShown:
Math.floor((root.statusListItemInlineTagsSlot.availableWidth
- compactRow.width) / statusListItemInlineTagsSlot.children[0].width) - 1
function selectToken() {
root.tokenSelected({name, symbol, totalBalance, totalCurrencyBalance, balances, decimals})
root.tokenSelected({name, symbol, totalRawBalance, totalBalance,
totalCurrencyBalance, balances, decimals})
}
}
Connections {
target: root.sensor
function onContainsMouseChanged() {
root.tokenHovered({name, symbol, totalBalance, totalCurrencyBalance, balances, decimals}, root.sensor.containsMouse)
root.tokenHovered({name, symbol, totalRawBalance, totalBalance,
totalCurrencyBalance, balances, decimals},
root.sensor.containsMouse)
}
}

View File

@ -1,8 +1,9 @@
import QtQuick 2.13
import QtQuick.Layouts 1.13
import QtQuick 2.15
import QtQuick.Layouts 1.15
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1 as SQUtils
import StatusQ.Controls.Validators 0.1
import "../controls"
@ -12,127 +13,197 @@ import utils 1.0
ColumnLayout {
id: root
property alias input: topAmountToSendInput
readonly property bool inputNumberValid: !!input.text && !isNaN(d.inputNumber)
readonly property double inputNumber: inputNumberValid ? d.inputNumber : 0
readonly property int minSendCryptoDecimals: !inputIsFiat ? LocaleUtils.fractionalPartLength(inputNumber) : 0
readonly property int minReceiveCryptoDecimals: !inputIsFiat ? minSendCryptoDecimals + 1 : 0
readonly property int minSendFiatDecimals: inputIsFiat ? LocaleUtils.fractionalPartLength(inputNumber) : 0
readonly property int minReceiveFiatDecimals: inputIsFiat ? minSendFiatDecimals + 1 : 0
readonly property alias input: topAmountToSendInput
readonly property bool inputNumberValid: !!input.text && !isNaN(d.parsedInput)
readonly property int minSendCryptoDecimals:
!inputIsFiat ? LocaleUtils.fractionalPartLength(d.inputNumber) : 0
readonly property int minReceiveCryptoDecimals:
!inputIsFiat ? minSendCryptoDecimals + 1 : 0
readonly property int minSendFiatDecimals:
inputIsFiat ? LocaleUtils.fractionalPartLength(d.inputNumber) : 0
readonly property int minReceiveFiatDecimals:
inputIsFiat ? minSendFiatDecimals + 1 : 0
property string selectedSymbol // Crypto asset symbol like ETH
property string currentCurrency // Fiat currency symbol like USD
property int multiplierIndex // How divisible the token is, 18 for ETH
property double maxInputBalance
property string selectedSymbol
property bool isBridgeTx: false
property bool interactive: false
property double maxInputBalance
property bool inputIsFiat: false
property double cryptoValueToSend
Binding {
target: root
property: "cryptoValueToSend"
value: {
const value = !inputIsFiat ? inputNumber : getCryptoValue(fiatValueToSend)
return root.selectedSymbol, value
}
delayed: true
}
property double fiatValueToSend
Binding {
target: root
property: "fiatValueToSend"
value: {
const value = inputIsFiat ? inputNumber : getFiatValue(cryptoValueToSend)
return root.selectedSymbol, value
}
delayed: true
}
property string currentCurrency
property var getFiatValue: function(cryptoValue) {}
property var getCryptoValue: function(fiatValue) {}
property var formatCurrencyAmount: function() {}
// Crypto value to send expressed in base units (like wei for ETH),
// as a string representing integer decimal
readonly property alias cryptoValueToSend: d.cryptoValueRawToSend
readonly property alias cryptoValueToSendFloat: d.cryptoValueToSend
property var getFiatValue: cryptoValue => {}
property var getCryptoValue: fiatValue => {}
property var formatCurrencyAmount:
(amount, symbol, options = null, locale = null) => {}
signal reCalculateSuggestedRoute()
QtObject {
id: d
readonly property string zeroString: LocaleUtils.numberToLocaleString(0, 2, LocaleUtils.userInputLocale)
readonly property double inputNumber: LocaleUtils.numberFromLocaleString(topAmountToSendInput.text, LocaleUtils.userInputLocale)
property Timer waitTimer: Timer {
property double cryptoValueToSend
property double fiatValueToSend
Binding on cryptoValueToSend {
value: {
root.selectedSymbol
return root.inputIsFiat ? root.getCryptoValue(d.fiatValueToSend)
: d.inputNumber
}
delayed: true
}
Binding on fiatValueToSend {
value: {
root.selectedSymbol
return root.inputIsFiat ? d.inputNumber
: root.getFiatValue(d.cryptoValueToSend)
}
delayed: true
}
readonly property string cryptoValueRawToSend: {
if (!root.inputNumberValid)
return "0"
return SQUtils.AmountsArithmetic.fromNumber(
d.cryptoValueToSend, root.multiplierIndex).toString()
}
readonly property string zeroString:
LocaleUtils.numberToLocaleString(0, 2, LocaleUtils.userInputLocale)
readonly property double parsedInput:
LocaleUtils.numberFromLocaleString(topAmountToSendInput.text,
LocaleUtils.userInputLocale)
readonly property double inputNumber:
root.inputNumberValid ? d.parsedInput : 0
readonly property Timer waitTimer: Timer {
interval: 1000
onTriggered: reCalculateSuggestedRoute()
}
}
onMaxInputBalanceChanged: {
floatValidator.top = maxInputBalance
input.validate()
}
StatusBaseText {
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
text: root.isBridgeTx ? qsTr("Amount to bridge") : qsTr("Amount to send")
text: root.isBridgeTx ? qsTr("Amount to bridge")
: qsTr("Amount to send")
font.pixelSize: 13
lineHeight: 18
lineHeightMode: Text.FixedHeight
color: Theme.palette.directColor1
}
RowLayout {
id: topItem
property double topAmountToSend: !inputIsFiat ? cryptoValueToSend : fiatValueToSend
property string topAmountSymbol: !inputIsFiat ? root.selectedSymbol : root.currentCurrency
property double topAmountToSend: !inputIsFiat ? d.cryptoValueToSend
: d.fiatValueToSend
property string topAmountSymbol: !inputIsFiat ? root.selectedSymbol
: root.currentCurrency
Layout.alignment: Qt.AlignLeft
AmountInputWithCursor {
id: topAmountToSendInput
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.maximumWidth: 250
Layout.preferredWidth: (!!text) ? input.edit.paintedWidth : textMetrics.advanceWidth
Layout.preferredWidth: !!text ? input.edit.paintedWidth
: textMetrics.advanceWidth
placeholderText: d.zeroString
input.edit.color: input.valid ? Theme.palette.directColor1 : Theme.palette.dangerColor1
input.edit.color: input.valid ? Theme.palette.directColor1
: Theme.palette.dangerColor1
input.edit.readOnly: !root.interactive
validators: [
StatusFloatValidator {
id: floatValidator
bottom: 0
top: root.maxInputBalance
errorMessage: ""
locale: LocaleUtils.userInputLocale
},
StatusValidator {
errorMessage: ""
validate: (text) => {
const num = parseFloat(text)
if (isNaN(num))
return true
return num <= root.maxInputBalance
}
}
]
TextMetrics {
id: textMetrics
text: topAmountToSendInput.placeholderText
font: topAmountToSendInput.input.placeholder.font
}
Keys.onReleased: {
const amount = LocaleUtils.numberFromLocaleString(topAmountToSendInput.text, LocaleUtils.userInputLocale)
if (isNaN(amount)) {
return
}
d.waitTimer.restart()
const amount = LocaleUtils.numberFromLocaleString(
topAmountToSendInput.text,
LocaleUtils.userInputLocale)
if (!isNaN(amount))
d.waitTimer.restart()
}
}
}
Item {
id: bottomItem
property double bottomAmountToSend: inputIsFiat ? cryptoValueToSend : fiatValueToSend
property string bottomAmountSymbol: inputIsFiat ? selectedSymbol : currentCurrency
property double bottomAmountToSend: inputIsFiat ? d.cryptoValueToSend
: d.fiatValueToSend
property string bottomAmountSymbol: inputIsFiat ? selectedSymbol
: currentCurrency
Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
Layout.preferredWidth: txtBottom.width
Layout.preferredHeight: txtBottom.height
StatusBaseText {
id: txtBottom
anchors.top: parent.top
anchors.left: parent.left
text: root.formatCurrencyAmount(bottomItem.bottomAmountToSend, bottomItem.bottomAmountSymbol)
text: root.formatCurrencyAmount(bottomItem.bottomAmountToSend,
bottomItem.bottomAmountSymbol)
font.pixelSize: 13
color: Theme.palette.directColor5
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
topAmountToSendInput.validate()
if(!!topAmountToSendInput.text) {
topAmountToSendInput.text = root.formatCurrencyAmount(bottomItem.bottomAmountToSend, bottomItem.bottomAmountSymbol, {noSymbol: true, rawAmount: true}, LocaleUtils.userInputLocale)
topAmountToSendInput.text = root.formatCurrencyAmount(
bottomItem.bottomAmountToSend,
bottomItem.bottomAmountSymbol,
{ noSymbol: true, rawAmount: true },
LocaleUtils.userInputLocale)
}
inputIsFiat = !inputIsFiat
d.waitTimer.restart()

View File

@ -109,7 +109,7 @@ Item {
(root.errorMode || !advancedInput.valid) && advancedInputCurrencyAmount > 0 ? "error" : "default"
cardIcon.source: Style.svg(model.iconUrl)
disabledText: qsTr("Disabled")
disableText: qsTr("Disable")
disableText: qsTr("Disable")
enableText: qsTr("Enable")
advancedMode: root.customMode
disabled: !model.isEnabled
@ -133,7 +133,6 @@ Item {
BalanceExceeded {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
amountToSend: root.amountToSend
errorType: root.errorType
visible: root.errorType === Constants.NoRoute
}

View File

@ -79,7 +79,6 @@ Item {
width: stackLayout.width - Style.current.bigPadding
isBridgeTx: root.isBridgeTx
isERC721Transfer: root.isERC721Transfer
amountToSend: root.amountToSend
minReceiveCryptoDecimals: root.minReceiveCryptoDecimals
isLoading: root.isLoading
store: root.store

View File

@ -16,7 +16,6 @@ RowLayout {
id: root
property var store
property double amountToSend
property int minReceiveCryptoDecimals: 0
property bool isLoading: false
property bool isBridgeTx: false
@ -82,7 +81,6 @@ RowLayout {
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: Style.current.smallPadding
Layout.rightMargin: Style.current.padding
amountToSend: root.amountToSend
errorType: root.errorType
isLoading: root.isLoading && !root.isBridgeTx
}

View File

@ -0,0 +1 @@
TransactionStore 1.0 TransactionStore.qml

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit db9adb631f0631c60468cb30e1d941946022f5f4
Subproject commit 4cab5b61060a00ad6878d09a2f8f1e2a73bb21f5