openethereum/js/src/util/validation.js
Nicolas Gotchac a99721004b Minimise transactions progress (#4942)
* Watch the requests and display them throughout the app

* Linting

* Showing Requests

* Fully working Transaction Requests Display

* Add FormattedMessage to Requests

* Clean-up the Transfer dialog

* Update Validations

* Cleanup Create Wallet

* Clean Deploy Contract Dialog

* Cleanup Contract Execution

* Fix Requests

* Cleanup Wallet Settings

* Don't show stepper in Portal if less than 2 steps

* WIP local storage requests

* Caching requests and saving contract deployments

* Add Historic prop to Requests MethodDecoding

* Fix tests

* Add Contract address to MethodDecoding

* PR Grumbles - Part I

* PR Grumbles - Part II

* Use API Subscription methods

* Linting

* Move SavedRequests and add tests

* Added tests for Requests Actions

* Fixing tests

* PR Grumbles + Playground fix

* Revert Playground changes

* PR Grumbles

* Better showEth in MethodDecoding
2017-03-28 14:34:31 +02:00

233 lines
5.4 KiB
JavaScript

// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import BigNumber from 'bignumber.js';
import apiutil from '~/api/util';
import { NULL_ADDRESS } from './constants';
// TODO: Convert to FormattedMessages as soon as comfortable with the impact, i.e. errors
// not being concatted into strings in components, all supporting a non-string format
export const ERRORS = {
invalidAddress: 'address is an invalid network address',
invalidAmount: 'the supplied amount should be a valid positive number',
invalidAmountDecimals: 'the supplied amount exceeds the allowed decimals',
duplicateAddress: 'the address is already in your address book',
invalidChecksum: 'address has failed the checksum formatting',
invalidName: 'name should not be blank and longer than 2',
invalidAbi: 'abi should be a valid JSON array',
invalidCode: 'code should be the compiled hex string',
invalidNumber: 'invalid number format',
negativeNumber: 'input number should be positive',
decimalNumber: 'input number should not contain decimals',
gasException: 'the transaction will throw an exception with the current values',
gasBlockLimit: 'the transaction execution will exceed the block gas limit'
};
export function validateAbi (abi) {
let abiError = null;
let abiParsed = null;
try {
abiParsed = JSON.parse(abi);
if (!apiutil.isArray(abiParsed)) {
abiError = ERRORS.invalidAbi;
return {
error: abiError,
abi,
abiError,
abiParsed
};
}
// Validate each elements of the Array
const invalidIndex = abiParsed
.map((o) => isValidAbiEvent(o) || isValidAbiFunction(o) || isAbiFallback(o))
.findIndex((valid) => !valid);
if (invalidIndex !== -1) {
const invalid = abiParsed[invalidIndex];
// TODO: Needs seperate error when using FormattedMessage (no concats)
abiError = `${ERRORS.invalidAbi} (#${invalidIndex}: ${invalid.name || invalid.type})`;
return {
error: abiError,
abi,
abiError,
abiParsed
};
}
abi = JSON.stringify(abiParsed);
} catch (error) {
abiError = ERRORS.invalidAbi;
}
return {
error: abiError,
abi,
abiError,
abiParsed
};
}
function isValidAbiFunction (object) {
if (!object) {
return false;
}
return ((object.type === 'function' && object.name) || object.type === 'constructor') &&
(object.inputs && apiutil.isArray(object.inputs));
}
function isAbiFallback (object) {
if (!object) {
return false;
}
return object.type === 'fallback';
}
function isValidAbiEvent (object) {
if (!object) {
return false;
}
return (object.type === 'event') &&
(object.name) &&
(object.inputs && apiutil.isArray(object.inputs));
}
export function validateAddress (address) {
let addressError = null;
if (!address) {
addressError = ERRORS.invalidAddress;
} else if (!apiutil.isAddressValid(address)) {
addressError = ERRORS.invalidAddress;
} else {
address = apiutil.toChecksumAddress(address);
}
return {
error: addressError,
address,
addressError
};
}
export function validateCode (code) {
let codeError = null;
if (!code || !code.length) {
codeError = ERRORS.invalidCode;
} else if (!apiutil.isHex(code)) {
codeError = ERRORS.invalidCode;
}
return {
error: codeError,
code,
codeError
};
}
export function validateName (name) {
const nameError = !name || name.trim().length < 2
? ERRORS.invalidName
: null;
return {
error: nameError,
name,
nameError
};
}
export function validatePositiveNumber (number) {
let numberError = null;
try {
const v = new BigNumber(number);
if (v.lt(0)) {
numberError = ERRORS.invalidAmount;
}
} catch (e) {
numberError = ERRORS.invalidAmount;
}
return {
error: numberError,
number,
numberError
};
}
export function validateDecimalsNumber (number, base = 1) {
let numberError = null;
try {
const s = new BigNumber(number).mul(base).toFixed();
if (s.indexOf('.') !== -1) {
numberError = ERRORS.invalidAmountDecimals;
}
} catch (e) {
numberError = ERRORS.invalidAmount;
}
return {
error: numberError,
number,
numberError
};
}
export function validateUint (value) {
let valueError = null;
try {
const bn = new BigNumber(value);
if (bn.lt(0)) {
valueError = ERRORS.negativeNumber;
} else if (!bn.isInteger()) {
valueError = ERRORS.decimalNumber;
}
} catch (e) {
valueError = ERRORS.invalidNumber;
}
return {
error: valueError,
value,
valueError
};
}
export function isNullAddress (address) {
if (address && address.substr(0, 2) === '0x') {
return isNullAddress(address.substr(2));
}
return address === NULL_ADDRESS;
}