Merge pull request #526 from trezor/feature/regexp-cleanup

Feature/regexps cleanup
pull/533/head
Vladimir Volek 5 years ago committed by GitHub
commit 199d178f7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -7,26 +7,11 @@ import { findDevice, getPendingAmount, findToken } from 'reducers/utils';
import { toFiatCurrency } from 'utils/fiatConverter';
import * as SEND from 'actions/constants/send';
import * as ethUtils from 'utils/ethUtils';
import * as validators from 'utils/validators';
import type { Dispatch, GetState, PayloadAction } from 'flowtype';
import type { State, FeeLevel } from 'reducers/SendFormEthereumReducer';
// general regular expressions
const NUMBER_RE: RegExp = new RegExp('^(0|0\\.([0-9]+)?|[1-9][0-9]*\\.?([0-9]+)?|\\.[0-9]+)$');
const UPPERCASE_RE = new RegExp('^(.*[A-Z].*)$');
const ABS_RE = new RegExp('^[0-9]+$');
const ETH_18_RE = new RegExp(
'^(0|0\\.([0-9]{0,18})?|[1-9][0-9]*\\.?([0-9]{0,18})?|\\.[0-9]{0,18})$'
);
const dynamicRegexp = (decimals: number): RegExp => {
if (decimals > 0) {
return new RegExp(
`^(0|0\\.([0-9]{0,${decimals}})?|[1-9][0-9]*\\.?([0-9]{0,${decimals}})?|\\.[0-9]{1,${decimals}})$`
);
}
return ABS_RE;
};
/*
* Called from SendFormActions.observe
* Reaction for WEB3.GAS_PRICE_UPDATED action
@ -168,7 +153,10 @@ export const addressValidation = ($state: State): PayloadAction<State> => (): St
state.errors.address = 'Address is not set';
} else if (!EthereumjsUtil.isValidAddress(address)) {
state.errors.address = 'Address is not valid';
} else if (address.match(UPPERCASE_RE) && !EthereumjsUtil.isValidChecksumAddress(address)) {
} else if (
validators.hasUppercase(address) &&
!EthereumjsUtil.isValidChecksumAddress(address)
) {
state.errors.address = 'Address is not a valid checksum';
}
return state;
@ -244,7 +232,7 @@ export const amountValidation = ($state: State): PayloadAction<State> => (
const { amount } = state;
if (amount.length < 1) {
state.errors.amount = 'Amount is not set';
} else if (amount.length > 0 && !amount.match(NUMBER_RE)) {
} else if (amount.length > 0 && !validators.isNumber(amount)) {
state.errors.amount = 'Amount is not a number';
} else {
const isToken: boolean = state.currency !== state.networkSymbol;
@ -258,9 +246,8 @@ export const amountValidation = ($state: State): PayloadAction<State> => (
account.deviceState
);
if (!token) return state;
const decimalRegExp = dynamicRegexp(parseInt(token.decimals, 0));
if (!state.amount.match(decimalRegExp)) {
if (!validators.hasDecimals(state.amount, parseInt(token.decimals, 0))) {
state.errors.amount = `Maximum ${token.decimals} decimals allowed`;
} else if (new BigNumber(state.total).isGreaterThan(account.balance)) {
state.errors.amount = `Not enough ${state.networkSymbol} to cover transaction fee`;
@ -273,7 +260,7 @@ export const amountValidation = ($state: State): PayloadAction<State> => (
} else if (new BigNumber(state.amount).isLessThanOrEqualTo('0')) {
state.errors.amount = 'Amount is too low';
}
} else if (!state.amount.match(ETH_18_RE)) {
} else if (!validators.hasDecimals(state.amount, 18)) {
state.errors.amount = 'Maximum 18 decimals allowed';
} else if (
new BigNumber(state.total).isGreaterThan(
@ -302,7 +289,7 @@ export const gasLimitValidation = ($state: State): PayloadAction<State> => (
const { gasLimit } = state;
if (gasLimit.length < 1) {
state.errors.gasLimit = 'Gas limit is not set';
} else if (gasLimit.length > 0 && !gasLimit.match(NUMBER_RE)) {
} else if (gasLimit.length > 0 && !validators.isNumber(gasLimit)) {
state.errors.gasLimit = 'Gas limit is not a number';
} else {
const gl: BigNumber = new BigNumber(gasLimit);
@ -331,7 +318,7 @@ export const gasPriceValidation = ($state: State): PayloadAction<State> => (): S
const { gasPrice } = state;
if (gasPrice.length < 1) {
state.errors.gasPrice = 'Gas price is not set';
} else if (gasPrice.length > 0 && !gasPrice.match(NUMBER_RE)) {
} else if (gasPrice.length > 0 && !validators.isNumber(gasPrice)) {
state.errors.gasPrice = 'Gas price is not a number';
} else {
const gp: BigNumber = new BigNumber(gasPrice);
@ -360,7 +347,7 @@ export const nonceValidation = ($state: State): PayloadAction<State> => (
const { nonce } = state;
if (nonce.length < 1) {
state.errors.nonce = 'Nonce is not set';
} else if (!nonce.match(ABS_RE)) {
} else if (!validators.isAbs(nonce)) {
state.errors.nonce = 'Nonce is not a valid number';
} else {
const n: BigNumber = new BigNumber(nonce);

@ -5,6 +5,7 @@ import * as SEND from 'actions/constants/send';
import { findDevice, getPendingAmount } from 'reducers/utils';
import { toDecimalAmount } from 'utils/formatUtils';
import { toFiatCurrency } from 'utils/fiatConverter';
import * as validators from 'utils/validators';
import type {
Dispatch,
@ -16,10 +17,8 @@ import type {
import type { State, FeeLevel } from 'reducers/SendFormRippleReducer';
import AddressValidator from 'wallet-address-validator';
// general regular expressions
const ABS_RE = new RegExp('^[0-9]+$');
const NUMBER_RE: RegExp = new RegExp('^(0|0\\.([0-9]+)?|[1-9][0-9]*\\.?([0-9]+)?|\\.[0-9]+)$');
const XRP_6_RE = new RegExp('^(0|0\\.([0-9]{0,6})?|[1-9][0-9]*\\.?([0-9]{0,6})?|\\.[0-9]{0,6})$');
const U_INT_32 = 0xffffffff;
/*
@ -270,11 +269,11 @@ const amountValidation = ($state: State): PayloadAction<State> => (
const { amount } = state;
if (amount.length < 1) {
state.errors.amount = 'Amount is not set';
} else if (amount.length > 0 && !amount.match(NUMBER_RE)) {
} else if (amount.length > 0 && !validators.isNumber(amount)) {
state.errors.amount = 'Amount is not a number';
} else {
const pendingAmount: BigNumber = getPendingAmount(pending, state.networkSymbol);
if (!state.amount.match(XRP_6_RE)) {
if (!validators.hasDecimals(state.amount, 6)) {
state.errors.amount = 'Maximum 6 decimals allowed';
} else if (
new BigNumber(state.total).isGreaterThan(
@ -319,7 +318,7 @@ export const feeValidation = ($state: State): PayloadAction<State> => (
const { fee } = state;
if (fee.length < 1) {
state.errors.fee = 'Fee is not set';
} else if (fee.length > 0 && !fee.match(ABS_RE)) {
} else if (fee.length > 0 && !validators.isAbs(fee)) {
state.errors.fee = 'Fee must be an absolute number';
} else {
const gl: BigNumber = new BigNumber(fee);
@ -340,7 +339,7 @@ export const destinationTagValidation = ($state: State): PayloadAction<State> =>
const { destinationTag } = state;
if (destinationTag.length > 0 && !destinationTag.match(ABS_RE)) {
if (destinationTag.length > 0 && !validators.isAbs(destinationTag)) {
state.errors.destinationTag = 'Destination tag must be an absolute number';
}

@ -0,0 +1,100 @@
import * as utils from '../validators';
describe('validators utils', () => {
it('hasDecimals', () => {
expect(utils.hasDecimals('0', 18)).toBe(true);
expect(utils.hasDecimals('0.0', 18)).toBe(true);
expect(utils.hasDecimals('0.00000000', 18)).toBe(true);
expect(utils.hasDecimals('0.00000001', 18)).toBe(true);
expect(utils.hasDecimals('+0.0', 18)).toBe(false);
expect(utils.hasDecimals('-0.0', 18)).toBe(false);
expect(utils.hasDecimals('1', 18)).toBe(true);
expect(utils.hasDecimals('+1', 18)).toBe(false);
expect(utils.hasDecimals('+100000', 18)).toBe(false);
expect(utils.hasDecimals('.', 18)).toBe(false);
expect(utils.hasDecimals('-.1', 18)).toBe(false);
expect(utils.hasDecimals('0.1', 18)).toBe(true);
expect(utils.hasDecimals('0.12314841', 18)).toBe(true);
expect(utils.hasDecimals('0.1381841848184814818391931933', 18)).toBe(false); //28 decimals
expect(utils.hasDecimals('0.100000000000000000', 18)).toBe(true); //18s decimals
expect(utils.hasDecimals('100.', 18)).toBe(true);
expect(utils.hasDecimals('.1', 18)).toBe(false);
expect(utils.hasDecimals('.000000001', 18)).toBe(false);
expect(utils.hasDecimals('.13134818481481841', 18)).toBe(false);
expect(utils.hasDecimals('001.12314841', 18)).toBe(false);
expect(utils.hasDecimals('83819319391491949941', 18)).toBe(true);
expect(utils.hasDecimals('-83819319391491949941', 18)).toBe(false);
expect(utils.hasDecimals('+0.131831848184', 18)).toBe(false);
expect(utils.hasDecimals('0.127373193981774718318371831731761626162613', 18)).toBe(false);
expect(utils.hasDecimals('0.131831848184a', 18)).toBe(false);
expect(utils.hasDecimals('100a', 18)).toBe(false);
expect(utils.hasDecimals('.100a', 18)).toBe(false);
expect(utils.hasDecimals('a.100', 18)).toBe(false);
expect(utils.hasDecimals('abc', 18)).toBe(false);
expect(utils.hasDecimals('1abc0', 18)).toBe(false);
});
it('hasDecimals decimals=0', () => {
expect(utils.hasDecimals('0', 0)).toBe(true);
expect(utils.hasDecimals('0.1', 0)).toBe(false);
expect(utils.hasDecimals('0.12345', 0)).toBe(false);
expect(utils.hasDecimals('1', 0)).toBe(true);
expect(utils.hasDecimals('1.1', 0)).toBe(false);
expect(utils.hasDecimals('1000000', 0)).toBe(true);
expect(utils.hasDecimals('-1000000', 0)).toBe(false);
expect(utils.hasDecimals('.0', 0)).toBe(false);
expect(utils.hasDecimals('0.', 0)).toBe(false);
expect(utils.hasDecimals('.', 0)).toBe(false);
});
it('hasUppercase', () => {
expect(utils.hasUppercase('0')).toBe(false);
expect(utils.hasUppercase('abc')).toBe(false);
expect(utils.hasUppercase('abcD')).toBe(true);
expect(utils.hasUppercase('Abcd')).toBe(true);
expect(utils.hasUppercase('aBcd')).toBe(true);
expect(utils.hasUppercase('123abc123')).toBe(false);
expect(utils.hasUppercase('0x123abc456')).toBe(false);
expect(utils.hasUppercase('0x123aBc456')).toBe(true);
});
it('isNumber', () => {
expect(utils.isNumber('0')).toBe(true);
expect(utils.isNumber('0.0')).toBe(true);
expect(utils.isNumber('0.00000000')).toBe(true);
expect(utils.isNumber('0.00000001')).toBe(true);
expect(utils.isNumber('+0.0')).toBe(false);
expect(utils.isNumber('-0.0')).toBe(false);
expect(utils.isNumber('1')).toBe(true);
expect(utils.isNumber('+1')).toBe(false);
expect(utils.isNumber('+100000')).toBe(false);
expect(utils.isNumber('.')).toBe(false);
expect(utils.isNumber('')).toBe(false);
expect(utils.isNumber(' ')).toBe(false);
expect(utils.isNumber('-.1')).toBe(false);
expect(utils.isNumber('0.1')).toBe(true);
expect(utils.isNumber('0.12314841')).toBe(true);
expect(utils.isNumber('0.1381841848184814818391931933')).toBe(true); //28 decimals
expect(utils.isNumber('0.100000000000000000')).toBe(true); //18s decimals
expect(utils.isNumber('100.')).toBe(true);
expect(utils.isNumber('.1')).toBe(false);
expect(utils.isNumber('.000000001')).toBe(false);
expect(utils.isNumber('.13134818481481841')).toBe(false);
expect(utils.isNumber('001.12314841')).toBe(false);
expect(utils.isNumber('83819319391491949941')).toBe(true);
expect(utils.isNumber('-83819319391491949941')).toBe(false);
expect(utils.isNumber('+0.131831848184')).toBe(false);
expect(utils.isNumber('0.131831848184a')).toBe(false);
expect(utils.isNumber('100a')).toBe(false);
expect(utils.isNumber('.100a')).toBe(false);
expect(utils.isNumber('a.100')).toBe(false);
expect(utils.isNumber('abc')).toBe(false);
expect(utils.isNumber('1abc0')).toBe(false);
});
});

@ -0,0 +1,27 @@
/* @flow */
export const hasUppercase = (value: string) => {
const UPPERCASE_RE = new RegExp('^(.*[A-Z].*)$');
return UPPERCASE_RE.test(value);
};
export const hasDecimals = (value: string, decimals: number) => {
if (decimals === 0) {
return isAbs(value);
}
const ETH_DECIMALS_RE = new RegExp(
`^(0|0\\.([0-9]{0,${decimals}})?|[1-9][0-9]*\\.?([0-9]{0,${decimals}})?)$`
);
return ETH_DECIMALS_RE.test(value);
};
export const isAbs = (value: string) => {
const ABS_RE = new RegExp('^[0-9]+$');
return ABS_RE.test(value);
};
export const isNumber = (value: string) => {
const NUMBER_RE = new RegExp(`^(0|0\\.([0-9]+)?|[1-9][0-9]*\\.?([0-9]+)?)$`);
return NUMBER_RE.test(value);
};
Loading…
Cancel
Save