a99721004b
* 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
233 lines
5.4 KiB
JavaScript
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;
|
|
}
|