├── .gitignore ├── .jshintrc ├── .travis.yml ├── LICENSE ├── README.md ├── bower.json ├── dist ├── iota.crypto.js └── iota.crypto.min.js ├── examples └── multisig.js ├── gulpfile.js ├── iota-crypto-browser.js ├── lib ├── crypto │ ├── bundle │ │ └── bundle.js │ ├── converter │ │ ├── converter.js │ │ └── words.js │ ├── curl │ │ └── curl.js │ ├── helpers │ │ └── adder.js │ ├── hmac │ │ └── hmac.js │ ├── kerl │ │ └── kerl.js │ └── signing │ │ ├── oldSigning.js │ │ └── signing.js ├── errors │ └── inputErrors.js ├── iota.crypto.js ├── multisig │ ├── address.js │ └── multisig.js └── utils │ ├── asciiToTrytes.js │ ├── extractJson.js │ ├── inputValidator.js │ └── utils.js ├── package.json └── test ├── kerl ├── kerl.absorb-multi-squeeze.js ├── kerl.absorb-squeeze.js └── kerl.multi-absorb-multi-squeeze.js ├── mocha.opts ├── utils ├── utils.checksum.js ├── utils.convertUnits.js ├── utils.extractJson.js ├── utils.fromTrytes.js ├── utils.isBundle.js └── utils.toTrytes.js └── valid ├── valid.isAddress.js ├── valid.isArrayOfAttachedTrytes.js ├── valid.isArrayOfHashes.js ├── valid.isArrayOfTrytes.js ├── valid.isArrayOfTxObjects.js ├── valid.isHash.js ├── valid.isInputs.js ├── valid.isNinesTrytes.js ├── valid.isNum.js ├── valid.isString.js ├── valid.isTransfersArray.js ├── valid.isTrytes.js ├── valid.isUri.js └── valid.isValue.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bower_modules 3 | .DS_Store 4 | */**/.DS_Store 5 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "esnext": false, 3 | "esversion": 5, 4 | "asi": true 5 | } 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | 2 | language: node_js 3 | node_js: 4 | - "node" 5 | - "4.1" 6 | - "4.0" 7 | before_script: 8 | - npm install 9 | - npm install -g gulp 10 | script: 11 | - gulp 12 | - npm test 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 IOTA Stiftung 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iota.crypto.js", 3 | "version": "0.4.1", 4 | "description": "Javascript Library for IOTA", 5 | "main": "./dist/iota.crypto.js", 6 | "authors": [ 7 | { 8 | "name": "Dominik Schiener (IOTA Foundation)", 9 | "website": "https://iota.org" 10 | }, 11 | { 12 | "name": "Paul Handy (IOTA Foundation)", 13 | "website": "https://iota.org" 14 | } 15 | ], 16 | "license": "MIT", 17 | "keywords": [ 18 | "iota", 19 | "tangle", 20 | "library", 21 | "browser", 22 | "javascript", 23 | "micropayments" 24 | ], 25 | "bugs": { 26 | "url": "https://github.com/iotaledger/iota.crypto.js/issues" 27 | }, 28 | "homepage": "https://github.com/iotaledger/iota.crypto.js", 29 | "ignore": [ 30 | "**/.*", 31 | "node_modules", 32 | "bower_components", 33 | "test", 34 | "tests", 35 | "lib", 36 | "package.json", 37 | "gulpfile.js", 38 | "iota-crypto-browser.js", 39 | ".gitignore" 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /examples/multisig.js: -------------------------------------------------------------------------------- 1 | var IOTA = require('../lib/iota'); 2 | 3 | var iota = new IOTA({ 4 | 'host': 'http://localhost', 5 | 'port': 14700 6 | }); 7 | 8 | // First co-signer uses index 0 and security level 3 9 | var digestOne = iota.multisig.getDigest('ABCDFG', 0, 3); 10 | 11 | // Second cosigner also uses index 0 and security level 3 for the private key 12 | var digestTwo = iota.multisig.getDigest('FDSAG', 0, 3); 13 | 14 | // Multisig address constructor 15 | var Address = iota.multisig.address; 16 | 17 | // Initiate the multisig address generation 18 | var address = new Address() 19 | 20 | // Absorb the first cosigners key digest 21 | .absorb(digestOne) 22 | 23 | // Absorb the second cosigners key digest 24 | .absorb(digestTwo) 25 | 26 | //and finally we finalize the address itself 27 | .finalize(); 28 | 29 | 30 | console.log("MULTISIG ADDRESS: ", address); 31 | 32 | // Simple validation if the multisig was created correctly 33 | // Can be called by each cosigner independently 34 | var isValid = iota.multisig.validateAddress(address, [digestOne, digestTwo]); 35 | 36 | console.log("IS VALID MULTISIG ADDRESS:", isValid); 37 | 38 | 39 | // SIGNING EXAMPLE 40 | // 41 | // Even though these functions are c alled subsequently, the addSignature functions have to be called by each 42 | // cosigner independently. With the previous signer sharing the output (bundle with the transaction objects) 43 | // 44 | // When it comes to defining the remainder address, you have to generate that address before making a transfer 45 | // Important to know here is the total sum of the security levels used by the cosigners. 46 | var multisigTransfer = [ 47 | {'address': 'ZGHXPZYDKXPEOSQTAQOIXEEI9K9YKFKCWKYYTYAUWXK9QZAVMJXWAIZABOXHHNNBJIEBEUQRTBWGLYMTX', 'value': 999} 48 | ]; 49 | // Define remainder address 50 | var remainderAddress = 'NZRALDYNVGJWUVLKDWFKJVNYLWQGCWYCURJIIZRLJIKSAIVZSGEYKTZRDBGJLOA9AWYJQB9IPWRAKUC9FBDRZJZXZG'; 51 | 52 | iota.multisig.initiateTransfer(6, address, remainderAddress, multisigTransfer, function(e, initiatedBundle) { 53 | 54 | if (e) { 55 | console.log(e); 56 | } 57 | 58 | iota.multisig.addSignature(initiatedBundle, address, iota.multisig.getKey('ABCDFG', 0, 3), function(e,firstSignedBundle) { 59 | 60 | if (e) { 61 | console.log(e); 62 | } 63 | 64 | iota.multisig.addSignature(firstSignedBundle, address, iota.multisig.getKey('FDSAG', 0, 3), function(e,finalBundle) { 65 | 66 | if (!e) { 67 | console.log("IS VALID SIGNATURE: ", iota.utils.validateSignatures(finalBundle, address)); 68 | } 69 | }); 70 | }); 71 | 72 | }) 73 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | jshint = require('gulp-jshint'), 3 | uglify = require('gulp-uglify'), 4 | rename = require('gulp-rename'), 5 | source = require("vinyl-source-stream"), 6 | buffer = require("vinyl-buffer"), 7 | browserify = require('browserify'), 8 | del = require('del'), 9 | gulpNSP = require('gulp-nsp'); 10 | 11 | 12 | 13 | var DEST = './dist/' 14 | 15 | /** 16 | Lint the JS code 17 | **/ 18 | gulp.task('lint', [], function(){ 19 | return gulp.src(['./lib/*.js']) 20 | .pipe(jshint()) 21 | .pipe(jshint.reporter('default')); 22 | }); 23 | 24 | /** 25 | Remove existing dist folder 26 | **/ 27 | gulp.task('clean', ['lint'], function(cb) { 28 | del([DEST]).then(cb.bind(null, null)); 29 | }); 30 | 31 | //To check your package.json 32 | gulp.task('nsp', function (cb) { 33 | gulpNSP({package: __dirname + '/package.json'}, cb); 34 | }); 35 | 36 | /** 37 | Build for the browser 38 | **/ 39 | gulp.task('dist', function() { 40 | return browserify("./iota-crypto-browser.js") 41 | .bundle() 42 | .pipe(source('iota.crypto.js')) 43 | .pipe(gulp.dest(DEST)) 44 | .pipe(rename('iota.crypto.min.js')) 45 | .pipe(buffer()) 46 | .pipe(uglify()) 47 | .pipe(gulp.dest(DEST)); 48 | }); 49 | 50 | gulp.task('default', ['lint', 'clean', 'nsp', 'dist']); 51 | -------------------------------------------------------------------------------- /iota-crypto-browser.js: -------------------------------------------------------------------------------- 1 | 2 | window.IOTA = require('./lib/iota.crypto.js'); 3 | -------------------------------------------------------------------------------- /lib/crypto/bundle/bundle.js: -------------------------------------------------------------------------------- 1 | var Curl = require("../curl/curl"); 2 | var Kerl = require("../kerl/kerl"); 3 | var Converter = require("../converter/converter"); 4 | var tritAdd = require("../helpers/adder"); 5 | 6 | /** 7 | * 8 | * @constructor bundle 9 | **/ 10 | function Bundle() { 11 | 12 | // Declare empty bundle 13 | this.bundle = []; 14 | } 15 | 16 | /** 17 | * 18 | * 19 | **/ 20 | 21 | Bundle.prototype.addEntry = function(signatureMessageLength, address, value, tag, timestamp, index) { 22 | 23 | for (var i = 0; i < signatureMessageLength; i++) { 24 | 25 | var transactionObject = new Object(); 26 | transactionObject.address = address; 27 | transactionObject.value = i == 0 ? value : 0; 28 | transactionObject.obsoleteTag = tag; 29 | transactionObject.tag = tag; 30 | transactionObject.timestamp = timestamp; 31 | 32 | this.bundle[this.bundle.length] = transactionObject; 33 | } 34 | } 35 | 36 | /** 37 | * 38 | * 39 | **/ 40 | Bundle.prototype.addTrytes = function(signatureFragments) { 41 | 42 | var emptySignatureFragment = ''; 43 | var emptyHash = '999999999999999999999999999999999999999999999999999999999999999999999999999999999'; 44 | var emptyTag = '9'.repeat(27); 45 | var emptyTimestamp = '9'.repeat(9); 46 | 47 | for (var j = 0; emptySignatureFragment.length < 2187; j++) { 48 | emptySignatureFragment += '9'; 49 | } 50 | 51 | for (var i = 0; i < this.bundle.length; i++) { 52 | 53 | // Fill empty signatureMessageFragment 54 | this.bundle[i].signatureMessageFragment = signatureFragments[i] ? signatureFragments[i] : emptySignatureFragment; 55 | 56 | // Fill empty trunkTransaction 57 | this.bundle[i].trunkTransaction = emptyHash; 58 | 59 | // Fill empty branchTransaction 60 | this.bundle[i].branchTransaction = emptyHash; 61 | 62 | this.bundle[i].attachmentTimestamp = emptyTimestamp; 63 | this.bundle[i].attachmentTimestampLowerBound = emptyTimestamp; 64 | this.bundle[i].attachmentTimestampUpperBound = emptyTimestamp; 65 | // Fill empty nonce 66 | this.bundle[i].nonce = emptyTag; 67 | } 68 | } 69 | 70 | 71 | /** 72 | * 73 | * 74 | **/ 75 | Bundle.prototype.finalize = function() { 76 | var validBundle = false; 77 | 78 | while(!validBundle) { 79 | 80 | var kerl = new Kerl(); 81 | kerl.initialize(); 82 | 83 | for (var i = 0; i < this.bundle.length; i++) { 84 | 85 | var valueTrits = Converter.trits(this.bundle[i].value); 86 | while (valueTrits.length < 81) { 87 | valueTrits[valueTrits.length] = 0; 88 | } 89 | 90 | var timestampTrits = Converter.trits(this.bundle[i].timestamp); 91 | while (timestampTrits.length < 27) { 92 | timestampTrits[timestampTrits.length] = 0; 93 | } 94 | 95 | var currentIndexTrits = Converter.trits(this.bundle[i].currentIndex = i); 96 | while (currentIndexTrits.length < 27) { 97 | currentIndexTrits[currentIndexTrits.length] = 0; 98 | } 99 | 100 | var lastIndexTrits = Converter.trits(this.bundle[i].lastIndex = this.bundle.length - 1); 101 | while (lastIndexTrits.length < 27) { 102 | lastIndexTrits[lastIndexTrits.length] = 0; 103 | } 104 | 105 | var bundleEssence = Converter.trits(this.bundle[i].address + Converter.trytes(valueTrits) + this.bundle[i].obsoleteTag + Converter.trytes(timestampTrits) + Converter.trytes(currentIndexTrits) + Converter.trytes(lastIndexTrits)); 106 | kerl.absorb(bundleEssence, 0, bundleEssence.length); 107 | } 108 | 109 | var hash = []; 110 | kerl.squeeze(hash, 0, Curl.HASH_LENGTH); 111 | hash = Converter.trytes(hash); 112 | 113 | for (var i = 0; i < this.bundle.length; i++) { 114 | 115 | this.bundle[i].bundle = hash; 116 | } 117 | 118 | var normalizedHash = this.normalizedBundle(hash); 119 | if(normalizedHash.indexOf(13 /* = M */) != -1) { 120 | // Insecure bundle. Increment Tag and recompute bundle hash. 121 | var increasedTag = tritAdd(Converter.trits(this.bundle[0].obsoleteTag), [1]); 122 | this.bundle[0].obsoleteTag = Converter.trytes(increasedTag); 123 | } else { 124 | validBundle = true; 125 | } 126 | } 127 | } 128 | 129 | /** 130 | * Normalizes the bundle hash 131 | * 132 | **/ 133 | Bundle.prototype.normalizedBundle = function(bundleHash) { 134 | 135 | var normalizedBundle = []; 136 | 137 | for (var i = 0; i < 3; i++) { 138 | 139 | var sum = 0; 140 | for (var j = 0; j < 27; j++) { 141 | 142 | sum += (normalizedBundle[i * 27 + j] = Converter.value(Converter.trits(bundleHash.charAt(i * 27 + j)))); 143 | } 144 | 145 | if (sum >= 0) { 146 | 147 | while (sum-- > 0) { 148 | 149 | for (var j = 0; j < 27; j++) { 150 | 151 | if (normalizedBundle[i * 27 + j] > -13) { 152 | 153 | normalizedBundle[i * 27 + j]--; 154 | break; 155 | } 156 | } 157 | } 158 | } else { 159 | 160 | while (sum++ < 0) { 161 | 162 | for (var j = 0; j < 27; j++) { 163 | 164 | if (normalizedBundle[i * 27 + j] < 13) { 165 | 166 | normalizedBundle[i * 27 + j]++; 167 | break; 168 | } 169 | } 170 | } 171 | } 172 | } 173 | 174 | return normalizedBundle; 175 | } 176 | 177 | module.exports = Bundle; 178 | -------------------------------------------------------------------------------- /lib/crypto/converter/converter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Conversion functions 4 | * 5 | **/ 6 | 7 | var RADIX = 3; 8 | var RADIX_BYTES = 256; 9 | var MAX_TRIT_VALUE = 1; 10 | var MIN_TRIT_VALUE = -1; 11 | var BYTE_HASH_LENGTH = 48; 12 | 13 | // All possible tryte values 14 | var trytesAlphabet = "9ABCDEFGHIJKLMNOPQRSTUVWXYZ" 15 | 16 | // map of all trits representations 17 | var trytesTrits = [ 18 | [ 0, 0, 0], 19 | [ 1, 0, 0], 20 | [-1, 1, 0], 21 | [ 0, 1, 0], 22 | [ 1, 1, 0], 23 | [-1, -1, 1], 24 | [ 0, -1, 1], 25 | [ 1, -1, 1], 26 | [-1, 0, 1], 27 | [ 0, 0, 1], 28 | [ 1, 0, 1], 29 | [-1, 1, 1], 30 | [ 0, 1, 1], 31 | [ 1, 1, 1], 32 | [-1, -1, -1], 33 | [ 0, -1, -1], 34 | [ 1, -1, -1], 35 | [-1, 0, -1], 36 | [ 0, 0, -1], 37 | [ 1, 0, -1], 38 | [-1, 1, -1], 39 | [ 0, 1, -1], 40 | [ 1, 1, -1], 41 | [-1, -1, 0], 42 | [ 0, -1, 0], 43 | [ 1, -1, 0], 44 | [-1, 0, 0] 45 | ]; 46 | 47 | /** 48 | * Converts trytes into trits 49 | * 50 | * @method trits 51 | * @param {String|Int} input Tryte value to be converted. Can either be string or int 52 | * @param {Array} state (optional) state to be modified 53 | * @returns {Array} trits 54 | **/ 55 | var trits = function( input, state ) { 56 | 57 | var trits = state || []; 58 | 59 | if (Number.isInteger(input)) { 60 | 61 | var absoluteValue = input < 0 ? -input : input; 62 | 63 | while (absoluteValue > 0) { 64 | 65 | var remainder = absoluteValue % 3; 66 | absoluteValue = Math.floor(absoluteValue / 3); 67 | 68 | if (remainder > 1) { 69 | remainder = -1; 70 | absoluteValue++; 71 | } 72 | 73 | trits[trits.length] = remainder; 74 | } 75 | if (input < 0) { 76 | 77 | for (var i = 0; i < trits.length; i++) { 78 | 79 | trits[i] = -trits[i]; 80 | } 81 | } 82 | } else { 83 | 84 | for (var i = 0; i < input.length; i++) { 85 | 86 | var index = trytesAlphabet.indexOf(input.charAt(i)); 87 | trits[i * 3] = trytesTrits[index][0]; 88 | trits[i * 3 + 1] = trytesTrits[index][1]; 89 | trits[i * 3 + 2] = trytesTrits[index][2]; 90 | } 91 | } 92 | 93 | return trits; 94 | } 95 | 96 | /** 97 | * Converts trits into trytes 98 | * 99 | * @method trytes 100 | * @param {Array} trits 101 | * @returns {String} trytes 102 | **/ 103 | var trytes = function(trits) { 104 | 105 | var trytes = ""; 106 | 107 | for ( var i = 0; i < trits.length; i += 3 ) { 108 | 109 | // Iterate over all possible tryte values to find correct trit representation 110 | for ( var j = 0; j < trytesAlphabet.length; j++ ) { 111 | 112 | if ( trytesTrits[ j ][ 0 ] === trits[ i ] && trytesTrits[ j ][ 1 ] === trits[ i + 1 ] && trytesTrits[ j ][ 2 ] === trits[ i + 2 ] ) { 113 | 114 | trytes += trytesAlphabet.charAt( j ); 115 | break; 116 | 117 | } 118 | 119 | } 120 | 121 | } 122 | 123 | return trytes; 124 | } 125 | 126 | /** 127 | * Converts trits into an integer value 128 | * 129 | * @method value 130 | * @param {Array} trits 131 | * @returns {int} value 132 | **/ 133 | var value = function(trits) { 134 | 135 | var returnValue = 0; 136 | 137 | for ( var i = trits.length; i-- > 0; ) { 138 | 139 | returnValue = returnValue * 3 + trits[ i ]; 140 | } 141 | 142 | return returnValue; 143 | } 144 | 145 | /** 146 | * Converts an integer value to trits 147 | * 148 | * @method value 149 | * @param {Int} value 150 | * @returns {Array} trits 151 | **/ 152 | var fromValue = function(value) { 153 | 154 | var destination = []; 155 | var absoluteValue = value < 0 ? -value : value; 156 | var i = 0; 157 | 158 | while( absoluteValue > 0 ) { 159 | 160 | var remainder = ( absoluteValue % RADIX ); 161 | absoluteValue = Math.floor( absoluteValue / RADIX ); 162 | 163 | if ( remainder > MAX_TRIT_VALUE ) { 164 | 165 | remainder = MIN_TRIT_VALUE; 166 | absoluteValue++; 167 | 168 | } 169 | 170 | destination[ i ] = remainder; 171 | i++; 172 | 173 | } 174 | 175 | if ( value < 0 ) { 176 | 177 | for ( var j = 0; j < destination.length; j++ ) { 178 | 179 | // switch values 180 | destination[ j ] = destination[ j ] === 0 ? 0: -destination[ j ]; 181 | 182 | } 183 | 184 | } 185 | 186 | return destination; 187 | } 188 | 189 | module.exports = { 190 | trits : trits, 191 | trytes : trytes, 192 | value : value, 193 | fromValue : fromValue 194 | }; 195 | -------------------------------------------------------------------------------- /lib/crypto/converter/words.js: -------------------------------------------------------------------------------- 1 | var INT_LENGTH = 12; 2 | var BYTE_LENGTH = 48; 3 | var RADIX = 3; 4 | /// hex representation of (3^242)/2 5 | var HALF_3 = new Uint32Array([ 6 | 0xa5ce8964, 7 | 0x9f007669, 8 | 0x1484504f, 9 | 0x3ade00d9, 10 | 0x0c24486e, 11 | 0x50979d57, 12 | 0x79a4c702, 13 | 0x48bbae36, 14 | 0xa9f6808b, 15 | 0xaa06a805, 16 | 0xa87fabdf, 17 | 0x5e69ebef 18 | ]); 19 | 20 | var clone_uint32Array = function(sourceArray) { 21 | var destination = new ArrayBuffer(sourceArray.byteLength); 22 | new Uint32Array(destination).set(new Uint32Array(sourceArray)); 23 | 24 | return destination; 25 | }; 26 | 27 | var ta_slice = function(array) { 28 | if (array.slice !== undefined) { 29 | return array.slice(); 30 | } 31 | 32 | return clone_uint32Array(array); 33 | }; 34 | 35 | var ta_reverse = function(array) { 36 | if (array.reverse !== undefined) { 37 | array.reverse(); 38 | return; 39 | } 40 | 41 | var i = 0, 42 | n = array.length, 43 | middle = Math.floor(n / 2), 44 | temp = null; 45 | 46 | for (; i < middle; i += 1) { 47 | temp = array[i]; 48 | array[i] = array[n - 1 - i]; 49 | array[n - 1 - i] = temp; 50 | } 51 | }; 52 | 53 | /// negates the (unsigned) input array 54 | var bigint_not = function(arr) { 55 | for (var i = 0; i < arr.length; i++) { 56 | arr[i] = (~arr[i]) >>> 0; 57 | } 58 | }; 59 | 60 | /// rshift that works with up to 53 61 | /// JS's shift operators only work on 32 bit integers 62 | /// ours is up to 33 or 34 bits though, so 63 | /// we need to implement shifting manually 64 | var rshift = function(number, shift) { 65 | return (number / Math.pow(2, shift)) >>> 0; 66 | }; 67 | 68 | /// swaps endianness 69 | var swap32 = function(val) { 70 | return ((val & 0xFF) << 24) | 71 | ((val & 0xFF00) << 8) | 72 | ((val >> 8) & 0xFF00) | 73 | ((val >> 24) & 0xFF); 74 | } 75 | 76 | /// add with carry 77 | var full_add = function(lh, rh, carry) { 78 | var v = lh + rh; 79 | var l = (rshift(v, 32)) & 0xFFFFFFFF; 80 | var r = (v & 0xFFFFFFFF) >>> 0; 81 | var carry1 = l != 0; 82 | 83 | if (carry) { 84 | v = r + 1; 85 | } 86 | l = (rshift(v, 32)) & 0xFFFFFFFF; 87 | r = (v & 0xFFFFFFFF) >>> 0; 88 | var carry2 = l != 0; 89 | 90 | return [r, carry1 || carry2]; 91 | }; 92 | 93 | /// subtracts rh from base 94 | var bigint_sub = function(base, rh) { 95 | var noborrow = true; 96 | 97 | for (var i = 0; i < base.length; i++) { 98 | var vc = full_add(base[i], (~rh[i] >>> 0), noborrow); 99 | base[i] = vc[0]; 100 | noborrow = vc[1]; 101 | } 102 | 103 | if (!noborrow) { 104 | throw "noborrow"; 105 | } 106 | }; 107 | 108 | /// compares two (unsigned) big integers 109 | var bigint_cmp = function(lh, rh) { 110 | for (var i = lh.length; i-- > 0;) { 111 | var a = lh[i] >>> 0; 112 | var b = rh[i] >>> 0; 113 | if (a < b) { 114 | return -1; 115 | } else if (a > b) { 116 | return 1; 117 | } 118 | } 119 | return 0; 120 | }; 121 | 122 | /// adds rh to base in place 123 | var bigint_add = function(base, rh) { 124 | var carry = false; 125 | for (var i = 0; i < base.length; i++) { 126 | var vc = full_add(base[i], rh[i], carry); 127 | base[i] = vc[0]; 128 | carry = vc[1]; 129 | } 130 | }; 131 | 132 | /// adds a small (i.e. <32bit) number to base 133 | var bigint_add_small = function(base, other) { 134 | var vc = full_add(base[0], other, false); 135 | base[0] = vc[0]; 136 | var carry = vc[1]; 137 | 138 | var i = 1; 139 | while (carry && i < base.length) { 140 | var vc = full_add(base[i], 0, carry); 141 | base[i] = vc[0]; 142 | carry = vc[1]; 143 | i += 1; 144 | } 145 | 146 | return i; 147 | }; 148 | 149 | /// converts the given byte array to trits 150 | var words_to_trits = function(words) { 151 | if (words.length != INT_LENGTH) { 152 | throw "Invalid words length"; 153 | } 154 | 155 | var trits = new Int8Array(243); 156 | var base = new Uint32Array(words); 157 | 158 | ta_reverse(base); 159 | 160 | var flip_trits = false; 161 | if (base[INT_LENGTH - 1] >> 31 == 0) { 162 | // positive two's complement number. 163 | // add HALF_3 to move it to the right place. 164 | bigint_add(base, HALF_3); 165 | } else { 166 | // negative number. 167 | bigint_not(base); 168 | if (bigint_cmp(base, HALF_3) > 0) { 169 | bigint_sub(base, HALF_3); 170 | flip_trits = true; 171 | } else { 172 | /// bigint is between (unsigned) HALF_3 and (2**384 - 3**242/2). 173 | bigint_add_small(base, 1); 174 | var tmp = ta_slice(HALF_3); 175 | bigint_sub(tmp, base); 176 | base = tmp; 177 | } 178 | } 179 | 180 | 181 | var rem = 0; 182 | 183 | for (var i = 0; i < 242; i++) { 184 | rem = 0; 185 | for (var j = INT_LENGTH - 1; j >= 0; j--) { 186 | var lhs = (rem != 0 ? rem * 0xFFFFFFFF + rem : 0) + base[j]; 187 | var rhs = RADIX; 188 | 189 | var q = (lhs / rhs) >>> 0; 190 | var r = (lhs % rhs) >>> 0; 191 | 192 | base[j] = q; 193 | rem = r; 194 | } 195 | 196 | trits[i] = rem - 1; 197 | } 198 | 199 | if (flip_trits) { 200 | for (var i = 0; i < trits.length; i++) { 201 | trits[i] = -trits[i]; 202 | } 203 | } 204 | 205 | return trits; 206 | } 207 | 208 | var is_null = function(arr) { 209 | for (var i = 0; i < arr.length; i++) { 210 | if (arr[i] != 0) { 211 | return false; 212 | break; 213 | } 214 | } 215 | return true; 216 | } 217 | 218 | var trits_to_words = function(trits) { 219 | if (trits.length != 243) { 220 | throw "Invalid trits length"; 221 | } 222 | 223 | var base = new Uint32Array(INT_LENGTH); 224 | 225 | if (trits.slice(0, 242).every(function(a) { 226 | a == -1 227 | })) { 228 | base = ta_slice(HALF_3); 229 | bigint_not(base); 230 | bigint_add_small(base, 1); 231 | } else { 232 | var size = 1; 233 | for (var i = trits.length - 1; i-- > 0;) { 234 | var trit = trits[i] + 1; 235 | 236 | //multiply by radix 237 | { 238 | var sz = size; 239 | var carry = 0; 240 | 241 | for (var j = 0; j < sz; j++) { 242 | var v = base[j] * RADIX + carry; 243 | carry = rshift(v, 32); 244 | base[j] = (v & 0xFFFFFFFF) >>> 0; 245 | } 246 | 247 | if (carry > 0) { 248 | base[sz] = carry; 249 | size += 1; 250 | } 251 | } 252 | 253 | //addition 254 | { 255 | var sz = bigint_add_small(base, trit); 256 | if (sz > size) { 257 | size = sz; 258 | } 259 | } 260 | } 261 | 262 | if (!is_null(base)) { 263 | if (bigint_cmp(HALF_3, base) <= 0) { 264 | // base >= HALF_3 265 | // just do base - HALF_3 266 | bigint_sub(base, HALF_3); 267 | } else { 268 | // base < HALF_3 269 | // so we need to transform it to a two's complement representation 270 | // of (base - HALF_3). 271 | // as we don't have a wrapping (-), we need to use some bit magic 272 | var tmp = ta_slice(HALF_3); 273 | bigint_sub(tmp, base); 274 | bigint_not(tmp); 275 | bigint_add_small(tmp, 1); 276 | base = tmp; 277 | } 278 | } 279 | } 280 | 281 | ta_reverse(base); 282 | 283 | for (var i = 0; i < base.length; i++) { 284 | base[i] = swap32(base[i]); 285 | } 286 | 287 | return base; 288 | }; 289 | 290 | module.exports = { 291 | trits_to_words: trits_to_words, 292 | words_to_trits: words_to_trits 293 | }; 294 | -------------------------------------------------------------------------------- /lib/crypto/curl/curl.js: -------------------------------------------------------------------------------- 1 | var Converter = require("../converter/converter"); 2 | 3 | /** 4 | ** Cryptographic related functions to IOTA's Curl (sponge function) 5 | **/ 6 | 7 | var NUMBER_OF_ROUNDS = 81; 8 | var HASH_LENGTH = 243; 9 | var STATE_LENGTH = 3 * HASH_LENGTH; 10 | 11 | function Curl(rounds) { 12 | if (rounds) { 13 | this.rounds = rounds; 14 | } else { 15 | this.rounds = NUMBER_OF_ROUNDS; 16 | } 17 | // truth table 18 | this.truthTable = [1, 0, -1, 2, 1, -1, 0, 2, -1, 1, 0]; 19 | } 20 | 21 | Curl.HASH_LENGTH = HASH_LENGTH; 22 | 23 | /** 24 | * Initializes the state with STATE_LENGTH trits 25 | * 26 | * @method initialize 27 | **/ 28 | Curl.prototype.initialize = function(state, length) { 29 | 30 | if (state) { 31 | 32 | this.state = state; 33 | 34 | } else { 35 | 36 | this.state = []; 37 | 38 | for (var i = 0; i < STATE_LENGTH; i++) { 39 | 40 | this.state[i] = 0; 41 | 42 | } 43 | } 44 | } 45 | 46 | Curl.prototype.reset = function() { 47 | this.initialize(); 48 | } 49 | 50 | /** 51 | * Sponge absorb function 52 | * 53 | * @method absorb 54 | **/ 55 | Curl.prototype.absorb = function(trits, offset, length) { 56 | 57 | do { 58 | 59 | var i = 0; 60 | var limit = (length < HASH_LENGTH ? length : HASH_LENGTH); 61 | 62 | while (i < limit) { 63 | 64 | this.state[i++] = trits[offset++]; 65 | } 66 | 67 | this.transform(); 68 | 69 | } while (( length -= HASH_LENGTH ) > 0) 70 | 71 | } 72 | 73 | /** 74 | * Sponge squeeze function 75 | * 76 | * @method squeeze 77 | **/ 78 | Curl.prototype.squeeze = function(trits, offset, length) { 79 | 80 | do { 81 | 82 | var i = 0; 83 | var limit = (length < HASH_LENGTH ? length : HASH_LENGTH); 84 | 85 | while (i < limit) { 86 | 87 | trits[offset++] = this.state[i++]; 88 | } 89 | 90 | this.transform(); 91 | 92 | } while (( length -= HASH_LENGTH ) > 0) 93 | } 94 | 95 | /** 96 | * Sponge transform function 97 | * 98 | * @method transform 99 | **/ 100 | Curl.prototype.transform = function() { 101 | 102 | var stateCopy = [], index = 0; 103 | 104 | for (var round = 0; round < this.rounds; round++) { 105 | 106 | stateCopy = this.state.slice(); 107 | 108 | for (var i = 0; i < STATE_LENGTH; i++) { 109 | 110 | this.state[i] = this.truthTable[stateCopy[index] + (stateCopy[index += (index < 365 ? 364 : -365)] << 2) + 5]; 111 | } 112 | } 113 | } 114 | 115 | module.exports = Curl 116 | -------------------------------------------------------------------------------- /lib/crypto/helpers/adder.js: -------------------------------------------------------------------------------- 1 | /* copyright Paul Handy, 2017 */ 2 | 3 | function sum( a, b ) { 4 | 5 | var s = a + b; 6 | 7 | switch( s ) { 8 | 9 | case 2: return -1; 10 | case -2: return 1; 11 | default: return s; 12 | 13 | } 14 | } 15 | 16 | function cons( a, b ) { 17 | 18 | if( a === b ) { 19 | 20 | return a; 21 | 22 | } 23 | 24 | return 0; 25 | } 26 | 27 | function any( a, b ) { 28 | 29 | var s = a + b; 30 | 31 | if ( s > 0 ) { 32 | 33 | return 1; 34 | 35 | } else if ( s < 0 ) { 36 | 37 | return -1; 38 | 39 | } 40 | 41 | return 0; 42 | } 43 | 44 | function full_add( a, b, c ) { 45 | 46 | var s_a = sum( a, b ); 47 | var c_a = cons( a, b ); 48 | var c_b = cons( s_a, c ); 49 | var c_out = any( c_a, c_b ); 50 | var s_out = sum( s_a, c ); 51 | 52 | return [ s_out, c_out ]; 53 | 54 | } 55 | 56 | function add( a, b ) { 57 | 58 | var out = new Array( Math.max( a.length, b.length ) ); 59 | var carry = 0; 60 | var a_i, b_i; 61 | 62 | for( var i = 0; i < out.length; i++ ) { 63 | 64 | a_i = i < a.length ? a[ i ] : 0; 65 | b_i = i < b.length ? b[ i ] : 0; 66 | var f_a = full_add( a_i, b_i, carry ); 67 | out[ i ] = f_a[ 0 ]; 68 | carry = f_a[ 1 ]; 69 | 70 | } 71 | 72 | return out; 73 | 74 | } 75 | 76 | module.exports = add; 77 | -------------------------------------------------------------------------------- /lib/crypto/hmac/hmac.js: -------------------------------------------------------------------------------- 1 | var Curl = require("../curl/curl"); 2 | var Converter = require("../converter/converter"); 3 | var HMAC_ROUNDS = 27; 4 | 5 | function hmac(key) { 6 | this._key = Converter.trits(key); 7 | } 8 | 9 | hmac.prototype.addHMAC = function(bundle) { 10 | var curl = new Curl(HMAC_ROUNDS); 11 | var key = this._key; 12 | for(var i = 0; i < bundle.bundle.length; i++) { 13 | if (bundle.bundle[i].value > 0) { 14 | var bundleHashTrits = Converter.trits(bundle.bundle[i].bundle); 15 | var hmac = new Int8Array(243); 16 | curl.initialize(); 17 | curl.absorb(key); 18 | curl.absorb(bundleHashTrits); 19 | curl.squeeze(hmac); 20 | var hmacTrytes = Converter.trytes(hmac); 21 | bundle.bundle[i].signatureMessageFragment = hmacTrytes + bundle.bundle[i].signatureMessageFragment.substring(81, 2187); 22 | } 23 | } 24 | } 25 | 26 | module.exports = hmac; 27 | -------------------------------------------------------------------------------- /lib/crypto/kerl/kerl.js: -------------------------------------------------------------------------------- 1 | var CryptoJS = require("crypto-js"); 2 | var Converter = require("../converter/converter"); 3 | var Curl = require("../curl/curl"); 4 | var WConverter = require("../converter/words"); 5 | 6 | var BIT_HASH_LENGTH = 384; 7 | 8 | function Kerl() { 9 | 10 | 11 | this.k = CryptoJS.algo.SHA3.create(); 12 | this.k.init({ 13 | outputLength: BIT_HASH_LENGTH 14 | }); 15 | } 16 | 17 | Kerl.BIT_HASH_LENGTH = BIT_HASH_LENGTH; 18 | Kerl.HASH_LENGTH = Curl.HASH_LENGTH; 19 | 20 | Kerl.prototype.initialize = function(state) {} 21 | 22 | Kerl.prototype.reset = function() { 23 | 24 | this.k.reset(); 25 | 26 | } 27 | 28 | Kerl.prototype.absorb = function(trits, offset, length) { 29 | 30 | 31 | if (length && ((length % 243) !== 0)) { 32 | 33 | throw new Error('Illegal length provided'); 34 | 35 | } 36 | 37 | do { 38 | var limit = (length < Curl.HASH_LENGTH ? length : Curl.HASH_LENGTH); 39 | 40 | var trit_state = trits.slice(offset, offset + limit); 41 | offset += limit; 42 | 43 | // convert trit state to words 44 | var wordsToAbsorb = WConverter.trits_to_words(trit_state); 45 | 46 | // absorb the trit stat as wordarray 47 | this.k.update( 48 | CryptoJS.lib.WordArray.create(wordsToAbsorb)); 49 | 50 | } while ((length -= Curl.HASH_LENGTH) > 0); 51 | 52 | } 53 | 54 | 55 | 56 | Kerl.prototype.squeeze = function(trits, offset, length) { 57 | 58 | if (length && ((length % 243) !== 0)) { 59 | 60 | throw new Error('Illegal length provided'); 61 | 62 | } 63 | do { 64 | 65 | // get the hash digest 66 | var kCopy = this.k.clone(); 67 | var final = kCopy.finalize(); 68 | 69 | // Convert words to trits and then map it into the internal state 70 | var trit_state = WConverter.words_to_trits(final.words); 71 | 72 | var i = 0; 73 | var limit = (length < Curl.HASH_LENGTH ? length : Curl.HASH_LENGTH); 74 | 75 | while (i < limit) { 76 | trits[offset++] = trit_state[i++]; 77 | } 78 | 79 | this.reset(); 80 | 81 | for (i = 0; i < final.words.length; i++) { 82 | final.words[i] = final.words[i] ^ 0xFFFFFFFF; 83 | } 84 | 85 | this.k.update(final); 86 | 87 | } while ((length -= Curl.HASH_LENGTH) > 0); 88 | } 89 | 90 | module.exports = Kerl; 91 | -------------------------------------------------------------------------------- /lib/crypto/signing/oldSigning.js: -------------------------------------------------------------------------------- 1 | var Curl = require("../curl/curl"); 2 | var Converter = require("../converter/converter"); 3 | var Bundle = require("../bundle/bundle"); 4 | var add = require("../helpers/adder"); 5 | 6 | /** 7 | * Signing related functions 8 | * 9 | **/ 10 | var key = function(seed, index, length) { 11 | 12 | while ((seed.length % 243) !== 0) { 13 | seed.push(0); 14 | } 15 | 16 | var indexTrits = Converter.fromValue( index ); 17 | var subseed = add( seed.slice( ), indexTrits ); 18 | 19 | var curl = new Curl( ); 20 | 21 | curl.initialize( ); 22 | curl.absorb(subseed, 0, subseed.length); 23 | curl.squeeze(subseed, 0, subseed.length); 24 | 25 | curl.initialize( ); 26 | curl.absorb(subseed, 0, subseed.length); 27 | 28 | var key = [], offset = 0, buffer = []; 29 | 30 | while (length-- > 0) { 31 | 32 | for (var i = 0; i < 27; i++) { 33 | 34 | curl.squeeze(buffer, 0, subseed.length); 35 | for (var j = 0; j < 243; j++) { 36 | 37 | key[offset++] = buffer[j]; 38 | } 39 | } 40 | } 41 | return key; 42 | } 43 | 44 | /** 45 | * 46 | * 47 | **/ 48 | var digests = function(key) { 49 | 50 | var digests = [], buffer = []; 51 | 52 | for (var i = 0; i < Math.floor(key.length / 6561); i++) { 53 | 54 | var keyFragment = key.slice(i * 6561, (i + 1) * 6561); 55 | 56 | for (var j = 0; j < 27; j++) { 57 | 58 | buffer = keyFragment.slice(j * 243, (j + 1) * 243); 59 | 60 | for (var k = 0; k < 26; k++) { 61 | 62 | var kCurl = new Curl(); 63 | kCurl.initialize(); 64 | kCurl.absorb(buffer, 0, buffer.length); 65 | kCurl.squeeze(buffer, 0, Curl.HASH_LENGTH); 66 | } 67 | 68 | for (var k = 0; k < 243; k++) { 69 | 70 | keyFragment[j * 243 + k] = buffer[k]; 71 | } 72 | } 73 | 74 | var curl = new Curl() 75 | 76 | curl.initialize(); 77 | curl.absorb(keyFragment, 0, keyFragment.length); 78 | curl.squeeze(buffer, 0, Curl.HASH_LENGTH); 79 | 80 | for (var j = 0; j < 243; j++) { 81 | 82 | digests[i * 243 + j] = buffer[j]; 83 | } 84 | } 85 | return digests; 86 | } 87 | 88 | /** 89 | * 90 | * 91 | **/ 92 | var address = function(digests) { 93 | 94 | var addressTrits = []; 95 | 96 | var curl = new Curl(); 97 | 98 | curl.initialize(); 99 | curl.absorb(digests, 0, digests.length); 100 | curl.squeeze(addressTrits, 0, Curl.HASH_LENGTH); 101 | 102 | return addressTrits; 103 | } 104 | 105 | /** 106 | * 107 | * 108 | **/ 109 | var digest = function(normalizedBundleFragment, signatureFragment) { 110 | 111 | var buffer = [] 112 | 113 | var curl = new Curl(); 114 | 115 | curl.initialize(); 116 | 117 | for (var i = 0; i< 27; i++) { 118 | buffer = signatureFragment.slice(i * 243, (i + 1) * 243); 119 | 120 | for (var j = normalizedBundleFragment[i] + 13; j-- > 0; ) { 121 | 122 | var jCurl = new Curl(); 123 | 124 | jCurl.initialize(); 125 | jCurl.absorb(buffer, 0, buffer.length); 126 | jCurl.squeeze(buffer, 0, Curl.HASH_LENGTH); 127 | } 128 | 129 | curl.absorb(buffer, 0, buffer.length); 130 | } 131 | 132 | curl.squeeze(buffer, 0, Curl.HASH_LENGTH); 133 | return buffer; 134 | } 135 | 136 | /** 137 | * 138 | * 139 | **/ 140 | var signatureFragment = function(normalizedBundleFragment, keyFragment) { 141 | 142 | var signatureFragment = keyFragment.slice(), hash = []; 143 | 144 | var curl = new Curl(); 145 | 146 | for (var i = 0; i < 27; i++) { 147 | 148 | hash = signatureFragment.slice(i * 243, (i + 1) * 243); 149 | 150 | for (var j = 0; j < 13 - normalizedBundleFragment[i]; j++) { 151 | 152 | curl.initialize(); 153 | curl.absorb(hash, 0, hash.length); 154 | curl.squeeze(hash, 0, Curl.HASH_LENGTH); 155 | } 156 | 157 | for (var j = 0; j < 243; j++) { 158 | 159 | signatureFragment[i * 243 + j] = hash[j]; 160 | } 161 | } 162 | 163 | return signatureFragment; 164 | } 165 | 166 | /** 167 | * 168 | * 169 | **/ 170 | var validateSignatures = function(expectedAddress, signatureFragments, bundleHash) { 171 | 172 | var self = this; 173 | var bundle = new Bundle(); 174 | 175 | var normalizedBundleFragments = []; 176 | var normalizedBundleHash = bundle.normalizedBundle(bundleHash); 177 | 178 | // Split hash into 3 fragments 179 | for (var i = 0; i < 3; i++) { 180 | normalizedBundleFragments[i] = normalizedBundleHash.slice(i * 27, (i + 1) * 27); 181 | } 182 | 183 | // Get digests 184 | var digests = []; 185 | 186 | for (var i = 0; i < signatureFragments.length; i++) { 187 | 188 | var digestBuffer = digest(normalizedBundleFragments[i % 3], Converter.trits(signatureFragments[i])); 189 | 190 | for (var j = 0; j < 243; j++) { 191 | 192 | digests[i * 243 + j] = digestBuffer[j] 193 | } 194 | } 195 | 196 | var address = Converter.trytes(self.address(digests)); 197 | 198 | return (expectedAddress === address); 199 | } 200 | 201 | 202 | module.exports = { 203 | key : key, 204 | digests : digests, 205 | address : address, 206 | digest : digest, 207 | signatureFragment : signatureFragment, 208 | validateSignatures : validateSignatures 209 | } 210 | -------------------------------------------------------------------------------- /lib/crypto/signing/signing.js: -------------------------------------------------------------------------------- 1 | var Curl = require("../curl/curl"); 2 | var Kerl = require("../kerl/kerl"); 3 | var Converter = require("../converter/converter"); 4 | var Bundle = require("../bundle/bundle"); 5 | var add = require("../helpers/adder"); 6 | var oldSigning = require("./oldSigning"); 7 | var errors = require("../../errors/inputErrors"); 8 | 9 | /** 10 | * Signing related functions 11 | * 12 | **/ 13 | var key = function(seed, index, length) { 14 | 15 | while ((seed.length % 243) !== 0) { 16 | seed.push(0); 17 | } 18 | 19 | var indexTrits = Converter.fromValue( index ); 20 | var subseed = add( seed.slice( ), indexTrits ); 21 | 22 | var kerl = new Kerl( ); 23 | 24 | kerl.initialize( ); 25 | kerl.absorb(subseed, 0, subseed.length); 26 | kerl.squeeze(subseed, 0, subseed.length); 27 | 28 | kerl.reset( ); 29 | kerl.absorb(subseed, 0, subseed.length); 30 | 31 | var key = [], offset = 0, buffer = []; 32 | 33 | while (length-- > 0) { 34 | 35 | for (var i = 0; i < 27; i++) { 36 | 37 | kerl.squeeze(buffer, 0, subseed.length); 38 | for (var j = 0; j < 243; j++) { 39 | 40 | key[offset++] = buffer[j]; 41 | } 42 | } 43 | } 44 | return key; 45 | } 46 | 47 | /** 48 | * 49 | * 50 | **/ 51 | var digests = function(key) { 52 | 53 | var digests = [], buffer = []; 54 | 55 | for (var i = 0; i < Math.floor(key.length / 6561); i++) { 56 | 57 | var keyFragment = key.slice(i * 6561, (i + 1) * 6561); 58 | 59 | for (var j = 0; j < 27; j++) { 60 | 61 | buffer = keyFragment.slice(j * 243, (j + 1) * 243); 62 | 63 | for (var k = 0; k < 26; k++) { 64 | 65 | var kKerl = new Kerl(); 66 | kKerl.initialize(); 67 | kKerl.absorb(buffer, 0, buffer.length); 68 | kKerl.squeeze(buffer, 0, Curl.HASH_LENGTH); 69 | } 70 | 71 | for (var k = 0; k < 243; k++) { 72 | 73 | keyFragment[j * 243 + k] = buffer[k]; 74 | } 75 | } 76 | 77 | var kerl = new Kerl() 78 | 79 | kerl.initialize(); 80 | kerl.absorb(keyFragment, 0, keyFragment.length); 81 | kerl.squeeze(buffer, 0, Curl.HASH_LENGTH); 82 | 83 | for (var j = 0; j < 243; j++) { 84 | 85 | digests[i * 243 + j] = buffer[j]; 86 | } 87 | } 88 | return digests; 89 | } 90 | 91 | /** 92 | * 93 | * 94 | **/ 95 | var address = function(digests) { 96 | 97 | var addressTrits = []; 98 | 99 | var kerl = new Kerl(); 100 | 101 | kerl.initialize(); 102 | kerl.absorb(digests, 0, digests.length); 103 | kerl.squeeze(addressTrits, 0, Curl.HASH_LENGTH); 104 | 105 | return addressTrits; 106 | } 107 | 108 | /** 109 | * 110 | * 111 | **/ 112 | var digest = function(normalizedBundleFragment, signatureFragment) { 113 | 114 | var buffer = [] 115 | 116 | var kerl = new Kerl(); 117 | 118 | kerl.initialize(); 119 | 120 | for (var i = 0; i< 27; i++) { 121 | buffer = signatureFragment.slice(i * 243, (i + 1) * 243); 122 | 123 | for (var j = normalizedBundleFragment[i] + 13; j-- > 0; ) { 124 | 125 | var jKerl = new Kerl(); 126 | 127 | jKerl.initialize(); 128 | jKerl.absorb(buffer, 0, buffer.length); 129 | jKerl.squeeze(buffer, 0, Curl.HASH_LENGTH); 130 | } 131 | 132 | kerl.absorb(buffer, 0, buffer.length); 133 | } 134 | 135 | kerl.squeeze(buffer, 0, Curl.HASH_LENGTH); 136 | return buffer; 137 | } 138 | 139 | /** 140 | * 141 | * 142 | **/ 143 | var signatureFragment = function(normalizedBundleFragment, keyFragment) { 144 | 145 | var signatureFragment = keyFragment.slice(), hash = []; 146 | 147 | var kerl = new Kerl(); 148 | 149 | for (var i = 0; i < 27; i++) { 150 | 151 | hash = signatureFragment.slice(i * 243, (i + 1) * 243); 152 | 153 | for (var j = 0; j < 13 - normalizedBundleFragment[i]; j++) { 154 | 155 | kerl.initialize(); 156 | kerl.reset(); 157 | kerl.absorb(hash, 0, hash.length); 158 | kerl.squeeze(hash, 0, Curl.HASH_LENGTH); 159 | } 160 | 161 | for (var j = 0; j < 243; j++) { 162 | 163 | signatureFragment[i * 243 + j] = hash[j]; 164 | } 165 | } 166 | 167 | return signatureFragment; 168 | } 169 | 170 | /** 171 | * 172 | * 173 | **/ 174 | var validateSignatures = function(expectedAddress, signatureFragments, bundleHash) { 175 | if (!bundleHash) { 176 | throw errors.invalidBundleHash(); 177 | } 178 | 179 | var self = this; 180 | var bundle = new Bundle(); 181 | 182 | var normalizedBundleFragments = []; 183 | var normalizedBundleHash = bundle.normalizedBundle(bundleHash); 184 | 185 | // Split hash into 3 fragments 186 | for (var i = 0; i < 3; i++) { 187 | normalizedBundleFragments[i] = normalizedBundleHash.slice(i * 27, (i + 1) * 27); 188 | } 189 | 190 | // Get digests 191 | var digests = []; 192 | 193 | for (var i = 0; i < signatureFragments.length; i++) { 194 | 195 | var digestBuffer = digest(normalizedBundleFragments[i % 3], Converter.trits(signatureFragments[i])); 196 | 197 | for (var j = 0; j < 243; j++) { 198 | 199 | digests[i * 243 + j] = digestBuffer[j] 200 | } 201 | } 202 | 203 | var address = Converter.trytes(self.address(digests)); 204 | 205 | return (expectedAddress === address); 206 | } 207 | 208 | 209 | module.exports = { 210 | key : key, 211 | digests : digests, 212 | address : address, 213 | digest : digest, 214 | signatureFragment : signatureFragment, 215 | validateSignatures : validateSignatures 216 | } 217 | -------------------------------------------------------------------------------- /lib/errors/inputErrors.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | 4 | invalidTrytes: function() { 5 | return new Error("Invalid Trytes provided"); 6 | }, 7 | invalidSeed: function() { 8 | return new Error("Invalid Seed provided"); 9 | }, 10 | invalidIndex: function() { 11 | return new Error("Invalid Index option provided"); 12 | }, 13 | invalidSecurity: function() { 14 | return new Error("Invalid Security option provided"); 15 | }, 16 | invalidChecksum: function(address) { 17 | return new Error("Invalid Checksum supplied for address: " + address) 18 | }, 19 | invalidAttachedTrytes: function() { 20 | return new Error("Invalid attached Trytes provided"); 21 | }, 22 | invalidTransfers: function() { 23 | return new Error("Invalid transfers object"); 24 | }, 25 | invalidKey: function() { 26 | return new Error("You have provided an invalid key value"); 27 | }, 28 | invalidTrunkOrBranch: function(hash) { 29 | return new Error("You have provided an invalid hash as a trunk/branch: " + hash); 30 | }, 31 | invalidUri: function(uri) { 32 | return new Error("You have provided an invalid URI for your Neighbor: " + uri) 33 | }, 34 | notInt: function() { 35 | return new Error("One of your inputs is not an integer"); 36 | }, 37 | invalidInputs: function() { 38 | return new Error("Invalid inputs provided"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/iota.crypto.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | curl: require('./crypto/curl/curl'), 3 | kerl: require('./crypto/kerl/kerl'), 4 | bundle: require('./crypto/bundle/bundle'), 5 | converter: require('./crypto/converter/converter'), 6 | signing: require('./crypto/signing/signing'), 7 | oldSigning: require('./crypto/signing/oldSigning'), 8 | hmac: require('./crypto/hmac/hmac'), 9 | multisig: require('./multisig/multisig'), 10 | utils: require("./utils/utils"), 11 | valid: require("./errors/inputErrors"), 12 | add: require("./crypto/helpers/adder") 13 | } 14 | -------------------------------------------------------------------------------- /lib/multisig/address.js: -------------------------------------------------------------------------------- 1 | var Converter = require('../crypto/converter/converter'); 2 | var Curl = require('../crypto/curl/curl'); 3 | var Kerl = require('../crypto/kerl/kerl'); 4 | var Signing = require('../crypto/signing/signing'); 5 | var Utils = require('../utils/utils'); 6 | var inputValidator = require('../utils/inputValidator'); 7 | 8 | 9 | /** 10 | * Initializes a new multisig address 11 | * 12 | * @method addDigest 13 | * @param {string|array} digest digest trytes 14 | * @return {object} address instance 15 | * 16 | **/ 17 | function Address(digests) { 18 | 19 | if (!(this instanceof Address)) { 20 | return new Address(digests); 21 | } 22 | 23 | // Initialize kerl instance 24 | this._kerl = new Kerl(); 25 | this._kerl.initialize(); 26 | 27 | 28 | // Add digests if any 29 | if (digests) { 30 | 31 | this.absorb(digests); 32 | } 33 | } 34 | 35 | /** 36 | * Absorbs key digests 37 | * 38 | * @method absorb 39 | * @param {string|array} digest digest trytes 40 | * @return {object} address instance 41 | * 42 | **/ 43 | Address.prototype.absorb = function (digest) { 44 | 45 | // Construct array 46 | var digests = Array.isArray(digest) ? digest : [digest]; 47 | 48 | // Add digests 49 | for (var i = 0; i < digests.length; i++) { 50 | 51 | // Get trits of digest 52 | var digestTrits = Converter.trits(digests[i]); 53 | 54 | // Absorb digest 55 | this._kerl.absorb(digestTrits, 0, digestTrits.length); 56 | } 57 | 58 | return this; 59 | } 60 | 61 | /** 62 | * Finalizes and returns the multisig address in trytes 63 | * 64 | * @method finalize 65 | * @param {string} digest digest trytes, optional 66 | * @return {string} address trytes 67 | * 68 | **/ 69 | Address.prototype.finalize = function (digest) { 70 | 71 | // Absorb last digest if provided 72 | if (digest) { 73 | this.absorb(digest); 74 | } 75 | 76 | // Squeeze the address trits 77 | var addressTrits = []; 78 | this._kerl.squeeze(addressTrits, 0, Curl.HASH_LENGTH); 79 | 80 | // Convert trits into trytes and return the address 81 | return Converter.trytes(addressTrits); 82 | } 83 | 84 | 85 | module.exports = Address; 86 | -------------------------------------------------------------------------------- /lib/multisig/multisig.js: -------------------------------------------------------------------------------- 1 | var Signing = require('../crypto/signing/signing'); 2 | var Converter = require('../crypto/converter/converter'); 3 | var Kerl = require('../crypto/kerl/kerl'); 4 | var Curl = require('../crypto/curl/curl'); 5 | var Bundle = require('../crypto/bundle/bundle'); 6 | var Utils = require('../utils/utils'); 7 | var inputValidator = require('../utils/inputValidator'); 8 | var errors = require('../errors/inputErrors'); 9 | var Address = require('./address'); 10 | 11 | function Multisig(provider) { 12 | 13 | this._makeRequest = provider; 14 | } 15 | 16 | 17 | /** 18 | * Gets the key value of a seed 19 | * 20 | * @method getKey 21 | * @param {string} seed 22 | * @param {int} index 23 | * @param {int} security Security level to be used for the private key / address. Can be 1, 2 or 3 24 | * @returns {string} digest trytes 25 | **/ 26 | Multisig.getKey = function(seed, index, security) { 27 | 28 | return Converter.trytes(Signing.key(Converter.trits(seed), index, security)); 29 | } 30 | 31 | /** 32 | * Gets the digest value of a seed 33 | * 34 | * @method getDigest 35 | * @param {string} seed 36 | * @param {int} index 37 | * @param {int} security Security level to be used for the private key / address. Can be 1, 2 or 3 38 | * @returns {string} digest trytes 39 | **/ 40 | Multisig.getDigest = function(seed, index, security) { 41 | 42 | var key = Signing.key(Converter.trits(seed), index, security); 43 | return Converter.trytes(Signing.digests(key)); 44 | } 45 | 46 | /** 47 | * Multisig address constructor 48 | */ 49 | Multisig.address = Address; 50 | 51 | /** 52 | * Validates a generated multisig address 53 | * 54 | * @method validateAddress 55 | * @param {string} multisigAddress 56 | * @param {array} digests 57 | * @returns {bool} 58 | **/ 59 | Multisig.validateAddress = function(multisigAddress, digests) { 60 | 61 | var kerl = new Kerl(); 62 | 63 | // initialize Kerl with the provided state 64 | kerl.initialize(); 65 | 66 | // Absorb all key digests 67 | digests.forEach(function(keyDigest) { 68 | var trits = Converter.trits(keyDigest); 69 | kerl.absorb(Converter.trits(keyDigest), 0, trits.length); 70 | }) 71 | 72 | // Squeeze address trits 73 | var addressTrits = []; 74 | kerl.squeeze(addressTrits, 0, Curl.HASH_LENGTH); 75 | 76 | // Convert trits into trytes and return the address 77 | return Converter.trytes(addressTrits) === multisigAddress; 78 | } 79 | 80 | 81 | /** 82 | * Prepares transfer by generating the bundle with the corresponding cosigner transactions 83 | * Does not contain signatures 84 | * 85 | * @method initiateTransfer 86 | * @param {object} input the input addresses as well as the securitySum, and balance 87 | * where `address` is the input multisig address 88 | * and `securitySum` is the sum of security levels used by all co-signers 89 | * and `balance` is the expected balance, if you wish to override getBalances 90 | * @param {string} remainderAddress Has to be generated by the cosigners before initiating the transfer, can be null if fully spent 91 | * @param {object} transfers 92 | * @param {function} callback 93 | * @returns {array} Array of transaction objects 94 | **/ 95 | Multisig.initiateTransfer = function(input, remainderAddress, transfers, callback) { 96 | 97 | var self = this; 98 | 99 | // If message or tag is not supplied, provide it 100 | // Also remove the checksum of the address if it's there 101 | transfers.forEach(function(thisTransfer) { 102 | thisTransfer.message = thisTransfer.message ? thisTransfer.message : ''; 103 | thisTransfer.tag = thisTransfer.tag ? thisTransfer.tag : ''; 104 | thisTransfer.obsoleteTag = thisTransfer.obsoleteTag ? thisTransfer.obsoleteTag : ''; 105 | thisTransfer.address = Utils.noChecksum(thisTransfer.address); 106 | }) 107 | 108 | // Input validation of transfers object 109 | if (!inputValidator.isTransfersArray(transfers)) { 110 | return callback(errors.invalidTransfers()); 111 | } 112 | 113 | // check if int 114 | if (!inputValidator.isValue(input.securitySum)) { 115 | return callback(errors.invalidInputs()); 116 | } 117 | 118 | // validate input address 119 | if (!inputValidator.isAddress(input.address)) { 120 | return callback(errors.invalidTrytes()); 121 | } 122 | 123 | // validate remainder address 124 | if (remainderAddress && !inputValidator.isAddress(remainderAddress)) { 125 | return callback(errors.invalidTrytes()); 126 | } 127 | 128 | // Create a new bundle 129 | var bundle = new Bundle(); 130 | 131 | var totalValue = 0; 132 | var signatureFragments = []; 133 | var tag; 134 | 135 | // 136 | // Iterate over all transfers, get totalValue 137 | // and prepare the signatureFragments, message and tag 138 | // 139 | for (var i = 0; i < transfers.length; i++) { 140 | 141 | var signatureMessageLength = 1; 142 | 143 | // If message longer than 2187 trytes, increase signatureMessageLength (add multiple transactions) 144 | if (transfers[i].message.length > 2187) { 145 | 146 | // Get total length, message / maxLength (2187 trytes) 147 | signatureMessageLength += Math.floor(transfers[i].message.length / 2187); 148 | 149 | var msgCopy = transfers[i].message; 150 | 151 | // While there is still a message, copy it 152 | while (msgCopy) { 153 | 154 | var fragment = msgCopy.slice(0, 2187); 155 | msgCopy = msgCopy.slice(2187, msgCopy.length); 156 | 157 | // Pad remainder of fragment 158 | for (var j = 0; fragment.length < 2187; j++) { 159 | fragment += '9'; 160 | } 161 | 162 | signatureFragments.push(fragment); 163 | } 164 | 165 | } else { 166 | // Else, get single fragment with 2187 of 9's trytes 167 | var fragment = ''; 168 | 169 | if (transfers[i].message) { 170 | fragment = transfers[i].message.slice(0, 2187) 171 | } 172 | 173 | for (var j = 0; fragment.length < 2187; j++) { 174 | fragment += '9'; 175 | } 176 | 177 | signatureFragments.push(fragment); 178 | } 179 | 180 | // get current timestamp in seconds 181 | var timestamp = Math.floor(Date.now() / 1000); 182 | 183 | // If no tag defined, get 27 tryte tag. 184 | tag = transfers[i].tag ? transfers[i].tag : '999999999999999999999999999'; 185 | 186 | // Pad for required 27 tryte length 187 | for (var j = 0; tag.length < 27; j++) { 188 | tag += '9'; 189 | } 190 | 191 | // Add first entries to the bundle 192 | // Slice the address in case the user provided a checksummed one 193 | bundle.addEntry(signatureMessageLength, transfers[i].address.slice(0, 81), transfers[i].value, tag, timestamp); 194 | 195 | // Sum up total value 196 | totalValue += parseInt(transfers[i].value); 197 | } 198 | 199 | // Get inputs if we are sending tokens 200 | if (totalValue) { 201 | 202 | function createBundle(totalBalance, callback) { 203 | if (totalBalance > 0) { 204 | 205 | var toSubtract = 0 - totalBalance; 206 | var timestamp = Math.floor(Date.now() / 1000); 207 | 208 | // Add input as bundle entry 209 | // Only a single entry, signatures will be added later 210 | bundle.addEntry(input.securitySum, input.address, toSubtract, tag, timestamp); 211 | } 212 | 213 | if (totalValue > totalBalance) { 214 | return callback(new Error("Not enough balance.")); 215 | } 216 | 217 | 218 | // If there is a remainder value 219 | // Add extra output to send remaining funds to 220 | if (totalBalance > totalValue) { 221 | 222 | var remainder = totalBalance - totalValue; 223 | 224 | // Remainder bundle entry if necessary 225 | if (!remainderAddress) { 226 | return callback(new Error("No remainder address defined")); 227 | } 228 | 229 | bundle.addEntry(1, remainderAddress, remainder, tag, timestamp); 230 | } 231 | 232 | bundle.finalize(); 233 | bundle.addTrytes(signatureFragments); 234 | 235 | return callback(null, bundle.bundle); 236 | }; 237 | 238 | if (input.balance) { 239 | createBundle(input.balance, callback); 240 | } else { 241 | var command = { 242 | 'command': 'getBalances', 243 | 'addresses': new Array(input.address), 244 | 'threshold': 100 245 | } 246 | self._makeRequest.send(command, function(e, balances) { 247 | if (e) return callback(e); 248 | createBundle(parseInt(balances.balances[0]), callback); 249 | }); 250 | } 251 | 252 | } else { 253 | 254 | return callback(new Error("Invalid value transfer: the transfer does not require a signature.")); 255 | } 256 | 257 | } 258 | 259 | 260 | /** 261 | * Adds the cosigner signatures to the corresponding bundle transaction 262 | * 263 | * @method addSignature 264 | * @param {array} bundleToSign 265 | * @param {int} cosignerIndex 266 | * @param {string} inputAddress 267 | * @param {string} key 268 | * @param {function} callback 269 | * @returns {array} trytes Returns bundle trytes 270 | **/ 271 | Multisig.addSignature = function(bundleToSign, inputAddress, key, callback) { 272 | 273 | var bundle = new Bundle(); 274 | bundle.bundle = bundleToSign; 275 | 276 | // Get the security used for the private key 277 | // 1 security level = 2187 trytes 278 | var security = (key.length / 2187); 279 | 280 | // convert private key trytes into trits 281 | var key = Converter.trits(key); 282 | 283 | 284 | // First get the total number of already signed transactions 285 | // use that for the bundle hash calculation as well as knowing 286 | // where to add the signature 287 | var numSignedTxs = 0; 288 | 289 | for (var i = 0; i < bundle.bundle.length; i++) { 290 | 291 | if (bundle.bundle[i].address === inputAddress) { 292 | 293 | // If transaction is already signed, increase counter 294 | if (!inputValidator.isNinesTrytes(bundle.bundle[i].signatureMessageFragment)) { 295 | 296 | numSignedTxs++; 297 | } 298 | // Else sign the transactionse 299 | else { 300 | 301 | var bundleHash = bundle.bundle[i].bundle; 302 | 303 | // First 6561 trits for the firstFragment 304 | var firstFragment = key.slice(0, 6561); 305 | 306 | // Get the normalized bundle hash 307 | var normalizedBundleHash = bundle.normalizedBundle(bundleHash); 308 | var normalizedBundleFragments = []; 309 | 310 | // Split hash into 3 fragments 311 | for (var k = 0; k < 3; k++) { 312 | normalizedBundleFragments[k] = normalizedBundleHash.slice(k * 27, (k + 1) * 27); 313 | } 314 | 315 | // First bundle fragment uses 27 trytes 316 | var firstBundleFragment = normalizedBundleFragments[numSignedTxs % 3]; 317 | 318 | // Calculate the new signatureFragment with the first bundle fragment 319 | var firstSignedFragment = Signing.signatureFragment(firstBundleFragment, firstFragment); 320 | 321 | // Convert signature to trytes and assign the new signatureFragment 322 | bundle.bundle[i].signatureMessageFragment = Converter.trytes(firstSignedFragment); 323 | 324 | for (var j = 1; j < security; j++) { 325 | 326 | // Next 6561 trits for the firstFragment 327 | var nextFragment = key.slice(6561 * j, (j + 1) * 6561); 328 | 329 | // Use the next 27 trytes 330 | var nextBundleFragment = normalizedBundleFragments[(numSignedTxs + j) % 3]; 331 | 332 | // Calculate the new signatureFragment with the first bundle fragment 333 | var nextSignedFragment = Signing.signatureFragment(nextBundleFragment, nextFragment); 334 | 335 | // Convert signature to trytes and add new bundle entry at i + j position 336 | // Assign the signature fragment 337 | bundle.bundle[i + j].signatureMessageFragment = Converter.trytes(nextSignedFragment); 338 | } 339 | 340 | break; 341 | } 342 | } 343 | } 344 | 345 | return callback(null, bundle.bundle); 346 | } 347 | 348 | module.exports = Multisig; 349 | -------------------------------------------------------------------------------- /lib/utils/asciiToTrytes.js: -------------------------------------------------------------------------------- 1 | // 2 | // Conversion of ascii encoded bytes to trytes. 3 | // Input is a string (can be stringified JSON object), return value is Trytes 4 | // 5 | // How the conversion works: 6 | // 2 Trytes === 1 Byte 7 | // There are a total of 27 different tryte values: 9ABCDEFGHIJKLMNOPQRSTUVWXYZ 8 | // 9 | // 1. We get the decimal value of an individual ASCII character 10 | // 2. From the decimal value, we then derive the two tryte values by basically calculating the tryte equivalent (e.g. 100 === 19 + 3 * 27) 11 | // a. The first tryte value is the decimal value modulo 27 (27 trytes) 12 | // b. The second value is the remainder (decimal value - first value), divided by 27 13 | // 3. The two values returned from Step 2. are then input as indices into the available values list ('9ABCDEFGHIJKLMNOPQRSTUVWXYZ') to get the correct tryte value 14 | // 15 | // EXAMPLES 16 | // Lets say we want to convert the ASCII character "Z". 17 | // 1. 'Z' has a decimal value of 90. 18 | // 2. 90 can be represented as 9 + 3 * 27. To make it simpler: 19 | // a. First value: 90 modulo 27 is 9. This is now our first value 20 | // b. Second value: (90 - 9) / 27 is 3. This is our second value. 21 | // 3. Our two values are now 9 and 3. To get the tryte value now we simply insert it as indices into '9ABCDEFGHIJKLMNOPQRSTUVWXYZ' 22 | // a. The first tryte value is '9ABCDEFGHIJKLMNOPQRSTUVWXYZ'[9] === "I" 23 | // b. The second tryte value is '9ABCDEFGHIJKLMNOPQRSTUVWXYZ'[3] === "C" 24 | // Our tryte pair is "IC" 25 | // 26 | // RESULT: 27 | // The ASCII char "Z" is represented as "IC" in trytes. 28 | // 29 | function toTrytes(input) { 30 | 31 | // If input is not a string, return null 32 | if ( typeof input !== 'string' ) return null 33 | 34 | var TRYTE_VALUES = "9ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 35 | var trytes = ""; 36 | 37 | for (var i = 0; i < input.length; i++) { 38 | var char = input[i]; 39 | var asciiValue = char.charCodeAt(0); 40 | 41 | // If not recognizable ASCII character, return null 42 | if (asciiValue > 255) { 43 | //asciiValue = 32 44 | return null; 45 | } 46 | 47 | var firstValue = asciiValue % 27; 48 | var secondValue = (asciiValue - firstValue) / 27; 49 | 50 | var trytesValue = TRYTE_VALUES[firstValue] + TRYTE_VALUES[secondValue]; 51 | 52 | trytes += trytesValue; 53 | } 54 | 55 | return trytes; 56 | } 57 | 58 | 59 | // 60 | // Trytes to bytes 61 | // Reverse operation from the byteToTrytes function in send.js 62 | // 2 Trytes == 1 Byte 63 | // We assume that the trytes are a JSON encoded object thus for our encoding: 64 | // First character = { 65 | // Last character = } 66 | // Everything after that is 9's padding 67 | // 68 | function fromTrytes(inputTrytes) { 69 | 70 | // If input is not a string, return null 71 | if ( typeof inputTrytes !== 'string' ) return null 72 | 73 | // If input length is odd, return null 74 | if ( inputTrytes.length % 2 ) return null 75 | 76 | var TRYTE_VALUES = "9ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 77 | var outputString = ""; 78 | 79 | for (var i = 0; i < inputTrytes.length; i += 2) { 80 | // get a trytes pair 81 | var trytes = inputTrytes[i] + inputTrytes[i + 1]; 82 | 83 | var firstValue = TRYTE_VALUES.indexOf(trytes[0]); 84 | var secondValue = TRYTE_VALUES.indexOf(trytes[1]); 85 | 86 | var decimalValue = firstValue + secondValue * 27; 87 | 88 | var character = String.fromCharCode(decimalValue); 89 | 90 | outputString += character; 91 | } 92 | 93 | return outputString; 94 | } 95 | 96 | module.exports = { 97 | toTrytes: toTrytes, 98 | fromTrytes: fromTrytes 99 | } 100 | -------------------------------------------------------------------------------- /lib/utils/extractJson.js: -------------------------------------------------------------------------------- 1 | var ascii = require("./asciiToTrytes"); 2 | var inputValidator = require("./inputValidator"); 3 | 4 | /** 5 | * extractJson takes a bundle as input and from the signatureMessageFragments extracts the correct JSON 6 | * data which was encoded and sent with the transaction. 7 | * 8 | * @method extractJson 9 | * @param {array} bundle 10 | * @returns {Object} 11 | **/ 12 | function extractJson(bundle) { 13 | 14 | // if wrong input return null 15 | if ( !inputValidator.isArray(bundle) || bundle[0] === undefined ) return null; 16 | 17 | 18 | // Sanity check: if the first tryte pair is not opening bracket, it's not a message 19 | var firstTrytePair = bundle[0].signatureMessageFragment[0] + bundle[0].signatureMessageFragment[1]; 20 | 21 | if (firstTrytePair !== "OD") return null; 22 | 23 | var index = 0; 24 | var notEnded = true; 25 | var trytesChunk = ''; 26 | var trytesChecked = 0; 27 | var preliminaryStop = false; 28 | var finalJson = ''; 29 | 30 | while (index < bundle.length && notEnded) { 31 | 32 | var messageChunk = bundle[index].signatureMessageFragment; 33 | 34 | // We iterate over the message chunk, reading 9 trytes at a time 35 | for (var i = 0; i < messageChunk.length; i += 9) { 36 | 37 | // get 9 trytes 38 | var trytes = messageChunk.slice(i, i + 9); 39 | trytesChunk += trytes; 40 | 41 | // Get the upper limit of the tytes that need to be checked 42 | // because we only check 2 trytes at a time, there is sometimes a leftover 43 | var upperLimit = trytesChunk.length - trytesChunk.length % 2; 44 | 45 | var trytesToCheck = trytesChunk.slice(trytesChecked, upperLimit); 46 | 47 | // We read 2 trytes at a time and check if it equals the closing bracket character 48 | for (var j = 0; j < trytesToCheck.length; j += 2) { 49 | 50 | var trytePair = trytesToCheck[j] + trytesToCheck[j + 1]; 51 | 52 | // If closing bracket char was found, and there are only trailing 9's 53 | // we quit and remove the 9's from the trytesChunk. 54 | if ( preliminaryStop && trytePair === '99' ) { 55 | 56 | notEnded = false; 57 | // TODO: Remove the trailing 9's from trytesChunk 58 | //var closingBracket = trytesToCheck.indexOf('QD') + 1; 59 | 60 | //trytesChunk = trytesChunk.slice( 0, ( trytesChunk.length - trytesToCheck.length ) + ( closingBracket % 2 === 0 ? closingBracket : closingBracket + 1 ) ); 61 | 62 | break; 63 | } 64 | 65 | finalJson += ascii.fromTrytes(trytePair); 66 | 67 | // If tryte pair equals closing bracket char, we set a preliminary stop 68 | // the preliminaryStop is useful when we have a nested JSON object 69 | if (trytePair === "QD") { 70 | preliminaryStop = true; 71 | } 72 | } 73 | 74 | if (!notEnded) 75 | break; 76 | 77 | trytesChecked += trytesToCheck.length; 78 | } 79 | 80 | // If we have not reached the end of the message yet, we continue with the next 81 | // transaction in the bundle 82 | index += 1; 83 | 84 | } 85 | 86 | // If we did not find any JSON, return null 87 | if (notEnded) { 88 | 89 | return null; 90 | 91 | } else { 92 | 93 | return finalJson; 94 | 95 | } 96 | } 97 | 98 | module.exports = extractJson; 99 | -------------------------------------------------------------------------------- /lib/utils/inputValidator.js: -------------------------------------------------------------------------------- 1 | /** 2 | * checks if input is correct address 3 | * 4 | * @method isAddress 5 | * @param {string} address 6 | * @returns {boolean} 7 | **/ 8 | var isAddress = function(address) { 9 | // TODO: In the future check checksum 10 | 11 | // Check if address with checksum 12 | if (address.length === 90) { 13 | 14 | if (!isTrytes(address, 90)) { 15 | return false; 16 | } 17 | } else { 18 | 19 | if (!isTrytes(address, 81)) { 20 | return false; 21 | } 22 | } 23 | 24 | return true; 25 | } 26 | 27 | /** 28 | * checks if input is correct trytes consisting of A-Z9 29 | * optionally validate length 30 | * 31 | * @method isTrytes 32 | * @param {string} trytes 33 | * @param {integer} length optional 34 | * @returns {boolean} 35 | **/ 36 | var isTrytes = function(trytes, length) { 37 | 38 | // If no length specified, just validate the trytes 39 | if (!length) length = "0," 40 | 41 | var regexTrytes = new RegExp("^[9A-Z]{" + length +"}$"); 42 | return regexTrytes.test(trytes) && isString(trytes); 43 | } 44 | 45 | /** 46 | * checks if input is correct trytes consisting of A-Z9 47 | * optionally validate length 48 | * 49 | * @method isNinesTrytes 50 | * @param {string} trytes 51 | * @returns {boolean} 52 | **/ 53 | var isNinesTrytes = function(trytes) { 54 | 55 | return /^[9]+$/.test(trytes) && isString(trytes); 56 | } 57 | 58 | /** 59 | * checks if integer value 60 | * 61 | * @method isValue 62 | * @param {string} value 63 | * @returns {boolean} 64 | **/ 65 | var isValue = function(value) { 66 | 67 | // check if correct number 68 | return Number.isInteger(value) 69 | } 70 | 71 | /** 72 | * checks whether input is a value or not. Can be a string, float or integer 73 | * 74 | * @method isNum 75 | * @param {int} 76 | * @returns {boolean} 77 | **/ 78 | var isNum = function(input) { 79 | 80 | return /^(\d+\.?\d{0,15}|\.\d{0,15})$/.test(input); 81 | } 82 | 83 | /** 84 | * checks if input is correct hash 85 | * 86 | * @method isHash 87 | * @param {string} hash 88 | * @returns {boolean} 89 | **/ 90 | var isHash = function(hash) { 91 | 92 | // Check if valid, 81 trytes 93 | if (!isTrytes(hash, 81)) { 94 | 95 | return false; 96 | } 97 | 98 | return true; 99 | } 100 | 101 | /** 102 | * checks whether input is a string or not 103 | * 104 | * @method isString 105 | * @param {string} 106 | * @returns {boolean} 107 | **/ 108 | var isString = function(string) { 109 | 110 | return typeof string === 'string'; 111 | } 112 | 113 | 114 | /** 115 | * checks whether input is an array or not 116 | * 117 | * @method isArray 118 | * @param {object} 119 | * @returns {boolean} 120 | **/ 121 | var isArray = function(array) { 122 | 123 | return array instanceof Array; 124 | } 125 | 126 | 127 | /** 128 | * checks whether input is object or not 129 | * 130 | * @method isObject 131 | * @param {object} 132 | * @returns {boolean} 133 | **/ 134 | var isObject = function(object) { 135 | 136 | return typeof object === 'object'; 137 | } 138 | 139 | 140 | 141 | /** 142 | * checks if input is correct hash 143 | * 144 | * @method isTransfersArray 145 | * @param {array} hash 146 | * @returns {boolean} 147 | **/ 148 | var isTransfersArray = function(transfersArray) { 149 | 150 | if (!isArray(transfersArray)) return false; 151 | 152 | for (var i = 0; i < transfersArray.length; i++) { 153 | 154 | var transfer = transfersArray[i]; 155 | 156 | // Check if valid address 157 | var address = transfer.address; 158 | if (!isAddress(address)) { 159 | return false; 160 | } 161 | 162 | // Validity check for value 163 | var value = transfer.value; 164 | if (!isValue(value)) { 165 | return false; 166 | } 167 | 168 | // Check if message is correct trytes of any length 169 | var message = transfer.message; 170 | if (!isTrytes(message, "0,")) { 171 | return false; 172 | } 173 | 174 | // Check if tag is correct trytes of {0,27} trytes 175 | var tag = transfer.tag || transfer.obsoleteTag; 176 | if (!isTrytes(tag, "0,27")) { 177 | return false; 178 | } 179 | 180 | } 181 | 182 | return true; 183 | } 184 | 185 | /** 186 | * checks if input is list of correct trytes 187 | * 188 | * @method isArrayOfHashes 189 | * @param {list} hashesArray 190 | * @returns {boolean} 191 | **/ 192 | var isArrayOfHashes = function(hashesArray) { 193 | 194 | if (!isArray(hashesArray)) return false; 195 | 196 | for (var i = 0; i < hashesArray.length; i++) { 197 | 198 | var hash = hashesArray[i]; 199 | 200 | // Check if address with checksum 201 | if (hash.length === 90) { 202 | 203 | if (!isTrytes(hash, 90)) { 204 | return false; 205 | } 206 | } else { 207 | 208 | if (!isTrytes(hash, 81)) { 209 | return false; 210 | } 211 | } 212 | } 213 | 214 | return true; 215 | } 216 | 217 | /** 218 | * checks if input is list of correct trytes 219 | * 220 | * @method isArrayOfTrytes 221 | * @param {list} trytesArray 222 | * @returns {boolean} 223 | **/ 224 | var isArrayOfTrytes = function(trytesArray) { 225 | 226 | if (!isArray(trytesArray)) return false; 227 | 228 | for (var i = 0; i < trytesArray.length; i++) { 229 | 230 | var tryteValue = trytesArray[i]; 231 | 232 | // Check if correct 2673 trytes 233 | if (!isTrytes(tryteValue, 2673)) { 234 | return false; 235 | } 236 | } 237 | 238 | return true; 239 | } 240 | 241 | /** 242 | * checks if attached trytes if last 241 trytes are non-zero 243 | * 244 | * @method isArrayOfAttachedTrytes 245 | * @param {array} trytesArray 246 | * @returns {boolean} 247 | **/ 248 | var isArrayOfAttachedTrytes = function(trytesArray) { 249 | 250 | if (!isArray(trytesArray)) return false; 251 | 252 | for (var i = 0; i < trytesArray.length; i++) { 253 | 254 | var tryteValue = trytesArray[i]; 255 | 256 | // Check if correct 2673 trytes 257 | if (!isTrytes(tryteValue, 2673)) { 258 | return false; 259 | } 260 | 261 | var lastTrytes = tryteValue.slice(2673 - (3 * 81)); 262 | 263 | if (/^[9]+$/.test(lastTrytes)) { 264 | return false; 265 | } 266 | } 267 | 268 | return true; 269 | } 270 | 271 | /** 272 | * checks if correct bundle with transaction object 273 | * 274 | * @method isArrayOfTxObjects 275 | * @param {array} bundle 276 | * @returns {boolean} 277 | **/ 278 | var isArrayOfTxObjects = function(bundle) { 279 | 280 | if (!isArray(bundle) || bundle.length === 0) return false; 281 | 282 | var validArray = true; 283 | 284 | bundle.forEach(function(txObject) { 285 | 286 | var keysToValidate = [ 287 | { 288 | key: 'hash', 289 | validator: isHash, 290 | args: null 291 | }, { 292 | key: 'signatureMessageFragment', 293 | validator: isTrytes, 294 | args: 2187 295 | }, { 296 | key: 'address', 297 | validator: isHash, 298 | args: null 299 | }, { 300 | key: 'value', 301 | validator: isValue, 302 | args: null 303 | }, { 304 | key: 'obsoleteTag', 305 | validator: isTrytes, 306 | args: 27 307 | }, { 308 | key: 'timestamp', 309 | validator: isValue, 310 | args: null 311 | }, { 312 | key: 'currentIndex', 313 | validator: isValue, 314 | args: null 315 | },{ 316 | key: 'lastIndex', 317 | validator: isValue, 318 | args: null 319 | }, { 320 | key: 'bundle', 321 | validator: isHash, 322 | args: null 323 | }, { 324 | key: 'trunkTransaction', 325 | validator: isHash, 326 | args: null 327 | }, { 328 | key: 'branchTransaction', 329 | validator: isHash, 330 | args: null 331 | }, { 332 | key: 'tag', 333 | validator: isTrytes, 334 | args: 27 335 | }, { 336 | key: 'attachmentTimestamp', 337 | validator: isValue, 338 | args: null 339 | }, { 340 | key: 'attachmentTimestampLowerBound', 341 | validator: isValue, 342 | args: null 343 | }, { 344 | key: 'attachmentTimestampUpperBound', 345 | validator: isValue, 346 | args: null 347 | }, { 348 | key: 'nonce', 349 | validator: isTrytes, 350 | args: 27 351 | } 352 | ] 353 | 354 | for (var i = 0; i < keysToValidate.length; i++) { 355 | 356 | var key = keysToValidate[i].key; 357 | var validator = keysToValidate[i].validator; 358 | var args = keysToValidate[i].args 359 | 360 | // If input does not have keyIndex and address, return false 361 | if (!txObject.hasOwnProperty(key)) { 362 | validArray = false; 363 | break; 364 | } 365 | 366 | // If input validator function does not return true, exit 367 | if (!validator(txObject[key], args)) { 368 | validArray = false; 369 | break; 370 | } 371 | } 372 | }) 373 | 374 | return validArray; 375 | } 376 | 377 | /** 378 | * checks if correct inputs list 379 | * 380 | * @method isInputs 381 | * @param {array} inputs 382 | * @returns {boolean} 383 | **/ 384 | var isInputs = function(inputs) { 385 | 386 | if (!isArray(inputs)) return false; 387 | 388 | for (var i = 0; i < inputs.length; i++) { 389 | 390 | var input = inputs[i]; 391 | 392 | // If input does not have keyIndex and address, return false 393 | if (!input.hasOwnProperty('security') || !input.hasOwnProperty('keyIndex') || !input.hasOwnProperty('address')) return false; 394 | 395 | if (!isAddress(input.address)) { 396 | return false; 397 | } 398 | 399 | if (!isValue(input.security)) { 400 | return false; 401 | } 402 | 403 | if (!isValue(input.keyIndex)) { 404 | return false; 405 | } 406 | } 407 | 408 | return true; 409 | } 410 | 411 | /** 412 | * Checks that a given uri is valid 413 | * 414 | * Valid Examples: 415 | * udp://[2001:db8:a0b:12f0::1]:14265 416 | * udp://[2001:db8:a0b:12f0::1] 417 | * udp://8.8.8.8:14265 418 | * udp://domain.com 419 | * udp://domain2.com:14265 420 | * 421 | * @method isUri 422 | * @param {string} node 423 | * @returns {bool} valid 424 | **/ 425 | var isUri = function(node) { 426 | 427 | var getInside = /^(udp|tcp):\/\/([\[][^\]\.]*[\]]|[^\[\]:]*)[:]{0,1}([0-9]{1,}$|$)/i; 428 | 429 | var stripBrackets = /[\[]{0,1}([^\[\]]*)[\]]{0,1}/; 430 | 431 | 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*$)/; 432 | 433 | if(!getInside.test(node)) { 434 | return false; 435 | } 436 | 437 | return uriTest.test(stripBrackets.exec(getInside.exec(node)[1])[1]); 438 | } 439 | 440 | module.exports = { 441 | isAddress: isAddress, 442 | isTrytes: isTrytes, 443 | isNinesTrytes: isNinesTrytes, 444 | isValue: isValue, 445 | isHash: isHash, 446 | isTransfersArray: isTransfersArray, 447 | isArrayOfHashes: isArrayOfHashes, 448 | isArrayOfTrytes: isArrayOfTrytes, 449 | isArrayOfAttachedTrytes: isArrayOfAttachedTrytes, 450 | isArrayOfTxObjects: isArrayOfTxObjects, 451 | isInputs: isInputs, 452 | isString: isString, 453 | isNum: isNum, 454 | isArray: isArray, 455 | isObject: isObject, 456 | isUri: isUri 457 | } 458 | -------------------------------------------------------------------------------- /lib/utils/utils.js: -------------------------------------------------------------------------------- 1 | var inputValidator = require("./inputValidator"); 2 | var Curl = require("../crypto/curl/curl"); 3 | var Kerl = require("../crypto/kerl/kerl"); 4 | var Converter = require("../crypto/converter/converter"); 5 | var Signing = require("../crypto/signing/signing"); 6 | var CryptoJS = require("crypto-js"); 7 | var ascii = require("./asciiToTrytes"); 8 | var extractJson = require("./extractJson"); 9 | 10 | 11 | /** 12 | * Table of IOTA Units based off of the standard System of Units 13 | **/ 14 | var unitMap = { 15 | 'i' : 1, 16 | 'Ki' : 1000, 17 | 'Mi' : 1000000, 18 | 'Gi' : 1000000000, 19 | 'Ti' : 1000000000000, 20 | 'Pi' : 1000000000000000 // For the very, very rich 21 | } 22 | 23 | /** 24 | * converts IOTA units 25 | * 26 | * @method convertUnits 27 | * @param {string || int || float} value 28 | * @param {string} fromUnit 29 | * @param {string} toUnit 30 | * @returns {integer} converted 31 | **/ 32 | var convertUnits = function(value, fromUnit, toUnit) { 33 | 34 | // Check if wrong unit provided 35 | if (unitMap[fromUnit] === undefined || unitMap[toUnit] === undefined) { 36 | 37 | throw new Error("Invalid unit provided"); 38 | } 39 | 40 | var afterComma = String(value).match(/\.([\d]+)$/); 41 | 42 | if (afterComma && afterComma[1].length > String(unitMap[fromUnit]).length - 1) { 43 | 44 | throw new Error("Too many digits after comma"); 45 | } 46 | 47 | // If not valid value, throw error 48 | if (!inputValidator.isNum(value)) { 49 | 50 | throw new Error("Invalid value"); 51 | } 52 | 53 | 54 | var floatValue = parseFloat(value); 55 | 56 | var converted = (floatValue * unitMap[fromUnit]) / unitMap[toUnit]; 57 | 58 | return converted; 59 | } 60 | 61 | /** 62 | * Generates the 9-tryte checksum of an address 63 | * 64 | * @method addChecksum 65 | * @param {string | list} inputValue 66 | * @param {int} checksumLength 67 | @ @param {bool} isAddress default is true 68 | * @returns {string | list} address (with checksum) 69 | **/ 70 | var addChecksum = function(inputValue, checksumLength, isAddress) { 71 | 72 | // checksum length is either user defined, or 9 trytes 73 | var checksumLength = checksumLength || 9; 74 | var isAddress = (isAddress !== false); 75 | 76 | // the length of the trytes to be validated 77 | var validationLength = isAddress ? 81 : null; 78 | 79 | var isSingleInput = inputValidator.isString( inputValue ); 80 | 81 | // If only single address, turn it into an array 82 | if ( isSingleInput ) inputValue = new Array( inputValue ); 83 | 84 | var inputsWithChecksum = []; 85 | 86 | inputValue.forEach(function(thisValue) { 87 | 88 | // check if correct trytes 89 | if (!inputValidator.isTrytes(thisValue, validationLength)) { 90 | throw new Error("Invalid input"); 91 | } 92 | 93 | var kerl = new Kerl(); 94 | kerl.initialize(); 95 | 96 | // Address trits 97 | var addressTrits = Converter.trits(thisValue); 98 | 99 | // Checksum trits 100 | var checksumTrits = []; 101 | 102 | // Absorb address trits 103 | kerl.absorb(addressTrits, 0, addressTrits.length); 104 | 105 | // Squeeze checksum trits 106 | kerl.squeeze(checksumTrits, 0, Curl.HASH_LENGTH); 107 | 108 | // First 9 trytes as checksum 109 | var checksum = Converter.trytes( checksumTrits ).substring( 81 - checksumLength, 81 ); 110 | inputsWithChecksum.push( thisValue + checksum ); 111 | }); 112 | 113 | if (isSingleInput) { 114 | 115 | return inputsWithChecksum[ 0 ]; 116 | 117 | } else { 118 | 119 | return inputsWithChecksum; 120 | 121 | } 122 | } 123 | 124 | /** 125 | * Removes the 9-tryte checksum of an address 126 | * 127 | * @method noChecksum 128 | * @param {string | list} address 129 | * @returns {string | list} address (without checksum) 130 | **/ 131 | var noChecksum = function(address) { 132 | 133 | var isSingleAddress = inputValidator.isString(address) 134 | 135 | // If only single address, turn it into an array 136 | if (isSingleAddress) address = new Array(address); 137 | 138 | var addressesWithChecksum = []; 139 | 140 | address.forEach(function(thisAddress) { 141 | addressesWithChecksum.push(thisAddress.slice(0, 81)) 142 | }) 143 | 144 | // return either string or the list 145 | if (isSingleAddress) { 146 | 147 | return addressesWithChecksum[0]; 148 | 149 | } else { 150 | 151 | return addressesWithChecksum; 152 | 153 | } 154 | } 155 | 156 | /** 157 | * Validates the checksum of an address 158 | * 159 | * @method isValidChecksum 160 | * @param {string} addressWithChecksum 161 | * @returns {bool} 162 | **/ 163 | var isValidChecksum = function(addressWithChecksum) { 164 | 165 | var addressWithoutChecksum = noChecksum(addressWithChecksum); 166 | 167 | var newChecksum = addChecksum(addressWithoutChecksum); 168 | 169 | return newChecksum === addressWithChecksum; 170 | } 171 | 172 | /** 173 | * Converts transaction trytes of 2673 trytes into a transaction object 174 | * 175 | * @method transactionObject 176 | * @param {string} trytes 177 | * @returns {String} transactionObject 178 | **/ 179 | var transactionObject = function(trytes) { 180 | 181 | if (!trytes) return; 182 | 183 | // validity check 184 | for (var i = 2279; i < 2295; i++) { 185 | 186 | if (trytes.charAt(i) !== "9") { 187 | 188 | return null; 189 | 190 | } 191 | } 192 | 193 | var thisTransaction = {}; 194 | var transactionTrits = Converter.trits(trytes); 195 | var hash = []; 196 | 197 | var curl = new Curl(); 198 | 199 | // generate the correct transaction hash 200 | curl.initialize(); 201 | curl.absorb(transactionTrits, 0, transactionTrits.length); 202 | curl.squeeze(hash, 0, 243); 203 | 204 | thisTransaction.hash = Converter.trytes(hash); 205 | thisTransaction.signatureMessageFragment = trytes.slice(0, 2187); 206 | thisTransaction.address = trytes.slice(2187, 2268); 207 | thisTransaction.value = Converter.value(transactionTrits.slice(6804, 6837)); 208 | thisTransaction.obsoleteTag = trytes.slice(2295, 2322); 209 | thisTransaction.timestamp = Converter.value(transactionTrits.slice(6966, 6993)); 210 | thisTransaction.currentIndex = Converter.value(transactionTrits.slice(6993, 7020)); 211 | thisTransaction.lastIndex = Converter.value(transactionTrits.slice(7020, 7047)); 212 | thisTransaction.bundle = trytes.slice(2349, 2430); 213 | thisTransaction.trunkTransaction = trytes.slice(2430, 2511); 214 | thisTransaction.branchTransaction = trytes.slice(2511, 2592); 215 | 216 | thisTransaction.tag = trytes.slice(2592, 2619); 217 | thisTransaction.attachmentTimestamp = Converter.value(transactionTrits.slice(7857, 7884)); 218 | thisTransaction.attachmentTimestampLowerBound = Converter.value(transactionTrits.slice(7884, 7911)); 219 | thisTransaction.attachmentTimestampUpperBound = Converter.value(transactionTrits.slice(7911, 7938)); 220 | thisTransaction.nonce = trytes.slice(2646, 2673); 221 | 222 | return thisTransaction; 223 | } 224 | 225 | /** 226 | * Converts a transaction object into trytes 227 | * 228 | * @method transactionTrytes 229 | * @param {object} transactionTrytes 230 | * @returns {String} trytes 231 | **/ 232 | var transactionTrytes = function(transaction) { 233 | 234 | var valueTrits = Converter.trits(transaction.value); 235 | while (valueTrits.length < 81) { 236 | valueTrits[valueTrits.length] = 0; 237 | } 238 | 239 | var timestampTrits = Converter.trits(transaction.timestamp); 240 | while (timestampTrits.length < 27) { 241 | timestampTrits[timestampTrits.length] = 0; 242 | } 243 | 244 | var currentIndexTrits = Converter.trits(transaction.currentIndex); 245 | while (currentIndexTrits.length < 27) { 246 | currentIndexTrits[currentIndexTrits.length] = 0; 247 | } 248 | 249 | var lastIndexTrits = Converter.trits(transaction.lastIndex); 250 | while (lastIndexTrits.length < 27) { 251 | lastIndexTrits[lastIndexTrits.length] = 0; 252 | } 253 | 254 | var attachmentTimestampTrits = Converter.trits(transaction.attachmentTimestamp || 0); 255 | while (attachmentTimestampTrits.length < 27) { 256 | attachmentTimestampTrits[attachmentTimestampTrits.length] = 0; 257 | } 258 | 259 | var attachmentTimestampLowerBoundTrits = Converter.trits(transaction.attachmentTimestampLowerBound || 0); 260 | while (attachmentTimestampLowerBoundTrits.length < 27) { 261 | attachmentTimestampLowerBoundTrits[attachmentTimestampLowerBoundTrits.length] = 0; 262 | } 263 | 264 | var attachmentTimestampUpperBoundTrits = Converter.trits(transaction.attachmentTimestampUpperBound || 0); 265 | while (attachmentTimestampUpperBoundTrits.length < 27) { 266 | attachmentTimestampUpperBoundTrits[attachmentTimestampUpperBoundTrits.length] = 0; 267 | } 268 | 269 | transaction.tag = transaction.tag || transaction.obsoleteTag; 270 | 271 | return transaction.signatureMessageFragment 272 | + transaction.address 273 | + Converter.trytes(valueTrits) 274 | + transaction.obsoleteTag 275 | + Converter.trytes(timestampTrits) 276 | + Converter.trytes(currentIndexTrits) 277 | + Converter.trytes(lastIndexTrits) 278 | + transaction.bundle 279 | + transaction.trunkTransaction 280 | + transaction.branchTransaction 281 | + transaction.tag 282 | + Converter.trytes(attachmentTimestampTrits) 283 | + Converter.trytes(attachmentTimestampLowerBoundTrits) 284 | + Converter.trytes(attachmentTimestampUpperBoundTrits) 285 | + transaction.nonce; 286 | } 287 | 288 | /** 289 | * Categorizes a list of transfers between sent and received 290 | * 291 | * @method categorizeTransfers 292 | * @param {object} transfers Transfers (bundles) 293 | * @param {list} addresses List of addresses that belong to the user 294 | * @returns {String} trytes 295 | **/ 296 | var categorizeTransfers = function(transfers, addresses) { 297 | 298 | var categorized = { 299 | 'sent' : [], 300 | 'received' : [] 301 | } 302 | 303 | // Iterate over all bundles and sort them between incoming and outgoing transfers 304 | transfers.forEach(function(bundle) { 305 | 306 | var spentAlreadyAdded = false; 307 | 308 | // Iterate over every bundle entry 309 | bundle.forEach(function(bundleEntry, bundleIndex) { 310 | 311 | // If bundle address in the list of addresses associated with the seed 312 | // add the bundle to the 313 | if (addresses.indexOf(bundleEntry.address) > -1) { 314 | 315 | // Check if it's a remainder address 316 | var isRemainder = (bundleEntry.currentIndex === bundleEntry.lastIndex) && bundleEntry.lastIndex !== 0; 317 | 318 | // check if sent transaction 319 | if (bundleEntry.value < 0 && !spentAlreadyAdded && !isRemainder) { 320 | 321 | categorized.sent.push(bundle); 322 | 323 | // too make sure we do not add transactions twice 324 | spentAlreadyAdded = true; 325 | } 326 | // check if received transaction, or 0 value (message) 327 | // also make sure that this is not a 2nd tx for spent inputs 328 | else if (bundleEntry.value >= 0 && !spentAlreadyAdded && !isRemainder) { 329 | 330 | categorized.received.push(bundle); 331 | } 332 | } 333 | }) 334 | }) 335 | 336 | return categorized; 337 | } 338 | 339 | 340 | /** 341 | * Validates the signatures 342 | * 343 | * @method validateSignatures 344 | * @param {array} signedBundle 345 | * @param {string} inputAddress 346 | * @returns {bool} 347 | **/ 348 | var validateSignatures = function(signedBundle, inputAddress) { 349 | 350 | 351 | var bundleHash; 352 | var signatureFragments = []; 353 | 354 | for (var i = 0; i < signedBundle.length; i++) { 355 | 356 | if (signedBundle[i].address === inputAddress) { 357 | 358 | bundleHash = signedBundle[i].bundle; 359 | 360 | // if we reached remainder bundle 361 | if (inputValidator.isNinesTrytes(signedBundle[i].signatureMessageFragment)) { 362 | break; 363 | } 364 | 365 | signatureFragments.push(signedBundle[i].signatureMessageFragment) 366 | } 367 | } 368 | 369 | if (!bundleHash) { 370 | return false; 371 | } 372 | 373 | return Signing.validateSignatures(inputAddress, signatureFragments, bundleHash); 374 | } 375 | 376 | 377 | /** 378 | * Checks is a Bundle is valid. Validates signatures and overall structure. Has to be tail tx first. 379 | * 380 | * @method isValidBundle 381 | * @param {array} bundle 382 | * @returns {bool} valid 383 | **/ 384 | var isBundle = function(bundle) { 385 | 386 | // If not correct bundle 387 | if (!inputValidator.isArrayOfTxObjects(bundle)) return false; 388 | 389 | var totalSum = 0, lastIndex, bundleHash = bundle[0].bundle; 390 | 391 | // Prepare to absorb txs and get bundleHash 392 | var bundleFromTxs = []; 393 | 394 | var kerl = new Kerl(); 395 | kerl.initialize(); 396 | 397 | // Prepare for signature validation 398 | var signaturesToValidate = []; 399 | 400 | bundle.forEach(function(bundleTx, index) { 401 | 402 | totalSum += bundleTx.value; 403 | 404 | // currentIndex has to be equal to the index in the array 405 | if (bundleTx.currentIndex !== index) return false; 406 | 407 | // Get the transaction trytes 408 | var thisTxTrytes = transactionTrytes(bundleTx); 409 | 410 | // Absorb bundle hash + value + timestamp + lastIndex + currentIndex trytes. 411 | var thisTxTrits = Converter.trits(thisTxTrytes.slice(2187, 2187 + 162)); 412 | kerl.absorb(thisTxTrits, 0, thisTxTrits.length); 413 | 414 | // Check if input transaction 415 | if (bundleTx.value < 0) { 416 | var thisAddress = bundleTx.address; 417 | 418 | var newSignatureToValidate = { 419 | 'address': thisAddress, 420 | 'signatureFragments': Array(bundleTx.signatureMessageFragment) 421 | } 422 | 423 | // Find the subsequent txs with the remaining signature fragment 424 | for (var i = index; i < bundle.length - 1; i++) { 425 | var newBundleTx = bundle[i + 1]; 426 | 427 | // Check if new tx is part of the signature fragment 428 | if (newBundleTx.address === thisAddress && newBundleTx.value === 0) { 429 | newSignatureToValidate.signatureFragments.push(newBundleTx.signatureMessageFragment); 430 | } 431 | } 432 | 433 | signaturesToValidate.push(newSignatureToValidate); 434 | } 435 | }); 436 | 437 | // Check for total sum, if not equal 0 return error 438 | if (totalSum !== 0) return false; 439 | 440 | // get the bundle hash from the bundle transactions 441 | kerl.squeeze(bundleFromTxs, 0, Curl.HASH_LENGTH); 442 | var bundleFromTxs = Converter.trytes(bundleFromTxs); 443 | 444 | // Check if bundle hash is the same as returned by tx object 445 | if (bundleFromTxs !== bundleHash) return false; 446 | 447 | // Last tx in the bundle should have currentIndex === lastIndex 448 | if (bundle[bundle.length - 1].currentIndex !== bundle[bundle.length - 1].lastIndex) return false; 449 | 450 | // Validate the signatures 451 | for (var i = 0; i < signaturesToValidate.length; i++) { 452 | 453 | var isValidSignature = Signing.validateSignatures(signaturesToValidate[i].address, signaturesToValidate[i].signatureFragments, bundleHash); 454 | 455 | if (!isValidSignature) return false; 456 | } 457 | 458 | return true; 459 | } 460 | 461 | module.exports = { 462 | inputValidator : inputValidator, 463 | convertUnits : convertUnits, 464 | addChecksum : addChecksum, 465 | noChecksum : noChecksum, 466 | isValidChecksum : isValidChecksum, 467 | transactionObject : transactionObject, 468 | transactionTrytes : transactionTrytes, 469 | categorizeTransfers : categorizeTransfers, 470 | toTrytes : ascii.toTrytes, 471 | fromTrytes : ascii.fromTrytes, 472 | extractJson : extractJson, 473 | validateSignatures : validateSignatures, 474 | isBundle : isBundle 475 | } 476 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iota.crypto.js", 3 | "version": "0.4.2", 4 | "description": "Javascript Crypto Library for IOTA", 5 | "main": "./lib/iota.crypto.js", 6 | "scripts": { 7 | "build": "gulp", 8 | "test": "mocha" 9 | }, 10 | "authors": [ 11 | { 12 | "name": "Dominik Schiener (IOTA Foundation)", 13 | "website": "https://iota.org" 14 | }, 15 | { 16 | "name": "Paul Handy (IOTA Foundation)", 17 | "website": "https://iota.org" 18 | } 19 | ], 20 | "keywords": [ 21 | "iota", 22 | "crypto", 23 | "tangle", 24 | "library", 25 | "browser", 26 | "javascript", 27 | "nodejs" 28 | ], 29 | "license": "MIT", 30 | "bugs": { 31 | "url": "https://github.com/iotaledger/iota.crypto.js/issues" 32 | }, 33 | "repository": { 34 | "type": "git", 35 | "url": "https://github.com/iotaledger/iota.crypto.js.git" 36 | }, 37 | "dependencies": { 38 | "crypto-js": "^3.1.9-1" 39 | }, 40 | "devDependencies": { 41 | "bower": ">=1.8.0", 42 | "browserify": ">=14.1.0", 43 | "chai": "^4.0.2", 44 | "del": "^3.0.0", 45 | "gulp": "^3.9.1", 46 | "gulp-jshint": "^2.0.2", 47 | "gulp-nsp": ">=2.4.2", 48 | "gulp-rename": ">=1.2.2", 49 | "gulp-replace": "^0.6.1", 50 | "gulp-uglify": "^3.0.0", 51 | "jshint": "^2.9.4", 52 | "mocha": "^3.2.0", 53 | "vinyl-buffer": "^1.0.0", 54 | "vinyl-source-stream": "^1.1.0" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /test/kerl/kerl.absorb-multi-squeeze.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var Converter = require('../../lib/crypto/converter/converter'); 4 | var Kerl = require('../../lib/crypto/kerl/kerl'); 5 | 6 | describe('kerl.absorb-multi-squeeze', function() { 7 | 8 | var tests = [{ 9 | input: '9MIDYNHBWMBCXVDEFOFWINXTERALUKYYPPHKP9JJFGJEIUY9MUDVNFZHMMWZUYUSWAIOWEVTHNWMHANBH', 10 | expected: 'G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJBVBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA' 11 | }]; 12 | 13 | tests.forEach(function(test){ 14 | 15 | it('Should produce valid hash: ' + test.expected, function() { 16 | var trits = Converter.trits(test.input); 17 | var kerl = new Kerl(); 18 | kerl.initialize(); 19 | kerl.absorb(trits, 0, trits.length); 20 | var hashTrits = []; 21 | kerl.squeeze(hashTrits, 0, Kerl.HASH_LENGTH * 2); 22 | var hash = Converter.trytes(hashTrits); 23 | assert.deepEqual(test.expected, hash); 24 | }); 25 | 26 | }); 27 | 28 | }); 29 | -------------------------------------------------------------------------------- /test/kerl/kerl.absorb-squeeze.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var Converter = require('../../lib/crypto/converter/converter'); 4 | var Kerl = require('../../lib/crypto/kerl/kerl'); 5 | 6 | describe('kerl.absorb-squeeze', function() { 7 | 8 | var tests = [{ 9 | input: 'GYOMKVTSNHVJNCNFBBAH9AAMXLPLLLROQY99QN9DLSJUHDPBLCFFAIQXZA9BKMBJCYSFHFPXAHDWZFEIZ', 10 | expected: 'OXJCNFHUNAHWDLKKPELTBFUCVW9KLXKOGWERKTJXQMXTKFKNWNNXYD9DMJJABSEIONOSJTTEVKVDQEWTW' 11 | }]; 12 | 13 | tests.forEach(function(test){ 14 | 15 | it('Should produce valid hash: ' + test.expected, function() { 16 | var trits = Converter.trits(test.input); 17 | var kerl = new Kerl(); 18 | kerl.initialize(); 19 | kerl.absorb(trits, 0, trits.length); 20 | var hashTrits = []; 21 | kerl.squeeze(hashTrits, 0, Kerl.HASH_LENGTH); 22 | var hash = Converter.trytes(hashTrits); 23 | assert.deepEqual(test.expected, hash); 24 | }); 25 | 26 | }); 27 | 28 | }); 29 | -------------------------------------------------------------------------------- /test/kerl/kerl.multi-absorb-multi-squeeze.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var Converter = require('../../lib/crypto/converter/converter'); 4 | var Kerl = require('../../lib/crypto/kerl/kerl'); 5 | 6 | describe('kerl.multi-absorb-multi-squeeze', function() { 7 | 8 | var tests = [{ 9 | input: 'G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJBVBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA', 10 | expected: 'LUCKQVACOGBFYSPPVSSOXJEKNSQQRQKPZC9NXFSMQNRQCGGUL9OHVVKBDSKEQEBKXRNUJSRXYVHJTXBPDWQGNSCDCBAIRHAQCOWZEBSNHIJIGPZQITIBJQ9LNTDIBTCQ9EUWKHFLGFUVGGUWJONK9GBCDUIMAYMMQX' 11 | }]; 12 | 13 | tests.forEach(function(test){ 14 | 15 | it('Should produce valid hash: ' + test.expected, function() { 16 | var trits = Converter.trits(test.input); 17 | var kerl = new Kerl(); 18 | kerl.initialize(); 19 | kerl.absorb(trits, 0, trits.length); 20 | var hashTrits = []; 21 | kerl.squeeze(hashTrits, 0, Kerl.HASH_LENGTH * 2); 22 | var hash = Converter.trytes(hashTrits); 23 | assert.deepEqual(test.expected, hash); 24 | }); 25 | 26 | }); 27 | 28 | }); 29 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --reporter spec --recursive 2 | -------------------------------------------------------------------------------- /test/utils/utils.checksum.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var Utils = require('../../lib/utils/utils.js'); 4 | 5 | describe('utils.checksum', function() { 6 | 7 | var tests = [ 8 | { 9 | addressWithChecksum: 'UYEEERFQYTPFAHIPXDQAQYWYMSMCLMGBTYAXLWFRFFWPYFOICOVLK9A9VYNCKK9TQUNBTARCEQXJHD9VYXOEDEOMRC' 10 | } 11 | ] 12 | 13 | tests.forEach(function(test) { 14 | 15 | it('should validate checksum: ' + test.addressWithChecksum, function() { 16 | 17 | var isValidChecksum = Utils.isValidChecksum(test.addressWithChecksum); 18 | 19 | assert.equal(isValidChecksum, true); 20 | }); 21 | }) 22 | }); 23 | -------------------------------------------------------------------------------- /test/utils/utils.convertUnits.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var Utils = require('../../lib/utils/utils.js'); 4 | 5 | 6 | describe('utils.convertUnits', function() { 7 | 8 | var tests = [ 9 | { 10 | value: 100, 11 | fromUnit: 'Gi', 12 | toUnit: 'i', 13 | expected: 100000000000 14 | }, 15 | { 16 | value: 10.1, 17 | fromUnit: 'Gi', 18 | toUnit: 'i', 19 | expected: 10100000000 20 | }, 21 | { 22 | value: '10.1000', 23 | fromUnit: 'Gi', 24 | toUnit: 'i', 25 | expected: 10100000000 26 | }, 27 | { 28 | value: 1, 29 | fromUnit: 'i', 30 | toUnit: 'Ti', 31 | expected: 0.000000000001 32 | }, 33 | { 34 | value: 1, 35 | fromUnit: 'Ti', 36 | toUnit: 'i', 37 | expected: 1000000000000 38 | }, 39 | { 40 | value: 1000, 41 | fromUnit: 'Gi', 42 | toUnit: 'Ti', 43 | expected: 1 44 | } 45 | ] 46 | 47 | tests.forEach(function(test) { 48 | 49 | it('should convert: ' + test.value + ' ' + test.fromUnit + ' to ' + test.expected + ' ' + test.toUnit, function() { 50 | 51 | var converted = Utils.convertUnits(test.value, test.fromUnit, test.toUnit); 52 | 53 | assert.equal(converted, test.expected); 54 | }); 55 | }) 56 | }); 57 | -------------------------------------------------------------------------------- /test/utils/utils.extractJson.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var Utils = require('../../lib/utils/utils.js'); 4 | 5 | describe('utils.extractJson', function() { 6 | 7 | var tests = [ 8 | // JSON in a single transaction 9 | { 10 | bundle: [ 11 | { 12 | "signatureMessageFragment":"ODEALAPCLAEADBEALAQCLAQAEALARCLADBEALASCLAQAEALATCLADBEALAHAPCGDSCUCSCIBIALAEAQD9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" 13 | } 14 | ], 15 | expectedTrytes: "ODEALAPCLAEADBEALAQCLAQAEALARCLADBEALASCLAQAEALATCLADBEALAHAPCGDSCUCSCIBIALAEAQD", 16 | expectedJson: "{ 'a' : 'b', 'c': 'd', 'e': '#asdfd?$' }" 17 | }, 18 | // empty JSON {} 19 | { 20 | bundle: [ 21 | { 22 | "signatureMessageFragment":"ODQD99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" 23 | } 24 | ], 25 | expectedTrytes: "ODQD", 26 | expectedJson: "{}" 27 | }, 28 | // Nested JSON with array 29 | { 30 | bundle: [ 31 | { 32 | "signatureMessageFragment":"ODEALAPCLAEADBEALAQCLAQAEALARCLADBEAODLABDTCGDHDTCSCLADBEALAYCGDCDBDLAQAEALAADIDRCWCLADBEALAKDCDKDLAQAEALAPCFDFDPCMDLADBEAJCEAHDFDIDTCQAEAUCPC9DGDTCQAEALAMDTCGDLAEALCEAQDEAQD999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" 33 | } 34 | ], 35 | expectedTrytes: "ODEALAPCLAEADBEALAQCLAQAEALARCLADBEAODLABDTCGDHDTCSCLADBEALAYCGDCDBDLAQAEALAADIDRCWCLADBEALAKDCDKDLAQAEALAPCFDFDPCMDLADBEAJCEAHDFDIDTCQAEAUCPC9DGDTCQAEALAMDTCGDLAEALCEAQDEAQD", 36 | expectedJson: "{ 'a' : 'b', 'c': {'nested': 'json', 'much': 'wow', 'array': [ true, false, 'yes' ] } }" 37 | }, 38 | // Message which exceeds the 2187 trytes limit and as such requires multiple transactions 39 | { 40 | bundle: [ 41 | { 42 | signatureMessageFragment: 'ODLAADTCGDGDPCVCTCLADBEALASBYBCCKBEAXCGDEAPCEAFDTCJDCD9DIDHDXCCDBDPCFDMDEABDTCKDEAHDFDPCBDGDPCRCHDXCCDBDPC9DEAGDTCHDHD9DTCADTCBDHDEAPCBDSCEASCPCHDPCEAHDFDPCBDGDUCTCFDEA9DPCMDTCFDEAUCCDFDEAHDWCTCEASBBDHDTCFDBDTCHDEACDUCEACCWCXCBDVCGDSAEASBHDLAGDEAQCPCGDTCSCEACDBDEAPCEABDTCKDEASCXCGDHDFDXCQCIDHDTCSCEA9DTCSCVCTCFDQAEAHDWCTCEACCPCBDVC9DTCQAEAKDWCXCRCWCEACDJDTCFDRCCDADTCGDEAHDWCTCEAXCBDTCUCUCXCRCXCTCBDRCXCTCGDEACDUCEARCIDFDFDTCBDHDEALB9DCDRCZCRCWCPCXCBDEASCTCGDXCVCBDGDEAPCBDSCEAXCBDHDFDCDSCIDRCTCGDEAPCEABDTCKDEAKDPCMDEACDUCEAFDTCPCRCWCXCBDVCEARCCDBDGDTCBDGDIDGDEAXCBDEAPCEASCTCRCTCBDHDFDPC9DXCNDTCSCEADDTCTCFDRAHDCDRADDTCTCFDEAGDMDGDHDTCADSAEAPBCDFDEAHDWCTCEAUCXCFDGDHDEAHDXCADTCEATCJDTCFDQAEAHDWCFDCDIDVCWCEASBYBCCKBEADDTCCDDD9DTCEARCPCBDEAHDFDPCBDGDUCTCFDEAADCDBDTCMDEAKDXCHDWCCDIDHDEAPCBDMDEAUCTCTCGDSAEACCWCXCGDEAADTCPCBDGDEAHDWCPCHDEATCJDTCBDEAXCBDUCXCBDXCHDTCGDXCADPC9D9DMDEAGDADPC9D9DEABDPCBDCDDDPCMDADTCBDHDGDEARCPCBDEAQCTCEAADPCSCTCEAHDWCFDCDIDVCWCEASBYBCCKBSAEASBYBCCKBEAXCGDEAHDWCTCEAADXCGDGDXCBDVCEADDIDNDND9DTCEADDXCTCRCTCEAUCCDFDEAHDWCTCEAWBPCRCWCXCBDTCEAOBRCCDBDCDADMDEAHDCDEAUCID9D9DMDEATCADTCFDVCTCEAPCBDSCEAFDTCPCRCWCEAXCHDGDEASCTCGDXCFDTCSCEADDCDHDTCBDHDXCPC9DSAEAFCTCEATCBDJDXCGDXCCDBDEASBYBCCKBEAHDCDEAQCTCEAHDWCTCEADDIDQC9DXCRCQAEADDTCFDADXCGDGDXCCDBD9DTCGDGDEAQCPCRCZCQCCDBDTCEAUCCDFDEAHDWCTCEASBBDHDTCFDBDTCHDEACDUCEACCWCXCBDVCGDEAHDWCPCHDEATCBDPCQC9DTCGDEAHDFDIDTCEAXCBDHDTCFDCDDDTCFDPCQCXC9DXCHDMDEAQCTCHDKDTCTCBDEAPC9D9DEASCTCJDXCRCTCGDSAEACCPCBDVC9DTCDBEAKBEASCXCFDTCRCHDTCSCEAPCRCMDRC9DXCRCEAVCFDPCDDWCEAMANBKBQBNAEAPCGDEAPCEASCXCGDHDFDXCQCIDHDTCSCEA9DTCSCVCTCFDEAKDWCXCRCWCEAGDHDCDFDTCGDEAPC9D9DEAHDFDPCBDGDPCRCHDXCCDBDEASCPCHDPCEACDUCEAHDWCTCEASBYBCCKBEABDTCHDKDCDFDZCSAEASBHDEAXCGDEAPCEALB9DCDRCZCRCWCPCXCBDEAKDXCHDWCCDIDHDEAHDWCTCEAQC9DCDRCZCGDEAPCBDSCEAHDWCTCEARCWCPCXCBDEAMAGDCDEAXCGDEAXCHDEAFDTCPC9D9DMDEAPCEALB9DCDRCZCRCWCPCXCBDIBNASAEACCWCTCEACCPCBDVC9DTCEAXCGDEAHDWCTCEAUCXCFDGDHDEASCXCGDHDFDXCQCIDHDTCSCEA9DTCSCVCTCFDEAHDCDEAPCRCWCXCTCJDTCEAGDRCPC9DPCQCXC9DXCHDMDQAEABDCDEAUCTCTCEAHDFDPCBDGDPCRCHDXCCDBDGDQAEASCPCHDPCEAXCBDHDTCVCFDXCHDMDEAPCBDSCEAHDFDPCBDGDADXCGDGDXCCDBDEAPCGDEAKDTC9D9DEAPCGDEAEDIDPCBDHDIDADRARCCDADDDIDHDXCBDVCEADDFDCDHDTCRCHDX' 43 | }, 44 | { 45 | signatureMessageFragment: 'CCDBDSAEAMBCDBDHDFDPCFDMDEAHDCDEAHDCDSCPCMDLAGDEALB9DCDRCZCRCWCPCXCBDGDQAEARCCDBDGDTCBDGDIDGDEAXCGDEABDCDRA9DCDBDVCTCFDEASCTCRCCDIDDD9DTCSCEAQCIDHDEAXCBDGDHDTCPCSCEAPCBDEAXCBDHDFDXCBDGDXCRCEADDPCFDHDEACDUCEAHDWCTCEAGDMDGDHDTCADQAEA9DTCPCSCXCBDVCEAHDCDEAPCEARCCDADDD9DTCHDTC9DMDEASCTCRCTCBDHDFDPC9DXCNDTCSCEAPCBDSCEAGDTC9DUCRAFDTCVCID9DPCHDXCBDVCEADDTCTCFDRAHDCDRADDTCTCFDEABDTCHDKDCDFDZCSAEAKB9D9DEASBYBCCKBLAGDEAKDWCXCRCWCEAKDXC9D9DEATCJDTCFDEATCLDXCGDHDEAWCPCJDTCEAQCTCTCBDEARCFDTCPCHDTCSCEAKDXCHDWCEAHDWCTCEAVCTCBDTCGDXCGDEAHDFDPCBDGDPCRCHDXCCDBDSAEACCWCXCGDEAADTCPCBDGDEAHDWCPCHDEAHDWCTCEAHDCDHDPC9DEAGDIDDDDD9DMDEACDUCEASBYBCCKBLAGDEAKDXC9D9DEAPC9DKDPCMDGDEAGDHDPCMDEAHDWCTCEAGDPCADTCEAPCBDSCEAMDCDIDEARCPCBDBDCDHDEAADXCBDTCEASBYBCCKBLAGDSAEACCWCTCFDTCUCCDFDTCEAZCTCTCDDEAXCBDEAADXCBDSCQAEAXCUCEAMDCDIDEASCCDEAZBFDCDCDUCEACDUCEAFCCDFDZCEAXCBDEASBYBCCKBEAMDCDIDEAPCFDTCEABDCDHDEAVCTCBDTCFDPCHDXCBDVCEABDTCKDEASBYBCCKBEAHDCDZCTCBDGDQAEAMDCDIDLAFDTCEAGDXCADDD9DMDEAJDTCFDXCUCMDXCBDVCEACDHDWCTCFDEAHDFDPCBDGDPCRCHDXCCDBDGDSALAQD999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999' 46 | } 47 | ], 48 | expectedTrytes: "ODLAADTCGDGDPCVCTCLADBEALASBYBCCKBEAXCGDEAPCEAFDTCJDCD9DIDHDXCCDBDPCFDMDEABDTCKDEAHDFDPCBDGDPCRCHDXCCDBDPC9DEAGDTCHDHD9DTCADTCBDHDEAPCBDSCEASCPCHDPCEAHDFDPCBDGDUCTCFDEA9DPCMDTCFDEAUCCDFDEAHDWCTCEASBBDHDTCFDBDTCHDEACDUCEACCWCXCBDVCGDSAEASBHDLAGDEAQCPCGDTCSCEACDBDEAPCEABDTCKDEASCXCGDHDFDXCQCIDHDTCSCEA9DTCSCVCTCFDQAEAHDWCTCEACCPCBDVC9DTCQAEAKDWCXCRCWCEACDJDTCFDRCCDADTCGDEAHDWCTCEAXCBDTCUCUCXCRCXCTCBDRCXCTCGDEACDUCEARCIDFDFDTCBDHDEALB9DCDRCZCRCWCPCXCBDEASCTCGDXCVCBDGDEAPCBDSCEAXCBDHDFDCDSCIDRCTCGDEAPCEABDTCKDEAKDPCMDEACDUCEAFDTCPCRCWCXCBDVCEARCCDBDGDTCBDGDIDGDEAXCBDEAPCEASCTCRCTCBDHDFDPC9DXCNDTCSCEADDTCTCFDRAHDCDRADDTCTCFDEAGDMDGDHDTCADSAEAPBCDFDEAHDWCTCEAUCXCFDGDHDEAHDXCADTCEATCJDTCFDQAEAHDWCFDCDIDVCWCEASBYBCCKBEADDTCCDDD9DTCEARCPCBDEAHDFDPCBDGDUCTCFDEAADCDBDTCMDEAKDXCHDWCCDIDHDEAPCBDMDEAUCTCTCGDSAEACCWCXCGDEAADTCPCBDGDEAHDWCPCHDEATCJDTCBDEAXCBDUCXCBDXCHDTCGDXCADPC9D9DMDEAGDADPC9D9DEABDPCBDCDDDPCMDADTCBDHDGDEARCPCBDEAQCTCEAADPCSCTCEAHDWCFDCDIDVCWCEASBYBCCKBSAEASBYBCCKBEAXCGDEAHDWCTCEAADXCGDGDXCBDVCEADDIDNDND9DTCEADDXCTCRCTCEAUCCDFDEAHDWCTCEAWBPCRCWCXCBDTCEAOBRCCDBDCDADMDEAHDCDEAUCID9D9DMDEATCADTCFDVCTCEAPCBDSCEAFDTCPCRCWCEAXCHDGDEASCTCGDXCFDTCSCEADDCDHDTCBDHDXCPC9DSAEAFCTCEATCBDJDXCGDXCCDBDEASBYBCCKBEAHDCDEAQCTCEAHDWCTCEADDIDQC9DXCRCQAEADDTCFDADXCGDGDXCCDBD9DTCGDGDEAQCPCRCZCQCCDBDTCEAUCCDFDEAHDWCTCEASBBDHDTCFDBDTCHDEACDUCEACCWCXCBDVCGDEAHDWCPCHDEATCBDPCQC9DTCGDEAHDFDIDTCEAXCBDHDTCFDCDDDTCFDPCQCXC9DXCHDMDEAQCTCHDKDTCTCBDEAPC9D9DEASCTCJDXCRCTCGDSAEACCPCBDVC9DTCDBEAKBEASCXCFDTCRCHDTCSCEAPCRCMDRC9DXCRCEAVCFDPCDDWCEAMANBKBQBNAEAPCGDEAPCEASCXCGDHDFDXCQCIDHDTCSCEA9DTCSCVCTCFDEAKDWCXCRCWCEAGDHDCDFDTCGDEAPC9D9DEAHDFDPCBDGDPCRCHDXCCDBDEASCPCHDPCEACDUCEAHDWCTCEASBYBCCKBEABDTCHDKDCDFDZCSAEASBHDEAXCGDEAPCEALB9DCDRCZCRCWCPCXCBDEAKDXCHDWCCDIDHDEAHDWCTCEAQC9DCDRCZCGDEAPCBDSCEAHDWCTCEARCWCPCXCBDEAMAGDCDEAXCGDEAXCHDEAFDTCPC9D9DMDEAPCEALB9DCDRCZCRCWCPCXCBDIBNASAEACCWCTCEACCPCBDVC9DTCEAXCGDEAHDWCTCEAUCXCFDGDHDEASCXCGDHDFDXCQCIDHDTCSCEA9DTCSCVCTCFDEAHDCDEAPCRCWCXCTCJDTCEAGDRCPC9DPCQCXC9DXCHDMDQAEABDCDEAUCTCTCEAHDFDPCBDGDPCRCHDXCCDBDGDQAEASCPCHDPCEAXCBDHDTCVCFDXCHDMDEAPCBDSCEAHDFDPCBDGDADXCGDGDXCCDBDEAPCGDEAKDTC9D9DEAPCGDEAEDIDPCBDHDIDADRARCCDADDDIDHDXCBDVCEADDFDCDHDTCRCHDXCCDBDSAEAMBCDBDHDFDPCFDMDEAHDCDEAHDCDSCPCMDLAGDEALB9DCDRCZCRCWCPCXCBDGDQAEARCCDBDGDTCBDGDIDGDEAXCGDEABDCDRA9DCDBDVCTCFDEASCTCRCCDIDDD9DTCSCEAQCIDHDEAXCBDGDHDTCPCSCEAPCBDEAXCBDHDFDXCBDGDXCRCEADDPCFDHDEACDUCEAHDWCTCEAGDMDGDHDTCADQAEA9DTCPCSCXCBDVCEAHDCDEAPCEARCCDADDD9DTCHDTC9DMDEASCTCRCTCBDHDFDPC9DXCNDTCSCEAPCBDSCEAGDTC9DUCRAFDTCVCID9DPCHDXCBDVCEADDTCTCFDRAHDCDRADDTCTCFDEABDTCHDKDCDFDZCSAEAKB9D9DEASBYBCCKBLAGDEAKDWCXCRCWCEAKDXC9D9DEATCJDTCFDEATCLDXCGDHDEAWCPCJDTCEAQCTCTCBDEARCFDTCPCHDTCSCEAKDXCHDWCEAHDWCTCEAVCTCBDTCGDXCGDEAHDFDPCBDGDPCRCHDXCCDBDSAEACCWCXCGDEAADTCPCBDGDEAHDWCPCHDEAHDWCTCEAHDCDHDPC9DEAGDIDDDDD9DMDEACDUCEASBYBCCKBLAGDEAKDXC9D9DEAPC9DKDPCMDGDEAGDHDPCMDEAHDWCTCEAGDPCADTCEAPCBDSCEAMDCDIDEARCPCBDBDCDHDEAADXCBDTCEASBYBCCKBLAGDSAEACCWCTCFDTCUCCDFDTCEAZCTCTCDDEAXCBDEAADXCBDSCQAEAXCUCEAMDCDIDEASCCDEAZBFDCDCDUCEACDUCEAFCCDFDZCEAXCBDEASBYBCCKBEAMDCDIDEAPCFDTCEABDCDHDEAVCTCBDTCFDPCHDXCBDVCEABDTCKDEASBYBCCKBEAHDCDZCTCBDGDQAEAMDCDIDLAFDTCEAGDXCADDD9DMDEAJDTCFDXCUCMDXCBDVCEACDHDWCTCFDEAHDFDPCBDGDPCRCHDXCCDBDGDSALAQD", 49 | expectedJson: "{'message': 'IOTA is a revolutionary new transactional settlement and data transfer layer for the Internet of Things. It's based on a new distributed ledger, the Tangle, which overcomes the inefficiencies of current Blockchain designs and introduces a new way of reaching consensus in a decentralized peer-to-peer system. For the first time ever, through IOTA people can transfer money without any fees. This means that even infinitesimally small nanopayments can be made through IOTA. IOTA is the missing puzzle piece for the Machine Economy to fully emerge and reach its desired potential. We envision IOTA to be the public, permissionless backbone for the Internet of Things that enables true interoperability between all devices. Tangle: A directed acyclic graph (DAG) as a distributed ledger which stores all transaction data of the IOTA network. It is a Blockchain without the blocks and the chain (so is it really a Blockchain?). The Tangle is the first distributed ledger to achieve scalability, no fee transactions, data integrity and transmission as well as quantum-computing protection. Contrary to today's Blockchains, consensus is no-longer decoupled but instead an intrinsic part of the system, leading to a completely decentralized and self-regulating peer-to-peer network. All IOTA\'s which will ever exist have been created with the genesis transaction. This means that the total supply of IOTA\'s will always stay the same and you cannot mine IOTA\'s. Therefore keep in mind, if you do Proof of Work in IOTA you are not generating new IOTA tokens, you\'re simply verifying other transactions.'}" 50 | }, 51 | // Message which exceeds the 2187 trytes limit and as such requires multiple transactions. Different length 52 | { 53 | bundle: [ 54 | { 55 | signatureMessageFragment: 'ODLAADTCGDGDPCVCTCLADBEALASBYBCCKBEAXCGDEAPCEAFDTCJDCD9DIDHDXCCDBDPCFDMDEABDTCKDEAHDFDPCBDGDPCRCHDXCCDBDPC9DEAGDTCHDHD9DTCADTCBDHDEAPCBDSCEASCPCHDPCEAHDFDPCBDGDUCTCFDEA9DPCMDTCFDEAUCCDFDEAHDWCTCEASBBDHDTCFDBDTCHDEACDUCEACCWCXCBDVCGDSAEASBHDLAGDEAQCPCGDTCSCEACDBDEAPCEABDTCKDEASCXCGDHDFDXCQCIDHDTCSCEA9DTCSCVCTCFDQAEAHDWCTCEACCPCBDVC9DTCQAEAKDWCXCRCWCEACDJDTCFDRCCDADTCGDEAHDWCTCEAXCBDTCUCUCXCRCXCTCBDRCXCTCGDEACDUCEARCIDFDFDTCBDHDEALB9DCDRCZCRCWCPCXCBDEASCTCGDXCVCBDGDEAPCBDSCEAXCBDHDFDCDSCIDRCTCGDEAPCEABDTCKDEAKDPCMDEACDUCEAFDTCPCRCWCXCBDVCEARCCDBDGDTCBDGDIDGDEAXCBDEAPCEASCTCRCTCBDHDFDPC9DXCNDTCSCEADDTCTCFDRAHDCDRADDTCTCFDEAGDMDGDHDTCADSAEAPBCDFDEAHDWCTCEAUCXCFDGDHDEAHDXCADTCEATCJDTCFDQAEAHDWCFDCDIDVCWCEASBYBCCKBEADDTCCDDD9DTCEARCPCBDEAHDFDPCBDGDUCTCFDEAADCDBDTCMDEAKDXCHDWCCDIDHDEAPCBDMDEAUCTCTCGDSAEACCWCXCGDEAADTCPCBDGDEAHDWCPCHDEATCJDTCBDEAXCBDUCXCBDXCHDTCGDXCADPC9D9DMDEAGDADPC9D9DEABDPCBDCDDDPCMDADTCBDHDGDEARCPCBDEAQCTCEAADPCSCTCEAHDWCFDCDIDVCWCEASBYBCCKBSAEASBYBCCKBEAXCGDEAHDWCTCEAADXCGDGDXCBDVCEADDIDNDND9DTCEADDXCTCRCTCEAUCCDFDEAHDWCTCEAWBPCRCWCXCBDTCEAOBRCCDBDCDADMDEAHDCDEAUCID9D9DMDEATCADTCFDVCTCEAPCBDSCEAFDTCPCRCWCEAXCHDGDEASCTCGDXCFDTCSCEADDCDHDTCBDHDXCPC9DSAEAFCTCEATCBDJDXCGDXCCDBDEASBYBCCKBEAHDCDEAQCTCEAHDWCTCEADDIDQC9DXCRCQAEADDTCFDADXCGDGDXCCDBD9DTCGDGDEAQCPCRCZCQCCDBDTCEAUCCDFDEAHDWCTCEASBBDHDTCFDBDTCHDEACDUCEACCWCXCBDVCGDEAHDWCPCHDEATCBDPCQC9DTCGDEAHDFDIDTCEAXCBDHDTCFDCDDDTCFDPCQCXC9DXCHDMDEAQCTCHDKDTCTCBDEAPC9D9DEASCTCJDXCRCTCGDSAEACCPCBDVC9DTCDBEAKBEASCXCFDTCRCHDTCSCEAPCRCMDRC9DXCRCEAVCFDPCDDWCEAMANBKBQBNAEAPCGDEAPCEASCXCGDHDFDXCQCIDHDTCSCEA9DTCSCVCTCFDEAKDWCXCRCWCEAGDHDCDFDTCGDEAPC9D9DEAHDFDPCBDGDPCRCHDXCCDBDEASCPCHDPCEACDUCEAHDWCTCEASBYBCCKBEABDTCHDKDCDFDZCSAEASBHDEAXCGDEAPCEALB9DCDRCZCRCWCPCXCBDEAKDXCHDWCCDIDHDEAHDWCTCEAQC9DCDRCZCGDEAPCBDSCEAHDWCTCEARCWCPCXCBDEAMAGDCDEAXCGDEAXCHDEAFDTCPC9D9DMDEAPCEALB9DCDRCZCRCWCPCXCBDIBNASAEACCWCTCEACCPCBDVC9DTCEAXCGDEAHDWCTCEAUCXCFDGDHDEASCXCGDHDFDXCQCIDHDTCSCEA9DTCSCVCTCFDEAHDCDEAPCRCWCXCTCJDTCEAGDRCPC9DPCQCXC9DXCHDMDQAEABDCDEAUCTCTCEAHDFDPCBDGDPCRCHDXCCDBDGDQAEASCPCHDPCEAXCBDHDTCVCFDXCHDMDEAPCBDSCEAHDFDPCBDGDADXCGDGDXCCDBDEAPCGDEAKDTC9D9DEAPCGDEAEDIDPCBDHDIDADRARCCDADDDIDHDXCBDVCEADDFDCDHDTCRCHDX' 56 | }, 57 | { 58 | signatureMessageFragment: 'CCDBDSAEAMBCDBDHDFDPCFDMDEAHDCDEAHDCDSCPCMDLAGDEALB9DCDRCZCRCWCPCXCBDGDQAEARCCDBDGDTCBDGDIDGDEAXCGDEABDCDRA9DCDBDVCTCFDEASCTCRCCDIDDD9DTCSCEAQCIDHDEAXCBDGDHDTCPCSCEAPCBDEAXCBDHDFDXCBDGDXCRCEADDPCFDHDEACDUCEAHDWCTCEAGDMDGDHDTCADQAEA9DTCPCSCXCBDVCEAHDCDEAPCEARCCDADDD9DTCHDTC9DMDEASCTCRCTCBDHDFDPC9DXCNDTCSCEAPCBDSCEAGDTC9DUCRAFDTCVCID9DPCHDXCBDVCEADDTCTCFDRAHDCDRADDTCTCFDEABDTCHDKDCDFDZCSAEAKB9D9DEASBYBCCKBLAGDEAKDWCXCRCWCEAKDXC9D9DEATCJDTCFDEATCLDXCGDHDEAWCPCJDTCEAQCTCTCBDEARCFDTCPCHDTCSCEAKDXCHDWCEAHDWCTCEAVCTCBDTCGDXCGDEAHDFDPCBDGDPCRCHDXCCDBDSAEACCWCXCGDEAADTCPCBDGDEAHDWCPCHDEAHDWCTCEAHDCDHDPC9DEAGDIDDDDD9DMDEACDUCEASBYBCCKBLAGDEAKDXC9D9DEAPC9DKDPCMDGDEAGDHDPCMDEAHDWCTCEAGDPCADTCEAPCBDSCEAMDCDIDEARCPCBDBDCDHDEAADXCBDTCEASBYBCCKBLAGDSAEACCWCTCFDTCUCCDFDTCEAZCTCTCDDEAXCBDEAADXCBDSCQAEAXCUCEAMDCDIDEASCCDEAZBFDCDCDUCEACDUCEAFCCDFDZCEAXCBDEASBYBCCKBEAMDCDIDEAPCFDTCEABDCDHDEAVCTCBDTCFDPCHDXCBDVCEABDTCKDEASBYBCCKBEAHDCDZCTCBDGDQAEAMDCDIDLAFDTCEAGDXCADDD9DMDEAJDTCFDXCUCMDXCBDVCEACDHDWCTCFDEAHDFDPCBDGDPCRCHDXCCDBDLAQD9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999' 59 | } 60 | ], 61 | expectedTrytes: "ODLAADTCGDGDPCVCTCLADBEALASBYBCCKBEAXCGDEAPCEAFDTCJDCD9DIDHDXCCDBDPCFDMDEABDTCKDEAHDFDPCBDGDPCRCHDXCCDBDPC9DEAGDTCHDHD9DTCADTCBDHDEAPCBDSCEASCPCHDPCEAHDFDPCBDGDUCTCFDEA9DPCMDTCFDEAUCCDFDEAHDWCTCEASBBDHDTCFDBDTCHDEACDUCEACCWCXCBDVCGDSAEASBHDLAGDEAQCPCGDTCSCEACDBDEAPCEABDTCKDEASCXCGDHDFDXCQCIDHDTCSCEA9DTCSCVCTCFDQAEAHDWCTCEACCPCBDVC9DTCQAEAKDWCXCRCWCEACDJDTCFDRCCDADTCGDEAHDWCTCEAXCBDTCUCUCXCRCXCTCBDRCXCTCGDEACDUCEARCIDFDFDTCBDHDEALB9DCDRCZCRCWCPCXCBDEASCTCGDXCVCBDGDEAPCBDSCEAXCBDHDFDCDSCIDRCTCGDEAPCEABDTCKDEAKDPCMDEACDUCEAFDTCPCRCWCXCBDVCEARCCDBDGDTCBDGDIDGDEAXCBDEAPCEASCTCRCTCBDHDFDPC9DXCNDTCSCEADDTCTCFDRAHDCDRADDTCTCFDEAGDMDGDHDTCADSAEAPBCDFDEAHDWCTCEAUCXCFDGDHDEAHDXCADTCEATCJDTCFDQAEAHDWCFDCDIDVCWCEASBYBCCKBEADDTCCDDD9DTCEARCPCBDEAHDFDPCBDGDUCTCFDEAADCDBDTCMDEAKDXCHDWCCDIDHDEAPCBDMDEAUCTCTCGDSAEACCWCXCGDEAADTCPCBDGDEAHDWCPCHDEATCJDTCBDEAXCBDUCXCBDXCHDTCGDXCADPC9D9DMDEAGDADPC9D9DEABDPCBDCDDDPCMDADTCBDHDGDEARCPCBDEAQCTCEAADPCSCTCEAHDWCFDCDIDVCWCEASBYBCCKBSAEASBYBCCKBEAXCGDEAHDWCTCEAADXCGDGDXCBDVCEADDIDNDND9DTCEADDXCTCRCTCEAUCCDFDEAHDWCTCEAWBPCRCWCXCBDTCEAOBRCCDBDCDADMDEAHDCDEAUCID9D9DMDEATCADTCFDVCTCEAPCBDSCEAFDTCPCRCWCEAXCHDGDEASCTCGDXCFDTCSCEADDCDHDTCBDHDXCPC9DSAEAFCTCEATCBDJDXCGDXCCDBDEASBYBCCKBEAHDCDEAQCTCEAHDWCTCEADDIDQC9DXCRCQAEADDTCFDADXCGDGDXCCDBD9DTCGDGDEAQCPCRCZCQCCDBDTCEAUCCDFDEAHDWCTCEASBBDHDTCFDBDTCHDEACDUCEACCWCXCBDVCGDEAHDWCPCHDEATCBDPCQC9DTCGDEAHDFDIDTCEAXCBDHDTCFDCDDDTCFDPCQCXC9DXCHDMDEAQCTCHDKDTCTCBDEAPC9D9DEASCTCJDXCRCTCGDSAEACCPCBDVC9DTCDBEAKBEASCXCFDTCRCHDTCSCEAPCRCMDRC9DXCRCEAVCFDPCDDWCEAMANBKBQBNAEAPCGDEAPCEASCXCGDHDFDXCQCIDHDTCSCEA9DTCSCVCTCFDEAKDWCXCRCWCEAGDHDCDFDTCGDEAPC9D9DEAHDFDPCBDGDPCRCHDXCCDBDEASCPCHDPCEACDUCEAHDWCTCEASBYBCCKBEABDTCHDKDCDFDZCSAEASBHDEAXCGDEAPCEALB9DCDRCZCRCWCPCXCBDEAKDXCHDWCCDIDHDEAHDWCTCEAQC9DCDRCZCGDEAPCBDSCEAHDWCTCEARCWCPCXCBDEAMAGDCDEAXCGDEAXCHDEAFDTCPC9D9DMDEAPCEALB9DCDRCZCRCWCPCXCBDIBNASAEACCWCTCEACCPCBDVC9DTCEAXCGDEAHDWCTCEAUCXCFDGDHDEASCXCGDHDFDXCQCIDHDTCSCEA9DTCSCVCTCFDEAHDCDEAPCRCWCXCTCJDTCEAGDRCPC9DPCQCXC9DXCHDMDQAEABDCDEAUCTCTCEAHDFDPCBDGDPCRCHDXCCDBDGDQAEASCPCHDPCEAXCBDHDTCVCFDXCHDMDEAPCBDSCEAHDFDPCBDGDADXCGDGDXCCDBDEAPCGDEAKDTC9D9DEAPCGDEAEDIDPCBDHDIDADRARCCDADDDIDHDXCBDVCEADDFDCDHDTCRCHDXCCDBDSAEAMBCDBDHDFDPCFDMDEAHDCDEAHDCDSCPCMDLAGDEALB9DCDRCZCRCWCPCXCBDGDQAEARCCDBDGDTCBDGDIDGDEAXCGDEABDCDRA9DCDBDVCTCFDEASCTCRCCDIDDD9DTCSCEAQCIDHDEAXCBDGDHDTCPCSCEAPCBDEAXCBDHDFDXCBDGDXCRCEADDPCFDHDEACDUCEAHDWCTCEAGDMDGDHDTCADQAEA9DTCPCSCXCBDVCEAHDCDEAPCEARCCDADDD9DTCHDTC9DMDEASCTCRCTCBDHDFDPC9DXCNDTCSCEAPCBDSCEAGDTC9DUCRAFDTCVCID9DPCHDXCBDVCEADDTCTCFDRAHDCDRADDTCTCFDEABDTCHDKDCDFDZCSAEAKB9D9DEASBYBCCKBLAGDEAKDWCXCRCWCEAKDXC9D9DEATCJDTCFDEATCLDXCGDHDEAWCPCJDTCEAQCTCTCBDEARCFDTCPCHDTCSCEAKDXCHDWCEAHDWCTCEAVCTCBDTCGDXCGDEAHDFDPCBDGDPCRCHDXCCDBDSAEACCWCXCGDEAADTCPCBDGDEAHDWCPCHDEAHDWCTCEAHDCDHDPC9DEAGDIDDDDD9DMDEACDUCEASBYBCCKBLAGDEAKDXC9D9DEAPC9DKDPCMDGDEAGDHDPCMDEAHDWCTCEAGDPCADTCEAPCBDSCEAMDCDIDEARCPCBDBDCDHDEAADXCBDTCEASBYBCCKBLAGDSAEACCWCTCFDTCUCCDFDTCEAZCTCTCDDEAXCBDEAADXCBDSCQAEAXCUCEAMDCDIDEASCCDEAZBFDCDCDUCEACDUCEAFCCDFDZCEAXCBDEASBYBCCKBEAMDCDIDEAPCFDTCEABDCDHDEAVCTCBDTCFDPCHDXCBDVCEABDTCKDEASBYBCCKBEAHDCDZCTCBDGDQAEAMDCDIDLAFDTCEAGDXCADDD9DMDEAJDTCFDXCUCMDXCBDVCEACDHDWCTCFDEAHDFDPCBDGDPCRCHDXCCDBDLAQD", 62 | expectedJson: "{'message': 'IOTA is a revolutionary new transactional settlement and data transfer layer for the Internet of Things. It's based on a new distributed ledger, the Tangle, which overcomes the inefficiencies of current Blockchain designs and introduces a new way of reaching consensus in a decentralized peer-to-peer system. For the first time ever, through IOTA people can transfer money without any fees. This means that even infinitesimally small nanopayments can be made through IOTA. IOTA is the missing puzzle piece for the Machine Economy to fully emerge and reach its desired potential. We envision IOTA to be the public, permissionless backbone for the Internet of Things that enables true interoperability between all devices. Tangle: A directed acyclic graph (DAG) as a distributed ledger which stores all transaction data of the IOTA network. It is a Blockchain without the blocks and the chain (so is it really a Blockchain?). The Tangle is the first distributed ledger to achieve scalability, no fee transactions, data integrity and transmission as well as quantum-computing protection. Contrary to today's Blockchains, consensus is no-longer decoupled but instead an intrinsic part of the system, leading to a completely decentralized and self-regulating peer-to-peer network. All IOTA\'s which will ever exist have been created with the genesis transaction. This means that the total supply of IOTA\'s will always stay the same and you cannot mine IOTA\'s. Therefore keep in mind, if you do Proof of Work in IOTA you are not generating new IOTA tokens, you\'re simply verifying other transaction'}" 63 | }, 64 | // No ending bracket, should fail 65 | { 66 | bundle: [ 67 | { 68 | signatureMessageFragment: 'ODLAADTCGDGDPCVCTCLADBEALASBYBCCKBEAXCGDEAPCEAFDTCJDCD9DIDHDXCCDBDPCFDMDEABDTCKDEAHDFDPCBDGDPCRCHDXCCDBDPC9DEAGDTCHDHD9DTCADTCBDHDEAPCBDSCEASCPCHDPCEAHDFDPCBDGDUCTCFDEA9DPCMDTCFDEAUCCDFDEAHDWCTCEASBBDHDTCFDBDTCHDEACDUCEACCWCXCBDVCGDSAEASBHDLAGDEAQCPCGDTCSCEACDBDEAPCEABDTCKDEASCXCGDHDFDXCQCIDHDTCSCEA9DTCSCVCTCFDQAEAHDWCTCEACCPCBDVC9DTCQAEAKDWCXCRCWCEACDJDTCFDRCCDADTCGDEAHDWCTCEAXCBDTCUCUCXCRCXCTCBDRCXCTCGDEACDUCEARCIDFDFDTCBDHDEALB9DCDRCZCRCWCPCXCBDEASCTCGDXCVCBDGDEAPCBDSCEAXCBDHDFDCDSCIDRCTCGDEAPCEABDTCKDEAKDPCMDEACDUCEAFDTCPCRCWCXCBDVCEARCCDBDGDTCBDGDIDGDEAXCBDEAPCEASCTCRCTCBDHDFDPC9DXCNDTCSCEADDTCTCFDRAHDCDRADDTCTCFDEAGDMDGDHDTCADSAEAPBCDFDEAHDWCTCEAUCXCFDGDHDEAHDXCADTCEATCJDTCFDQAEAHDWCFDCDIDVCWCEASBYBCCKBEADDTCCDDD9DTCEARCPCBDEAHDFDPCBDGDUCTCFDEAADCDBDTCMDEAKDXCHDWCCDIDHDEAPCBDMDEAUCTCTCGDSAEACCWCXCGDEAADTCPCBDGDEAHDWCPCHDEATCJDTCBDEAXCBDUCXCBDXCHDTCGDXCADPC9D9DMDEAGDADPC9D9DEABDPCBDCDDDPCMDADTCBDHDGDEARCPCBDEAQCTCEAADPCSCTCEAHDWCFDCDIDVCWCEASBYBCCKBSAEASBYBCCKBEAXCGDEAHDWCTCEAADXCGDGDXCBDVCEADDIDNDND9DTCEADDXCTCRCTCEAUCCDFDEAHDWCTCEAWBPCRCWCXCBDTCEAOBRCCDBDCDADMDEAHDCDEAUCID9D9DMDEATCADTCFDVCTCEAPCBDSCEAFDTCPCRCWCEAXCHDGDEASCTCGDXCFDTCSCEADDCDHDTCBDHDXCPC9DSAEAFCTCEATCBDJDXCGDXCCDBDEASBYBCCKBEAHDCDEAQCTCEAHDWCTCEADDIDQC9DXCRCQAEADDTCFDADXCGDGDXCCDBD9DTCGDGDEAQCPCRCZCQCCDBDTCEAUCCDFDEAHDWCTCEASBBDHDTCFDBDTCHDEACDUCEACCWCXCBDVCGDEAHDWCPCHDEATCBDPCQC9DTCGDEAHDFDIDTCEAXCBDHDTCFDCDDDTCFDPCQCXC9DXCHDMDEAQCTCHDKDTCTCBDEAPC9D9DEASCTCJDXCRCTCGDSAEACCPCBDVC9DTCDBEAKBEASCXCFDTCRCHDTCSCEAPCRCMDRC9DXCRCEAVCFDPCDDWCEAMANBKBQBNAEAPCGDEAPCEASCXCGDHDFDXCQCIDHDTCSCEA9DTCSCVCTCFDEAKDWCXCRCWCEAGDHDCDFDTCGDEAPC9D9DEAHDFDPCBDGDPCRCHDXCCDBDEASCPCHDPCEACDUCEAHDWCTCEASBYBCCKBEABDTCHDKDCDFDZCSAEASBHDEAXCGDEAPCEALB9DCDRCZCRCWCPCXCBDEAKDXCHDWCCDIDHDEAHDWCTCEAQC9DCDRCZCGDEAPCBDSCEAHDWCTCEARCWCPCXCBDEAMAGDCDEAXCGDEAXCHDEAFDTCPC9D9DMDEAPCEALB9DCDRCZCRCWCPCXCBDIBNASAEACCWCTCEACCPCBDVC9DTCEAXCGDEAHDWCTCEAUCXCFDGDHDEASCXCGDHDFDXCQCIDHDTCSCEA9DTCSCVCTCFDEAHDCDEAPCRCWCXCTCJDTCEAGDRCPC9DPCQCXC9DXCHDMDQAEABDCDEAUCTCTCEAHDFDPCBDGDPCRCHDXCCDBDGDQAEASCPCHDPCEAXCBDHDTCVCFDXCHDMDEAPCBDSCEAHDFDPCBDGDADXCGDGDXCCDBDEAPCGDEAKDTC9D9DEAPCGDEAEDIDPCBDHDIDADRARCCDADDDIDHDXCBDVCEADDFDCDHDTCRCHDX' 69 | }, 70 | { 71 | signatureMessageFragment: 'CCDBDSAEAMBCDBDHDFDPCFDMDEAHDCDEAHDCDSCPCMDLAGDEALB9DCDRCZCRCWCPCXCBDGDQAEARCCDBDGDTCBDGDIDGDEAXCGDEABDCDRA9DCDBDVCTCFDEASCTCRCCDIDDD9DTCSCEAQCIDHDEAXCBDGDHDTCPCSCEAPCBDEAXCBDHDFDXCBDGDXCRCEADDPCFDHDEACDUCEAHDWCTCEAGDMDGDHDTCADQAEA9DTCPCSCXCBDVCEAHDCDEAPCEARCCDADDD9DTCHDTC9DMDEASCTCRCTCBDHDFDPC9DXCNDTCSCEAPCBDSCEAGDTC9DUCRAFDTCVCID9DPCHDXCBDVCEADDTCTCFDRAHDCDRADDTCTCFDEABDTCHDKDCDFDZCSAEAKB9D9DEASBYBCCKBLAGDEAKDWCXCRCWCEAKDXC9D9DEATCJDTCFDEATCLDXCGDHDEAWCPCJDTCEAQCTCTCBDEARCFDTCPCHDTCSCEAKDXCHDWCEAHDWCTCEAVCTCBDTCGDXCGDEAHDFDPCBDGDPCRCHDXCCDBDSAEACCWCXCGDEAADTCPCBDGDEAHDWCPCHDEAHDWCTCEAHDCDHDPC9DEAGDIDDDDD9DMDEACDUCEASBYBCCKBLAGDEAKDXC9D9DEAPC9DKDPCMDGDEAGDHDPCMDEAHDWCTCEAGDPCADTCEAPCBDSCEAMDCDIDEARCPCBDBDCDHDEAADXCBDTCEASBYBCCKBLAGDSAEACCWCTCFDTCUCCDFDTCEAZCTCTCDDEAXCBDEAADXCBDSCQAEAXCUCEAMDCDIDEASCCDEAZBFDCDCDUCEACDUCEAFCCDFDZCEAXCBDEASBYBCCKBEAMDCDIDEAPCFDTCEABDCDHDEAVCTCBDTCFDPCHDXCBDVCEABDTCKDEASBYBCCKBEAHDCDZCTCBDGDQAEAMDCDIDLAFDTCEAGDXCADDD9DMDEAJDTCFDXCUCMDXCBDVCEACDHDWCTCFDEAHDFDPCBDGDPCRCHDXCCDBDLA999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999' 72 | } 73 | ], 74 | expectedJson: false 75 | }, 76 | // empty array, should fail 77 | { 78 | bundle: [], 79 | expectedJson: false 80 | }, 81 | // empty array, should fail 82 | { 83 | bundle: 'ODEALAPCLAEADBEALAQCLAQAEALARCLADBEAODLABDTCGDHDTCSCLADBEALAYCGDCDBDLAQAEALAADIDRCWCLADBEALAKDCDKDLAQAEALAPCFDFDPCMDLADBEAJCEAHDFDIDTCQAEAUCPC9DGDTCQAEALAMDTCGDLAEALCEAQDEAQD', 84 | expectedJson: false 85 | } 86 | ] 87 | 88 | tests.forEach(function(test) { 89 | 90 | it('should get JSON: : ' + test.expectedJson, function() { 91 | 92 | var message = Utils.extractJson( test.bundle ); 93 | 94 | if (test.expectedJson) { 95 | 96 | assert.strictEqual( message, test.expectedJson ); 97 | 98 | } else { 99 | 100 | assert.isNull( message ); 101 | 102 | } 103 | }); 104 | 105 | }) 106 | }); 107 | -------------------------------------------------------------------------------- /test/utils/utils.fromTrytes.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var Utils = require('../../lib/utils/utils.js'); 4 | 5 | 6 | describe('utils.fromTrytes', function() { 7 | 8 | var tests = [ 9 | { 10 | message: " ASDFDSAFDSAja9fd", 11 | expected: true 12 | }, 13 | { 14 | message: "994239432", 15 | expected: true 16 | }, 17 | { 18 | message: "{ 'a' : 'b', 'c': 'd', 'e': '#asdfd?$' }", 19 | expected: true 20 | }, 21 | { 22 | message: "{ 'a' : 'b', 'c': {'nested': 'json', 'much': 'wow', 'array': [ true, false, 'yes' ] } }", 23 | expected: true 24 | }, 25 | { 26 | message: 994239432, 27 | expected: false 28 | }, 29 | { 30 | message: 'true', 31 | expected: true 32 | }, 33 | { 34 | message: Array(9, 'yes', true), 35 | expected: false 36 | }, 37 | { 38 | message: { 'a' : 'b' }, 39 | expected: false 40 | } 41 | ] 42 | 43 | tests.forEach(function(test) { 44 | 45 | it('should convert trytes to string and back. Test: ' + test.message + ' with result: ' + test.expected, function() { 46 | 47 | var trytes = Utils.toTrytes(test.message); 48 | 49 | var toString = Utils.fromTrytes(trytes); 50 | 51 | if (test.expected) { 52 | 53 | assert.strictEqual(toString, test.message); 54 | 55 | } else { 56 | 57 | assert.isNull(toString); 58 | 59 | } 60 | }); 61 | 62 | }) 63 | }); 64 | -------------------------------------------------------------------------------- /test/utils/utils.isBundle.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var Utils = require('../../lib/utils/utils'); 4 | 5 | 6 | describe('utils.isBundle', function() { 7 | 8 | var tests = [ 9 | // Valid bundle 10 | { 11 | 'bundle': [ { hash: 'CKUBZGZUZJPZSPHWLPXMJPMWTTQYGSNDMBLSPIVZGHVJHEBABBAXWYKTGYHZAUKAPGALKEBXHHSD99999', 12 | signatureMessageFragment: '999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999', 13 | address: 'PPJFBGPEFOMNBNTTCFBTQCGY9BVXTS9LWQVFNXODIHVEPJLFRSJYMYBDFOOFWPIBAYBLBZO9PHYOLEJBA', 14 | value: 1, 15 | obsoleteTag: 'BIGTEST99999999999999999999', 16 | timestamp: 1502215514, 17 | currentIndex: 0, 18 | lastIndex: 3, 19 | bundle: 'ZNSJHWENEAN9VKGQICUBWGKBKRQVPMDIIUEFNVBYRROMEJNCCHGPJIWQERZASRQDYZKDJDXZJRFRVKRWY', 20 | trunkTransaction: 'UEBOMWXEKEQCZFOTGRDF9MXZQDXX9VBKQNKLQDTNMNSY9RM9ZVPHVNXOIYEJLBIPE9JSHMWQPPXZ99999', 21 | branchTransaction: 'GPWZXISZREDVZTRCPSZAJYPDHNFF9AGZXIYWIDLVWZDHBIQRPSJPXAUNRMXCZLIRSBHBILATOQYQX9999', 22 | tag: 'VUTFNPTRCHCH9JDRPPEJHJDZKJX', 23 | attachmentTimestamp: -1789972691417, 24 | attachmentTimestampLowerBound: -442481168685, 25 | attachmentTimestampUpperBound: -1558788566106, 26 | nonce: 'RJTBFCUPVBRCZNAVV9HPS9IRKVM' }, 27 | { hash: 'UEBOMWXEKEQCZFOTGRDF9MXZQDXX9VBKQNKLQDTNMNSY9RM9ZVPHVNXOIYEJLBIPE9JSHMWQPPXZ99999', 28 | signatureMessageFragment: 'QHYTTDPBSHHHFXNQWXWMOINNIOUXCMJTZGWSCJEMWFUVDSYSRHABDKLPXFGHX9DVOPGCE9CNDPQEYOLRWADEPEQVIAXHVGALDOPHJGSQYFPOCEOZQRVIVNXES9DPCGBYIDIUZRGI9PGZWYHOXNCMDXT9YRXWVBPPABP9XQFS9SNUFIDS9ZDDONYHYGNNEMAAM9XOGYPFIGVXAVEQMTXXLJZFOCILIWUYODUYERZLVFSCRO9PAFWCIGSUQQOAZQOYJZIOMTVCVFLXTCNLIUMVM9FREBSBLEFGWRFGNV9XPOJYVXMXROYDUUWHRSVIOMFHSEVZDNERZMZPVHSYUVCQLKZGDTQNOHSBORQJBLDLDM9OBVJXMMPRTQADQCMPOETPZSGXGYUA9QOWJDBTWXEXBCPLPKVATHQQWTUNDCHCAKOOFWPCOFCRCUMFGWTTSRVNPIQJMOGQJV9UGBVWDQLCGGDJUC9QII9SOYDOGXC9VIPZKOAYL9BSTIUXUPESUMBWYZHXLEAAGCVYHNSUUUGDVILVSUTQBIFSPVQHWGNCQVOV9UQMHAWXBEZFEGHRB9RARBVRHQN9VXVJSCMEQMAFSYXLRZLSPHJUPTJXRQ9AHJWQDBBMKVEPRUIDQJGUVHVMDXNTDUCYTBYGZHZVQFEBGYZGSUPN9GHXLDQGH9RMVSYQ9VTHQXOXRDISURXPYTMLAUKQDCOLXTPRNFYNTZHDYH9UWLTNP9AZMSNV9EIDNUGPQUADTBHO9EKMUHEZKHVZJYZXMUMCONPD9KXXZDWBH9YLZNFVKI9BUWKGAMEUKD9AGGXZGAFWDLJF9XADITKONBUTGUHYYWYKKSCGSFUNGIG9EJIPUETMBDUNGZUPXKEYTQCVKIEIQTURL9XEVPT9RBFHXMCFYDGPRTFUWZWMYRMQVKNYAHKRZIBDN9DWQ9CDUSQBFTDSOTQKCZORVSMIHPJBJ9HWHFG9IUZVOYTQWBMRG9VBSQVTIDBREOXNRARNPAYPLLQGJRWRNJLFE99MEXVOKGEH99VFBAVCJOYTVDMSTRDWBDIEWVWLNZEJCNHIRUKZEPWVFGGITVQLMTDYHSSCHUYPCRDWRRATKHMUWFLRMODOTIYBDVVFPJMHUMFXKDTBGYIRYIHAPFHHOCURRJVTIOSLUMVYCTQKLTZVDJIETCETCQXJITTGMTMXNDGIHAMAPVDEPXRXXMBO9ZWOUJJWHWUFRHLAKGCLIQCPWDJIVZILIWUSNDYPSOEGRAEJGNQBDYWCXZCSNQ9AZFLZ9GDCBJTHXBD9IQLXDUZ9ICEVSOLSTIEQUJNYH9OOZJIVHTDZMIBZ9SVBBBGTEGTCKKUEQZOMDEXXRFLKTDXKGHVXMDOSQGJXDWYRZ9PNSEAZNSZFAJQAAACNHZDMBIBKHAIC9HXELOEGCYN9LVZCDJ9XRDJSNFMBGVZAQZLCCSDUPRRYFCQRBRYMFYEAM9SZWC9JBLQEQJZCWFLZKUKQJTOGRMRCRGKMPYRAIBSQARAZXETXDSRLIGQIBMPQCQAIFVZKJVTHBFT9PRBTHVGCGXFPRBDWLBDRHVJISDNRQEUUIUXMNVHRIUSMIQAMIQHEMF9OBWPUZWHIUEFAMBHZHDGKMKFL9SKTURRPJOKYM9CJYOYTGPRDPOUUZQUTYDBPUDLOPRAVWUWZRRNZGCLVNUATOYALLKQRWDCEDSJKKJWOQFIAMA9XLJYEYWOOUUWGQIOSEAJLOPCXWBEPYURZZRZOYTZVGRCWMOQZGAUGGWFNZHIHHUCAKZPLEQFWBVKLFYIXIJSEQLEFWRUSJFKVIBGHNESKHBYXNUSTUNSSBUJNCETWZ9MZXNHQQWCIDEJFDYBXWTXTWSOUDTUIITZR9OMZNZXDAIOCPSPRAUQRZDBWNFT9OXAOINSXXJSLVSHAHDGHLJAJIDEHNOFJXNTJZ9XAEHTNWKMDFEYCWZ9VYERIXNIMELVOYVGTIB99ACZUJYUMP9MQKPOFIRFMMWQ9YSWHLYLZ9QANFECFLKWBXYEOBH9MYACFUSLVCCWCIJDGJPWZBNGJUKYYIFIESAUAMW9Q9GDKGCMOSFANYUTZTUXEEQJWQCFNMGTLPZDZNRVGPXPSFOFNGKZGNNPQWWEIFOGLHOEUSAOIMKI9JFFBGLQQMWQJPJNOQFSMCJTRIRTVLEQIIIVVICD', 29 | address: 'ZWXPIOIUFRIC9EZCUUJWEOZKBWH9ROHCIP9WRZGUXQZMUTMTGGEBPHBUMWK9GTLEXCIVWWR9ZAENHKSJ9', 30 | value: -2000000000, 31 | obsoleteTag: 'BIGTEST99999999999999999999', 32 | timestamp: 1502215514, 33 | currentIndex: 1, 34 | lastIndex: 3, 35 | bundle: 'ZNSJHWENEAN9VKGQICUBWGKBKRQVPMDIIUEFNVBYRROMEJNCCHGPJIWQERZASRQDYZKDJDXZJRFRVKRWY', 36 | trunkTransaction: 'YBRMGZC9SHQNUNDGZEIHETCZJX9DZJ9AAXHGSPQWEAIVC9OSZWVUGBMVX9MUWYJVNNUJTCNOTUGP99999', 37 | branchTransaction: 'GPWZXISZREDVZTRCPSZAJYPDHNFF9AGZXIYWIDLVWZDHBIQRPSJPXAUNRMXCZLIRSBHBILATOQYQX9999', 38 | tag: 'KOXCGHOATHMIGGHJX9PJYKYCEWI', 39 | attachmentTimestamp: -3519568744220, 40 | attachmentTimestampLowerBound: -2402437163849, 41 | attachmentTimestampUpperBound: 2116140926633, 42 | nonce: 'MFSLEXDI9CVT9LE99XOGC9ABHOV' }, 43 | { hash: 'YBRMGZC9SHQNUNDGZEIHETCZJX9DZJ9AAXHGSPQWEAIVC9OSZWVUGBMVX9MUWYJVNNUJTCNOTUGP99999', 44 | signatureMessageFragment: 'ICJAYWSUQXPRGDBXWGOVLAIHIGTRCLPBZIFMCKWBF9MWICVBGMYYNTSVWDUNALFZMSLMGKTILEUULOBMDCHTKABBHXU9RCNRAGDPEDJLULAXEZYTQQUAXZYARFXUGFDZLRPZSTXLOJFIMBUGHJNLWJNOMULNQOVCBYFNLSZZH9YCEA99UEEGEDXNSISHHMBRSAADCYIP9XICGFSPRLNMXMFVGWHKDUZQLZBKHDVBOAZQBFSYDDYZHQOVYJZAKMFXFIWCMGO9VTYZEAVGEDZFKY9VMTLDWOKSYFUGUF9IWUTZMTHJINKFQ9CNPKUVGXKEJXJZICZSSFHZYDFOKNINWU9IFJUKETQPSUBAKOKFNEWEAYXZEHVDUUATVGRFBDWNTBPETJECHXPUHRGWXOKOYVUJPQKASXBYWDZFGMHAAQGDCQWEAFFGMMANYZ9JGJURTQCLJBGOUQVYVGRWWGHRRGKYSSIDHZZLPVNYPAJYMMHD9EKOYAYVWWVPUHZQTFBOXJQIFVOYXSNQ9XQISMIZAQELLVRVFXQKLKTZSRJNBRPNFFGOTSMDADAYSVVUDPDXYETLZVPH9BSFOJMHVENEIRHKNV9GOEYHZIOSJIMNTUMTBEGFBMZQGXQYADGRE9MPHVXHGFT9YSRAIS9YMMXBYACDQVIXOQLRQSVPGPLHGZUSBTSOEJNEVSEZBYRUDHUJMEDDZRNBUPSDWIDXDKHXHUIE9KSCGYE9PKBTSKRXMCERJWCUENIGJKHKFKXYEXSGFHKYGXCVYETWQERNDIZACUPLXFKBFOLTGYOQIPFX9YPCVIYVNYACOFYSPKHHLKSBXIJQDZLQ9JWPDICSXWTUWHAQIRWHUFHZNYMJMJCVIZWPBGURYIDQSYDTHMBHSB9LFOCGVNNZEXFSQUGFS9IGGNBYDVXQSATZTVKFUYCWQXISDQWFVUJQVQQQBBKGZDZETQKHYQIHDUMYULXVYEX9SKILMGPP9CJPWIWHCFGMCWGOXAGRVFIABEQBSSRFSAAOAYRAQOQWTUIMD9EFTWJZRLHCBRCOWSORAPFRGGSZECFQQDFKWYRSDPLLXJLNZJJMYOG9QZYWEIWY9KWPBPGJZCJZIFDCNFTUGIN9VMJL9XHRJXWNYTBZCYHKTKHWKDGVUDIZJPMXOYUHUVCOULMRRBYH9CJHVGMVLNKZFMYXQFJSYRLILZISXVMTNQ9BLADY9YDBPUOFBQTFJWYUZX99Z9LFJJ9WV9NAMBUEXOZQTNIGPKDEYE9FTO99SSMCCCGWD9DDVAFKRP9OMAGBSHZMORJTIPHOHKT9YEAQCFIULKTYJWUL9ABACZRZUMFZSWFBLOZUUTBSKRLPQCDZNQIWPRXYEZSLWTFRYKWZPHNUXII9MWFCKBEOEXOJC9ITEQNQPQPQUHVQZDJEZNIMRTIEYW99ZIZGVH9QEVCOWZKXAYNCMDWNBWTDAQDMAXCPHTTLUOIXTWLZNRTVSLKQFAQHRJSCMWD9XRFNCXNRUDOILEJPXRAXUCJNMHYBVONKBQYDGMDOPMVJNURTADTGVASPCB9ZPQVWIRI9VVKBTZE99MFGFHFCESXMTXFGLMELWORBZTEMEEZHEEFHRCPY9DMZHPXYI9CPDREJSECKCSIEHUQJACGNPWIOSUCARELRIFHMC9GCRIKK9PVKUCYMILFMRMKCYPVOAIIAVIDNXEXDNMLE9FLUGVFROOJMPRYWXDNWGWTSFNMZPIPWDZOVWLUBQSMJPZUABZJAYN9KLRULXKUXMRLRWYKIE9EYYCODKHCRGZHKOIRSQBP9LAFQAUPPKYNJ9SOMOCPHMRHIYAEKXZMAXZBAQZBDTUBGKQAONOIVBKITECYVELHCST9QHWGALGNBYUNQNALDRZLZIJDPABN9MWDIVTVHHTOHFKFMIYSTOSRXAOYOMCYOLZZSMGWF9KWDMVMMYRPOHHWZKOXYQYAUPWXIPZTXKNZXLUSKZGEMGODFEM9AAOMNH9JDAYIJRA9WBYXGHTZJCUVYQXCXWH9WKLVQBNUYETQPTCRSL9GNARBVQUPEOXSUVNPOCAPWHWJWZNOPGCJLFLIACQZRN9XYNZOU9DZSBTTUUXVAUOVZWDHIZHNWA9KSUWCNU9C9OQXIZYUUQP9QKEOXUIXYTHTRZJIAUKSKFFNVGIPVJGVNVKHDQTTMXKA', 45 | address: 'ZWXPIOIUFRIC9EZCUUJWEOZKBWH9ROHCIP9WRZGUXQZMUTMTGGEBPHBUMWK9GTLEXCIVWWR9ZAENHKSJ9', 46 | value: 0, 47 | obsoleteTag: 'BIGTEST99999999999999999999', 48 | timestamp: 1502215514, 49 | currentIndex: 2, 50 | lastIndex: 3, 51 | bundle: 'ZNSJHWENEAN9VKGQICUBWGKBKRQVPMDIIUEFNVBYRROMEJNCCHGPJIWQERZASRQDYZKDJDXZJRFRVKRWY', 52 | trunkTransaction: 'F9AYXWCOWNCRJKTGHRYAURGOCMEXHWQE9YYCLNPOWZECDKPATVVBA9VJJBMEWVPNYYFNYWNDPMUU99999', 53 | branchTransaction: 'GPWZXISZREDVZTRCPSZAJYPDHNFF9AGZXIYWIDLVWZDHBIQRPSJPXAUNRMXCZLIRSBHBILATOQYQX9999', 54 | tag: '9GDNXRQSWHOVQWCUXESHIHTSGG9', 55 | attachmentTimestamp: -1576624671529, 56 | attachmentTimestampLowerBound: 116988204706, 57 | attachmentTimestampUpperBound: -2233110606683, 58 | nonce: 'KESGKIIXKGV9BPIBCXLBYBBVTCH' }, 59 | { hash: 'F9AYXWCOWNCRJKTGHRYAURGOCMEXHWQE9YYCLNPOWZECDKPATVVBA9VJJBMEWVPNYYFNYWNDPMUU99999', 60 | signatureMessageFragment: '999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999', 61 | address: 'BRU9LRH9YNGTYMFRODMPMEAPIDTDYUFLQLFWTXKNXQYHSYNEMCFVFGKMIWWOWDFOAJ9RRZVCWX9ELQEP9', 62 | value: 1999999999, 63 | obsoleteTag: 'BIGTEST99999999999999999999', 64 | timestamp: 1502215528, 65 | currentIndex: 3, 66 | lastIndex: 3, 67 | bundle: 'ZNSJHWENEAN9VKGQICUBWGKBKRQVPMDIIUEFNVBYRROMEJNCCHGPJIWQERZASRQDYZKDJDXZJRFRVKRWY', 68 | trunkTransaction: 'GPWZXISZREDVZTRCPSZAJYPDHNFF9AGZXIYWIDLVWZDHBIQRPSJPXAUNRMXCZLIRSBHBILATOQYQX9999', 69 | branchTransaction: 'TRKDBAIFTWTNRMCLVGBSXJXZO9VNFMYOSDJXELM9LNUHXOQBFRMNAAZTWURMNGUZDJVXNITXWZKAZ9999', 70 | tag: 'MIRMAZTQUR9MMEPCWOMHMDLZPFE', 71 | attachmentTimestamp: -1737679689424, 72 | attachmentTimestampLowerBound: -282646045775, 73 | attachmentTimestampUpperBound: 2918881518838, 74 | nonce: 'IJZRLQMGVIYWOS9FDKDRPONJWNB' } ], 75 | 'expected': true 76 | }, 77 | // Invalid bundle 78 | { 79 | 'bundle': [ 80 | { 81 | "hash":"IPQYUNLDGKCLJVEJGVVISSQYVDJJWOXCW9RZXIDFKMBXDVZDXFBZNZJKBSTIMBKAXHFTGETEIPTZGNTJK", 82 | "signatureMessageFragment":"", 83 | "address":"A9RGRKVGWMWMKOLVMDFWJUHNUNYWZTJADGGPZGXNLERLXYWJE9WQHWWBMCPZMVVMJUMWWBLZLNMLDCGDJ", 84 | "value":0, 85 | "tag":"999999999999999999999999999", 86 | "timestamp":1482522289, 87 | "currentIndex":0, 88 | "lastIndex":0, 89 | "bundle":"TXEFLKNPJRBYZPORHZU9CEMFIFVVQBUSTDGSJCZMBTZCDTTJVUFPTCCVHHORPMGCURKTH9VGJIXUQJVHK", 90 | "trunkTransaction":"999999999999999999999999999999999999999999999999999999999999999999999999999999999", 91 | "branchTransaction":"999999999999999999999999999999999999999999999999999999999999999999999999999999999", 92 | "nonce":"999999999999999999999999999999999999999999999999999999999999999999999999999999999" 93 | } 94 | ], 95 | 'expected': false 96 | } 97 | ] 98 | 99 | tests.forEach(function(test) { 100 | 101 | it('should should be valid bundle: ' + test.expected, function() { 102 | 103 | var isValid = Utils.isBundle(test.bundle); 104 | 105 | assert.equal(isValid, test.expected); 106 | }); 107 | 108 | }) 109 | }); 110 | -------------------------------------------------------------------------------- /test/utils/utils.toTrytes.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var Utils = require('../../lib/utils/utils.js'); 4 | 5 | 6 | describe('utils.toTrytes', function() { 7 | 8 | var tests = [ 9 | { 10 | message: " ΣASDFDSAFDSAja9fd", 11 | expected: null 12 | }, 13 | { 14 | message: " ASDFDSAFDSAja9fd", 15 | expected: true 16 | }, 17 | { 18 | message: "994239432", 19 | expected: true 20 | }, 21 | { 22 | message: "{ 'a' : 'b', 'c': 'd', 'e': '#asdfd?$' }", 23 | expected: true 24 | }, 25 | { 26 | message: "{ 'a' : 'b', 'c': {'nested': 'json', 'much': 'wow', 'array': [ true, false, 'yes' ] } }", 27 | expected: true 28 | }, 29 | { 30 | message: "{ 'a' : 'b', 'c': {'nested': 'json', 'much': 'wow', 'array': [ true, false, 'yes' ] } }", 31 | expected: true 32 | }, 33 | { 34 | message: "{'message': 'IOTA is a revolutionary new transactional settlement and data transfer layer for the Internet of Things. It's based on a new distributed ledger, the Tangle, which overcomes the inefficiencies of current Blockchain designs and introduces a new way of reaching consensus in a decentralized peer-to-peer system. For the first time ever, through IOTA people can transfer money without any fees. This means that even infinitesimally small nanopayments can be made through IOTA. IOTA is the missing puzzle piece for the Machine Economy to fully emerge and reach its desired potential. We envision IOTA to be the public, permissionless backbone for the Internet of Things that enables true interoperability between all devices. Tangle: A directed acyclic graph (DAG) as a distributed ledger which stores all transaction data of the IOTA network. It is a Blockchain without the blocks and the chain (so is it really a Blockchain?). The Tangle is the first distributed ledger to achieve scalability, no fee transactions, data integrity and transmission as well as quantum-computing protection. Contrary to today's Blockchains, consensus is no-longer decoupled but instead an intrinsic part of the system, leading to a completely decentralized and self-regulating peer-to-peer network. All IOTA\'s which will ever exist have been created with the genesis transaction. This means that the total supply of IOTA\'s will always stay the same and you cannot mine IOTA\'s. Therefore keep in mind, if you do Proof of Work in IOTA you are not generating new IOTA tokens, you\'re simply verifying other transactions.'}", 35 | expected: true 36 | }, 37 | { 38 | message: 994239432, 39 | expected: false 40 | }, 41 | { 42 | message: true, 43 | expected: false 44 | }, 45 | { 46 | message: Array(9, 'yes', true), 47 | expected: false 48 | }, 49 | { 50 | message: { 'a' : 'b' }, 51 | expected: false 52 | } 53 | ] 54 | 55 | tests.forEach(function(test) { 56 | 57 | it('should convert: ' + test.message + ' to trytes with result: ' + test.expected, function() { 58 | 59 | var trytes = Utils.toTrytes(test.message); 60 | 61 | if (test.expected) { 62 | 63 | assert.isNotNull(trytes); 64 | 65 | } else { 66 | 67 | assert.isNull(trytes); 68 | } 69 | }); 70 | 71 | }) 72 | }); 73 | -------------------------------------------------------------------------------- /test/valid/valid.isAddress.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var valid = require('../../lib/utils/inputValidator'); 4 | 5 | 6 | describe('valid.isAddress', function() { 7 | 8 | var tests = [ 9 | 'JALLWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMPIVGPNE', 10 | 'JALLWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLS', 11 | 'JALLWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSASD', 12 | '123adfdsafLWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLASD', 13 | 1432432 14 | 15 | ] 16 | 17 | // 0 test 18 | it('should be valid address: ' + tests[0], function() { 19 | 20 | var isAddress = valid.isAddress(tests[0]); 21 | assert.isTrue(isAddress); 22 | }) 23 | 24 | // 1 test 25 | it('should be valid address: ' + tests[1], function() { 26 | 27 | var isAddress = valid.isAddress(tests[1]); 28 | assert.isTrue(isAddress); 29 | }) 30 | 31 | // 2 test 32 | it('should be invalid address: ' + tests[2], function() { 33 | 34 | var isAddress = valid.isAddress(tests[2]); 35 | assert.isFalse(isAddress); 36 | }) 37 | 38 | // 3 test 39 | it('should be invalid address: ' + tests[3], function() { 40 | 41 | var isAddress = valid.isAddress(tests[3]); 42 | assert.isFalse(isAddress); 43 | }) 44 | 45 | // 4 test 46 | it('should be invalid address: ' + tests[4], function() { 47 | 48 | var isAddress = valid.isAddress(tests[4]); 49 | assert.isFalse(isAddress); 50 | }) 51 | 52 | }); 53 | -------------------------------------------------------------------------------- /test/valid/valid.isArrayOfAttachedTrytes.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var valid = require('../../lib/utils/inputValidator'); 4 | 5 | 6 | describe('valid.isArrayOfAttachedTrytes', function() { 7 | 8 | var tests = [ 9 | [ 10 | 'AB9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999A9RGRKVGWMWMKOLVMDFWJUHNUNYWZTJADGGPZGXNLERLXYWJE9WQHWWBMCPZMVVMJUMWWBLZLNMLDCGDJ999999999999999999999999999999999999999999999999999999YGYQIVD99999999999999999999TXEFLKNPJRBYZPORHZU9CEMFIFVVQBUSTDGSJCZMBTZCDTTJVUFPTCCVHHORPMGCURKTH9VGJIXUQJVHK99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999ACDS', 11 | '999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999A9RGRKVGWMWMKOLVMDFWJUHNUNYWZTJADGGPZGXNLERLXYWJE9WQHWWBMCPZMVVMJUMWWBLZLNMLDCGDJ999999999999999999999999999999999999999999999999999999YGYQIVD99999999999999999999TXEFLKNPJRBYZPORHZU9CEMFIFVVQBUSTDGSJCZMBTZCDTTJVUFPTCCVHHORPMGCURKTH9VGJIXUQJVHK999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999FDS' 12 | ], 13 | [ 14 | '999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999A9RGRKVGWMWMKOLVMDFWJUHNUNYWZTJADGGPZGXNLERLXYWJE9WQHWWBMCPZMVVMJUMWWBLZLNMLDCGDJ999999999999999999999999999999999999999999999999999999YGYQIVD99999999999999999999TXEFLKNPJRBYZPORHZU9CEMFIFVVQBUSTDGSJCZMBTZCDTTJVUFPTCCVHHORPMGCURKTH9VGJIXUQJVHK999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999' 15 | ], 16 | 'ABCDWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQRVNLLSJ', 17 | { 18 | address: 'JALLWDTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMP' 19 | } 20 | ] 21 | 22 | // 0 test 23 | it('should be valid isArrayOfAttachedTrytes: 0', function() { 24 | 25 | var isArrayOfAttachedTrytes = valid.isArrayOfAttachedTrytes(tests[0]); 26 | assert.isTrue(isArrayOfAttachedTrytes); 27 | }) 28 | 29 | // 1 test 30 | it('should be invalid isArrayOfAttachedTrytes: 1', function() { 31 | 32 | var isArrayOfAttachedTrytes = valid.isArrayOfAttachedTrytes(tests[1]); 33 | assert.isFalse(isArrayOfAttachedTrytes); 34 | }) 35 | 36 | // 2 test 37 | it('should be invalid isArrayOfAttachedTrytes: 2', function() { 38 | 39 | var isArrayOfAttachedTrytes = valid.isArrayOfAttachedTrytes(tests[2]); 40 | assert.isFalse(isArrayOfAttachedTrytes); 41 | }) 42 | 43 | // 3 test 44 | it('should be invalid isArrayOfAttachedTrytes: 3', function() { 45 | 46 | var isArrayOfAttachedTrytes = valid.isArrayOfAttachedTrytes(tests[3]); 47 | assert.isFalse(isArrayOfAttachedTrytes); 48 | }) 49 | 50 | }); 51 | -------------------------------------------------------------------------------- /test/valid/valid.isArrayOfHashes.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var valid = require('../../lib/utils/inputValidator'); 4 | 5 | 6 | describe('valid.isArrayOfHashes', function() { 7 | 8 | var tests = [ 9 | [ 10 | 'JALLWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMPIVGPNE', 11 | 'ABCDWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQRVNLLSJ' 12 | ], 13 | [ 14 | 'JALLWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMPIVGPNE', 15 | 'fdsafBCDWDUOSTSJEEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQRVNLLSJ' 16 | ], 17 | 'ABCDWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQRVNLLSJ', 18 | { 19 | address: 'JALLWDTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMP' 20 | } 21 | ] 22 | 23 | // 0 test 24 | it('should be valid isArrayOfHashes: 0', function() { 25 | 26 | var isArrayOfHashes = valid.isArrayOfHashes(tests[0]); 27 | assert.isTrue(isArrayOfHashes); 28 | }) 29 | 30 | // 1 test 31 | it('should be invalid isArrayOfHashes: 1', function() { 32 | 33 | var isArrayOfHashes = valid.isArrayOfHashes(tests[1]); 34 | assert.isFalse(isArrayOfHashes); 35 | }) 36 | 37 | // 2 test 38 | it('should be invalid isArrayOfHashes: 2', function() { 39 | 40 | var isArrayOfHashes = valid.isArrayOfHashes(tests[2]); 41 | assert.isFalse(isArrayOfHashes); 42 | }) 43 | 44 | // 3 test 45 | it('should be invalid isArrayOfHashes: 3', function() { 46 | 47 | var isArrayOfHashes = valid.isArrayOfHashes(tests[3]); 48 | assert.isFalse(isArrayOfHashes); 49 | }) 50 | }); 51 | -------------------------------------------------------------------------------- /test/valid/valid.isArrayOfTrytes.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var valid = require('../../lib/utils/inputValidator'); 4 | 5 | 6 | describe('valid.isArrayOfTrytes', function() { 7 | 8 | var tests = [ 9 | [ 10 | 'AB9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999A9RGRKVGWMWMKOLVMDFWJUHNUNYWZTJADGGPZGXNLERLXYWJE9WQHWWBMCPZMVVMJUMWWBLZLNMLDCGDJ999999999999999999999999999999999999999999999999999999YGYQIVD99999999999999999999TXEFLKNPJRBYZPORHZU9CEMFIFVVQBUSTDGSJCZMBTZCDTTJVUFPTCCVHHORPMGCURKTH9VGJIXUQJVHK999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999', 11 | '999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999A9RGRKVGWMWMKOLVMDFWJUHNUNYWZTJADGGPZGXNLERLXYWJE9WQHWWBMCPZMVVMJUMWWBLZLNMLDCGDJ999999999999999999999999999999999999999999999999999999YGYQIVD99999999999999999999TXEFLKNPJRBYZPORHZU9CEMFIFVVQBUSTDGSJCZMBTZCDTTJVUFPTCCVHHORPMGCURKTH9VGJIXUQJVHK999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999' 12 | ], 13 | [ 14 | 'JALLWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMPIVGPNE', 15 | 'fdsafBCDWDUOSTSJEEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQRVNLLSJ' 16 | ], 17 | 'ABCDWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQRVNLLSJ', 18 | { 19 | address: 'JALLWDTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMP' 20 | } 21 | ] 22 | 23 | // 0 test 24 | it('should be valid isArrayOfTrytes: 0', function() { 25 | 26 | var isArrayOfTrytes = valid.isArrayOfTrytes(tests[0]); 27 | assert.isTrue(isArrayOfTrytes); 28 | }) 29 | 30 | // 1 test 31 | it('should be invalid isArrayOfTrytes: 1', function() { 32 | 33 | var isArrayOfTrytes = valid.isArrayOfTrytes(tests[1]); 34 | assert.isFalse(isArrayOfTrytes); 35 | }) 36 | 37 | // 2 test 38 | it('should be invalid isArrayOfTrytes: 2', function() { 39 | 40 | var isArrayOfTrytes = valid.isArrayOfTrytes(tests[2]); 41 | assert.isFalse(isArrayOfTrytes); 42 | }) 43 | 44 | // 3 test 45 | it('should be invalid isArrayOfTrytes: 3', function() { 46 | 47 | var isArrayOfTrytes = valid.isArrayOfTrytes(tests[3]); 48 | assert.isFalse(isArrayOfTrytes); 49 | }) 50 | 51 | }); 52 | -------------------------------------------------------------------------------- /test/valid/valid.isArrayOfTxObjects.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var valid = require('../../lib/utils/inputValidator.js'); 4 | 5 | 6 | describe('valid.isArrayOfTxObjects', function() { 7 | 8 | var tests = [ 9 | // test 0: false 10 | { 11 | bundle: [], 12 | expected: false 13 | }, 14 | // test 1: false 15 | { 16 | bundle: "ASDFDSAFDSAja9fd", 17 | expected: false 18 | }, 19 | // test 2: false 20 | { 21 | bundle: [ 22 | { 23 | "hash":"IPQYUNLDGKCLJVEJGVVISSQYVDJJWOXCW9RZXIDFKMBXDVZDXFBZNZJKBSTIMBKAXHFTGETEIPTZGNTJK", 24 | "signatureMessageFragment":"999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", 25 | "address":"A9RGRKVGWMWMKOLVMDFWJUHNUNYWZTJADGGPZGXNLERLXYWJE9WQHWWBMCPZMVVMJUMWWBLZLNMLDCGDJ", 26 | "tag":"999999999999999999999999999", 27 | "timestamp":1482522289, 28 | "currentIndex":0, 29 | "lastIndex":0, 30 | "bundle":"TXEFLKNPJRBYZPORHZU9CEMFIFVVQBUSTDGSJCZMBTZCDTTJVUFPTCCVHHORPMGCURKTH9VGJIXUQJVHK", 31 | "trunkTransaction":"999999999999999999999999999999999999999999999999999999999999999999999999999999999", 32 | "branchTransaction":"999999999999999999999999999999999999999999999999999999999999999999999999999999999", 33 | "nonce":"999999999999999999999999999999999999999999999999999999999999999999999999999999999" 34 | } 35 | ], 36 | expected: false 37 | }, 38 | // test 3: true 39 | { 40 | bundle: [ 41 | { 42 | "hash":"IPQYUNLDGKCLJVEJGVVISSQYVDJJWOXCW9RZXIDFKMBXDVZDXFBZNZJKBSTIMBKAXHFTGETEIPTZGNTJK", 43 | "signatureMessageFragment":"999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", 44 | "address":"A9RGRKVGWMWMKOLVMDFWJUHNUNYWZTJADGGPZGXNLERLXYWJE9WQHWWBMCPZMVVMJUMWWBLZLNMLDCGDJ", 45 | "value":0, 46 | "obsoleteTag":"999999999999999999999999999", 47 | "timestamp":1482522289, 48 | "currentIndex":0, 49 | "lastIndex":0, 50 | "bundle":"TXEFLKNPJRBYZPORHZU9CEMFIFVVQBUSTDGSJCZMBTZCDTTJVUFPTCCVHHORPMGCURKTH9VGJIXUQJVHK", 51 | "trunkTransaction":"999999999999999999999999999999999999999999999999999999999999999999999999999999999", 52 | "branchTransaction":"999999999999999999999999999999999999999999999999999999999999999999999999999999999", 53 | "tag": "MIRMAZTQUR9MMEPCWOMHMDLZPFE", 54 | "attachmentTimestamp": -1737679689424, 55 | "attachmentTimestampLowerBound": -282646045775, 56 | "attachmentTimestampUpperBound": 2918881518838, 57 | "nonce": "IJZRLQMGVIYWOS9FDKDRPONJWNB" } 58 | ], 59 | expected: true 60 | }, 61 | // test 4: true 62 | { 63 | bundle: [ 64 | { 65 | "hash":"IPQYUNLDGKCLJVEJGVVISSQYVDJJWOXCW9RZXIDFKMBXDVZDXFBZNZJKBSTIMBKAXHFTGETEIPTZGNTJK", 66 | "signatureMessageFragment":"999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", 67 | "address":"A9RGRKVGWMWMKOLVMDFWJUHNUNYWZTJADGGPZGXNLERLXYWJE9WQHWWBMCPZMVVMJUMWWBLZLNMLDCGDJ", 68 | "value":0, 69 | "obsoleteTag":"999999999999999999999999999", 70 | "timestamp":1482522289, 71 | "currentIndex":0, 72 | "lastIndex":0, 73 | "bundle":"TXEFLKNPJRBYZPORHZU9CEMFIFVVQBUSTDGSJCZMBTZCDTTJVUFPTCCVHHORPMGCURKTH9VGJIXUQJVHK", 74 | "trunkTransaction":"999999999999999999999999999999999999999999999999999999999999999999999999999999999", 75 | "branchTransaction":"999999999999999999999999999999999999999999999999999999999999999999999999999999999", 76 | "tag": "MIRMAZTQUR9MMEPCWOMHMDLZPFE", 77 | "attachmentTimestamp": -1737679689424, 78 | "attachmentTimestampLowerBound": -282646045775, 79 | "attachmentTimestampUpperBound": 2918881518838, 80 | "nonce": "IJZRLQMGVIYWOS9FDKDRPONJWNB" 81 | 82 | }, 83 | { 84 | "hash":"IPQYUNLDGKCLJVEJGVVISSQYVDJJWOXCW9RZXIDFKMBXDVZDXFBZNZJKBSTIMBKAXHFTGETEIPTZGNTJK", 85 | "signatureMessageFragment":"999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", 86 | "address":"A9RGRKVGWMWMKOLVMDFWJUHNUNYWZTJADGGPZGXNLERLXYWJE9WQHWWBMCPZMVVMJUMWWBLZLNMLDCGDJ", 87 | "value":0, 88 | "obsoleteTag":"999999999999999999999999999", 89 | "timestamp":1482522289, 90 | "currentIndex":0, 91 | "lastIndex":0, 92 | "bundle":"TXEFLKNPJRBYZPORHZU9CEMFIFVVQBUSTDGSJCZMBTZCDTTJVUFPTCCVHHORPMGCURKTH9VGJIXUQJVHK", 93 | "trunkTransaction":"999999999999999999999999999999999999999999999999999999999999999999999999999999999", 94 | "branchTransaction":"999999999999999999999999999999999999999999999999999999999999999999999999999999999", 95 | "tag": "MIRMAZTQUR9MMEPCWOMHMDLZPFE", 96 | "attachmentTimestamp": -1737679689424, 97 | "attachmentTimestampLowerBound": -282646045775, 98 | "attachmentTimestampUpperBound": 2918881518838, 99 | "nonce": "IJZRLQMGVIYWOS9FDKDRPONJWNB" 100 | } 101 | ], 102 | expected: true 103 | } 104 | ] 105 | 106 | tests.forEach(function(test) { 107 | 108 | it('should should be array of tx objects: ' + test.expected, function() { 109 | 110 | var isValid = valid.isArrayOfTxObjects(test.bundle); 111 | 112 | assert.equal(isValid, test.expected); 113 | }); 114 | 115 | }) 116 | }); 117 | -------------------------------------------------------------------------------- /test/valid/valid.isHash.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var valid = require('../../lib/utils/inputValidator'); 4 | 5 | 6 | describe('valid.isHash', function() { 7 | 8 | var tests = [ 9 | 'JALLWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMPIVGPNE', 10 | 'JALLWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLS', 11 | '123adfdsafLWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLASD', 12 | 1432432 13 | 14 | ] 15 | 16 | // 0 test 17 | it('should be invalid hash: ' + tests[0], function() { 18 | 19 | var isHash = valid.isHash(tests[0]); 20 | assert.isFalse(isHash); 21 | }) 22 | 23 | // 1 test 24 | it('should be valid hash: ' + tests[1], function() { 25 | 26 | var isHash = valid.isHash(tests[1]); 27 | assert.isTrue(isHash); 28 | }) 29 | 30 | // 2 test 31 | it('should be invalid hash: ' + tests[2], function() { 32 | 33 | var isHash = valid.isHash(tests[2]); 34 | assert.isFalse(isHash); 35 | }) 36 | 37 | // 3 test 38 | it('should be invalid hash: ' + tests[3], function() { 39 | 40 | var isHash = valid.isHash(tests[3]); 41 | assert.isFalse(isHash); 42 | }) 43 | 44 | }); 45 | -------------------------------------------------------------------------------- /test/valid/valid.isInputs.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var valid = require('../../lib/utils/inputValidator'); 4 | 5 | 6 | describe('valid.isInputs', function() { 7 | 8 | var tests = [ 9 | [{ 10 | address: 'JALLWDTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMP', 11 | security: 0, 12 | keyIndex: 1 13 | }], 14 | [{ 15 | address: 'JALLWDTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMP', 16 | security: 'fd', 17 | keyIndex: 1 18 | }], 19 | [{ 20 | address: 'JALLWDTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMP', 21 | security: 0, 22 | keyIndex: 'fds' 23 | }], 24 | [{ 25 | address: 'JADTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMP', 26 | security: 0, 27 | keyIndex: 1 28 | }] 29 | ] 30 | 31 | // 0 test 32 | it('should be valid isInputs: 0', function() { 33 | 34 | var isInputs = valid.isInputs(tests[0]); 35 | assert.isTrue(isInputs); 36 | }) 37 | 38 | // 1 test 39 | it('should be invalid isInputs: 1', function() { 40 | 41 | var isInputs = valid.isInputs(tests[1]); 42 | assert.isFalse(isInputs); 43 | }) 44 | 45 | // 2 test 46 | it('should be invalid isInputs: 2', function() { 47 | 48 | var isInputs = valid.isInputs(tests[2]); 49 | assert.isFalse(isInputs); 50 | }) 51 | 52 | // 3 test 53 | it('should be invalid isInputs: 3', function() { 54 | 55 | var isInputs = valid.isInputs(tests[3]); 56 | assert.isFalse(isInputs); 57 | }) 58 | }); 59 | -------------------------------------------------------------------------------- /test/valid/valid.isNinesTrytes.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var valid = require('../../lib/utils/inputValidator'); 4 | 5 | 6 | describe('valid.isNinesTrytes', function() { 7 | 8 | var tests = [ 9 | '999999999999999999', 10 | 'JALLWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMPIVGPNE', 11 | 1432432 12 | 13 | ] 14 | 15 | // 0 test 16 | it('should be valid isNinesTrytes: ' + tests[0], function() { 17 | 18 | var isValid = valid.isNinesTrytes(tests[0]); 19 | assert.isTrue(isValid); 20 | }) 21 | 22 | // 1 test 23 | it('should be invalid isNinesTrytes: ' + tests[1], function() { 24 | 25 | var isValid = valid.isNinesTrytes(tests[1]); 26 | assert.isFalse(isValid); 27 | }) 28 | 29 | // 2 test 30 | it('should be invalid isNinesTrytes: ' + tests[2], function() { 31 | 32 | var isValid = valid.isNinesTrytes(tests[2]); 33 | assert.isFalse(isValid); 34 | }) 35 | 36 | }); 37 | -------------------------------------------------------------------------------- /test/valid/valid.isNum.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var valid = require('../../lib/utils/inputValidator'); 4 | 5 | 6 | describe('valid.isNum', function() { 7 | 8 | var tests = [ 9 | 'AFDS', 10 | '1234', 11 | 432.4321, 12 | 1234 13 | ] 14 | 15 | // 0 test 16 | it('should be invalid isNum: 0', function() { 17 | 18 | var isNum = valid.isNum(tests[0]); 19 | assert.isFalse(isNum); 20 | }) 21 | 22 | // 1 test 23 | it('should be invalid isNum: 1', function() { 24 | 25 | var isNum = valid.isNum(tests[1]); 26 | assert.isTrue(isNum); 27 | }) 28 | 29 | // 2 test 30 | it('should be valid isNum: 2', function() { 31 | 32 | var isNum = valid.isNum(tests[2]); 33 | assert.isTrue(isNum); 34 | }) 35 | 36 | // 3 test 37 | it('should be valid isNum: 2', function() { 38 | 39 | var isNum = valid.isNum(tests[3]); 40 | assert.isTrue(isNum); 41 | }) 42 | 43 | }); 44 | -------------------------------------------------------------------------------- /test/valid/valid.isString.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var valid = require('../../lib/utils/inputValidator'); 4 | 5 | 6 | describe('valid.isString', function() { 7 | 8 | var tests = [ 9 | 'AFDS', 10 | '1234', 11 | 1234 12 | ] 13 | 14 | // 0 test 15 | it('should be valid isString: 0', function() { 16 | 17 | var isString = valid.isString(tests[0]); 18 | assert.isTrue(isString); 19 | }) 20 | 21 | // 1 test 22 | it('should be valid isString: 1', function() { 23 | 24 | var isString = valid.isString(tests[1]); 25 | assert.isTrue(isString); 26 | }) 27 | 28 | // 2 test 29 | it('should be invalid isString: 2', function() { 30 | 31 | var isString = valid.isString(tests[2]); 32 | assert.isFalse(isString); 33 | }) 34 | 35 | }); 36 | -------------------------------------------------------------------------------- /test/valid/valid.isTransfersArray.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var valid = require('../../lib/utils/inputValidator'); 4 | 5 | 6 | describe('valid.isTransfersArray', function() { 7 | 8 | var tests = [ 9 | [{ 10 | address: 'JALLWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMPIVGPNE', 11 | value: 1234, 12 | }], 13 | [{ 14 | address: 'JALLWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMPIVGPNE', 15 | value: 1234.00, 16 | message: 'AFDSA', 17 | tag: 'ASDFDSAFDFDSA' 18 | }], 19 | [{ 20 | address: 'JALLWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMP', 21 | value: '1234', 22 | message: 'AFDSA', 23 | tag: 'ASDFDSAFDFDSA' 24 | }], 25 | { 26 | address: 'JALLWDTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMP', 27 | value: 1234, 28 | message: 'AFDSA', 29 | tag: 'ASDFDSAFDFDSA' 30 | } 31 | ] 32 | 33 | // 0 test 34 | it('should be invalid isTransfersArray: 0', function() { 35 | 36 | var isTransfersArray = valid.isTransfersArray(tests[0]); 37 | assert.isFalse(isTransfersArray); 38 | }) 39 | 40 | // 1 test 41 | it('should be valid isTransfersArray: 1', function() { 42 | 43 | var isTransfersArray = valid.isTransfersArray(tests[1]); 44 | assert.isTrue(isTransfersArray); 45 | }) 46 | 47 | // 2 test 48 | it('should be invalid isTransfersArray: 2', function() { 49 | 50 | var isTransfersArray = valid.isTransfersArray(tests[2]); 51 | assert.isFalse(isTransfersArray); 52 | }) 53 | 54 | // 3 test 55 | it('should be invalid isTransfersArray: 3', function() { 56 | 57 | var isTransfersArray = valid.isTransfersArray(tests[3]); 58 | assert.isFalse(isTransfersArray); 59 | }) 60 | }); 61 | -------------------------------------------------------------------------------- /test/valid/valid.isTrytes.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var valid = require('../../lib/utils/inputValidator'); 4 | 5 | 6 | describe('valid.isTrytes', function() { 7 | 8 | var tests = [ 9 | 'JALLWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLSJMPIVGPNE', 10 | '123adfdsafLWDUOSTSJVL9EEHKW9YQFPBVBJAGLNKRVGSQZCGHQWEMIIILJMTHVAGVDXJVZMBAMOZTSBQNRVNLLASD', 11 | 1432432 12 | 13 | ] 14 | 15 | // 0 test 16 | it('should be valid trytes: ' + tests[0], function() { 17 | 18 | var isValid = valid.isTrytes(tests[0]); 19 | assert.isTrue(isValid); 20 | }) 21 | 22 | // 1 test 23 | it('should be invalid trytes: ' + tests[1], function() { 24 | 25 | var isValid = valid.isTrytes(tests[1]); 26 | assert.isFalse(isValid); 27 | }) 28 | 29 | // 2 test 30 | it('should be invalid trytes: ' + tests[2], function() { 31 | 32 | var isValid = valid.isTrytes(tests[2]); 33 | assert.isFalse(isValid); 34 | }) 35 | 36 | }); 37 | -------------------------------------------------------------------------------- /test/valid/valid.isUri.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var valid = require('../../lib/utils/inputValidator'); 4 | 5 | 6 | describe('valid.isUri', function() { 7 | 8 | var tests = [ 9 | 'udp://8.8.8.8:14265', 10 | 'udp://[2001:db8:a0b:12f0::1]', 11 | 'udp://domain2.com', 12 | 'http://8.8.8.8:14265', 13 | 1234 14 | ] 15 | 16 | // 0 test 17 | it('should be valid isUri: ' + tests[0], function() { 18 | 19 | var isUri = valid.isUri(tests[0]); 20 | assert.isTrue(isUri); 21 | }) 22 | 23 | // 1 test 24 | it('should be valid isUri: ' + tests[1], function() { 25 | 26 | var isUri = valid.isUri(tests[1]); 27 | assert.isTrue(isUri); 28 | }) 29 | 30 | // 2 test 31 | it('should be valid isUri: ' + tests[2], function() { 32 | 33 | var isUri = valid.isUri(tests[2]); 34 | assert.isTrue(isUri); 35 | }) 36 | 37 | // 3 test 38 | it('should be invalid isUri: ' + tests[3], function() { 39 | 40 | var isUri = valid.isUri(tests[3]); 41 | assert.isFalse(isUri); 42 | }) 43 | 44 | // 3 test 45 | it('should be invalid isUri: ' + tests[4], function() { 46 | 47 | var isUri = valid.isUri(tests[4]); 48 | assert.isFalse(isUri); 49 | }) 50 | }); 51 | -------------------------------------------------------------------------------- /test/valid/valid.isValue.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var assert = chai.assert; 3 | var valid = require('../../lib/utils/inputValidator'); 4 | 5 | 6 | describe('valid.isValue', function() { 7 | 8 | var tests = [ 9 | 1234432, 10 | '12344321', 11 | 11234.0001, 12 | -130500, 13 | '12432.04321' 14 | 15 | ] 16 | 17 | // 0 test 18 | it('should be valid isValue: ' + tests[0], function() { 19 | 20 | var isValid = valid.isValue(tests[0]); 21 | assert.isTrue(isValid); 22 | }) 23 | 24 | // 1 test 25 | it('should be invalid isValue: ' + tests[1], function() { 26 | 27 | var isValid = valid.isValue(tests[1]); 28 | assert.isFalse(isValid); 29 | }) 30 | 31 | // 2 test 32 | it('should be invalid isValue: ' + tests[2], function() { 33 | 34 | var isValid = valid.isValue(tests[2]); 35 | assert.isFalse(isValid); 36 | }) 37 | 38 | // 3 test 39 | it('should be invalid isValue: ' + tests[3], function() { 40 | 41 | var isValid = valid.isValue(tests[3]); 42 | assert.isTrue(isValid); 43 | }) 44 | 45 | // 4 test 46 | it('should be invalid isValue: ' + tests[4], function() { 47 | 48 | var isValid = valid.isValue(tests[4]); 49 | assert.isFalse(isValid); 50 | }) 51 | 52 | }); 53 | --------------------------------------------------------------------------------