UNPKG

@colony/purser-core

Version:

A collection of helpers, utils, validators and normalizers to assist the individual purser modules

315 lines (283 loc) 12 kB
"use strict"; 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;