diff --git a/README.md b/README.md index 789eabc0..4b3b78fd 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,7 @@ npm install wallet-address-validator * Monero/XMR, `'monero'` or `'XMR'` * Namecoin/NMC, `'namecoin'` or `'NMC'` +* Nano/NANO, `'nano'` or `'NANO'` * NEO/NEO, `'NEO'` or `'NEO'` * NeoGas/GAS, `'neogas'` or `'GAS'` @@ -76,6 +77,7 @@ npm install wallet-address-validator * Qtum/QTUM, `'qtum'` or `'QTUM'` +* Raiblocks/XRB, `'raiblocks'` or `'XRB'` * Ripple/XRP, `'ripple'` or `'XRP'` * Snowgem/SNG, `'snowgem'` or `'SNG'` diff --git a/dist/wallet-address-validator.js b/dist/wallet-address-validator.js index 0690d415..408a78e5 100644 --- a/dist/wallet-address-validator.js +++ b/dist/wallet-address-validator.js @@ -2392,7 +2392,7 @@ module.exports = { } }; -},{"./crypto/base58":9,"./crypto/segwit_addr":14,"./crypto/utils":16}],9:[function(require,module,exports){ +},{"./crypto/base58":9,"./crypto/segwit_addr":15,"./crypto/utils":17}],9:[function(require,module,exports){ // Base58 encoding/decoding // Originally written by Mike Hearn for BitcoinJ // Copyright (c) 2011 Google Inc @@ -4201,6 +4201,283 @@ Blake256.prototype.digest = function (encoding) { module.exports = Blake256; }).call(this,require("buffer").Buffer) },{"buffer":3}],13:[function(require,module,exports){ +'use strict'; + +/** + * Credits to https://github.com/emilbayes/blake2b + * + * Copyright (c) 2017, Emil Bay github@tixz.dk + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +// 64-bit unsigned addition +// Sets v[a,a+1] += v[b,b+1] +// v should be a Uint32Array +function ADD64AA (v, a, b) { + var o0 = v[a] + v[b] + var o1 = v[a + 1] + v[b + 1] + if (o0 >= 0x100000000) { + o1++ + } + v[a] = o0 + v[a + 1] = o1 +} + +// 64-bit unsigned addition +// Sets v[a,a+1] += b +// b0 is the low 32 bits of b, b1 represents the high 32 bits +function ADD64AC (v, a, b0, b1) { + var o0 = v[a] + b0 + if (b0 < 0) { + o0 += 0x100000000 + } + var o1 = v[a + 1] + b1 + if (o0 >= 0x100000000) { + o1++ + } + v[a] = o0 + v[a + 1] = o1 +} + +// Little-endian byte access +function B2B_GET32 (arr, i) { + return (arr[i] ^ + (arr[i + 1] << 8) ^ + (arr[i + 2] << 16) ^ + (arr[i + 3] << 24)) +} + +// G Mixing function +// The ROTRs are inlined for speed +function B2B_G (a, b, c, d, ix, iy) { + var x0 = m[ix] + var x1 = m[ix + 1] + var y0 = m[iy] + var y1 = m[iy + 1] + + ADD64AA(v, a, b) // v[a,a+1] += v[b,b+1] ... in JS we must store a uint64 as two uint32s + ADD64AC(v, a, x0, x1) // v[a, a+1] += x ... x0 is the low 32 bits of x, x1 is the high 32 bits + + // v[d,d+1] = (v[d,d+1] xor v[a,a+1]) rotated to the right by 32 bits + var xor0 = v[d] ^ v[a] + var xor1 = v[d + 1] ^ v[a + 1] + v[d] = xor1 + v[d + 1] = xor0 + + ADD64AA(v, c, d) + + // v[b,b+1] = (v[b,b+1] xor v[c,c+1]) rotated right by 24 bits + xor0 = v[b] ^ v[c] + xor1 = v[b + 1] ^ v[c + 1] + v[b] = (xor0 >>> 24) ^ (xor1 << 8) + v[b + 1] = (xor1 >>> 24) ^ (xor0 << 8) + + ADD64AA(v, a, b) + ADD64AC(v, a, y0, y1) + + // v[d,d+1] = (v[d,d+1] xor v[a,a+1]) rotated right by 16 bits + xor0 = v[d] ^ v[a] + xor1 = v[d + 1] ^ v[a + 1] + v[d] = (xor0 >>> 16) ^ (xor1 << 16) + v[d + 1] = (xor1 >>> 16) ^ (xor0 << 16) + + ADD64AA(v, c, d) + + // v[b,b+1] = (v[b,b+1] xor v[c,c+1]) rotated right by 63 bits + xor0 = v[b] ^ v[c] + xor1 = v[b + 1] ^ v[c + 1] + v[b] = (xor1 >>> 31) ^ (xor0 << 1) + v[b + 1] = (xor0 >>> 31) ^ (xor1 << 1) +} + +// Initialization Vector +var BLAKE2B_IV32 = new Uint32Array([ + 0xF3BCC908, 0x6A09E667, 0x84CAA73B, 0xBB67AE85, + 0xFE94F82B, 0x3C6EF372, 0x5F1D36F1, 0xA54FF53A, + 0xADE682D1, 0x510E527F, 0x2B3E6C1F, 0x9B05688C, + 0xFB41BD6B, 0x1F83D9AB, 0x137E2179, 0x5BE0CD19 +]) + +var SIGMA8 = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3, + 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4, + 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8, + 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13, + 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9, + 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11, + 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10, + 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5, + 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 +] + +// These are offsets into a uint64 buffer. +// Multiply them all by 2 to make them offsets into a uint32 buffer, +// because this is Javascript and we don't have uint64s +var SIGMA82 = new Uint8Array(SIGMA8.map(function (x) { return x * 2 })) + +// Compression function. 'last' flag indicates last block. +// Note we're representing 16 uint64s as 32 uint32s +var v = new Uint32Array(32) +var m = new Uint32Array(32) +function blake2bCompress (ctx, last) { + var i = 0 + + // init work variables + for (i = 0; i < 16; i++) { + v[i] = ctx.h[i] + v[i + 16] = BLAKE2B_IV32[i] + } + + // low 64 bits of offset + v[24] = v[24] ^ ctx.t + v[25] = v[25] ^ (ctx.t / 0x100000000) + // high 64 bits not supported, offset may not be higher than 2**53-1 + + // last block flag set ? + if (last) { + v[28] = ~v[28] + v[29] = ~v[29] + } + + // get little-endian words + for (i = 0; i < 32; i++) { + m[i] = B2B_GET32(ctx.b, 4 * i) + } + + // twelve rounds of mixing + for (i = 0; i < 12; i++) { + B2B_G(0, 8, 16, 24, SIGMA82[i * 16 + 0], SIGMA82[i * 16 + 1]) + B2B_G(2, 10, 18, 26, SIGMA82[i * 16 + 2], SIGMA82[i * 16 + 3]) + B2B_G(4, 12, 20, 28, SIGMA82[i * 16 + 4], SIGMA82[i * 16 + 5]) + B2B_G(6, 14, 22, 30, SIGMA82[i * 16 + 6], SIGMA82[i * 16 + 7]) + B2B_G(0, 10, 20, 30, SIGMA82[i * 16 + 8], SIGMA82[i * 16 + 9]) + B2B_G(2, 12, 22, 24, SIGMA82[i * 16 + 10], SIGMA82[i * 16 + 11]) + B2B_G(4, 14, 16, 26, SIGMA82[i * 16 + 12], SIGMA82[i * 16 + 13]) + B2B_G(6, 8, 18, 28, SIGMA82[i * 16 + 14], SIGMA82[i * 16 + 15]) + } + + for (i = 0; i < 16; i++) { + ctx.h[i] = ctx.h[i] ^ v[i] ^ v[i + 16] + } +} + +// reusable parameter_block +var parameter_block = new Uint8Array([ + 0, 0, 0, 0, // 0: outlen, keylen, fanout, depth + 0, 0, 0, 0, // 4: leaf length, sequential mode + 0, 0, 0, 0, // 8: node offset + 0, 0, 0, 0, // 12: node offset + 0, 0, 0, 0, // 16: node depth, inner length, rfu + 0, 0, 0, 0, // 20: rfu + 0, 0, 0, 0, // 24: rfu + 0, 0, 0, 0, // 28: rfu + 0, 0, 0, 0, // 32: salt + 0, 0, 0, 0, // 36: salt + 0, 0, 0, 0, // 40: salt + 0, 0, 0, 0, // 44: salt + 0, 0, 0, 0, // 48: personal + 0, 0, 0, 0, // 52: personal + 0, 0, 0, 0, // 56: personal + 0, 0, 0, 0 // 60: personal +]) + +// Creates a BLAKE2b hashing context +// Requires an output length between 1 and 64 bytes +// Takes an optional Uint8Array key +function Blake2b (outlen, key, salt, personal) { + // zero out parameter_block before usage + parameter_block.fill(0) + // state, 'param block' + + this.b = new Uint8Array(128) + this.h = new Uint32Array(16) + this.t = 0 // input count + this.c = 0 // pointer within buffer + this.outlen = outlen // output length in bytes + + parameter_block[0] = outlen + if (key) parameter_block[1] = key.length + parameter_block[2] = 1 // fanout + parameter_block[3] = 1 // depth + + if (salt) parameter_block.set(salt, 32) + if (personal) parameter_block.set(personal, 48) + + // initialize hash state + for (var i = 0; i < 16; i++) { + this.h[i] = BLAKE2B_IV32[i] ^ B2B_GET32(parameter_block, i * 4) + } + + // key the hash, if applicable + if (key) { + blake2bUpdate(this, key) + // at the end + this.c = 128 + } +} + +Blake2b.prototype.update = function (input) { + blake2bUpdate(this, input) + return this +} + +Blake2b.prototype.digest = function (out) { + var buf = (!out || out === 'binary' || out === 'hex') ? new Uint8Array(this.outlen) : out + blake2bFinal(this, buf) + if (out === 'hex') return hexSlice(buf) + return buf +} + +Blake2b.prototype.final = Blake2b.prototype.digest + +// Updates a BLAKE2b streaming hash +// Requires hash context and Uint8Array (byte array) +function blake2bUpdate (ctx, input) { + for (var i = 0; i < input.length; i++) { + if (ctx.c === 128) { // buffer full ? + ctx.t += ctx.c // add counters + blake2bCompress(ctx, false) // compress (not last) + ctx.c = 0 // counter to zero + } + ctx.b[ctx.c++] = input[i] + } +} + +// Completes a BLAKE2b streaming hash +// Returns a Uint8Array containing the message digest +function blake2bFinal (ctx, out) { + ctx.t += ctx.c // mark last block offset + + while (ctx.c < 128) { // fill up with zeros + ctx.b[ctx.c++] = 0 + } + blake2bCompress(ctx, true) // final block flag = 1 + + for (var i = 0; i < ctx.outlen; i++) { + out[i] = ctx.h[i >> 2] >> (8 * (i & 3)) + } + return out +} + +function hexSlice (buf) { + var str = '' + for (var i = 0; i < buf.length; i++) str += toHex(buf[i]) + return str +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +module.exports = Blake2b; +},{}],14:[function(require,module,exports){ var JSBigInt = require('./biginteger')['JSBigInt']; /** @@ -4427,7 +4704,7 @@ var cnBase58 = (function () { return b58; })(); module.exports = cnBase58; -},{"./biginteger":11}],14:[function(require,module,exports){ +},{"./biginteger":11}],15:[function(require,module,exports){ // Copyright (c) 2017 Pieter Wuille // // Permission is hereby granted, free of charge, to any person obtaining a copy @@ -4523,7 +4800,7 @@ module.exports = { isValidAddress: isValidAddress, }; -},{"./bech32":10}],15:[function(require,module,exports){ +},{"./bech32":10}],16:[function(require,module,exports){ (function (process,global){ /** * [js-sha3]{@link https://github.com/emn178/js-sha3} @@ -5167,10 +5444,11 @@ var f = function (s) { module.exports = methods; }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"_process":6}],16:[function(require,module,exports){ +},{"_process":6}],17:[function(require,module,exports){ var jsSHA = require('jssha/src/sha256'); var Blake256 = require('./blake256'); var keccak256 = require('./sha3')['keccak256']; +var Blake2B = require('./blake2b'); function numberToHex (number) { var hex = Math.round(number).toString(16); @@ -5180,6 +5458,15 @@ function numberToHex (number) { return hex; } +function hexToUint8(hexString) { + var arr = []; + for (var i = 0; i < hexString.length; i += 2) { + arr.push(parseInt(hexString.substr(i, 2), 16)); + } + + return new Uint8Array(arr); +} + module.exports = { toHex: function (arrayOfBytes) { var hex = ''; @@ -5202,6 +5489,9 @@ module.exports = { blake256Checksum: function (payload) { return this.blake256(this.blake256(payload)).substr(0, 8); }, + blake2b: function (hexString, outlen) { + return new Blake2B(outlen).update(hexToUint8(hexString)).digest('hex'); + }, keccak256: function (hexString) { return keccak256(hexString); }, @@ -5210,11 +5500,12 @@ module.exports = { } }; -},{"./blake256":12,"./sha3":15,"jssha/src/sha256":5}],17:[function(require,module,exports){ +},{"./blake256":12,"./blake2b":13,"./sha3":16,"jssha/src/sha256":5}],18:[function(require,module,exports){ var XRPValidator = require('./ripple_validator'); var ETHValidator = require('./ethereum_validator'); var BTCValidator = require('./bitcoin_validator'); var XMRValidator = require('./monero_validator'); +var NANOValidator = require('./nano_validator'); // defines P2PKH and P2SH address types for standard (prod) and testnet networks var CURRENCIES = [{ @@ -5413,6 +5704,14 @@ var CURRENCIES = [{ addressTypes: {prod: ['18'], testnet: ['53']}, iAddressTypes: {prod: ['19'], testnet: ['54']}, validator: XMRValidator +},{ + name: 'nano', + symbol: 'nano', + validator: NANOValidator, +},{ + name: 'raiblocks', + symbol: 'xrb', + validator: NANOValidator, }]; @@ -5429,7 +5728,7 @@ module.exports = { } }; -},{"./bitcoin_validator":8,"./ethereum_validator":18,"./monero_validator":19,"./ripple_validator":20}],18:[function(require,module,exports){ +},{"./bitcoin_validator":8,"./ethereum_validator":19,"./monero_validator":20,"./nano_validator":21,"./ripple_validator":22}],19:[function(require,module,exports){ var cryptoUtils = require('./crypto/utils'); module.exports = { @@ -5465,7 +5764,7 @@ module.exports = { } }; -},{"./crypto/utils":16}],19:[function(require,module,exports){ +},{"./crypto/utils":17}],20:[function(require,module,exports){ var cryptoUtils = require('./crypto/utils'); var cnBase58 = require('./crypto/cnBase58'); @@ -5527,7 +5826,36 @@ module.exports = { } }; -},{"./crypto/cnBase58":13,"./crypto/utils":16}],20:[function(require,module,exports){ +},{"./crypto/cnBase58":14,"./crypto/utils":17}],21:[function(require,module,exports){ +var cryptoUtils = require('./crypto/utils'); +var baseX = require('base-x'); + +var ALLOWED_CHARS = '13456789abcdefghijkmnopqrstuwxyz'; + +var codec = baseX(ALLOWED_CHARS); +// https://github.com/nanocurrency/raiblocks/wiki/Accounts,-Keys,-Seeds,-and-Wallet-Identifiers +var regexp = new RegExp('^(xrb|nano)_([' + ALLOWED_CHARS + ']{60})$'); + +module.exports = { + isValidAddress: function (address) { + if (regexp.test(address)) { + return this.verifyChecksum(address); + } + + return false; + }, + + verifyChecksum: function (address) { + var bytes = codec.decode(regexp.exec(address)[2]).slice(-37); + // https://github.com/nanocurrency/raiblocks/blob/master/rai/lib/numbers.cpp#L73 + var computedChecksum = cryptoUtils.blake2b(cryptoUtils.toHex(bytes.slice(0, -5)), 5); + var checksum = cryptoUtils.toHex(bytes.slice(-5).reverse()); + + return computedChecksum === checksum + } +}; + +},{"./crypto/utils":17,"base-x":1}],22:[function(require,module,exports){ var cryptoUtils = require('./crypto/utils'); var baseX = require('base-x'); @@ -5557,7 +5885,7 @@ module.exports = { } }; -},{"./crypto/utils":16,"base-x":1}],21:[function(require,module,exports){ +},{"./crypto/utils":17,"base-x":1}],23:[function(require,module,exports){ var currencies = require('./currencies'); var DEFAULT_CURRENCY_NAME = 'bitcoin'; @@ -5574,5 +5902,5 @@ module.exports = { }, }; -},{"./currencies":17}]},{},[21])(21) +},{"./currencies":18}]},{},[23])(23) }); \ No newline at end of file diff --git a/dist/wallet-address-validator.min.js b/dist/wallet-address-validator.min.js index 7a2b4ca2..407ffa71 100644 --- a/dist/wallet-address-validator.min.js +++ b/dist/wallet-address-validator.min.js @@ -1 +1 @@ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).WAValidator=t()}}(function(){return function o(s,a,u){function f(e,t){if(!a[e]){if(!s[e]){var r="function"==typeof require&&require;if(!t&&r)return r(e,!0);if(h)return h(e,!0);var n=new Error("Cannot find module '"+e+"'");throw n.code="MODULE_NOT_FOUND",n}var i=a[e]={exports:{}};s[e][0].call(i.exports,function(t){var r=s[e][1][t];return f(r||t)},i,i.exports,o,s,a,u)}return a[e].exports}for(var h="function"==typeof require&&require,t=0;t>=8;for(;0>=8}for(var s=0;t[s]===h&&s>16&255,o[a++]=n>>8&255,o[a++]=255&n;2===i?(n=f[t.charCodeAt(r)]<<2|f[t.charCodeAt(r+1)]>>4,o[a++]=255&n):1===i&&(n=f[t.charCodeAt(r)]<<10|f[t.charCodeAt(r+1)]<<4|f[t.charCodeAt(r+2)]>>2,o[a++]=n>>8&255,o[a++]=255&n);return o},e.fromByteArray=function(t){for(var r,e=t.length,n=e%3,i="",o=[],s=0,a=e-n;s>2],i+=u[r<<4&63],i+="=="):2===n&&(r=(t[e-2]<<8)+t[e-1],i+=u[r>>10],i+=u[r>>4&63],i+=u[r<<2&63],i+="=");return o.push(i),o.join("")};for(var u=[],f=[],h="undefined"!=typeof Uint8Array?Uint8Array:Array,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",i=0,o=n.length;i>18&63]+u[i>>12&63]+u[i>>6&63]+u[63&i]);return o.join("")}f["-".charCodeAt(0)]=62,f["_".charCodeAt(0)]=63},{}],3:[function(t,r,e){"use strict";var n=t("base64-js"),o=t("ieee754");e.Buffer=c,e.SlowBuffer=function(t){+t!=t&&(t=0);return c.alloc(+t)},e.INSPECT_MAX_BYTES=50;var i=2147483647;function s(t){if(i>>1;case"base64":return O(t).length;default:if(n)return L(t).length;r=(""+r).toLowerCase(),n=!0}}function d(t,r,e){var n=t[r];t[r]=t[e],t[e]=n}function g(t,r,e,n,i){if(0===t.length)return-1;if("string"==typeof e?(n=e,e=0):2147483647=t.length){if(i)return-1;e=t.length-1}else if(e<0){if(!i)return-1;e=0}if("string"==typeof r&&(r=c.from(r,n)),c.isBuffer(r))return 0===r.length?-1:y(t,r,e,n,i);if("number"==typeof r)return r&=255,"function"==typeof Uint8Array.prototype.indexOf?i?Uint8Array.prototype.indexOf.call(t,r,e):Uint8Array.prototype.lastIndexOf.call(t,r,e):y(t,[r],e,n,i);throw new TypeError("val must be string, number or Buffer")}function y(t,r,e,n,i){var o,s=1,a=t.length,u=r.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||r.length<2)return-1;a/=s=2,u/=2,e/=2}function f(t,r){return 1===s?t[r]:t.readUInt16BE(r*s)}if(i){var h=-1;for(o=e;o>>10&1023|55296),h=56320|1023&h),n.push(h),i+=c}return function(t){var r=t.length;if(r<=_)return String.fromCharCode.apply(String,t);var e="",n=0;for(;nthis.length)return"";if((void 0===e||e>this.length)&&(e=this.length),e<=0)return"";if((e>>>=0)<=(r>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return B(this,r,e);case"utf8":case"utf-8":return m(this,r,e);case"ascii":return A(this,r,e);case"latin1":case"binary":return E(this,r,e);case"base64":return b(this,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return k(this,r,e);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}.apply(this,arguments)},c.prototype.equals=function(t){if(!c.isBuffer(t))throw new TypeError("Argument must be a Buffer");return this===t||0===c.compare(this,t)},c.prototype.inspect=function(){var t="",r=e.INSPECT_MAX_BYTES;return 0r&&(t+=" ... ")),""},c.prototype.compare=function(t,r,e,n,i){if(!c.isBuffer(t))throw new TypeError("Argument must be a Buffer");if(void 0===r&&(r=0),void 0===e&&(e=t?t.length:0),void 0===n&&(n=0),void 0===i&&(i=this.length),r<0||e>t.length||n<0||i>this.length)throw new RangeError("out of range index");if(i<=n&&e<=r)return 0;if(i<=n)return-1;if(e<=r)return 1;if(this===t)return 0;for(var o=(i>>>=0)-(n>>>=0),s=(e>>>=0)-(r>>>=0),a=Math.min(o,s),u=this.slice(n,i),f=t.slice(r,e),h=0;h>>=0,isFinite(e)?(e>>>=0,void 0===n&&(n="utf8")):(n=e,e=void 0)}var i=this.length-r;if((void 0===e||ithis.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var o,s,a,u,f,h,c,l,p,d=!1;;)switch(n){case"hex":return v(this,t,r,e);case"utf8":case"utf-8":return l=r,p=e,M(L(t,(c=this).length-l),c,l,p);case"ascii":return w(this,t,r,e);case"latin1":case"binary":return w(this,t,r,e);case"base64":return u=this,f=r,h=e,M(O(t),u,f,h);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return s=r,a=e,M(function(t,r){for(var e,n,i,o=[],s=0;s>8,i=e%256,o.push(i),o.push(n);return o}(t,(o=this).length-s),o,s,a);default:if(d)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),d=!0}},c.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var _=4096;function A(t,r,e){var n="";e=Math.min(t.length,e);for(var i=r;it.length)throw new RangeError("Index out of range")}function S(t,r,e,n,i,o){if(e+n>t.length)throw new RangeError("Index out of range");if(e<0)throw new RangeError("Index out of range")}function U(t,r,e,n,i){return r=+r,e>>>=0,i||S(t,0,e,4),o.write(t,r,e,n,23,4),e+4}function C(t,r,e,n,i){return r=+r,e>>>=0,i||S(t,0,e,8),o.write(t,r,e,n,52,8),e+8}c.prototype.slice=function(t,r){var e=this.length;(t=~~t)<0?(t+=e)<0&&(t=0):e>>=0,r>>>=0,e||x(t,r,this.length);for(var n=this[t],i=1,o=0;++o>>=0,r>>>=0,e||x(t,r,this.length);for(var n=this[t+--r],i=1;0>>=0,r||x(t,1,this.length),this[t]},c.prototype.readUInt16LE=function(t,r){return t>>>=0,r||x(t,2,this.length),this[t]|this[t+1]<<8},c.prototype.readUInt16BE=function(t,r){return t>>>=0,r||x(t,2,this.length),this[t]<<8|this[t+1]},c.prototype.readUInt32LE=function(t,r){return t>>>=0,r||x(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},c.prototype.readUInt32BE=function(t,r){return t>>>=0,r||x(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},c.prototype.readIntLE=function(t,r,e){t>>>=0,r>>>=0,e||x(t,r,this.length);for(var n=this[t],i=1,o=0;++o>>=0,r>>>=0,e||x(t,r,this.length);for(var n=r,i=1,o=this[t+--n];0>>=0,r||x(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},c.prototype.readInt16LE=function(t,r){t>>>=0,r||x(t,2,this.length);var e=this[t]|this[t+1]<<8;return 32768&e?4294901760|e:e},c.prototype.readInt16BE=function(t,r){t>>>=0,r||x(t,2,this.length);var e=this[t+1]|this[t]<<8;return 32768&e?4294901760|e:e},c.prototype.readInt32LE=function(t,r){return t>>>=0,r||x(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},c.prototype.readInt32BE=function(t,r){return t>>>=0,r||x(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},c.prototype.readFloatLE=function(t,r){return t>>>=0,r||x(t,4,this.length),o.read(this,t,!0,23,4)},c.prototype.readFloatBE=function(t,r){return t>>>=0,r||x(t,4,this.length),o.read(this,t,!1,23,4)},c.prototype.readDoubleLE=function(t,r){return t>>>=0,r||x(t,8,this.length),o.read(this,t,!0,52,8)},c.prototype.readDoubleBE=function(t,r){return t>>>=0,r||x(t,8,this.length),o.read(this,t,!1,52,8)},c.prototype.writeUIntLE=function(t,r,e,n){(t=+t,r>>>=0,e>>>=0,n)||T(this,t,r,e,Math.pow(2,8*e)-1,0);var i=1,o=0;for(this[r]=255&t;++o>>=0,e>>>=0,n)||T(this,t,r,e,Math.pow(2,8*e)-1,0);var i=e-1,o=1;for(this[r+i]=255&t;0<=--i&&(o*=256);)this[r+i]=t/o&255;return r+e},c.prototype.writeUInt8=function(t,r,e){return t=+t,r>>>=0,e||T(this,t,r,1,255,0),this[r]=255&t,r+1},c.prototype.writeUInt16LE=function(t,r,e){return t=+t,r>>>=0,e||T(this,t,r,2,65535,0),this[r]=255&t,this[r+1]=t>>>8,r+2},c.prototype.writeUInt16BE=function(t,r,e){return t=+t,r>>>=0,e||T(this,t,r,2,65535,0),this[r]=t>>>8,this[r+1]=255&t,r+2},c.prototype.writeUInt32LE=function(t,r,e){return t=+t,r>>>=0,e||T(this,t,r,4,4294967295,0),this[r+3]=t>>>24,this[r+2]=t>>>16,this[r+1]=t>>>8,this[r]=255&t,r+4},c.prototype.writeUInt32BE=function(t,r,e){return t=+t,r>>>=0,e||T(this,t,r,4,4294967295,0),this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t,r+4},c.prototype.writeIntLE=function(t,r,e,n){if(t=+t,r>>>=0,!n){var i=Math.pow(2,8*e-1);T(this,t,r,e,i-1,-i)}var o=0,s=1,a=0;for(this[r]=255&t;++o>0)-a&255;return r+e},c.prototype.writeIntBE=function(t,r,e,n){if(t=+t,r>>>=0,!n){var i=Math.pow(2,8*e-1);T(this,t,r,e,i-1,-i)}var o=e-1,s=1,a=0;for(this[r+o]=255&t;0<=--o&&(s*=256);)t<0&&0===a&&0!==this[r+o+1]&&(a=1),this[r+o]=(t/s>>0)-a&255;return r+e},c.prototype.writeInt8=function(t,r,e){return t=+t,r>>>=0,e||T(this,t,r,1,127,-128),t<0&&(t=255+t+1),this[r]=255&t,r+1},c.prototype.writeInt16LE=function(t,r,e){return t=+t,r>>>=0,e||T(this,t,r,2,32767,-32768),this[r]=255&t,this[r+1]=t>>>8,r+2},c.prototype.writeInt16BE=function(t,r,e){return t=+t,r>>>=0,e||T(this,t,r,2,32767,-32768),this[r]=t>>>8,this[r+1]=255&t,r+2},c.prototype.writeInt32LE=function(t,r,e){return t=+t,r>>>=0,e||T(this,t,r,4,2147483647,-2147483648),this[r]=255&t,this[r+1]=t>>>8,this[r+2]=t>>>16,this[r+3]=t>>>24,r+4},c.prototype.writeInt32BE=function(t,r,e){return t=+t,r>>>=0,e||T(this,t,r,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t,r+4},c.prototype.writeFloatLE=function(t,r,e){return U(this,t,r,!0,e)},c.prototype.writeFloatBE=function(t,r,e){return U(this,t,r,!1,e)},c.prototype.writeDoubleLE=function(t,r,e){return C(this,t,r,!0,e)},c.prototype.writeDoubleBE=function(t,r,e){return C(this,t,r,!1,e)},c.prototype.copy=function(t,r,e,n){if(!c.isBuffer(t))throw new TypeError("argument should be a Buffer");if(e||(e=0),n||0===n||(n=this.length),r>=t.length&&(r=t.length),r||(r=0),0=this.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-r>>=0,e=void 0===e?this.length:e>>>0,t||(t=0),"number"==typeof t)for(o=r;o>6|192,63&e|128)}else if(e<65536){if((r-=3)<0)break;o.push(e>>12|224,e>>6&63|128,63&e|128)}else{if(!(e<1114112))throw new Error("Invalid code point");if((r-=4)<0)break;o.push(e>>18|240,e>>12&63|128,e>>6&63|128,63&e|128)}}return o}function O(t){return n.toByteArray(function(t){if((t=(t=t.split("=")[0]).trim().replace(I,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function M(t,r,e,n){for(var i=0;i=r.length||i>=t.length);++i)r[i+e]=t[i];return i}function H(t){return t instanceof ArrayBuffer||null!=t&&null!=t.constructor&&"ArrayBuffer"===t.constructor.name&&"number"==typeof t.byteLength}function F(t){return t!=t}},{"base64-js":2,ieee754:4}],4:[function(t,r,e){e.read=function(t,r,e,n,i){var o,s,a=8*i-n-1,u=(1<>1,h=-7,c=e?i-1:0,l=e?-1:1,p=t[r+c];for(c+=l,o=p&(1<<-h)-1,p>>=-h,h+=a;0>=-h,h+=n;0>1,l=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,p=n?0:o-1,d=n?1:-1,g=r<0||0===r&&1/r<0?1:0;for(r=Math.abs(r),isNaN(r)||r===1/0?(a=isNaN(r)?1:0,s=h):(s=Math.floor(Math.log(r)/Math.LN2),r*(u=Math.pow(2,-s))<1&&(s--,u*=2),2<=(r+=1<=s+c?l/u:l*Math.pow(2,1-c))*u&&(s++,u/=2),h<=s+c?(a=0,s=h):1<=s+c?(a=(r*u-1)*Math.pow(2,i),s+=c):(a=r*Math.pow(2,c-1)*Math.pow(2,i),s=0));8<=i;t[e+p]=255&a,p+=d,a/=256,i-=8);for(s=s<= 1");if(0!==s.lastIndexOf("SHA-",0))throw Error("Chosen SHA variant is not supported");if(c=function(t,r){return F(t,r,s)},l=function(t,r,e,n){var i,o;if("SHA-224"!==s&&"SHA-256"!==s)throw Error("Unexpected error in SHA-2 implementation");for(i=15+(r+65>>>9<<4),o=16;t.length<=i;)t.push(0);for(t[r>>>5]|=128<<24-r%32,r+=e,t[i]=4294967295&r,t[i-1]=r/4294967296|0,e=t.length,r=0;r>>3)/4-1,n>>5;for(t=(r=u(t,y,v)).binLen,e=r.value,r=t>>>5,n=0;n>>5),v=t%h,m=!0},this.getHash=function(t,r){var e,n,i,o;if(!0===w)throw Error("Cannot call getHash after setting HMAC key");switch(i=k(r),t){case"HEX":e=function(t){return _(t,f,i)};break;case"B64":e=function(t){return A(t,f,i)};break;case"BYTES":e=function(t){return E(t,f)};break;case"ARRAYBUFFER":try{n=new ArrayBuffer(0)}catch(t){throw Error("ARRAYBUFFER not supported by this environment")}e=function(t){return B(t,f)};break;default:throw Error("format must be HEX, B64, BYTES, or ARRAYBUFFER")}for(o=l(y.slice(),v,g,p(a)),n=1;n>>2]>>>8*(3+n%4*-1),o+="0123456789abcdef".charAt(i>>>4&15)+"0123456789abcdef".charAt(15&i);return e.outputUpper?o.toUpperCase():o}function A(t,r,e){var n,i,o,s="",a=r/8;for(n=0;n>>2]:0,o=n+2>>2]:0,o=(t[n>>>2]>>>8*(3+n%4*-1)&255)<<16|(i>>>8*(3+(n+1)%4*-1)&255)<<8|o>>>8*(3+(n+2)%4*-1)&255,i=0;i<4;i+=1)s+=8*n+6*i<=r?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(o>>>6*(3-i)&63):e.b64Pad;return s}function E(t,r){var e,n,i="",o=r/8;for(e=0;e>>2]>>>8*(3+e%4*-1)&255,i+=String.fromCharCode(n);return i}function B(t,r){var e,n,i=r/8,o=new ArrayBuffer(i);for(n=new Uint8Array(o),e=0;e>>2]>>>8*(3+e%4*-1)&255;return o}function k(t){var r={outputUpper:!1,b64Pad:"=",shakeLen:-1};if(t=t||{},r.outputUpper=t.outputUpper||!1,!0===t.hasOwnProperty("b64Pad")&&(r.b64Pad=t.b64Pad),"boolean"!=typeof r.outputUpper)throw Error("Invalid outputUpper formatting option");if("string"!=typeof r.b64Pad)throw Error("Invalid b64Pad formatting option");return r}function x(t,l){var r;switch(l){case"UTF8":case"UTF16BE":case"UTF16LE":break;default:throw Error("encoding must be UTF8, UTF16BE, or UTF16LE")}switch(t){case"HEX":r=function(t,r,e){var n,i,o,s,a,u=t.length;if(0!=u%2)throw Error("String of HEX type must be in byte increments");for(r=r||[0],a=(e=e||0)>>>3,n=0;n>>1)+a)>>>2;r.length<=o;)r.push(0);r[o]|=i<<8*(3+s%4*-1)}return{value:r,binLen:4*u+e}};break;case"TEXT":r=function(t,r,e){var n,i,o,s,a,u,f,h,c=0;if(r=r||[0],a=(e=e||0)>>>3,"UTF8"===l)for(h=3,o=0;o>>6),i.push(128|63&n)):n<55296||57344<=n?i.push(224|n>>>12,128|n>>>6&63,128|63&n):(o+=1,n=65536+((1023&n)<<10|1023&t.charCodeAt(o)),i.push(240|n>>>18,128|n>>>12&63,128|n>>>6&63,128|63&n)),s=0;s>>2;r.length<=u;)r.push(0);r[u]|=i[s]<<8*(h+f%4*-1),c+=1}else if("UTF16BE"===l||"UTF16LE"===l)for(h=2,i="UTF16LE"===l||"UTF16LE"!==l&&!1,o=0;o>>8),u=(f=c+a)>>>2;r.length<=u;)r.push(0);r[u]|=n<<8*(h+f%4*-1),c+=2}return{value:r,binLen:8*c+e}};break;case"B64":r=function(t,r,e){var n,i,o,s,a,u,f,h=0;if(-1===t.search(/^[a-zA-Z0-9=+\/]+$/))throw Error("Invalid character in base-64 string");if(i=t.indexOf("="),t=t.replace(/\=/g,""),-1!==i&&i>=8;for(;0>=8}for(var s=0;t[s]===h&&s>16&255,o[a++]=n>>8&255,o[a++]=255&n;2===i?(n=f[t.charCodeAt(r)]<<2|f[t.charCodeAt(r+1)]>>4,o[a++]=255&n):1===i&&(n=f[t.charCodeAt(r)]<<10|f[t.charCodeAt(r+1)]<<4|f[t.charCodeAt(r+2)]>>2,o[a++]=n>>8&255,o[a++]=255&n);return o},e.fromByteArray=function(t){for(var r,e=t.length,n=e%3,i="",o=[],s=0,a=e-n;s>2],i+=u[r<<4&63],i+="=="):2===n&&(r=(t[e-2]<<8)+t[e-1],i+=u[r>>10],i+=u[r>>4&63],i+=u[r<<2&63],i+="=");return o.push(i),o.join("")};for(var u=[],f=[],h="undefined"!=typeof Uint8Array?Uint8Array:Array,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",i=0,o=n.length;i>18&63]+u[i>>12&63]+u[i>>6&63]+u[63&i]);return o.join("")}f["-".charCodeAt(0)]=62,f["_".charCodeAt(0)]=63},{}],3:[function(t,r,e){"use strict";var n=t("base64-js"),o=t("ieee754");e.Buffer=c,e.SlowBuffer=function(t){+t!=t&&(t=0);return c.alloc(+t)},e.INSPECT_MAX_BYTES=50;var i=2147483647;function s(t){if(i>>1;case"base64":return O(t).length;default:if(n)return L(t).length;r=(""+r).toLowerCase(),n=!0}}function d(t,r,e){var n=t[r];t[r]=t[e],t[e]=n}function g(t,r,e,n,i){if(0===t.length)return-1;if("string"==typeof e?(n=e,e=0):2147483647=t.length){if(i)return-1;e=t.length-1}else if(e<0){if(!i)return-1;e=0}if("string"==typeof r&&(r=c.from(r,n)),c.isBuffer(r))return 0===r.length?-1:y(t,r,e,n,i);if("number"==typeof r)return r&=255,"function"==typeof Uint8Array.prototype.indexOf?i?Uint8Array.prototype.indexOf.call(t,r,e):Uint8Array.prototype.lastIndexOf.call(t,r,e):y(t,[r],e,n,i);throw new TypeError("val must be string, number or Buffer")}function y(t,r,e,n,i){var o,s=1,a=t.length,u=r.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||r.length<2)return-1;a/=s=2,u/=2,e/=2}function f(t,r){return 1===s?t[r]:t.readUInt16BE(r*s)}if(i){var h=-1;for(o=e;o>>10&1023|55296),h=56320|1023&h),n.push(h),i+=c}return function(t){var r=t.length;if(r<=_)return String.fromCharCode.apply(String,t);var e="",n=0;for(;nthis.length)return"";if((void 0===e||e>this.length)&&(e=this.length),e<=0)return"";if((e>>>=0)<=(r>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return x(this,r,e);case"utf8":case"utf-8":return m(this,r,e);case"ascii":return A(this,r,e);case"latin1":case"binary":return E(this,r,e);case"base64":return b(this,r,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return B(this,r,e);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}.apply(this,arguments)},c.prototype.equals=function(t){if(!c.isBuffer(t))throw new TypeError("Argument must be a Buffer");return this===t||0===c.compare(this,t)},c.prototype.inspect=function(){var t="",r=e.INSPECT_MAX_BYTES;return 0r&&(t+=" ... ")),""},c.prototype.compare=function(t,r,e,n,i){if(!c.isBuffer(t))throw new TypeError("Argument must be a Buffer");if(void 0===r&&(r=0),void 0===e&&(e=t?t.length:0),void 0===n&&(n=0),void 0===i&&(i=this.length),r<0||e>t.length||n<0||i>this.length)throw new RangeError("out of range index");if(i<=n&&e<=r)return 0;if(i<=n)return-1;if(e<=r)return 1;if(this===t)return 0;for(var o=(i>>>=0)-(n>>>=0),s=(e>>>=0)-(r>>>=0),a=Math.min(o,s),u=this.slice(n,i),f=t.slice(r,e),h=0;h>>=0,isFinite(e)?(e>>>=0,void 0===n&&(n="utf8")):(n=e,e=void 0)}var i=this.length-r;if((void 0===e||ithis.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var o,s,a,u,f,h,c,l,p,d=!1;;)switch(n){case"hex":return v(this,t,r,e);case"utf8":case"utf-8":return l=r,p=e,M(L(t,(c=this).length-l),c,l,p);case"ascii":return w(this,t,r,e);case"latin1":case"binary":return w(this,t,r,e);case"base64":return u=this,f=r,h=e,M(O(t),u,f,h);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return s=r,a=e,M(function(t,r){for(var e,n,i,o=[],s=0;s>8,i=e%256,o.push(i),o.push(n);return o}(t,(o=this).length-s),o,s,a);default:if(d)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),d=!0}},c.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var _=4096;function A(t,r,e){var n="";e=Math.min(t.length,e);for(var i=r;it.length)throw new RangeError("Index out of range")}function T(t,r,e,n,i,o){if(e+n>t.length)throw new RangeError("Index out of range");if(e<0)throw new RangeError("Index out of range")}function S(t,r,e,n,i){return r=+r,e>>>=0,i||T(t,0,e,4),o.write(t,r,e,n,23,4),e+4}function C(t,r,e,n,i){return r=+r,e>>>=0,i||T(t,0,e,8),o.write(t,r,e,n,52,8),e+8}c.prototype.slice=function(t,r){var e=this.length;(t=~~t)<0?(t+=e)<0&&(t=0):e>>=0,r>>>=0,e||k(t,r,this.length);for(var n=this[t],i=1,o=0;++o>>=0,r>>>=0,e||k(t,r,this.length);for(var n=this[t+--r],i=1;0>>=0,r||k(t,1,this.length),this[t]},c.prototype.readUInt16LE=function(t,r){return t>>>=0,r||k(t,2,this.length),this[t]|this[t+1]<<8},c.prototype.readUInt16BE=function(t,r){return t>>>=0,r||k(t,2,this.length),this[t]<<8|this[t+1]},c.prototype.readUInt32LE=function(t,r){return t>>>=0,r||k(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},c.prototype.readUInt32BE=function(t,r){return t>>>=0,r||k(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},c.prototype.readIntLE=function(t,r,e){t>>>=0,r>>>=0,e||k(t,r,this.length);for(var n=this[t],i=1,o=0;++o>>=0,r>>>=0,e||k(t,r,this.length);for(var n=r,i=1,o=this[t+--n];0>>=0,r||k(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},c.prototype.readInt16LE=function(t,r){t>>>=0,r||k(t,2,this.length);var e=this[t]|this[t+1]<<8;return 32768&e?4294901760|e:e},c.prototype.readInt16BE=function(t,r){t>>>=0,r||k(t,2,this.length);var e=this[t+1]|this[t]<<8;return 32768&e?4294901760|e:e},c.prototype.readInt32LE=function(t,r){return t>>>=0,r||k(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},c.prototype.readInt32BE=function(t,r){return t>>>=0,r||k(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},c.prototype.readFloatLE=function(t,r){return t>>>=0,r||k(t,4,this.length),o.read(this,t,!0,23,4)},c.prototype.readFloatBE=function(t,r){return t>>>=0,r||k(t,4,this.length),o.read(this,t,!1,23,4)},c.prototype.readDoubleLE=function(t,r){return t>>>=0,r||k(t,8,this.length),o.read(this,t,!0,52,8)},c.prototype.readDoubleBE=function(t,r){return t>>>=0,r||k(t,8,this.length),o.read(this,t,!1,52,8)},c.prototype.writeUIntLE=function(t,r,e,n){(t=+t,r>>>=0,e>>>=0,n)||U(this,t,r,e,Math.pow(2,8*e)-1,0);var i=1,o=0;for(this[r]=255&t;++o>>=0,e>>>=0,n)||U(this,t,r,e,Math.pow(2,8*e)-1,0);var i=e-1,o=1;for(this[r+i]=255&t;0<=--i&&(o*=256);)this[r+i]=t/o&255;return r+e},c.prototype.writeUInt8=function(t,r,e){return t=+t,r>>>=0,e||U(this,t,r,1,255,0),this[r]=255&t,r+1},c.prototype.writeUInt16LE=function(t,r,e){return t=+t,r>>>=0,e||U(this,t,r,2,65535,0),this[r]=255&t,this[r+1]=t>>>8,r+2},c.prototype.writeUInt16BE=function(t,r,e){return t=+t,r>>>=0,e||U(this,t,r,2,65535,0),this[r]=t>>>8,this[r+1]=255&t,r+2},c.prototype.writeUInt32LE=function(t,r,e){return t=+t,r>>>=0,e||U(this,t,r,4,4294967295,0),this[r+3]=t>>>24,this[r+2]=t>>>16,this[r+1]=t>>>8,this[r]=255&t,r+4},c.prototype.writeUInt32BE=function(t,r,e){return t=+t,r>>>=0,e||U(this,t,r,4,4294967295,0),this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t,r+4},c.prototype.writeIntLE=function(t,r,e,n){if(t=+t,r>>>=0,!n){var i=Math.pow(2,8*e-1);U(this,t,r,e,i-1,-i)}var o=0,s=1,a=0;for(this[r]=255&t;++o>0)-a&255;return r+e},c.prototype.writeIntBE=function(t,r,e,n){if(t=+t,r>>>=0,!n){var i=Math.pow(2,8*e-1);U(this,t,r,e,i-1,-i)}var o=e-1,s=1,a=0;for(this[r+o]=255&t;0<=--o&&(s*=256);)t<0&&0===a&&0!==this[r+o+1]&&(a=1),this[r+o]=(t/s>>0)-a&255;return r+e},c.prototype.writeInt8=function(t,r,e){return t=+t,r>>>=0,e||U(this,t,r,1,127,-128),t<0&&(t=255+t+1),this[r]=255&t,r+1},c.prototype.writeInt16LE=function(t,r,e){return t=+t,r>>>=0,e||U(this,t,r,2,32767,-32768),this[r]=255&t,this[r+1]=t>>>8,r+2},c.prototype.writeInt16BE=function(t,r,e){return t=+t,r>>>=0,e||U(this,t,r,2,32767,-32768),this[r]=t>>>8,this[r+1]=255&t,r+2},c.prototype.writeInt32LE=function(t,r,e){return t=+t,r>>>=0,e||U(this,t,r,4,2147483647,-2147483648),this[r]=255&t,this[r+1]=t>>>8,this[r+2]=t>>>16,this[r+3]=t>>>24,r+4},c.prototype.writeInt32BE=function(t,r,e){return t=+t,r>>>=0,e||U(this,t,r,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),this[r]=t>>>24,this[r+1]=t>>>16,this[r+2]=t>>>8,this[r+3]=255&t,r+4},c.prototype.writeFloatLE=function(t,r,e){return S(this,t,r,!0,e)},c.prototype.writeFloatBE=function(t,r,e){return S(this,t,r,!1,e)},c.prototype.writeDoubleLE=function(t,r,e){return C(this,t,r,!0,e)},c.prototype.writeDoubleBE=function(t,r,e){return C(this,t,r,!1,e)},c.prototype.copy=function(t,r,e,n){if(!c.isBuffer(t))throw new TypeError("argument should be a Buffer");if(e||(e=0),n||0===n||(n=this.length),r>=t.length&&(r=t.length),r||(r=0),0=this.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-r>>=0,e=void 0===e?this.length:e>>>0,t||(t=0),"number"==typeof t)for(o=r;o>6|192,63&e|128)}else if(e<65536){if((r-=3)<0)break;o.push(e>>12|224,e>>6&63|128,63&e|128)}else{if(!(e<1114112))throw new Error("Invalid code point");if((r-=4)<0)break;o.push(e>>18|240,e>>12&63|128,e>>6&63|128,63&e|128)}}return o}function O(t){return n.toByteArray(function(t){if((t=(t=t.split("=")[0]).trim().replace(I,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function M(t,r,e,n){for(var i=0;i=r.length||i>=t.length);++i)r[i+e]=t[i];return i}function H(t){return t instanceof ArrayBuffer||null!=t&&null!=t.constructor&&"ArrayBuffer"===t.constructor.name&&"number"==typeof t.byteLength}function F(t){return t!=t}},{"base64-js":2,ieee754:4}],4:[function(t,r,e){e.read=function(t,r,e,n,i){var o,s,a=8*i-n-1,u=(1<>1,h=-7,c=e?i-1:0,l=e?-1:1,p=t[r+c];for(c+=l,o=p&(1<<-h)-1,p>>=-h,h+=a;0>=-h,h+=n;0>1,l=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,p=n?0:o-1,d=n?1:-1,g=r<0||0===r&&1/r<0?1:0;for(r=Math.abs(r),isNaN(r)||r===1/0?(a=isNaN(r)?1:0,s=h):(s=Math.floor(Math.log(r)/Math.LN2),r*(u=Math.pow(2,-s))<1&&(s--,u*=2),2<=(r+=1<=s+c?l/u:l*Math.pow(2,1-c))*u&&(s++,u/=2),h<=s+c?(a=0,s=h):1<=s+c?(a=(r*u-1)*Math.pow(2,i),s+=c):(a=r*Math.pow(2,c-1)*Math.pow(2,i),s=0));8<=i;t[e+p]=255&a,p+=d,a/=256,i-=8);for(s=s<= 1");if(0!==s.lastIndexOf("SHA-",0))throw Error("Chosen SHA variant is not supported");if(c=function(t,r){return F(t,r,s)},l=function(t,r,e,n){var i,o;if("SHA-224"!==s&&"SHA-256"!==s)throw Error("Unexpected error in SHA-2 implementation");for(i=15+(r+65>>>9<<4),o=16;t.length<=i;)t.push(0);for(t[r>>>5]|=128<<24-r%32,r+=e,t[i]=4294967295&r,t[i-1]=r/4294967296|0,e=t.length,r=0;r>>3)/4-1,n>>5;for(t=(r=u(t,y,v)).binLen,e=r.value,r=t>>>5,n=0;n>>5),v=t%h,m=!0},this.getHash=function(t,r){var e,n,i,o;if(!0===w)throw Error("Cannot call getHash after setting HMAC key");switch(i=B(r),t){case"HEX":e=function(t){return _(t,f,i)};break;case"B64":e=function(t){return A(t,f,i)};break;case"BYTES":e=function(t){return E(t,f)};break;case"ARRAYBUFFER":try{n=new ArrayBuffer(0)}catch(t){throw Error("ARRAYBUFFER not supported by this environment")}e=function(t){return x(t,f)};break;default:throw Error("format must be HEX, B64, BYTES, or ARRAYBUFFER")}for(o=l(y.slice(),v,g,p(a)),n=1;n>>2]>>>8*(3+n%4*-1),o+="0123456789abcdef".charAt(i>>>4&15)+"0123456789abcdef".charAt(15&i);return e.outputUpper?o.toUpperCase():o}function A(t,r,e){var n,i,o,s="",a=r/8;for(n=0;n>>2]:0,o=n+2>>2]:0,o=(t[n>>>2]>>>8*(3+n%4*-1)&255)<<16|(i>>>8*(3+(n+1)%4*-1)&255)<<8|o>>>8*(3+(n+2)%4*-1)&255,i=0;i<4;i+=1)s+=8*n+6*i<=r?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(o>>>6*(3-i)&63):e.b64Pad;return s}function E(t,r){var e,n,i="",o=r/8;for(e=0;e>>2]>>>8*(3+e%4*-1)&255,i+=String.fromCharCode(n);return i}function x(t,r){var e,n,i=r/8,o=new ArrayBuffer(i);for(n=new Uint8Array(o),e=0;e>>2]>>>8*(3+e%4*-1)&255;return o}function B(t){var r={outputUpper:!1,b64Pad:"=",shakeLen:-1};if(t=t||{},r.outputUpper=t.outputUpper||!1,!0===t.hasOwnProperty("b64Pad")&&(r.b64Pad=t.b64Pad),"boolean"!=typeof r.outputUpper)throw Error("Invalid outputUpper formatting option");if("string"!=typeof r.b64Pad)throw Error("Invalid b64Pad formatting option");return r}function k(t,l){var r;switch(l){case"UTF8":case"UTF16BE":case"UTF16LE":break;default:throw Error("encoding must be UTF8, UTF16BE, or UTF16LE")}switch(t){case"HEX":r=function(t,r,e){var n,i,o,s,a,u=t.length;if(0!=u%2)throw Error("String of HEX type must be in byte increments");for(r=r||[0],a=(e=e||0)>>>3,n=0;n>>1)+a)>>>2;r.length<=o;)r.push(0);r[o]|=i<<8*(3+s%4*-1)}return{value:r,binLen:4*u+e}};break;case"TEXT":r=function(t,r,e){var n,i,o,s,a,u,f,h,c=0;if(r=r||[0],a=(e=e||0)>>>3,"UTF8"===l)for(h=3,o=0;o>>6),i.push(128|63&n)):n<55296||57344<=n?i.push(224|n>>>12,128|n>>>6&63,128|63&n):(o+=1,n=65536+((1023&n)<<10|1023&t.charCodeAt(o)),i.push(240|n>>>18,128|n>>>12&63,128|n>>>6&63,128|63&n)),s=0;s>>2;r.length<=u;)r.push(0);r[u]|=i[s]<<8*(h+f%4*-1),c+=1}else if("UTF16BE"===l||"UTF16LE"===l)for(h=2,i="UTF16LE"===l||"UTF16LE"!==l&&!1,o=0;o>>8),u=(f=c+a)>>>2;r.length<=u;)r.push(0);r[u]|=n<<8*(h+f%4*-1),c+=2}return{value:r,binLen:8*c+e}};break;case"B64":r=function(t,r,e){var n,i,o,s,a,u,f,h=0;if(-1===t.search(/^[a-zA-Z0-9=+\/]+$/))throw Error("Invalid character in base-64 string");if(i=t.indexOf("="),t=t.replace(/\=/g,""),-1!==i&&i= 0x100000000) { + o1++ + } + v[a] = o0 + v[a + 1] = o1 +} + +// 64-bit unsigned addition +// Sets v[a,a+1] += b +// b0 is the low 32 bits of b, b1 represents the high 32 bits +function ADD64AC (v, a, b0, b1) { + var o0 = v[a] + b0 + if (b0 < 0) { + o0 += 0x100000000 + } + var o1 = v[a + 1] + b1 + if (o0 >= 0x100000000) { + o1++ + } + v[a] = o0 + v[a + 1] = o1 +} + +// Little-endian byte access +function B2B_GET32 (arr, i) { + return (arr[i] ^ + (arr[i + 1] << 8) ^ + (arr[i + 2] << 16) ^ + (arr[i + 3] << 24)) +} + +// G Mixing function +// The ROTRs are inlined for speed +function B2B_G (a, b, c, d, ix, iy) { + var x0 = m[ix] + var x1 = m[ix + 1] + var y0 = m[iy] + var y1 = m[iy + 1] + + ADD64AA(v, a, b) // v[a,a+1] += v[b,b+1] ... in JS we must store a uint64 as two uint32s + ADD64AC(v, a, x0, x1) // v[a, a+1] += x ... x0 is the low 32 bits of x, x1 is the high 32 bits + + // v[d,d+1] = (v[d,d+1] xor v[a,a+1]) rotated to the right by 32 bits + var xor0 = v[d] ^ v[a] + var xor1 = v[d + 1] ^ v[a + 1] + v[d] = xor1 + v[d + 1] = xor0 + + ADD64AA(v, c, d) + + // v[b,b+1] = (v[b,b+1] xor v[c,c+1]) rotated right by 24 bits + xor0 = v[b] ^ v[c] + xor1 = v[b + 1] ^ v[c + 1] + v[b] = (xor0 >>> 24) ^ (xor1 << 8) + v[b + 1] = (xor1 >>> 24) ^ (xor0 << 8) + + ADD64AA(v, a, b) + ADD64AC(v, a, y0, y1) + + // v[d,d+1] = (v[d,d+1] xor v[a,a+1]) rotated right by 16 bits + xor0 = v[d] ^ v[a] + xor1 = v[d + 1] ^ v[a + 1] + v[d] = (xor0 >>> 16) ^ (xor1 << 16) + v[d + 1] = (xor1 >>> 16) ^ (xor0 << 16) + + ADD64AA(v, c, d) + + // v[b,b+1] = (v[b,b+1] xor v[c,c+1]) rotated right by 63 bits + xor0 = v[b] ^ v[c] + xor1 = v[b + 1] ^ v[c + 1] + v[b] = (xor1 >>> 31) ^ (xor0 << 1) + v[b + 1] = (xor0 >>> 31) ^ (xor1 << 1) +} + +// Initialization Vector +var BLAKE2B_IV32 = new Uint32Array([ + 0xF3BCC908, 0x6A09E667, 0x84CAA73B, 0xBB67AE85, + 0xFE94F82B, 0x3C6EF372, 0x5F1D36F1, 0xA54FF53A, + 0xADE682D1, 0x510E527F, 0x2B3E6C1F, 0x9B05688C, + 0xFB41BD6B, 0x1F83D9AB, 0x137E2179, 0x5BE0CD19 +]) + +var SIGMA8 = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3, + 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4, + 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8, + 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13, + 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9, + 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11, + 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10, + 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5, + 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 +] + +// These are offsets into a uint64 buffer. +// Multiply them all by 2 to make them offsets into a uint32 buffer, +// because this is Javascript and we don't have uint64s +var SIGMA82 = new Uint8Array(SIGMA8.map(function (x) { return x * 2 })) + +// Compression function. 'last' flag indicates last block. +// Note we're representing 16 uint64s as 32 uint32s +var v = new Uint32Array(32) +var m = new Uint32Array(32) +function blake2bCompress (ctx, last) { + var i = 0 + + // init work variables + for (i = 0; i < 16; i++) { + v[i] = ctx.h[i] + v[i + 16] = BLAKE2B_IV32[i] + } + + // low 64 bits of offset + v[24] = v[24] ^ ctx.t + v[25] = v[25] ^ (ctx.t / 0x100000000) + // high 64 bits not supported, offset may not be higher than 2**53-1 + + // last block flag set ? + if (last) { + v[28] = ~v[28] + v[29] = ~v[29] + } + + // get little-endian words + for (i = 0; i < 32; i++) { + m[i] = B2B_GET32(ctx.b, 4 * i) + } + + // twelve rounds of mixing + for (i = 0; i < 12; i++) { + B2B_G(0, 8, 16, 24, SIGMA82[i * 16 + 0], SIGMA82[i * 16 + 1]) + B2B_G(2, 10, 18, 26, SIGMA82[i * 16 + 2], SIGMA82[i * 16 + 3]) + B2B_G(4, 12, 20, 28, SIGMA82[i * 16 + 4], SIGMA82[i * 16 + 5]) + B2B_G(6, 14, 22, 30, SIGMA82[i * 16 + 6], SIGMA82[i * 16 + 7]) + B2B_G(0, 10, 20, 30, SIGMA82[i * 16 + 8], SIGMA82[i * 16 + 9]) + B2B_G(2, 12, 22, 24, SIGMA82[i * 16 + 10], SIGMA82[i * 16 + 11]) + B2B_G(4, 14, 16, 26, SIGMA82[i * 16 + 12], SIGMA82[i * 16 + 13]) + B2B_G(6, 8, 18, 28, SIGMA82[i * 16 + 14], SIGMA82[i * 16 + 15]) + } + + for (i = 0; i < 16; i++) { + ctx.h[i] = ctx.h[i] ^ v[i] ^ v[i + 16] + } +} + +// reusable parameter_block +var parameter_block = new Uint8Array([ + 0, 0, 0, 0, // 0: outlen, keylen, fanout, depth + 0, 0, 0, 0, // 4: leaf length, sequential mode + 0, 0, 0, 0, // 8: node offset + 0, 0, 0, 0, // 12: node offset + 0, 0, 0, 0, // 16: node depth, inner length, rfu + 0, 0, 0, 0, // 20: rfu + 0, 0, 0, 0, // 24: rfu + 0, 0, 0, 0, // 28: rfu + 0, 0, 0, 0, // 32: salt + 0, 0, 0, 0, // 36: salt + 0, 0, 0, 0, // 40: salt + 0, 0, 0, 0, // 44: salt + 0, 0, 0, 0, // 48: personal + 0, 0, 0, 0, // 52: personal + 0, 0, 0, 0, // 56: personal + 0, 0, 0, 0 // 60: personal +]) + +// Creates a BLAKE2b hashing context +// Requires an output length between 1 and 64 bytes +// Takes an optional Uint8Array key +function Blake2b (outlen, key, salt, personal) { + // zero out parameter_block before usage + parameter_block.fill(0) + // state, 'param block' + + this.b = new Uint8Array(128) + this.h = new Uint32Array(16) + this.t = 0 // input count + this.c = 0 // pointer within buffer + this.outlen = outlen // output length in bytes + + parameter_block[0] = outlen + if (key) parameter_block[1] = key.length + parameter_block[2] = 1 // fanout + parameter_block[3] = 1 // depth + + if (salt) parameter_block.set(salt, 32) + if (personal) parameter_block.set(personal, 48) + + // initialize hash state + for (var i = 0; i < 16; i++) { + this.h[i] = BLAKE2B_IV32[i] ^ B2B_GET32(parameter_block, i * 4) + } + + // key the hash, if applicable + if (key) { + blake2bUpdate(this, key) + // at the end + this.c = 128 + } +} + +Blake2b.prototype.update = function (input) { + blake2bUpdate(this, input) + return this +} + +Blake2b.prototype.digest = function (out) { + var buf = (!out || out === 'binary' || out === 'hex') ? new Uint8Array(this.outlen) : out + blake2bFinal(this, buf) + if (out === 'hex') return hexSlice(buf) + return buf +} + +Blake2b.prototype.final = Blake2b.prototype.digest + +// Updates a BLAKE2b streaming hash +// Requires hash context and Uint8Array (byte array) +function blake2bUpdate (ctx, input) { + for (var i = 0; i < input.length; i++) { + if (ctx.c === 128) { // buffer full ? + ctx.t += ctx.c // add counters + blake2bCompress(ctx, false) // compress (not last) + ctx.c = 0 // counter to zero + } + ctx.b[ctx.c++] = input[i] + } +} + +// Completes a BLAKE2b streaming hash +// Returns a Uint8Array containing the message digest +function blake2bFinal (ctx, out) { + ctx.t += ctx.c // mark last block offset + + while (ctx.c < 128) { // fill up with zeros + ctx.b[ctx.c++] = 0 + } + blake2bCompress(ctx, true) // final block flag = 1 + + for (var i = 0; i < ctx.outlen; i++) { + out[i] = ctx.h[i >> 2] >> (8 * (i & 3)) + } + return out +} + +function hexSlice (buf) { + var str = '' + for (var i = 0; i < buf.length; i++) str += toHex(buf[i]) + return str +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +module.exports = Blake2b; \ No newline at end of file diff --git a/src/crypto/utils.js b/src/crypto/utils.js index 3cc39bdf..422e269a 100644 --- a/src/crypto/utils.js +++ b/src/crypto/utils.js @@ -1,6 +1,7 @@ var jsSHA = require('jssha/src/sha256'); var Blake256 = require('./blake256'); var keccak256 = require('./sha3')['keccak256']; +var Blake2B = require('./blake2b'); function numberToHex (number) { var hex = Math.round(number).toString(16); @@ -10,6 +11,15 @@ function numberToHex (number) { return hex; } +function hexToUint8(hexString) { + var arr = []; + for (var i = 0; i < hexString.length; i += 2) { + arr.push(parseInt(hexString.substr(i, 2), 16)); + } + + return new Uint8Array(arr); +} + module.exports = { toHex: function (arrayOfBytes) { var hex = ''; @@ -32,6 +42,9 @@ module.exports = { blake256Checksum: function (payload) { return this.blake256(this.blake256(payload)).substr(0, 8); }, + blake2b: function (hexString, outlen) { + return new Blake2B(outlen).update(hexToUint8(hexString)).digest('hex'); + }, keccak256: function (hexString) { return keccak256(hexString); }, diff --git a/src/currencies.js b/src/currencies.js index f555a9bd..5a12f0e3 100644 --- a/src/currencies.js +++ b/src/currencies.js @@ -2,6 +2,7 @@ var XRPValidator = require('./ripple_validator'); var ETHValidator = require('./ethereum_validator'); var BTCValidator = require('./bitcoin_validator'); var XMRValidator = require('./monero_validator'); +var NANOValidator = require('./nano_validator'); // defines P2PKH and P2SH address types for standard (prod) and testnet networks var CURRENCIES = [{ @@ -200,6 +201,14 @@ var CURRENCIES = [{ addressTypes: {prod: ['18'], testnet: ['53']}, iAddressTypes: {prod: ['19'], testnet: ['54']}, validator: XMRValidator +},{ + name: 'nano', + symbol: 'nano', + validator: NANOValidator, +},{ + name: 'raiblocks', + symbol: 'xrb', + validator: NANOValidator, }]; diff --git a/src/nano_validator.js b/src/nano_validator.js new file mode 100644 index 00000000..8960ab4e --- /dev/null +++ b/src/nano_validator.js @@ -0,0 +1,27 @@ +var cryptoUtils = require('./crypto/utils'); +var baseX = require('base-x'); + +var ALLOWED_CHARS = '13456789abcdefghijkmnopqrstuwxyz'; + +var codec = baseX(ALLOWED_CHARS); +// https://github.com/nanocurrency/raiblocks/wiki/Accounts,-Keys,-Seeds,-and-Wallet-Identifiers +var regexp = new RegExp('^(xrb|nano)_([' + ALLOWED_CHARS + ']{60})$'); + +module.exports = { + isValidAddress: function (address) { + if (regexp.test(address)) { + return this.verifyChecksum(address); + } + + return false; + }, + + verifyChecksum: function (address) { + var bytes = codec.decode(regexp.exec(address)[2]).slice(-37); + // https://github.com/nanocurrency/raiblocks/blob/master/rai/lib/numbers.cpp#L73 + var computedChecksum = cryptoUtils.blake2b(cryptoUtils.toHex(bytes.slice(0, -5)), 5); + var checksum = cryptoUtils.toHex(bytes.slice(-5).reverse()); + + return computedChecksum === checksum + } +}; diff --git a/test/wallet_address_validator.js b/test/wallet_address_validator.js index 462e72e6..808c8de5 100644 --- a/test/wallet_address_validator.js +++ b/test/wallet_address_validator.js @@ -369,6 +369,19 @@ describe('WAValidator.validate()', function () { valid('4Gd4DLiXzBmbVX2FZZ3Cvu6fUaWACup1qDowprUCje1kSP4FmbftiJMSfV8kWZXNqmVwj4m52xqtgFNUudVmsmGkGvkLcCibWfVUfUFVB7', 'monero'); valid('4J5sF94AzXgFgx8LuWc9dcWkJkGkD3cL3L2AuhX6QA9jFvSxxj6QhHqHXqM2b2Go7G8RyDzEbHxYd9G26XUUbuJChipEyBz9fENMU2Ua9b', 'XMR'); }); + + it('should return true for correct nano addresses', function () { + valid('xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3', 'nano'); + valid('xrb_13ezf4od79h1tgj9aiu4djzcmmguendtjfuhwfukhuucboua8cpoihmh8byo', 'nano'); + valid('xrb_35jjmmmh81kydepzeuf9oec8hzkay7msr6yxagzxpcht7thwa5bus5tomgz9', 'nano'); + valid('xrb_1111111111111111111111111111111111111111111111111111hifc8npp', 'nano'); + valid('xrb_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est', 'nano'); + valid('xrb_3wm37qz19zhei7nzscjcopbrbnnachs4p1gnwo5oroi3qonw6inwgoeuufdp', 'nano'); + valid('xrb_3arg3asgtigae3xckabaaewkx3bzsh7nwz7jkmjos79ihyaxwphhm6qgjps4', 'nano'); + valid('xrb_1f5e4w33ndqbkx4bw5jtp13kp5xghebfxcmw9hdt1f7goid1s4373w6tjmgu', 'nano'); + valid('xrb_1q79ahdr36uqn38p5tp5sqwkn73rnpj1k8obtuetdbjcx37d5gahhd1u9cuh', 'nano'); + valid('nano_1q79ahdr36uqn38p5tp5sqwkn73rnpj1k8obtuetdbjcx37d5gahhd1u9cuh', 'nano'); + }); }); describe('invalid results', function () { @@ -574,5 +587,13 @@ describe('WAValidator.validate()', function () { invalid('4LNSCKNSTPNbJYkyAEgL966eHJHLDHiq1PpwKoiFBybcSqNGYfLBJApC62uQEeGAFxfYEd29uXBBrJFo7DhKqFVNi3GhmN79EtD5dgycYz', 'monero'); invalid('4JpzTwf3i1GeCV76beVr19179oa8j1L8xNSC1bXMtAxxdf4aTTLqubL8EvXfQmUGKt9MMigFtKy91VtoTTSfg1LU7LocPruT6KcGC9RKJV', 'xmr'); }); + + it('should return false for incorrect nano addresses', function () { + commonTests('nano'); + invalid('xrb_1f5e4w33ndqbkx4bw5jtp13kp5xghebfxcmw9hdt1f7goid1s4373w6tjdgu', 'nano'); + invalid('nano_1f5e4w33ndqbkx4bw5jtp13kp5xghebfxcmw9hdt1f7goid1s4373w6tjdgu', 'nano'); + invalid('xrb_1111111112111111111111111111111111111111111111111111hifc8npp', 'nano'); + invalid('nano_111111111111111111111111111111111111111111111111111hifc8npp', 'nano'); + }); }); });