feat(@desktop/wallet): Round down max value in Send and Swap modals

This commit is contained in:
Dario Gabriel Lipicar 2024-11-28 11:47:58 -03:00 committed by dlipicar
parent 50132c5a0e
commit 228197e2c4
5 changed files with 194 additions and 8 deletions

View File

@ -0,0 +1,164 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import StatusQ 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import utils 1.0
import Storybook 1.0
SplitView {
id: root
Logs { id: logs }
QtObject {
id: d
readonly property var currencyAmount: {
"amount": parseFloat(ctrlAmount.text),
"symbol": ctrlSymbol.text,
"displayDecimals": ctrlDisplayDecimals.value,
"stripTrailingZeroes": ctrlStripTrailingZeroes.checked
}
readonly property var options: {
let ret = {}
if (ctrlNoSymbolOption.checked) {
ret.noSymbol = true
}
if (ctrlRawAmountOption.checked) {
ret.rawAmount = true
}
if (ctrlMinDecimalsOption.checked) {
ret.minDecimals = ctrlMinDecimalsOptionValue.value
}
if (ctrlRoundingModeOption.checked) {
ret.roundingMode = ctrlRoundingModeOptionValue.currentValue
}
return ret
}
}
Rectangle {
SplitView.fillWidth: true
SplitView.fillHeight: true
color: Theme.palette.baseColor3
StatusBaseText {
id: formattedText
//anchors.fill: parent
anchors.centerIn: parent
text: {
return LocaleUtils.currencyAmountToLocaleString(d.currencyAmount, d.options)
}
font.pixelSize: 24
}
}
LogsAndControlsPanel {
id: logsAndControlsPanel
SplitView.minimumWidth: 400
SplitView.preferredWidth: 400
logsView.logText: logs.logText
ColumnLayout {
anchors.fill: parent
RowLayout {
Layout.fillWidth: true
Label {
text: "Amount:"
}
TextField {
Layout.fillWidth: true
id: ctrlAmount
text: "123.456789"
}
}
RowLayout {
Layout.fillWidth: true
Label {
text: "Symbol:"
}
TextField {
Layout.fillWidth: true
id: ctrlSymbol
text: "ETH"
}
}
RowLayout {
Layout.fillWidth: true
Label {
text: "Display decimals:"
}
SpinBox {
id: ctrlDisplayDecimals
value: 4
from: 0
}
}
Switch {
id: ctrlStripTrailingZeroes
text: "Strip trailing zeroes"
checked: false
}
Switch {
id: ctrlNoSymbolOption
text: "No symbol"
checked: false
}
Switch {
id: ctrlRawAmountOption
text: "Raw amount"
checked: false
}
RowLayout {
Layout.fillWidth: true
Switch {
id: ctrlMinDecimalsOption
text: "Min decimals"
checked: false
}
SpinBox {
id: ctrlMinDecimalsOptionValue
value: 6
from: 0
}
}
RowLayout {
Layout.fillWidth: true
Switch {
id: ctrlRoundingModeOption
text: "Rounding mode"
checked: false
}
ComboBox {
Layout.fillWidth: true
id: ctrlRoundingModeOptionValue
textRole: "text"
valueRole: "value"
model: ListModel {
ListElement { text: "Default"; value: LocaleUtils.RoundingMode.Default }
ListElement { text: "Up"; value: LocaleUtils.RoundingMode.Up }
ListElement { text: "Down"; value: LocaleUtils.RoundingMode.Down }
}
currentIndex: 0
}
}
Item { Layout.fillHeight: true }
}
}
}
// category: Utils

View File

