@colony/purser-core
Version:
A collection of helpers, utils, validators and normalizers to assist the individual purser modules
315 lines (283 loc) • 12 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.messageDataValidator = exports.messageValidator = exports.hexSequenceValidator = exports.addressValidator = exports.bigNumberValidator = exports.safeIntegerValidator = exports.derivationPathValidator = void 0;
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _bn = _interopRequireDefault(require("bn.js"));
var _utils = require("./utils");
var _messages = require("./messages");
var _defaults = require("./defaults");
/**
* Validate a derivation path passed in as a string
*
* @method derivationPathValidator
*
* @param {string} derivationPath The derivation path to check
*
* @return {boolean} It only returns true if the derivation path is correct,
* otherwise an Error will be thrown and this will not finish execution.
*/
var derivationPathValidator = function derivationPathValidator(derivationPath) {
var derivationPathMessages = _messages.validators.derivationPath;
var COIN_MAINNET = _defaults.PATH.COIN_MAINNET,
COIN_TESTNET = _defaults.PATH.COIN_TESTNET;
var deSerializedDerivationPath;
var coinType;
try {
/*
* Because assignments get bubbled to the top of the method, we need to wrap
* this inside a try/catch block.
*
* Otherwise, this will fail before we have a change to assert it.
*/
deSerializedDerivationPath = derivationPath.split(_defaults.PATH.DELIMITER);
coinType = parseInt(deSerializedDerivationPath[1], 10);
} catch (caughtError) {
throw new Error("".concat(derivationPathMessages.notString, ": ").concat(derivationPath || _defaults.UNDEFINED));
}
/*
* We need to assert this in a separate step, otherwise, if the size of the split
* chunks is not correct the `match()` method call will fail before the
* validator generator sequence will actually start.
*/
(0, _utils.assertTruth)({
/*
* It should be composed of (at least) four parts
* (purpouse, coin, account, change and/or index)
*/
expression: deSerializedDerivationPath.length === 4,
message: ["".concat(derivationPathMessages.notValidParts, ": [")].concat((0, _toConsumableArray2.default)(deSerializedDerivationPath), [']'])
});
var validationSequence = [{
/*
* It should have the correct Header Key (the letter 'm')
*/
expression: deSerializedDerivationPath[0].split(_defaults.SPLITTER)[0].toLowerCase() === _defaults.PATH.HEADER_KEY,
message: ["".concat(derivationPathMessages.notValidHeaderKey, ":"), deSerializedDerivationPath[0] || _defaults.UNDEFINED]
}, {
/*
* It should have the Ethereum reserved Purpouse (44)
*/
expression: parseInt(deSerializedDerivationPath[0].split(_defaults.SPLITTER)[1], 10) === _defaults.PATH.PURPOSE,
message: ["".concat(derivationPathMessages.notValidPurpouse, ":"), deSerializedDerivationPath[0] || _defaults.UNDEFINED]
}, {
/*
* It should have the correct Coin type
*/
expression: coinType === COIN_MAINNET || coinType === COIN_TESTNET,
message: ["".concat(derivationPathMessages.notValidCoin, ":"), deSerializedDerivationPath[1] || _defaults.UNDEFINED]
}, {
/*
* It should have the correct Account format (eg: a number)
*/
expression: !!deSerializedDerivationPath[2].match(_defaults.MATCH.DIGITS),
message: ["".concat(derivationPathMessages.notValidAccount, ":"), deSerializedDerivationPath[2] || _defaults.UNDEFINED]
}, {
/*
* It should have the correct Change and/or Account Index format (eg: a number)
*/
expression: deSerializedDerivationPath[3].split(_defaults.SPLITTER).map(function (value) {
return !!value.match(_defaults.MATCH.DIGITS);
}).every(function (truth) {
return truth !== false;
}),
message: ["".concat(derivationPathMessages.notValidChangeIndex, ":"), deSerializedDerivationPath[3] || _defaults.UNDEFINED]
}, {
/*
* It should have the correct amount of Account Indexed (just one)
*/
expression: deSerializedDerivationPath[3].split(_defaults.SPLITTER).length <= 2,
message: ["".concat(derivationPathMessages.notValidAccountIndex, ":"), deSerializedDerivationPath[3] || _defaults.UNDEFINED]
}];
return (0, _utils.validatorGenerator)(validationSequence, "".concat(derivationPathMessages.genericError, ": ").concat(derivationPath || _defaults.UNDEFINED));
};
/**
* Validate an integer passed in to make sure is safe (< 9007199254740991) and positive
*
* @method safeIntegerValidator
*
* @param {number} integer The integer to validate
*
* @return {boolean} It only returns true if the integer is safe and positive,
* otherwise an Error will be thrown and this will not finish execution.
*/
exports.derivationPathValidator = derivationPathValidator;
var safeIntegerValidator = function safeIntegerValidator(integer) {
var safeIntegerMessages = _messages.validators.safeInteger;
var validationSequence = [{
/*
* It should be a number primitive
*/
expression: typeof integer === 'number',
message: "".concat(safeIntegerMessages.notNumber, ": ").concat(integer)
}, {
/*
* It should be a positive number
* This is a little less trutfull as integers can also be negative
*/
expression: integer >= 0,
message: "".concat(safeIntegerMessages.notPositive, ": ").concat(integer)
}, {
/*
* It should be under the safe integer limit: ± 9007199254740991
* See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger
*/
expression: Number.isSafeInteger(integer),
message: "".concat(safeIntegerMessages.notSafe, ": ").concat(integer)
}];
return (0, _utils.validatorGenerator)(validationSequence, "".concat(safeIntegerMessages.genericError, ": ").concat(integer));
};
/**
* Validate a Big Number instance object that was passed in
*
* @method bigNumberValidator
*
* @param {Object} bigNumber The big number instance to check
*
* @return {boolean} It only returns true if the object is an instance of Big Number,
* otherwise an Error will be thrown and this will not finish execution.
*/
exports.safeIntegerValidator = safeIntegerValidator;
var bigNumberValidator = function bigNumberValidator(bigNumber) {
var bigNumberMessages = _messages.validators.bigNumber;
var validationSequence = [{
/*
* It should be an instance of the BN Class
*/
expression: _bn.default.isBN(bigNumber),
message: "".concat(bigNumberMessages.notBigNumber, ": ").concat((0, _utils.objectToErrorString)(bigNumber))
}];
return (0, _utils.validatorGenerator)(validationSequence, "".concat(bigNumberMessages.genericError, ": ").concat((0, _utils.objectToErrorString)(bigNumber)));
};
/**
* Validate a BIP32 Ethereum Address
*
* @TODO Validate the checksum of the address.
*
* @method addressValidator
*
* @param {string} address The 'hex' address to check
*
* @return {boolean} It only returns true if the string is a valid address format,
* otherwise an Error will be thrown and this will not finish execution.
*/
exports.bigNumberValidator = bigNumberValidator;
var addressValidator = function addressValidator(address) {
var addressMessages = _messages.validators.address;
var addressLength = 0;
try {
/*
* Because length checking is bubbled to the top, we need to to wrap this inside
* a separate try-catch block, otherwise the whole thing will fail before the
* validation sequence will even start.
*/
addressLength = address.length;
} catch (caughtError) {
throw new Error("".concat(addressMessages.notStringSequence, ": ").concat(_defaults.UNDEFINED));
}
var validationSequence = [{
/*
* It should be a string
*/
expression: typeof address === 'string',
message: "".concat(addressMessages.notStringSequence, ": ").concat((0, _utils.objectToErrorString)(address) || _defaults.UNDEFINED)
}, {
/*
* It should be the correct length. Either 40 or 42 (with prefix)
*/
expression: addressLength === 40 || addressLength === 42,
message: "".concat(addressMessages.notLength, ": ").concat(address || _defaults.UNDEFINED)
}, {
/*
* It should be in the correct format (hex string of length 40 with or
* with out the `0x` prefix)
*/
expression: !!address.match(_defaults.MATCH.ADDRESS),
message: "".concat(addressMessages.notFormat, ": ").concat(address || _defaults.UNDEFINED)
}];
return (0, _utils.validatorGenerator)(validationSequence, "".concat(addressMessages.genericError, ": ").concat(address || _defaults.UNDEFINED));
};
/**
* Validate a hex string
*
* @method hexSequenceValidator
*
* @param {string} hexSequence The `hex` string to check
*
* @return {boolean} It only returns true if the string is a valid hex format,
* otherwise an Error will be thrown and this will not finish execution.
*/
exports.addressValidator = addressValidator;
var hexSequenceValidator = function hexSequenceValidator(hexSequence) {
var hexSequenceMessages = _messages.validators.hexSequence;
var validationSequence = [{
/*
* It should be a string
*/
expression: typeof hexSequence === 'string',
message: "".concat(hexSequenceMessages.notStringSequence, ": ").concat((0, _utils.objectToErrorString)(hexSequence) || _defaults.UNDEFINED)
}, {
/*
* It should be in the correct format (hex string with or with out the `0x` prefix)
*/
expression: !!hexSequence.match(_defaults.MATCH.HEX_STRING),
message: "".concat(hexSequenceMessages.notFormat, ": ").concat(hexSequence || _defaults.UNDEFINED)
}];
return (0, _utils.validatorGenerator)(validationSequence, "".concat(hexSequenceMessages.genericError, ": ").concat(hexSequence || _defaults.UNDEFINED));
};
/**
* Validate a hex string
*
* @method messageValidator
*
* @param {string} string The big number instance to check
*
* @return {boolean} It only returns true if the string is a valid format,
* otherwise an Error will be thrown and this will not finish execution.
*/
exports.hexSequenceValidator = hexSequenceValidator;
var messageValidator = function messageValidator(string) {
/*
* Real creative naming there, huh...?
*/
var messageMessages = _messages.validators.message;
var validationSequence = [{
/*
* It should be a string
*/
expression: typeof string === 'string',
message: "".concat(messageMessages.notString, ": ").concat((0, _utils.objectToErrorString)(string) || _defaults.UNDEFINED)
}, {
/*
* It should be under (or equal to) 1024 Bytes in size
*/
expression: string.length <= 1024,
message: "".concat(messageMessages.tooBig, ": ").concat(string || _defaults.UNDEFINED)
}];
return (0, _utils.validatorGenerator)(validationSequence, "".concat(messageMessages.genericError, ": ").concat(string || _defaults.UNDEFINED));
};
/**
* Validate a hex string
*
* @method messageDataValidator
*
* @param {any} data The messageData to check
*
* @return {boolean} It only returns true if the data is a valid format,
* otherwise an Error will be thrown and this will not finish execution.
*/
exports.messageValidator = messageValidator;
var messageDataValidator = function messageDataValidator(data) {
var messageMessages = _messages.validators.message;
var validationSequence = [{
/*
* It should be a hex string or UInt8Array
*/
expression: typeof data === 'string' && hexSequenceValidator(data) || data.constructor === Uint8Array,
message: "".concat(messageMessages.notString, ": ").concat((0, _utils.objectToErrorString)(data) || _defaults.UNDEFINED)
}];
return (0, _utils.validatorGenerator)(validationSequence, "".concat(messageMessages.genericError, ": ").concat(data || _defaults.UNDEFINED));
};
exports.messageDataValidator = messageDataValidator;