From 70e59320437c3c103156f60a5b631ad6f9f61cac Mon Sep 17 00:00:00 2001 From: Keith Date: Wed, 13 Nov 2019 15:10:53 +0800 Subject: [PATCH 1/2] fix(neuron-ui): add decimal validation on deposit value --- .../src/components/NervosDAO/index.tsx | 44 +++++++++++-------- packages/neuron-ui/src/locales/en.json | 3 +- packages/neuron-ui/src/locales/zh.json | 3 +- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/packages/neuron-ui/src/components/NervosDAO/index.tsx b/packages/neuron-ui/src/components/NervosDAO/index.tsx index a1120c5431..d4fd458d5c 100644 --- a/packages/neuron-ui/src/components/NervosDAO/index.tsx +++ b/packages/neuron-ui/src/components/NervosDAO/index.tsx @@ -10,6 +10,7 @@ import { updateNervosDaoData, clearNervosDaoData } from 'states/stateProvider/ac import calculateFee from 'utils/calculateFee' import { shannonToCKBFormatter, CKBToShannonFormatter } from 'utils/formatters' import { MIN_DEPOSIT_AMOUNT, MEDIUM_FEE_RATE, CapacityUnit } from 'utils/const' +import { verifyAmount } from 'utils/validators' import { generateDepositTx, generateWithdrawTx, generateClaimTx } from 'services/remote' import { ckbCore } from 'services/chain' @@ -56,27 +57,34 @@ const NervosDAO = ({ } clearTimeout(timer) timer = setTimeout(() => { + setErrorMessage('') + clearGeneratedTx() + + const verifyRes = verifyAmount(value) + if (verifyRes !== true) { + setErrorMessage(t(`messages.codes.${verifyRes.code}`, { fieldName: 'deposit' })) + return + } + if (+value < MIN_DEPOSIT_AMOUNT) { setErrorMessage(t('nervos-dao.minimal-fee-required', { minimal: MIN_DEPOSIT_AMOUNT })) - clearGeneratedTx() - } else { - setErrorMessage('') - generateDepositTx({ - feeRate: `${MEDIUM_FEE_RATE}`, - capacity: CKBToShannonFormatter(value, CapacityUnit.CKB), - walletID: wallet.id, - }).then(res => { - if (res.status === 1) { - dispatch({ - type: AppActions.UpdateGeneratedTx, - payload: res.result, - }) - } else { - clearGeneratedTx() - setErrorMessage(`${typeof res.message === 'string' ? res.message : res.message.content}`) - } - }) + return } + + generateDepositTx({ + feeRate: `${MEDIUM_FEE_RATE}`, + capacity: CKBToShannonFormatter(value, CapacityUnit.CKB), + walletID: wallet.id, + }).then(res => { + if (res.status === 1) { + dispatch({ + type: AppActions.UpdateGeneratedTx, + payload: res.result, + }) + } else { + setErrorMessage(`${typeof res.message === 'string' ? res.message : res.message.content}`) + } + }) }, 500) setDepositValue(value) }, diff --git a/packages/neuron-ui/src/locales/en.json b/packages/neuron-ui/src/locales/en.json index 0db1b58bc4..2a6e5d3ef5 100644 --- a/packages/neuron-ui/src/locales/en.json +++ b/packages/neuron-ui/src/locales/en.json @@ -270,7 +270,8 @@ "mnemonic": "Mnemonic", "keystore-path": "Keystore File", "keystore-name": "Wallet name", - "keystore-password": "Password" + "keystore-password": "Password", + "deposit": "Deposit" }, "codes": { "-3": "", diff --git a/packages/neuron-ui/src/locales/zh.json b/packages/neuron-ui/src/locales/zh.json index 732dd1e728..12bc52ddfd 100644 --- a/packages/neuron-ui/src/locales/zh.json +++ b/packages/neuron-ui/src/locales/zh.json @@ -270,7 +270,8 @@ "mnemonic": "助记词", "keystore-path": "Keystore 文件", "keystore-name": "钱包名称", - "keystore-password": "密码" + "keystore-password": "密码", + "deposit": "存入金额" }, "codes": { "-3": "", From f96c1543d5f881a2822931f8f27291c48dfd0312 Mon Sep 17 00:00:00 2001 From: Keith Date: Wed, 13 Nov 2019 16:40:29 +0800 Subject: [PATCH 2/2] refactor(neuron-ui): use bigint in comparison --- .../src/components/NervosDAO/index.tsx | 4 ++-- packages/neuron-ui/src/utils/formatters.ts | 2 +- packages/neuron-ui/src/utils/validators.ts | 22 +++++++++++++------ 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/packages/neuron-ui/src/components/NervosDAO/index.tsx b/packages/neuron-ui/src/components/NervosDAO/index.tsx index d4fd458d5c..bdd7010e76 100644 --- a/packages/neuron-ui/src/components/NervosDAO/index.tsx +++ b/packages/neuron-ui/src/components/NervosDAO/index.tsx @@ -9,7 +9,7 @@ import { updateNervosDaoData, clearNervosDaoData } from 'states/stateProvider/ac import calculateFee from 'utils/calculateFee' import { shannonToCKBFormatter, CKBToShannonFormatter } from 'utils/formatters' -import { MIN_DEPOSIT_AMOUNT, MEDIUM_FEE_RATE, CapacityUnit } from 'utils/const' +import { MIN_DEPOSIT_AMOUNT, MEDIUM_FEE_RATE, SHANNON_CKB_RATIO, CapacityUnit } from 'utils/const' import { verifyAmount } from 'utils/validators' import { generateDepositTx, generateWithdrawTx, generateClaimTx } from 'services/remote' @@ -66,7 +66,7 @@ const NervosDAO = ({ return } - if (+value < MIN_DEPOSIT_AMOUNT) { + if (BigInt(CKBToShannonFormatter(value)) < BigInt(MIN_DEPOSIT_AMOUNT * SHANNON_CKB_RATIO)) { setErrorMessage(t('nervos-dao.minimal-fee-required', { minimal: MIN_DEPOSIT_AMOUNT })) return } diff --git a/packages/neuron-ui/src/utils/formatters.ts b/packages/neuron-ui/src/utils/formatters.ts index 0240e1a73a..7edb19e965 100644 --- a/packages/neuron-ui/src/utils/formatters.ts +++ b/packages/neuron-ui/src/utils/formatters.ts @@ -72,7 +72,7 @@ export const currencyFormatter = ( return `${integer.replace(/\B(?=(\d{3})+(?!\d))/g, delimiter)}${dot}${decimal} ${unit}` } -export const CKBToShannonFormatter = (amount: string = '0', unit: CapacityUnit) => { +export const CKBToShannonFormatter = (amount: string = '0', unit: CapacityUnit = CapacityUnit.CKB) => { if (Number.isNaN(+amount)) { console.warn(`Amount is not a valid number`) return `${amount} ${unit}` diff --git a/packages/neuron-ui/src/utils/validators.ts b/packages/neuron-ui/src/utils/validators.ts index 3d6a5312fc..23727dfd2c 100644 --- a/packages/neuron-ui/src/utils/validators.ts +++ b/packages/neuron-ui/src/utils/validators.ts @@ -1,6 +1,14 @@ -import { MAX_NETWORK_NAME_LENGTH } from 'utils/const' +import { + MAX_NETWORK_NAME_LENGTH, + MIN_PASSWORD_LENGTH, + MAX_PASSWORD_LENGTH, + MIN_AMOUNT, + MAX_DECIMAL_DIGITS, + SHANNON_CKB_RATIO, + ErrorCode, +} from 'utils/const' +import { CKBToShannonFormatter } from 'utils/formatters' import { ckbCore } from 'services/chain' -import { MIN_PASSWORD_LENGTH, MAX_PASSWORD_LENGTH, MIN_AMOUNT, MAX_DECIMAL_DIGITS, ErrorCode } from './const' export const verifyAddress = (address: string): boolean => { if (typeof address !== 'string' || address.length !== 46) { @@ -14,27 +22,27 @@ export const verifyAddress = (address: string): boolean => { } export const verifyAmountRange = (amount: string = '') => { - return +amount >= MIN_AMOUNT + return BigInt(CKBToShannonFormatter(amount)) >= BigInt(MIN_AMOUNT * SHANNON_CKB_RATIO) } export const verifyAmount = (amount: string = '0') => { if (Number.isNaN(+amount)) { return { code: ErrorCode.FieldInvalid } } - if (+amount < 0) { - return { code: ErrorCode.NotNegative } - } const [, decimal = ''] = amount.split('.') if (decimal.length > MAX_DECIMAL_DIGITS) { return { code: ErrorCode.DecimalExceed, } } + if (BigInt(CKBToShannonFormatter(amount)) < BigInt(0)) { + return { code: ErrorCode.NotNegative } + } return true } export const verifyTotalAmount = (totalAmount: string, fee: string, balance: string) => { - if (+balance < 0) { + if (BigInt(balance) < BigInt(0)) { return false } return BigInt(totalAmount) + BigInt(fee) <= BigInt(balance)