@ -958,7 +958,7 @@ Item {
verify(tokenSelectorIcon.visible)
verify(maxTagButton.visible)
compare(maxTagButton.text, qsTr("Max. %1").arg(expectedToken.currentBalance === 0 ? "0"
: root.swapAdaptor.currencyStore.formatCurrencyAmount(WalletUtils.calculateMaxSafeSendAmount(expectedToken.currentBalance, expectedToken.symbol), expectedToken.symbol, {noSymbol: true})))
: root.swapAdaptor.currencyStore.formatCurrencyAmount(WalletUtils.calculateMaxSafeSendAmount(expectedToken.currentBalance, expectedToken.symbol), expectedToken.symbol, {noSymbol: true, roundingMode: LocaleUtils.RoundingMode.Down})))
compare(payPanel.selectedHoldingId, expectedToken.symbol)
compare(payPanel.value, valueToExchange)
compare(payPanel.rawValue, SQUtils.AmountsArithmetic.fromNumber(valueToExchangeString, expectedToken.decimals).toString())
@ -1056,7 +1056,7 @@ Item {
verify(tokenSelectorIcon.visible)
verify(maxTagButton.visible)
compare(maxTagButton.text, qsTr("Max. %1").arg(expectedToken.currentBalance === 0 ? "0"
: root.swapAdaptor.currencyStore.formatCurrencyAmount(WalletUtils.calculateMaxSafeSendAmount(expectedToken.currentBalance, expectedToken.symbol), expectedToken.symbol, {noSymbol: true})))
: root.swapAdaptor.currencyStore.formatCurrencyAmount(WalletUtils.calculateMaxSafeSendAmount(expectedToken.currentBalance, expectedToken.symbol), expectedToken.symbol, {noSymbol: true, roundingMode: LocaleUtils.RoundingMode.Down})))
compare(payPanel.selectedHoldingId, expectedToken.symbol)
compare(payPanel.value, valueToExchange)
compare(payPanel.rawValue, SQUtils.AmountsArithmetic.fromNumber(valueToExchangeString, expectedToken.decimals).toString())
@ -1191,7 +1191,7 @@ Item {
let maxPossibleValue = WalletUtils.calculateMaxSafeSendAmount(expectedToken.currentBalance, expectedToken.symbol)
let truncmaxPossibleValue = Math.trunc(maxPossibleValue*100)/100
compare(maxTagButton.text, qsTr("Max. %1").arg(truncmaxPossibleValue === 0 ? Qt.locale().zeroDigit
: root.swapAdaptor.currencyStore.formatCurrencyAmount(truncmaxPossibleValue, expectedToken.symbol, {noSymbol: true})))
: root.swapAdaptor.currencyStore.formatCurrencyAmount(truncmaxPossibleValue, expectedToken.symbol, {noSymbol: true, roundingMode: LocaleUtils.RoundingMode.Down})))
waitForItemPolished(amountToSendInput)
verify(amountToSendInput.interactive)
tryCompare(amountToSendInput, "cursorVisible", true)
@ -1244,7 +1244,7 @@ Item {
verify(maxTagButton.visible)
let maxPossibleValue = WalletUtils.calculateMaxSafeSendAmount(expectedToken.currentBalance, expectedToken.symbol)
compare(maxTagButton.text, qsTr("Max. %1").arg(maxPossibleValue === 0 ? "0"
: root.swapAdaptor.currencyStore.formatCurrencyAmount(maxPossibleValue, expectedToken.symbol, {noSymbol: true})))
: root.swapAdaptor.currencyStore.formatCurrencyAmount(maxPossibleValue, expectedToken.symbol, {noSymbol: true, roundingMode: LocaleUtils.RoundingMode.Down})))
verify(amountToSendInput.interactive)
verify(amountToSendInput.cursorVisible)
compare(amountToSendInput.text, "")
@ -1302,7 +1302,7 @@ Item {
// check states for the pay input selector
tryCompare(maxTagButton, "visible", true)
let maxPossibleValue = WalletUtils.calculateMaxSafeSendAmount(expectedToken.currentBalance, expectedToken.symbol)
tryCompare(maxTagButton, "text", qsTr("Max. %1").arg(maxPossibleValue === 0 ? Qt.locale().zeroDigit : root.swapAdaptor.currencyStore.formatCurrencyAmount(maxPossibleValue, expectedToken.symbol, {noSymbol: true})))
tryCompare(maxTagButton, "text", qsTr("Max. %1").arg(maxPossibleValue === 0 ? Qt.locale().zeroDigit : root.swapAdaptor.currencyStore.formatCurrencyAmount(maxPossibleValue, expectedToken.symbol, {noSymbol: true, roundingMode: LocaleUtils.RoundingMode.Down})))
compare(payPanel.selectedHoldingId, expectedToken.symbol)
tryCompare(payPanel, "valueValid", !!valueToExchangeString && valueToExchange <= maxPossibleValue)
@ -1697,7 +1697,7 @@ Item {
let maxPossibleValue = WalletUtils.calculateMaxSafeSendAmount(balance, expectedToken.symbol)
compare(maxTagButton.text, qsTr("Max. %1").arg(
maxPossibleValue === 0 ? "0" :
root.swapAdaptor.currencyStore.formatCurrencyAmount(maxPossibleValue, expectedToken.symbol, {noSymbol: true})))
root.swapAdaptor.currencyStore.formatCurrencyAmount(maxPossibleValue, expectedToken.symbol, {noSymbol: true, roundingMode: LocaleUtils.RoundingMode.Down})))
compare(payPanel.selectedHoldingId.toLowerCase(), expectedToken.symbol.toLowerCase())
compare(payPanel.valueValid, valueToExchange <= maxPossibleValue)
tryCompare(payPanel, "rawValue", SQUtils.AmountsArithmetic.fromNumber(valueToExchangeString, expectedToken.decimals).toString())

