UNPKG

@iota/validators

Version:

Collection of guards and validators, useful in IOTA development.

295 lines 10.3 kB
"use strict"; exports.__esModule = true; var constants_1 = require("./constants"); var errors = require("./errors"); // Required for markdown generation with JSDoc /** * @module validators */ /* Type guards */ /** * Checks if input is an `Int8Array` of trit values; `-1, 0, 1`. * * @method isTrits * * @param {any} input * * @return {boolean} */ exports.isTrits = function (input) { if (input instanceof Int8Array) { for (var i = 0; i < input.length; i++) { if (!(input[i] === 0 || input[i] === -1 || input[i] === 1)) { return false; } } return true; } return false; }; /** * Checks if trits are NULL. * * @method isNullTrits * * @param {Int8Array} trits * * @return {boolean} */ exports.isNullTrits = function (input) { if (input instanceof Int8Array) { if (input.length === 0) { return true; } for (var i = 0; i < input.length; i++) { if (input[i] !== 0) { return false; } } return true; } return false; }; /** * Checks if input is correct trytes consisting of [9A-Z]; optionally validate length * @method isTrytes * * @param {string} trytes * @param {string | number} [length='1,'] * * @return {boolean} */ exports.isTrytes = function (trytes, length) { if (length === void 0) { length = '1,'; } return typeof trytes === 'string' && new RegExp("^[9A-Z]{" + length + "}$").test(trytes); }; /** * @method isTrytesOfExactLength * * @param {string} trytes * @param {number} length * * @return {boolean} */ exports.isTrytesOfExactLength = function (trytes, length) { return typeof trytes === 'string' && new RegExp("^[9A-Z]{" + length + "}$").test(trytes); }; /** * @method isTrytesOfMaxLength * * @param {string} trytes * @param {number} length * * @return {boolean} */ exports.isTrytesOfMaxLength = function (trytes, length) { return typeof trytes === 'string' && new RegExp("^[9A-Z]{1," + length + "}$").test(trytes); }; /** * Checks if input contains `9`s only. * @method isEmpty * * @param {string} hash * * @return {boolean} */ exports.isEmpty = function (trytes) { return typeof trytes === 'string' && /^[9]+$/.test(trytes); }; exports.isNinesTrytes = exports.isEmpty; /** * Checks if input is correct hash (81 trytes) or address with checksum (90 trytes) * * @method isHash * * @param {string} hash * * @return {boolean} */ exports.isHash = function (hash) { return exports.isTrytesOfExactLength(hash, constants_1.HASH_TRYTE_SIZE) || exports.isTrytesOfExactLength(hash, constants_1.HASH_TRYTE_SIZE + 9); }; // address w/ checksum is valid hash /* Check if security level is valid positive integer */ exports.isSecurityLevel = function (security) { return Number.isInteger(security) && security > 0 && security < 4; }; /** * Checks if input is valid input object. Address can be passed with or without checksum. * It does not validate the checksum. * * @method isInput * * @param {string} address * * @return {boolean} */ exports.isInput = function (input) { return exports.isHash(input.address) && exports.isSecurityLevel(input.security) && (typeof input.balance === 'undefined' || (Number.isInteger(input.balance) && input.balance > 0)) && Number.isInteger(input.keyIndex) && input.keyIndex >= 0; }; /** * Checks that input is valid tag trytes. * * @method isTag * * @param {string} tag * * @return {boolean} */ exports.isTag = function (tag) { return exports.isTrytesOfMaxLength(tag, constants_1.TAG_TRYTE_SIZE); }; /** * Checks if input is valid `transfer` object. * * @method isTransfer * * @param {Transfer} transfer * * @return {boolean} */ exports.isTransfer = function (transfer) { return exports.isHash(transfer.address) && Number.isInteger(transfer.value) && transfer.value >= 0 && (!transfer.message || exports.isTrytes(transfer.message, '0,')) && (!transfer.tag || exports.isTag(transfer.tag)); }; /** * Checks that a given `URI` is valid * * Valid Examples: * - `udp://[2001:db8:a0b:12f0::1]:14265` * - `udp://[2001:db8:a0b:12f0::1]` * - `udp://8.8.8.8:14265` * - `udp://domain.com` * - `udp://domain2.com:14265` * * @method isUri * * @param {string} uri * * @return {boolean} */ exports.isUri = function (uri) { if (typeof uri !== 'string') { return false; } var getInside = /^(udp|tcp):\/\/([\[][^\]\.]*[\]]|[^\[\]:]*)[:]{0,1}([0-9]{1,}$|$)/i; var stripBrackets = /[\[]{0,1}([^\[\]]*)[\]]{0,1}/; var uriTest = /((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$))|(^\s*((?=.{1,255}$)(?=.*[A-Za-z].*)[0-9A-Za-z](?:(?:[0-9A-Za-z]|\b-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|\b-){0,61}[0-9A-Za-z])?)*)\s*$)/; return getInside.test(uri) && uriTest.test(stripBrackets.exec(getInside.exec(uri)[1])[1]); }; /* Check if start & end options are valid */ exports.isStartEndOptions = function (_a) { var start = _a.start, end = _a.end; return !end || (start <= end && end < start + constants_1.MAX_INDEX_DIFF); }; /* Checks all array items */ exports.isArray = function (f) { return function (x) { return Array.isArray(x) && x.length > 0 && x.every(function (y) { return f(y); }); }; }; /** * Runs each validator in sequence, and throws on the first occurence of invalid data. * Validators are passed as arguments and executed in given order. * You might want place `validate()` in promise chains before operations that require valid inputs, * taking advantage of built-in promise branching. * * @example * * ```js * try { * validate([ * value, // Given value * isTrytes, // Validator function * 'Invalid trytes' // Error message * ]) * } catch (err) { * console.log(err.message) // 'Invalid trytes' * } * ``` * * @method validate * * @throws {Error} error * @return {boolean} */ exports.validate = function () { var validators = []; for (var _i = 0; _i < arguments.length; _i++) { validators[_i] = arguments[_i]; } validators.forEach(function (validator) { if (Array.isArray(validator)) { var value = validator[0], isValid = validator[1], msg = validator[2]; if (!isValid(value)) { throw new Error(msg + ": " + JSON.stringify(value, null, 1)); } } }); return true; }; exports.arrayValidator = function (validator) { return function (arr, customMsg) { var _a = validator(arr[0]), _ = _a[0], // tslint:disable-line no-unused-variable isValid = _a[1], msg = _a[2]; return [ arr, function (x) { return Array.isArray(x) && x.every(function (value) { return isValid(value); }); }, customMsg || msg, ]; }; }; exports.depthValidator = function (depth) { return [ depth, function (n) { return Number.isInteger(n) && n > 0; }, errors.INVALID_DEPTH, ]; }; exports.minWeightMagnitudeValidator = function (minWeightMagnitude) { return [ minWeightMagnitude, Number.isInteger, errors.INVALID_MIN_WEIGHT_MAGNITUDE, ]; }; exports.seedValidator = function (seed) { return [seed, exports.isTrytes, errors.INVALID_SEED]; }; exports.securityLevelValidator = function (security) { return [ security, exports.isSecurityLevel, errors.INVALID_SECURITY_LEVEL, ]; }; exports.inputValidator = function (input) { return [input, exports.isInput, errors.INVALID_INPUT]; }; exports.remainderAddressValidator = function (input) { return [input, exports.isHash, errors.INVALID_REMAINDER_ADDRESS]; }; exports.tagValidator = function (tag) { return [tag, exports.isTag, errors.INVALID_TAG]; }; exports.transferValidator = function (transfer) { return [transfer, exports.isTransfer, errors.INVALID_TRANSFER]; }; exports.hashValidator = function (hash, errorMessage) { return [ hash, exports.isHash, errorMessage || errors.INVALID_HASH, ]; }; exports.trytesValidator = function (trytes, msg) { return [ trytes, function (t) { return (length ? exports.isTrytesOfExactLength(t, length) : exports.isTrytes(t)); }, msg || errors.INVALID_TRYTES, ]; }; exports.uriValidator = function (uri) { return [uri, exports.isUri, errors.INVALID_URI]; }; exports.integerValidator = function (integer, msg) { return [ integer, Number.isInteger, msg || errors.NOT_INT, ]; }; exports.indexValidator = function (index) { return [index, Number.isInteger, errors.INVALID_INDEX]; }; exports.startOptionValidator = function (start) { return [ start, function (s) { return Number.isInteger(s) && s >= 0; }, errors.INVALID_START_OPTION, ]; }; exports.startEndOptionsValidator = function (options) { return [ options, exports.isStartEndOptions, errors.INVALID_START_END_OPTIONS, ]; }; exports.getInputsThresholdValidator = function (threshold) { return [ threshold, function (s) { return Number.isInteger(s) && s >= 0; }, errors.INVALID_THRESHOLD, ]; }; exports.stringify = function (value) { return JSON.stringify(value, null, 1); }; //# sourceMappingURL=guards.js.map