fix(airdrop): fix decimals validation
* set decimal for assets on AidropSettingsPanel and HoldingsDropdown test pages * Disable amount length validation by default * Input: Align validation error string to the left edge * Update validation error copy fixes #11918
This commit is contained in:
parent
a2e85bb3eb
commit
2958a03c2c
|
@ -177,6 +177,10 @@ SplitView {
|
||||||
name: "chainName"
|
name: "chainName"
|
||||||
expression: model.index ? "Ethereum Mainnet" : "Goerli"
|
expression: model.index ? "Ethereum Mainnet" : "Goerli"
|
||||||
},
|
},
|
||||||
|
ExpressionRole {
|
||||||
|
name: "decimals"
|
||||||
|
expression: decimalsText.text
|
||||||
|
},
|
||||||
ExpressionRole {
|
ExpressionRole {
|
||||||
|
|
||||||
readonly property string icon1: "network/Network=Ethereum"
|
readonly property string icon1: "network/Network=Ethereum"
|
||||||
|
@ -192,7 +196,6 @@ SplitView {
|
||||||
value: TokenCategories.Category.Community
|
value: TokenCategories.Category.Community
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
Qt.callLater(() => airdropsSettingsPanel.assetsModel = this)
|
Qt.callLater(() => airdropsSettingsPanel.assetsModel = this)
|
||||||
}
|
}
|
||||||
|
@ -250,6 +253,19 @@ SplitView {
|
||||||
|
|
||||||
text: "Owner and TMaster tokens deployed"
|
text: "Owner and TMaster tokens deployed"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
Label {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: "Assets Decimals"
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id: decimalsText
|
||||||
|
text: "2"
|
||||||
|
width: 50
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,10 @@ SplitView {
|
||||||
expression: model.index ? "Ethereum Mainnet" : "Goerli"
|
expression: model.index ? "Ethereum Mainnet" : "Goerli"
|
||||||
},
|
},
|
||||||
ExpressionRole {
|
ExpressionRole {
|
||||||
|
name: "decimals"
|
||||||
|
expression: decimalsText.text
|
||||||
|
},
|
||||||
|
ExpressionRole {
|
||||||
readonly property string icon1: "network/Network=Ethereum"
|
readonly property string icon1: "network/Network=Ethereum"
|
||||||
readonly property string icon2: "network/Network=Testnet"
|
readonly property string icon2: "network/Network=Testnet"
|
||||||
|
|
||||||
|
@ -169,6 +172,16 @@ SplitView {
|
||||||
id: ctrlAllTokensMode
|
id: ctrlAllTokensMode
|
||||||
text: "All tokens mode"
|
text: "All tokens mode"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "Assets Decimals"
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id: decimalsText
|
||||||
|
Layout.preferredWidth: 50
|
||||||
|
text: "2"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,28 +24,32 @@ SplitView {
|
||||||
icon: Style.svg(ModelsData.networks.optimism),
|
icon: Style.svg(ModelsData.networks.optimism),
|
||||||
amount: "300",
|
amount: "300",
|
||||||
multiplierIndex: 0,
|
multiplierIndex: 0,
|
||||||
infiniteAmount: false
|
infiniteAmount: false,
|
||||||
|
decimals: 6
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Arbitrum",
|
name: "Arbitrum",
|
||||||
icon: Style.svg(ModelsData.networks.arbitrum),
|
icon: Style.svg(ModelsData.networks.arbitrum),
|
||||||
amount: "400000",
|
amount: "400000",
|
||||||
multiplierIndex: 3,
|
multiplierIndex: 3,
|
||||||
infiniteAmount: false
|
infiniteAmount: false,
|
||||||
|
decimals: 9
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Hermez",
|
name: "Hermez",
|
||||||
icon: Style.svg(ModelsData.networks.hermez),
|
icon: Style.svg(ModelsData.networks.hermez),
|
||||||
amount: "0",
|
amount: "0",
|
||||||
multiplierIndex: 0,
|
multiplierIndex: 0,
|
||||||
infiniteAmount: true
|
infiniteAmount: true,
|
||||||
|
decimals: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Ethereum",
|
name: "Ethereum",
|
||||||
icon: Style.svg(ModelsData.networks.ethereum),
|
icon: Style.svg(ModelsData.networks.ethereum),
|
||||||
amount: "12" + "0".repeat(18),
|
amount: "12" + "0".repeat(18),
|
||||||
multiplierIndex: 18,
|
multiplierIndex: 18,
|
||||||
infiniteAmount: false
|
infiniteAmount: false,
|
||||||
|
decimals: 9
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -130,10 +134,24 @@ SplitView {
|
||||||
|
|
||||||
text: "∞"
|
text: "∞"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "Decimals:"
|
||||||
|
}
|
||||||
|
TextField {
|
||||||
|
id: decimalsTextField
|
||||||
|
|
||||||
|
text: "0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
RowLayout {
|
||||||
text: "amount: " + tokenPanel.amount
|
Label {
|
||||||
|
text: "amount: " + tokenPanel.amount
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
text: "decimals: " + tokenPanel.decimals
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ StatusComboBox {
|
||||||
|
|
||||||
readonly property string currentName: control.currentText
|
readonly property string currentName: control.currentText
|
||||||
readonly property alias currentAmount: instantiator.amount
|
readonly property alias currentAmount: instantiator.amount
|
||||||
|
readonly property alias decimals: instantiator.decimals
|
||||||
readonly property alias currentMultiplierIndex: instantiator.multiplierIndex
|
readonly property alias currentMultiplierIndex: instantiator.multiplierIndex
|
||||||
readonly property alias currentInfiniteAmount: instantiator.infiniteAmount
|
readonly property alias currentInfiniteAmount: instantiator.infiniteAmount
|
||||||
readonly property alias currentIcon: instantiator.icon
|
readonly property alias currentIcon: instantiator.icon
|
||||||
|
@ -100,6 +101,7 @@ StatusComboBox {
|
||||||
property string amount
|
property string amount
|
||||||
property int multiplierIndex
|
property int multiplierIndex
|
||||||
property bool infiniteAmount
|
property bool infiniteAmount
|
||||||
|
property int decimals
|
||||||
|
|
||||||
model: SortFilterProxyModel {
|
model: SortFilterProxyModel {
|
||||||
sourceModel: root.model
|
sourceModel: root.model
|
||||||
|
@ -113,6 +115,7 @@ StatusComboBox {
|
||||||
readonly property list<Binding> bindings: [
|
readonly property list<Binding> bindings: [
|
||||||
Bind { property: "icon"; value: model.icon },
|
Bind { property: "icon"; value: model.icon },
|
||||||
Bind { property: "amount"; value: model.amount },
|
Bind { property: "amount"; value: model.amount },
|
||||||
|
Bind { property: "decimals"; value: model.decimals },
|
||||||
Bind { property: "multiplierIndex"; value: model.multiplierIndex },
|
Bind { property: "multiplierIndex"; value: model.multiplierIndex },
|
||||||
Bind { property: "infiniteAmount"; value: model.infiniteAmount }
|
Bind { property: "infiniteAmount"; value: model.infiniteAmount }
|
||||||
]
|
]
|
||||||
|
|
|
@ -21,6 +21,7 @@ ColumnLayout {
|
||||||
property alias tokenImage: item.iconSource
|
property alias tokenImage: item.iconSource
|
||||||
property alias amountText: amountInput.text
|
property alias amountText: amountInput.text
|
||||||
property alias amount: amountInput.amount
|
property alias amount: amountInput.amount
|
||||||
|
property alias decimals: amountInput.tokenDecimals
|
||||||
property alias multiplierIndex: amountInput.multiplierIndex
|
property alias multiplierIndex: amountInput.multiplierIndex
|
||||||
property alias tokenCategoryText: tokenLabel.text
|
property alias tokenCategoryText: tokenLabel.text
|
||||||
property alias networkLabelText: d.networkLabelText
|
property alias networkLabelText: d.networkLabelText
|
||||||
|
@ -88,6 +89,7 @@ ColumnLayout {
|
||||||
spacing: 10
|
spacing: 10
|
||||||
|
|
||||||
property alias currentAmount: inlineNetworksComboBox.currentAmount
|
property alias currentAmount: inlineNetworksComboBox.currentAmount
|
||||||
|
property alias decimals: inlineNetworksComboBox.decimals
|
||||||
property alias currentMultiplierIndex:
|
property alias currentMultiplierIndex:
|
||||||
inlineNetworksComboBox.currentMultiplierIndex
|
inlineNetworksComboBox.currentMultiplierIndex
|
||||||
property alias currentInfiniteAmount:
|
property alias currentInfiniteAmount:
|
||||||
|
@ -128,7 +130,8 @@ ColumnLayout {
|
||||||
|
|
||||||
maximumAmount: !!networksComboBoxLoader.item
|
maximumAmount: !!networksComboBoxLoader.item
|
||||||
? networksComboBoxLoader.item.currentAmount : "0"
|
? networksComboBoxLoader.item.currentAmount : "0"
|
||||||
|
tokenDecimals: !!networksComboBoxLoader.item
|
||||||
|
? networksComboBoxLoader.item.decimals : 0
|
||||||
multiplierIndex: !!networksComboBoxLoader.item
|
multiplierIndex: !!networksComboBoxLoader.item
|
||||||
? networksComboBoxLoader.item.currentMultiplierIndex : 0
|
? networksComboBoxLoader.item.currentMultiplierIndex : 0
|
||||||
|
|
||||||
|
|
|
@ -425,6 +425,7 @@ StatusDropdown {
|
||||||
name: chainName,
|
name: chainName,
|
||||||
icon: chainIcon,
|
icon: chainIcon,
|
||||||
amount: asset.remainingSupply,
|
amount: asset.remainingSupply,
|
||||||
|
decimals: asset.decimals,
|
||||||
multiplierIndex: asset.multiplierIndex,
|
multiplierIndex: asset.multiplierIndex,
|
||||||
infiniteAmount: asset.infiniteSupply
|
infiniteAmount: asset.infiniteSupply
|
||||||
})
|
})
|
||||||
|
|
|
@ -10,7 +10,6 @@ import utils 1.0
|
||||||
Input {
|
Input {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property int maximumLength: 10
|
|
||||||
property var locale: LocaleUtils.userInputLocale
|
property var locale: LocaleUtils.userInputLocale
|
||||||
|
|
||||||
readonly property alias amount: d.amount
|
readonly property alias amount: d.amount
|
||||||
|
@ -18,6 +17,7 @@ Input {
|
||||||
|
|
||||||
readonly property bool valid: validationError.length === 0
|
readonly property bool valid: validationError.length === 0
|
||||||
property bool allowDecimals: true
|
property bool allowDecimals: true
|
||||||
|
property int tokenDecimals: 0
|
||||||
|
|
||||||
property bool validateMaximumAmount: false
|
property bool validateMaximumAmount: false
|
||||||
property string maximumAmount: "0"
|
property string maximumAmount: "0"
|
||||||
|
@ -66,17 +66,12 @@ Input {
|
||||||
if (!root.allowDecimals)
|
if (!root.allowDecimals)
|
||||||
root.text = root.text.replace(root.locale.decimalPoint, "")
|
root.text = root.text.replace(root.locale.decimalPoint, "")
|
||||||
|
|
||||||
if(root.text.length === 0) {
|
if (root.text.length === 0) {
|
||||||
d.amount = "0"
|
d.amount = "0"
|
||||||
root.validationError = ""
|
root.validationError = ""
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d.getEffectiveDigitsCount(text) > root.maximumLength) {
|
|
||||||
root.validationError = qsTr("The maximum number of characters is %1").arg(root.maximumLength)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const amountNumber = LocaleUtils.numberFromLocaleString(root.text, root.locale)
|
const amountNumber = LocaleUtils.numberFromLocaleString(root.text, root.locale)
|
||||||
if (isNaN(amountNumber)) {
|
if (isNaN(amountNumber)) {
|
||||||
d.amount = "0"
|
d.amount = "0"
|
||||||
|
@ -84,23 +79,26 @@ Input {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fractionalPartLength = LocaleUtils.fractionalPartLength(amountNumber)
|
||||||
|
if (fractionalPartLength > root.tokenDecimals) {
|
||||||
|
d.amount = "0"
|
||||||
|
root.validationError = qsTr("Max %n decimal place(s) for this asset", "", root.tokenDecimals)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (!root.allowZero && amountNumber === 0) {
|
if (!root.allowZero && amountNumber === 0) {
|
||||||
d.amount = "0"
|
d.amount = "0"
|
||||||
root.validationError = qsTr("Amount must be greater than 0")
|
root.validationError = qsTr("Amount must be greater than 0")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const amount = SQUtils.AmountsArithmetic.fromNumber(
|
const amount = SQUtils.AmountsArithmetic.fromNumber(amountNumber, d.multiplierIndex)
|
||||||
amountNumber, d.multiplierIndex)
|
|
||||||
|
|
||||||
if (root.validateMaximumAmount) {
|
if (root.validateMaximumAmount && root.maximumAmount && root.maximumAmount.length > 0) {
|
||||||
const maximumAmount = SQUtils.AmountsArithmetic.fromString(
|
const maximumAmount = SQUtils.AmountsArithmetic.fromString(root.maximumAmount)
|
||||||
root.maximumAmount)
|
const maxExceeded = SQUtils.AmountsArithmetic.cmp(amount, maximumAmount) === 1
|
||||||
|
|
||||||
const maxExceeded = SQUtils.AmountsArithmetic.cmp(
|
if (maxExceeded) {
|
||||||
amount, maximumAmount) === 1
|
|
||||||
|
|
||||||
if (SQUtils.AmountsArithmetic.cmp(amount, maximumAmount) === 1) {
|
|
||||||
root.validationError = root.maximumExceededErrorText
|
root.validationError = root.maximumExceededErrorText
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -110,7 +108,7 @@ Input {
|
||||||
// As a target amount should be always integer number
|
// As a target amount should be always integer number
|
||||||
if (!Number.isInteger(amountNumber) && d.multiplierIndex === 0) {
|
if (!Number.isInteger(amountNumber) && d.multiplierIndex === 0) {
|
||||||
d.amount = amount.toString()
|
d.amount = amount.toString()
|
||||||
} else {
|
} else {
|
||||||
d.amount = amount.toFixed(0)
|
d.amount = amount.toFixed(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -177,9 +177,10 @@ Item {
|
||||||
id: validationErrorText
|
id: validationErrorText
|
||||||
visible: !!validationError
|
visible: !!validationError
|
||||||
text: validationError
|
text: validationError
|
||||||
|
anchors.left: inputField.left
|
||||||
|
anchors.leftMargin: 2
|
||||||
anchors.top: inputField.bottom
|
anchors.top: inputField.bottom
|
||||||
anchors.topMargin: validationErrorTopMargin
|
anchors.topMargin: validationErrorTopMargin
|
||||||
width: parent.width
|
|
||||||
horizontalAlignment: Text.AlignRight
|
horizontalAlignment: Text.AlignRight
|
||||||
font.pixelSize: 12
|
font.pixelSize: 12
|
||||||
height: 16
|
height: 16
|
||||||
|
|
Loading…
Reference in New Issue