View File

@ -136,6 +136,12 @@ QtObject {
return str.replace(d.nonDigitCharacterRegExp, "").length
}
enum RoundingMode {
Default,
Up,
Down
}
function currencyAmountToLocaleString(currencyAmount, options = null, locale = null) {
if (!currencyAmount) {
return qsTr("N/A")
@ -162,6 +168,7 @@ QtObject {
var optRawAmount = false
var optDisplayDecimals = currencyAmount.displayDecimals
var optStripTrailingZeroes = currencyAmount.stripTrailingZeroes
var optRoundingMode = LocaleUtils.RoundingMode.Default
if (options) {
if (options.noSymbol !== undefined && options.noSymbol === true) {
optNoSymbol = true
@ -175,6 +182,9 @@ QtObject {
if (options.stripTrailingZeroes !== undefined) {
optStripTrailingZeroes = options.stripTrailingZeroes
}
if (options.roundingMode !== undefined) {
optRoundingMode = options.roundingMode
}
}
var amountStr = ""
@ -207,6 +217,16 @@ QtObject {
displayDecimals = Math.min(optDisplayDecimals, Math.max(0, maxDigits - numIntegerDigits))
}
}
if (optRoundingMode !== LocaleUtils.RoundingMode.Default) {
let intAmount = amount * 10**displayDecimals
if (optRoundingMode === LocaleUtils.RoundingMode.Up) {
intAmount = Math.ceil(intAmount)
} else if (optRoundingMode === LocaleUtils.RoundingMode.Down) {
intAmount = Math.floor(intAmount)
}
amount = intAmount / 10**displayDecimals
}
amountStr = numberToLocaleString(amount, displayDecimals, locale)
if (optStripTrailingZeroes) {
amountStr = stripTrailingZeroes(amountStr, locale)

View File

@ -287,7 +287,8 @@ Control {
formattedValue: d.maxInputBalance === 0 ? LocaleUtils.userInputLocale.zeroDigit
: root.currencyStore.formatCurrencyAmount(
maxSafeValue, d.inputSymbol,
{ noSymbol: !amountToSendInput.fiatMode })
{ noSymbol: !amountToSendInput.fiatMode,
roundingMode: LocaleUtils.RoundingMode.Down })
visible: d.isSelectedHoldingValidAsset && root.swapSide === SwapInputPanel.SwapSide.Pay
// FIXME: This should be enabled after #15709 is resolved

View File

@ -465,7 +465,8 @@ StatusDialog {
formattedValue: d.currencyStore.formatCurrencyAmount(
maxSafeValue, d.inputSymbol,
{ noSymbol: !amountToSend.fiatMode })
{ noSymbol: !amountToSend.fiatMode,
roundingMode: LocaleUtils.RoundingMode.Down })
markAsInvalid: amountToSend.markAsInvalid