@iota/validators
Version:
Collection of guards and validators, useful in IOTA development.
295 lines • 10.3 kB
JavaScript
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
;