UNPKG

iota.lib.js

Version:
488 lines (398 loc) 12.2 kB
var ascii = require("./asciiToTrytes"); /** * checks if input is correct address * * @method isAddress * @param {string} address * @returns {boolean} **/ var isAddress = function(address) { // TODO: In the future check checksum if (!isString(address)) { return false; } // Check if address with checksum if (address.length === 90) { if (!isTrytes(address, 90)) { return false; } } else { if (!isTrytes(address, 81)) { return false; } } return true; } /** * checks if input is correct trytes consisting of A-Z9 * optionally validate length * * @method isTrytes * @param {string} trytes * @param {integer} length optional * @returns {boolean} **/ var isTrytes = function(trytes, length) { // If no length specified, just validate the trytes if (!length) length = "0," var regexTrytes = new RegExp("^[9A-Z]{" + length +"}$"); return isString(trytes) && regexTrytes.test(trytes); } /** * checks if input is correct trytes consisting of A-Z9 * optionally validate length * * @method isNinesTrytes * @param {string} trytes * @returns {boolean} **/ var isNinesTrytes = function(trytes) { return isString(trytes) && /^[9]+$/.test(trytes); } /** * convert the input string to trytes, then convert the resulting trytes to a string, * and check if the string matches the original input * * @method isSafeString * @param {string} input string to be checked * @return {boolean} */ var isSafeString = function(input) { return /^[\x00-\x7F]*$/.test(input) && ascii.fromTrytes(ascii.toTrytes(input)) === input; } /** * checks if integer value * * @method isValue * @param {string} value * @returns {boolean} **/ var isValue = function(value) { // check if correct number return Number.isInteger(value) } /** * checks whether input is a value or not. Can be a string, float or integer * * @method isNum * @param {int} * @returns {boolean} **/ var isNum = function(input) { return /^(\d+\.?\d{0,15}|\.\d{0,15})$/.test(input); } /** * checks if input is correct hash * * @method isHash * @param {string} hash * @returns {boolean} **/ var isHash = function(hash) { // Check if valid, 81 trytes if (!isTrytes(hash, 81)) { return false; } return true; } /** * checks whether input is a string or not * * @method isString * @param {string} * @returns {boolean} **/ var isString = function(string) { return typeof string === 'string'; } /** * checks whether input is an array or not * * @method isArray * @param {object} * @returns {boolean} **/ var isArray = function(array) { return array instanceof Array; } /** * checks whether input is object or not * * @method isObject * @param {object} * @returns {boolean} **/ var isObject = function(object) { var isArray = Array.isArray(object); var isNull = object === null; return !isArray && !isNull && typeof object === 'object'; }; /** * checks if input is correct hash * * @method isTransfersArray * @param {array} hash * @returns {boolean} **/ var isTransfersArray = function(transfersArray) { if (!isArray(transfersArray)) return false; for (var i = 0; i < transfersArray.length; i++) { var transfer = transfersArray[i]; // Check if valid address var address = transfer.address; if (!isAddress(address)) { return false; } // Validity check for value var value = transfer.value; if (!isValue(value)) { return false; } // Check if message is correct trytes of any length var message = transfer.message; if (!isTrytes(message, "0,")) { return false; } // Check if tag is correct trytes of {0,27} trytes var tag = transfer.tag || transfer.obsoleteTag; if (!isTrytes(tag, "0,27")) { return false; } } return true; } /** * checks if input is list of correct trytes * * @method isArrayOfHashes * @param {list} hashesArray * @returns {boolean} **/ var isArrayOfHashes = function(hashesArray) { if (!isArray(hashesArray)) return false; for (var i = 0; i < hashesArray.length; i++) { var hash = hashesArray[i]; // Check if address with checksum if (hash.length === 90) { if (!isTrytes(hash, 90)) { return false; } } else { if (!isTrytes(hash, 81)) { return false; } } } return true; } /** * checks if input is list of correct trytes * * @method isArrayOfTrytes * @param {list} trytesArray * @returns {boolean} **/ var isArrayOfTrytes = function(trytesArray) { if (!isArray(trytesArray)) return false; for (var i = 0; i < trytesArray.length; i++) { var tryteValue = trytesArray[i]; // Check if correct 2673 trytes if (!isTrytes(tryteValue, 2673)) { return false; } } return true; } /** * checks if attached trytes if last 241 trytes are non-zero * * @method isArrayOfAttachedTrytes * @param {array} trytesArray * @returns {boolean} **/ var isArrayOfAttachedTrytes = function(trytesArray) { if (!isArray(trytesArray)) return false; for (var i = 0; i < trytesArray.length; i++) { var tryteValue = trytesArray[i]; // Check if correct 2673 trytes if (!isTrytes(tryteValue, 2673)) { return false; } var lastTrytes = tryteValue.slice(2673 - (3 * 81)); if (/^[9]+$/.test(lastTrytes)) { return false; } } return true; } /** * checks if correct bundle with transaction object * * @method isArrayOfTxObjects * @param {array} bundle * @returns {boolean} **/ var isArrayOfTxObjects = function(bundle) { if (!isArray(bundle) || bundle.length === 0) return false; var validArray = true; bundle.forEach(function(txObject) { var keysToValidate = [ { key: 'hash', validator: isHash, args: null }, { key: 'signatureMessageFragment', validator: isTrytes, args: 2187 }, { key: 'address', validator: isHash, args: null }, { key: 'value', validator: isValue, args: null }, { key: 'obsoleteTag', validator: isTrytes, args: 27 }, { key: 'timestamp', validator: isValue, args: null }, { key: 'currentIndex', validator: isValue, args: null },{ key: 'lastIndex', validator: isValue, args: null }, { key: 'bundle', validator: isHash, args: null }, { key: 'trunkTransaction', validator: isHash, args: null }, { key: 'branchTransaction', validator: isHash, args: null }, { key: 'tag', validator: isTrytes, args: 27 }, { key: 'attachmentTimestamp', validator: isValue, args: null }, { key: 'attachmentTimestampLowerBound', validator: isValue, args: null }, { key: 'attachmentTimestampUpperBound', validator: isValue, args: null }, { key: 'nonce', validator: isTrytes, args: 27 } ] for (var i = 0; i < keysToValidate.length; i++) { var key = keysToValidate[i].key; var validator = keysToValidate[i].validator; var args = keysToValidate[i].args // If input does not have keyIndex and address, return false if (!txObject.hasOwnProperty(key)) { validArray = false; break; } // If input validator function does not return true, exit if (!validator(txObject[key], args)) { validArray = false; break; } } }) return validArray; } /** * checks if correct inputs list * * @method isInputs * @param {array} inputs * @returns {boolean} **/ var isInputs = function(inputs) { if (!isArray(inputs)) return false; for (var i = 0; i < inputs.length; i++) { var input = inputs[i]; // If input does not have keyIndex and address, return false if (!input.hasOwnProperty('security') || !input.hasOwnProperty('keyIndex') || !input.hasOwnProperty('address')) return false; if (!isAddress(input.address)) { return false; } if (!isValue(input.security)) { return false; } if (!isValue(input.keyIndex)) { return false; } } return true; } /** * 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} node * @returns {bool} valid **/ var isUri = function(node) { 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*$)/; if(!getInside.test(node)) { return false; } return uriTest.test(stripBrackets.exec(getInside.exec(node)[1])[1]); } var isTritArray = function (trits, length) { return (trits instanceof Array || trits instanceof Int8Array) && trits.every(function (trit) { return [-1, 0, 1].indexOf(trit) > -1 }) && (typeof length === 'number' ? trits.length === length : true) } module.exports = { isAddress: isAddress, isTrytes: isTrytes, isNinesTrytes: isNinesTrytes, isSafeString: isSafeString, isValue: isValue, isHash: isHash, isTransfersArray: isTransfersArray, isArrayOfHashes: isArrayOfHashes, isArrayOfTrytes: isArrayOfTrytes, isArrayOfAttachedTrytes: isArrayOfAttachedTrytes, isArrayOfTxObjects: isArrayOfTxObjects, isInputs: isInputs, isString: isString, isNum: isNum, isArray: isArray, isObject: isObject, isUri: isUri, isTritArray: isTritArray }