feat: Refactor AmountToSend to use exact amounts for transactions
Closes: #12168
This commit is contained in:
parent
4b6e9fd70b
commit
fb48e7be0b
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
import QtQuick 2.15
|
||||
|
||||
QtObject {}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
TransactionStore 1.0 TransactionStore.qml
|
|
@ -1 +1 @@
|
|||
Subproject commit db9adb631f0631c60468cb30e1d941946022f5f4
|
||||
Subproject commit 4cab5b61060a00ad6878d09a2f8f1e2a73bb21f5
|
Loading…
Reference in New Issue