From 72b8c49c2ae8a1d074f86ac1e08568d1644f91e1 Mon Sep 17 00:00:00 2001 From: Martin Varmuza Date: Tue, 14 May 2024 20:52:07 +0200 Subject: [PATCH] chore(address-validator): move trezor-address-validator package into monorepo --- .eslintrc.js | 1 + packages/address-validator/CHANGELOG.md | 3 + packages/address-validator/README.md | 11 + packages/address-validator/package.json | 25 + .../address-validator/src/ada_validator.js | 74 + .../address-validator/src/ae_validator.js | 30 + .../address-validator/src/ardr_validator.js | 19 + .../address-validator/src/atom_validator.js | 24 + .../address-validator/src/bch_validator.js | 95 + .../src/binance_validator.js | 17 + .../src/bitcoin_validator.js | 177 ++ .../address-validator/src/crypto/base32.js | 80 + .../address-validator/src/crypto/base58.js | 48 + .../address-validator/src/crypto/bech32.js | 64 + .../src/crypto/biginteger.js | 1460 +++++++++++++++ .../address-validator/src/crypto/blake256.js | 183 ++ .../address-validator/src/crypto/blake2b.js | 320 ++++ .../address-validator/src/crypto/cnBase58.js | 252 +++ packages/address-validator/src/crypto/sha3.js | 740 ++++++++ .../address-validator/src/crypto/utils.js | 137 ++ packages/address-validator/src/currencies.js | 1505 +++++++++++++++ .../address-validator/src/eos_validator.js | 22 + .../src/ethereum_validator.js | 44 + .../address-validator/src/hbar_validator.js | 23 + .../address-validator/src/icx_validator.js | 22 + packages/address-validator/src/index.d.ts | 26 + packages/address-validator/src/index.js | 33 + .../address-validator/src/iost_validator.js | 15 + .../address-validator/src/iota_validator.js | 14 + .../address-validator/src/lisk_validator.js | 26 + .../address-validator/src/loki_validator.js | 74 + .../address-validator/src/monero_validator.js | 84 + .../address-validator/src/nano_validator.js | 35 + .../address-validator/src/nem_validator.js | 31 + .../address-validator/src/nxt_validator.js | 18 + .../address-validator/src/ripple_validator.js | 36 + .../src/siacoin_validator.js | 28 + .../address-validator/src/steem_validator.js | 33 + .../src/stellar_validator.js | 46 + .../address-validator/src/sys_validator.js | 16 + .../address-validator/src/tezos_validator.js | 45 + .../address-validator/src/tron_validator.js | 72 + .../address-validator/src/zil_validator.js | 24 + .../wallet_address_get_currencies.test.js | 33 + .../tests/wallet_address_validator.test.js | 1638 +++++++++++++++++ packages/address-validator/tsconfig.json | 5 + packages/suite/package.json | 2 +- .../components/VerifyAddress/index.tsx | 2 +- packages/suite/tsconfig.json | 1 + suite-common/wallet-utils/package.json | 2 +- .../wallet-utils/src/validationUtils.ts | 3 +- suite-common/wallet-utils/tsconfig.json | 3 + tsconfig.json | 1 + yarn.lock | 1038 ++++++++++- 54 files changed, 8684 insertions(+), 76 deletions(-) create mode 100644 packages/address-validator/CHANGELOG.md create mode 100644 packages/address-validator/README.md create mode 100644 packages/address-validator/package.json create mode 100644 packages/address-validator/src/ada_validator.js create mode 100644 packages/address-validator/src/ae_validator.js create mode 100644 packages/address-validator/src/ardr_validator.js create mode 100644 packages/address-validator/src/atom_validator.js create mode 100644 packages/address-validator/src/bch_validator.js create mode 100644 packages/address-validator/src/binance_validator.js create mode 100644 packages/address-validator/src/bitcoin_validator.js create mode 100644 packages/address-validator/src/crypto/base32.js create mode 100644 packages/address-validator/src/crypto/base58.js create mode 100644 packages/address-validator/src/crypto/bech32.js create mode 100644 packages/address-validator/src/crypto/biginteger.js create mode 100644 packages/address-validator/src/crypto/blake256.js create mode 100644 packages/address-validator/src/crypto/blake2b.js create mode 100644 packages/address-validator/src/crypto/cnBase58.js create mode 100644 packages/address-validator/src/crypto/sha3.js create mode 100644 packages/address-validator/src/crypto/utils.js create mode 100644 packages/address-validator/src/currencies.js create mode 100644 packages/address-validator/src/eos_validator.js create mode 100644 packages/address-validator/src/ethereum_validator.js create mode 100644 packages/address-validator/src/hbar_validator.js create mode 100644 packages/address-validator/src/icx_validator.js create mode 100644 packages/address-validator/src/index.d.ts create mode 100644 packages/address-validator/src/index.js create mode 100644 packages/address-validator/src/iost_validator.js create mode 100644 packages/address-validator/src/iota_validator.js create mode 100644 packages/address-validator/src/lisk_validator.js create mode 100644 packages/address-validator/src/loki_validator.js create mode 100644 packages/address-validator/src/monero_validator.js create mode 100644 packages/address-validator/src/nano_validator.js create mode 100644 packages/address-validator/src/nem_validator.js create mode 100644 packages/address-validator/src/nxt_validator.js create mode 100644 packages/address-validator/src/ripple_validator.js create mode 100644 packages/address-validator/src/siacoin_validator.js create mode 100644 packages/address-validator/src/steem_validator.js create mode 100644 packages/address-validator/src/stellar_validator.js create mode 100644 packages/address-validator/src/sys_validator.js create mode 100644 packages/address-validator/src/tezos_validator.js create mode 100644 packages/address-validator/src/tron_validator.js create mode 100644 packages/address-validator/src/zil_validator.js create mode 100644 packages/address-validator/tests/wallet_address_get_currencies.test.js create mode 100644 packages/address-validator/tests/wallet_address_validator.test.js create mode 100644 packages/address-validator/tsconfig.json diff --git a/.eslintrc.js b/.eslintrc.js index 7053116baa06..0d8954e410e2 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -37,6 +37,7 @@ module.exports = { '**/public/*', 'packages/suite-data/files/*', 'packages/protobuf/scripts/protobuf-patches/*', + 'packages/address-validator', 'packages/connect-examples', 'ci/', ], diff --git a/packages/address-validator/CHANGELOG.md b/packages/address-validator/CHANGELOG.md new file mode 100644 index 000000000000..8e13de3bb817 --- /dev/null +++ b/packages/address-validator/CHANGELOG.md @@ -0,0 +1,3 @@ +# 1.0.0 + +- package created diff --git a/packages/address-validator/README.md b/packages/address-validator/README.md new file mode 100644 index 000000000000..6cf451e786cc --- /dev/null +++ b/packages/address-validator/README.md @@ -0,0 +1,11 @@ +# @trezor/address-validator + +Moved from https://github.com/trezor/trezor-address-validator + +which is a fork of + +https://github.com/christsim/multicoin-address-validator + +which is a fork of + +https://github.com/ryanralph/altcoin-address diff --git a/packages/address-validator/package.json b/packages/address-validator/package.json new file mode 100644 index 000000000000..c176f776c5c6 --- /dev/null +++ b/packages/address-validator/package.json @@ -0,0 +1,25 @@ +{ + "name": "@trezor/address-validator", + "version": "1.0.0", + "license": "See LICENSE.md in repo root", + "sideEffects": false, + "private": true, + "main": "src/index", + "scripts": { + "test:unit": "yarn g:jest -c ../../jest.config.base.js" + }, + "dependencies": { + "base-x": "^3.0.7", + "bech32": "^2.0.0", + "browserify-bignum": "^1.3.0-2", + "cbor-js": "^0.1.0", + "crc": "^3.8.0", + "groestl-hash-js": "1.0.0", + "jssha": "2.3.1", + "lodash": "^4.17.15" + }, + "devDependencies": { + "jest-environment-jsdom": "29.7.0", + "rimraf": "^5.0.5" + } +} diff --git a/packages/address-validator/src/ada_validator.js b/packages/address-validator/src/ada_validator.js new file mode 100644 index 000000000000..6ec31d624553 --- /dev/null +++ b/packages/address-validator/src/ada_validator.js @@ -0,0 +1,74 @@ +const { addressType } = require('./crypto/utils'); +var cbor = require('cbor-js'); +var CRC = require('crc'); +var base58 = require('./crypto/base58'); +var { bech32 } = require('bech32'); + +var DEFAULT_NETWORK_TYPE = 'prod'; + +function getDecoded(address) { + try { + var decoded = base58.decode(address); + return cbor.decode(new Uint8Array(decoded).buffer); + } catch (e) { + // if decoding fails, assume invalid address + return null; + } +} + +function isValidLegacyAddress(address) { + var decoded = getDecoded(address); + + if (!decoded || (!Array.isArray(decoded) && decoded.length != 2)) { + return false; + } + + var tagged = decoded[0]; + var validCrc = decoded[1]; + if (typeof validCrc != 'number') { + return false; + } + + // get crc of the payload + var crc = CRC.crc32(tagged); + + return crc == validCrc; +} + +// it is not possible to use bitcoin ./crypto/segwit_addr library, the cardano address is too long for that +function isValidBech32Address(address, currency, networkType) { + if (!currency.segwitHrp) { + return false; + } + var hrp = currency.segwitHrp[networkType]; + if (!hrp) { + return false; + } + + try { + var dec = bech32.decode(address, networkType === 'prod' ? 103 : 108); + } catch (err) { + return false; + } + + if (dec === null || dec.prefix !== hrp || dec.words.length < 1 || dec.words[0] > 16) { + return false; + } + + return true; +} + +module.exports = { + isValidAddress: function (address, currency, networkType) { + networkType = networkType || DEFAULT_NETWORK_TYPE; + return ( + isValidLegacyAddress(address) || isValidBech32Address(address, currency, networkType) + ); + }, + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/ae_validator.js b/packages/address-validator/src/ae_validator.js new file mode 100644 index 000000000000..da5b9bf60c73 --- /dev/null +++ b/packages/address-validator/src/ae_validator.js @@ -0,0 +1,30 @@ +const { addressType } = require('./crypto/utils'); +var base58 = require('./crypto/base58'); + +const ALLOWED_CHARS = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; + +var regexp = new RegExp('^(ak_)([' + ALLOWED_CHARS + ']+)$'); // Begins with ak_ followed by + +module.exports = { + isValidAddress: function (address, currency, networkType) { + let match = regexp.exec(address); + if (match !== null) { + return this.verifyChecksum(match[2]); + } else { + return false; + } + }, + + verifyChecksum: function (address) { + var decoded = base58.decode(address); + decoded.splice(-4, 4); // remove last 4 elements. Why is base 58 adding them? + return decoded.length === 32; + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/ardr_validator.js b/packages/address-validator/src/ardr_validator.js new file mode 100644 index 000000000000..0c7b6160f48e --- /dev/null +++ b/packages/address-validator/src/ardr_validator.js @@ -0,0 +1,19 @@ +const { addressType } = require('./crypto/utils'); +const ardorRegex = new RegExp('^ARDOR(-[A-Z0-9]{4}){3}(-[A-Z0-9]{5})$'); + +module.exports = { + isValidAddress: function (address, currency, networkType) { + if (!ardorRegex.test(address)) { + return false; + } + + return true; + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/atom_validator.js b/packages/address-validator/src/atom_validator.js new file mode 100644 index 000000000000..ba0158a6b34d --- /dev/null +++ b/packages/address-validator/src/atom_validator.js @@ -0,0 +1,24 @@ +const { addressType } = require('./crypto/utils'); +const { bech32 } = require('bech32'); + +const ALLOWED_CHARS = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l'; + +var regexp = new RegExp('^(cosmos)1([' + ALLOWED_CHARS + ']+)$'); // cosmos + bech32 separated by '1' + +module.exports = { + isValidAddress: function (address, currency, networkType) { + return regexp.exec(address) !== null; + }, + + verifyChecksum: function (address) { + const decoded = bech32.decode(address); + return decoded && decoded.words.length === 32; + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/bch_validator.js b/packages/address-validator/src/bch_validator.js new file mode 100644 index 000000000000..dd2c60cef3c2 --- /dev/null +++ b/packages/address-validator/src/bch_validator.js @@ -0,0 +1,95 @@ +const { addressType } = require('./crypto/utils'); +var cryptoUtils = require('./crypto/utils'); +var BTCValidator = require('./bitcoin_validator'); + +var GENERATOR = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]; + +function polymod(values) { + var chk = 1; + for (var p = 0; p < values.length; ++p) { + var top = chk >> 25; + chk = ((chk & 0x1ffffff) << 5) ^ values[p]; + for (var i = 0; i < 5; ++i) { + if ((top >> i) & 1) { + chk ^= GENERATOR[i]; + } + } + } + return chk; +} + +function hrpExpand(hrp) { + var ret = []; + var p; + for (p = 0; p < hrp.length; ++p) { + ret.push(hrp.charCodeAt(p) >> 5); + } + ret.push(0); + for (p = 0; p < hrp.length; ++p) { + ret.push(hrp.charCodeAt(p) & 31); + } + return ret; +} + +function verifyChecksum(hrp, data) { + return polymod(hrpExpand(hrp).concat(data)) === 1; +} + +function validateAddress(address, currency, networkType) { + var prefix = 'bitcoincash'; + var regexp = new RegExp(currency.regexp); + var raw_address; + + var res = address.split(':'); + if (res.length > 2) { + return false; + } + if (res.length === 1) { + raw_address = address; + } else { + if (res[0] !== 'bitcoincash') { + return false; + } + raw_address = res[1]; + } + + if (!regexp.test(raw_address)) { + return false; + } + + if (raw_address.toLowerCase() != raw_address && raw_address.toUpperCase() != raw_address) { + return false; + } + + var decoded = cryptoUtils.base32.b32decode(raw_address); + if (networkType === 'testnet') { + prefix = 'bchtest'; + } + + try { + if (verifyChecksum(prefix, decoded)) { + return false; + } + } catch (e) { + return false; + } + + return true; +} + +module.exports = { + isValidAddress: function (address, currency, networkType) { + return ( + validateAddress(address, currency, networkType) || + (currency.symbol !== 'bch' && + BTCValidator.isValidAddress(address, currency, networkType)) + ); + }, + getAddressType: function (address, currency, networkType) { + networkType = networkType || DEFAULT_NETWORK_TYPE; + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/binance_validator.js b/packages/address-validator/src/binance_validator.js new file mode 100644 index 000000000000..22e0c5a327cf --- /dev/null +++ b/packages/address-validator/src/binance_validator.js @@ -0,0 +1,17 @@ +const { addressType } = require('./crypto/utils'); +module.exports = { + isValidAddress: function (address) { + var binanceAddress = address.slice(address.indexOf('bnb')); + if (binanceAddress.length !== 42) { + return false; + } + return true; + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/bitcoin_validator.js b/packages/address-validator/src/bitcoin_validator.js new file mode 100644 index 000000000000..30b4799d1bbf --- /dev/null +++ b/packages/address-validator/src/bitcoin_validator.js @@ -0,0 +1,177 @@ +var bech32 = require('./crypto/bech32'); +var base58 = require('./crypto/base58'); +var cryptoUtils = require('./crypto/utils'); +const { addressType } = require('./crypto/utils'); + +var DEFAULT_NETWORK_TYPE = 'prod'; + +function getDecoded(address) { + try { + return base58.decode(address); + } catch (e) { + // if decoding fails, assume invalid address + return null; + } +} + +function getChecksum(hashFunction, payload) { + // Each currency may implement different hashing algorithm + switch (hashFunction) { + // blake then keccak hash chain + case 'blake256keccak256': + var blake = cryptoUtils.blake2b256(payload); + return cryptoUtils.keccak256Checksum(Buffer.from(blake, 'hex')); + case 'blake256': + return cryptoUtils.blake256Checksum(payload); + case 'keccak256': + return cryptoUtils.keccak256Checksum(payload); + case 'groestl512x2': + return cryptoUtils.groestl512x2(payload); + case 'sha256': + default: + return cryptoUtils.sha256Checksum(payload); + } +} + +function getAddressType(address, currency) { + currency = currency || {}; + // should be 25 bytes per btc address spec and 26 decred + var expectedLength = currency.expectedLength || 25; + var hashFunction = currency.hashFunction || 'sha256'; + var decoded = getDecoded(address); + if (decoded) { + var length = decoded.length; + + if (length !== expectedLength) { + return null; + } + + if (currency.regex) { + if (!currency.regex.test(address)) { + return null; + } + } + + var checksum = cryptoUtils.toHex(decoded.slice(length - 4, length)), + body = cryptoUtils.toHex(decoded.slice(0, length - 4)), + goodChecksum = getChecksum(hashFunction, body); + + return checksum === goodChecksum + ? cryptoUtils.toHex(decoded.slice(0, expectedLength - 24)) + : null; + } + + return null; +} + +function getOutputIndex(address, currency, networkType) { + const addressType = getAddressType(address, currency); + if (addressType) { + const correctAddressTypes = + currency.addressTypes[networkType] || + Object.keys(currency.addressTypes).reduce((all, key) => { + return all.concat(currency.addressTypes[key]); + }, []); + return correctAddressTypes.indexOf(addressType); + } + return null; +} + +function isValidPayToPublicKeyHashAddress(address, currency, networkType) { + return getOutputIndex(address, currency, networkType) === 0; +} + +function isValidPayToScriptHashAddress(address, currency, networkType) { + return getOutputIndex(address, currency, networkType) > 0; +} + +function isValidPayToWitnessScriptHashAddress(address, currency, networkType) { + try { + const hrp = currency.segwitHrp[networkType]; + const decoded = bech32.decode(hrp, address); + return decoded && decoded.version === 0 && decoded.program.length === 32; + } catch (err) { + return null; + } +} + +function isValidPayToWitnessPublicKeyHashAddress(address, currency, networkType) { + try { + const hrp = currency.segwitHrp[networkType]; + const decoded = bech32.decode(hrp, address); + + return decoded && decoded.version === 0 && decoded.program.length === 20; + } catch (err) { + return null; + } +} + +function isValidPayToTaprootAddress(address, currency, networkType) { + try { + const hrp = currency.segwitHrp[networkType]; + + const decoded = bech32.decode(hrp, address, true); + return decoded && decoded.version === 1 && decoded.program.length === 32; + } catch (err) { + return null; + } +} + +function isValidSegwitAddress(address, currency, networkType) { + if (!currency.segwitHrp) { + return false; + } + var hrp = currency.segwitHrp[networkType]; + if (!hrp) { + return false; + } + // try bech32 first + let ret = bech32.decode(hrp, address, false); + if (ret) { + if (ret.version === 0 || ret.program.length === 20 || ret.program.length === 32) { + return false; + } else { + return address.toLowerCase() === bech32.encode(hrp, ret.version, ret.program, false); + } + } + // then try bech32m + ret = bech32.decode(hrp, address, true); + if (ret) { + if (ret.version > 1 || ret.program.length !== 32) { + return address.toLowerCase() === bech32.encode(hrp, ret.version, ret.program, true); + } + } + + return false; +} + +module.exports = { + isValidAddress: function (address, currency, networkType) { + networkType = networkType || DEFAULT_NETWORK_TYPE; + const addrType = this.getAddressType(address, currency, networkType); + // Though WITNESS_UNKNOWN is a valid address, it's not spendable - so we mark it as invalid + return addrType !== undefined && addrType !== addressType.WITNESS_UNKNOWN; + }, + getAddressType: function (address, currency, networkType) { + networkType = networkType || DEFAULT_NETWORK_TYPE; + if (isValidPayToPublicKeyHashAddress(address, currency, networkType)) { + return addressType.P2PKH; + } + if (isValidPayToScriptHashAddress(address, currency, networkType)) { + return addressType.P2SH; + } + if (isValidPayToWitnessScriptHashAddress(address, currency, networkType)) { + return addressType.P2WSH; + } + if (isValidPayToWitnessPublicKeyHashAddress(address, currency, networkType)) { + return addressType.P2WPKH; + } + if (isValidPayToTaprootAddress(address, currency, networkType)) { + return addressType.P2TR; + } + if (isValidSegwitAddress(address, currency, networkType)) { + return addressType.WITNESS_UNKNOWN; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/crypto/base32.js b/packages/address-validator/src/crypto/base32.js new file mode 100644 index 000000000000..c6cbc292b991 --- /dev/null +++ b/packages/address-validator/src/crypto/base32.js @@ -0,0 +1,80 @@ +var alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; + +/** + * Encode a string to base32 + */ +var b32encode = function (s) { + var parts = []; + var quanta = Math.floor(s.length / 5); + var leftover = s.length % 5; + + if (leftover != 0) { + for (var i = 0; i < 5 - leftover; i++) { + s += '\x00'; + } + quanta += 1; + } + + for (var i = 0; i < quanta; i++) { + parts.push(alphabet.charAt(s.charCodeAt(i * 5) >> 3)); + parts.push( + alphabet.charAt(((s.charCodeAt(i * 5) & 0x07) << 2) | (s.charCodeAt(i * 5 + 1) >> 6)), + ); + parts.push(alphabet.charAt((s.charCodeAt(i * 5 + 1) & 0x3f) >> 1)); + parts.push( + alphabet.charAt( + ((s.charCodeAt(i * 5 + 1) & 0x01) << 4) | (s.charCodeAt(i * 5 + 2) >> 4), + ), + ); + parts.push( + alphabet.charAt( + ((s.charCodeAt(i * 5 + 2) & 0x0f) << 1) | (s.charCodeAt(i * 5 + 3) >> 7), + ), + ); + parts.push(alphabet.charAt((s.charCodeAt(i * 5 + 3) & 0x7f) >> 2)); + parts.push( + alphabet.charAt( + ((s.charCodeAt(i * 5 + 3) & 0x03) << 3) | (s.charCodeAt(i * 5 + 4) >> 5), + ), + ); + parts.push(alphabet.charAt(s.charCodeAt(i * 5 + 4) & 0x1f)); + } + + var replace = 0; + if (leftover == 1) replace = 6; + else if (leftover == 2) replace = 4; + else if (leftover == 3) replace = 3; + else if (leftover == 4) replace = 1; + + for (var i = 0; i < replace; i++) parts.pop(); + for (var i = 0; i < replace; i++) parts.push('='); + + return parts.join(''); +}; + +/** + * Decode a base32 string. + * This is made specifically for our use, deals only with proper strings + */ +var b32decode = function (s) { + var r = new ArrayBuffer((s.length * 5) / 8); + var b = new Uint8Array(r); + for (var j = 0; j < s.length / 8; j++) { + var v = [0, 0, 0, 0, 0, 0, 0, 0]; + for (var i = 0; i < 8; ++i) { + v[i] = alphabet.indexOf(s[j * 8 + i]); + } + var i = 0; + b[j * 5 + 0] = (v[i + 0] << 3) | (v[i + 1] >> 2); + b[j * 5 + 1] = ((v[i + 1] & 0x3) << 6) | (v[i + 2] << 1) | (v[i + 3] >> 4); + b[j * 5 + 2] = ((v[i + 3] & 0xf) << 4) | (v[i + 4] >> 1); + b[j * 5 + 3] = ((v[i + 4] & 0x1) << 7) | (v[i + 5] << 2) | (v[i + 6] >> 3); + b[j * 5 + 4] = ((v[i + 6] & 0x7) << 5) | v[i + 7]; + } + return b; +}; + +module.exports = { + b32decode: b32decode, + b32encode: b32encode, +}; diff --git a/packages/address-validator/src/crypto/base58.js b/packages/address-validator/src/crypto/base58.js new file mode 100644 index 000000000000..8e13fdb29c8e --- /dev/null +++ b/packages/address-validator/src/crypto/base58.js @@ -0,0 +1,48 @@ +// Base58 encoding/decoding +// Originally written by Mike Hearn for BitcoinJ +// Copyright (c) 2011 Google Inc +// Ported to JavaScript by Stefan Thomas +// Merged Buffer refactorings from base58-native by Stephen Pair +// Copyright (c) 2013 BitPay Inc + +var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; +var ALPHABET_MAP = {}; +for (var i = 0; i < ALPHABET.length; ++i) { + ALPHABET_MAP[ALPHABET.charAt(i)] = i; +} +var BASE = ALPHABET.length; + +module.exports = { + decode: function (string) { + if (string.length === 0) return []; + + var i, + j, + bytes = [0]; + for (i = 0; i < string.length; ++i) { + var c = string[i]; + if (!(c in ALPHABET_MAP)) throw new Error('Non-base58 character'); + + for (j = 0; j < bytes.length; ++j) bytes[j] *= BASE; + bytes[0] += ALPHABET_MAP[c]; + + var carry = 0; + for (j = 0; j < bytes.length; ++j) { + bytes[j] += carry; + carry = bytes[j] >> 8; + bytes[j] &= 0xff; + } + + while (carry) { + bytes.push(carry & 0xff); + carry >>= 8; + } + } + // deal with leading zeros + for (i = 0; string[i] === '1' && i < string.length - 1; ++i) { + bytes.push(0); + } + + return bytes.reverse(); + }, +}; diff --git a/packages/address-validator/src/crypto/bech32.js b/packages/address-validator/src/crypto/bech32.js new file mode 100644 index 000000000000..6bded9a3e68c --- /dev/null +++ b/packages/address-validator/src/crypto/bech32.js @@ -0,0 +1,64 @@ +const { bech32, bech32m } = require('bech32'); + +function convertbits(data, frombits, tobits, pad) { + var acc = 0; + var bits = 0; + var ret = []; + var maxv = (1 << tobits) - 1; + for (var p = 0; p < data.length; ++p) { + var value = data[p]; + if (value < 0 || value >> frombits !== 0) { + return null; + } + acc = (acc << frombits) | value; + bits += frombits; + while (bits >= tobits) { + bits -= tobits; + ret.push((acc >> bits) & maxv); + } + } + if (pad) { + if (bits > 0) { + ret.push((acc << (tobits - bits)) & maxv); + } + } else if (bits >= frombits || (acc << (tobits - bits)) & maxv) { + return null; + } + return ret; +} + +function decode(hrp, addr, m = false) { + let dec; + try { + if (m) { + dec = bech32m.decode(addr); + } else { + dec = bech32.decode(addr); + } + } catch (err) { + return null; + } + if (dec === null || dec.prefix !== hrp || dec.words.length < 1 || dec.words[0] > 16) { + return null; + } + var res = convertbits(dec.words.slice(1), 5, 8, false); + if (res === null || res.length < 2 || res.length > 40) { + return null; + } + return { version: dec.words[0], program: res }; +} + +function encode(hrp, version, program, m = false) { + var ret; + if (m) { + ret = bech32m.encode(hrp, [version].concat(convertbits(program, 8, 5, true))); + } else { + ret = bech32.encode(hrp, [version].concat(convertbits(program, 8, 5, true))); + } + if (decode(hrp, ret, m) === null) { + return null; + } + return ret; +} + +module.exports = { decode, encode }; diff --git a/packages/address-validator/src/crypto/biginteger.js b/packages/address-validator/src/crypto/biginteger.js new file mode 100644 index 000000000000..7a57877f665a --- /dev/null +++ b/packages/address-validator/src/crypto/biginteger.js @@ -0,0 +1,1460 @@ +/* + JavaScript BigInteger library version 0.9.1 + http://silentmatt.com/biginteger/ + Copyright (c) 2009 Matthew Crumley + Copyright (c) 2010,2011 by John Tobey + Licensed under the MIT license. + Support for arbitrary internal representation base was added by + Vitaly Magerya. +*/ + +/* + File: biginteger.js + Exports: + +*/ +(function (exports) { + 'use strict'; + /* + Class: BigInteger + An arbitrarily-large integer. + objects should be considered immutable. None of the "built-in" + methods modify *this* or their arguments. All properties should be + considered private. + All the methods of instances can be called "statically". The + static versions are convenient if you don't already have a + object. + As an example, these calls are equivalent. + > BigInteger(4).multiply(5); // returns BigInteger(20); + > BigInteger.multiply(4, 5); // returns BigInteger(20); + > var a = 42; + > var a = BigInteger.toJSValue("0b101010"); // Not completely useless... + */ + + var CONSTRUCT = {}; // Unique token to call "private" version of constructor + + /* + Constructor: BigInteger() + Convert a value to a . + Although is the constructor for objects, it is + best not to call it as a constructor. If *n* is a object, it is + simply returned as-is. Otherwise, is equivalent to + without a radix argument. + > var n0 = BigInteger(); // Same as + > var n1 = BigInteger("123"); // Create a new with value 123 + > var n2 = BigInteger(123); // Create a new with value 123 + > var n3 = BigInteger(n2); // Return n2, unchanged + The constructor form only takes an array and a sign. *n* must be an + array of numbers in little-endian order, where each digit is between 0 + and BigInteger.base. The second parameter sets the sign: -1 for + negative, +1 for positive, or 0 for zero. The array is *not copied and + may be modified*. If the array contains only zeros, the sign parameter + is ignored and is forced to zero. + > new BigInteger([5], -1): create a new BigInteger with value -5 + Parameters: + n - Value to convert to a . + Returns: + A value. + See Also: + , + */ + function BigInteger(n, s, token) { + if (token !== CONSTRUCT) { + if (n instanceof BigInteger) { + return n; + } else if (typeof n === 'undefined') { + return ZERO; + } + return BigInteger.parse(n); + } + + n = n || []; // Provide the nullary constructor for subclasses. + while (n.length && !n[n.length - 1]) { + --n.length; + } + this._d = n; + this._s = n.length ? s || 1 : 0; + } + + BigInteger._construct = function (n, s) { + return new BigInteger(n, s, CONSTRUCT); + }; + + // Base-10 speedup hacks in parse, toString, exp10 and log functions + // require base to be a power of 10. 10^7 is the largest such power + // that won't cause a precision loss when digits are multiplied. + var BigInteger_base = 10000000; + var BigInteger_base_log10 = 7; + + BigInteger.base = BigInteger_base; + BigInteger.base_log10 = BigInteger_base_log10; + + var ZERO = new BigInteger([], 0, CONSTRUCT); + // Constant: ZERO + // 0. + BigInteger.ZERO = ZERO; + + var ONE = new BigInteger([1], 1, CONSTRUCT); + // Constant: ONE + // 1. + BigInteger.ONE = ONE; + + var M_ONE = new BigInteger(ONE._d, -1, CONSTRUCT); + // Constant: M_ONE + // -1. + BigInteger.M_ONE = M_ONE; + + // Constant: _0 + // Shortcut for . + BigInteger._0 = ZERO; + + // Constant: _1 + // Shortcut for . + BigInteger._1 = ONE; + + /* + Constant: small + Array of from 0 to 36. + These are used internally for parsing, but useful when you need a "small" + . + See Also: + , , <_0>, <_1> + */ + BigInteger.small = [ + ZERO, + ONE, + /* Assuming BigInteger_base > 36 */ + new BigInteger([2], 1, CONSTRUCT), + new BigInteger([3], 1, CONSTRUCT), + new BigInteger([4], 1, CONSTRUCT), + new BigInteger([5], 1, CONSTRUCT), + new BigInteger([6], 1, CONSTRUCT), + new BigInteger([7], 1, CONSTRUCT), + new BigInteger([8], 1, CONSTRUCT), + new BigInteger([9], 1, CONSTRUCT), + new BigInteger([10], 1, CONSTRUCT), + new BigInteger([11], 1, CONSTRUCT), + new BigInteger([12], 1, CONSTRUCT), + new BigInteger([13], 1, CONSTRUCT), + new BigInteger([14], 1, CONSTRUCT), + new BigInteger([15], 1, CONSTRUCT), + new BigInteger([16], 1, CONSTRUCT), + new BigInteger([17], 1, CONSTRUCT), + new BigInteger([18], 1, CONSTRUCT), + new BigInteger([19], 1, CONSTRUCT), + new BigInteger([20], 1, CONSTRUCT), + new BigInteger([21], 1, CONSTRUCT), + new BigInteger([22], 1, CONSTRUCT), + new BigInteger([23], 1, CONSTRUCT), + new BigInteger([24], 1, CONSTRUCT), + new BigInteger([25], 1, CONSTRUCT), + new BigInteger([26], 1, CONSTRUCT), + new BigInteger([27], 1, CONSTRUCT), + new BigInteger([28], 1, CONSTRUCT), + new BigInteger([29], 1, CONSTRUCT), + new BigInteger([30], 1, CONSTRUCT), + new BigInteger([31], 1, CONSTRUCT), + new BigInteger([32], 1, CONSTRUCT), + new BigInteger([33], 1, CONSTRUCT), + new BigInteger([34], 1, CONSTRUCT), + new BigInteger([35], 1, CONSTRUCT), + new BigInteger([36], 1, CONSTRUCT), + ]; + + // Used for parsing/radix conversion + BigInteger.digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''); + + /* + Method: toString + Convert a to a string. + When *base* is greater than 10, letters are upper case. + Parameters: + base - Optional base to represent the number in (default is base 10). + Must be between 2 and 36 inclusive, or an Error will be thrown. + Returns: + The string representation of the . + */ + BigInteger.prototype.toString = function (base) { + base = +base || 10; + if (base < 2 || base > 36) { + throw new Error('illegal radix ' + base + '.'); + } + if (this._s === 0) { + return '0'; + } + if (base === 10) { + var str = this._s < 0 ? '-' : ''; + str += this._d[this._d.length - 1].toString(); + for (var i = this._d.length - 2; i >= 0; i--) { + var group = this._d[i].toString(); + while (group.length < BigInteger_base_log10) group = '0' + group; + str += group; + } + return str; + } else { + var numerals = BigInteger.digits; + base = BigInteger.small[base]; + var sign = this._s; + + var n = this.abs(); + var digits = []; + var digit; + + while (n._s !== 0) { + var divmod = n.divRem(base); + n = divmod[0]; + digit = divmod[1]; + // TODO: This could be changed to unshift instead of reversing at the end. + // Benchmark both to compare speeds. + digits.push(numerals[digit.valueOf()]); + } + return (sign < 0 ? '-' : '') + digits.reverse().join(''); + } + }; + + // Verify strings for parsing + BigInteger.radixRegex = [ + /^$/, + /^$/, + /^[01]*$/, + /^[012]*$/, + /^[0-3]*$/, + /^[0-4]*$/, + /^[0-5]*$/, + /^[0-6]*$/, + /^[0-7]*$/, + /^[0-8]*$/, + /^[0-9]*$/, + /^[0-9aA]*$/, + /^[0-9abAB]*$/, + /^[0-9abcABC]*$/, + /^[0-9a-dA-D]*$/, + /^[0-9a-eA-E]*$/, + /^[0-9a-fA-F]*$/, + /^[0-9a-gA-G]*$/, + /^[0-9a-hA-H]*$/, + /^[0-9a-iA-I]*$/, + /^[0-9a-jA-J]*$/, + /^[0-9a-kA-K]*$/, + /^[0-9a-lA-L]*$/, + /^[0-9a-mA-M]*$/, + /^[0-9a-nA-N]*$/, + /^[0-9a-oA-O]*$/, + /^[0-9a-pA-P]*$/, + /^[0-9a-qA-Q]*$/, + /^[0-9a-rA-R]*$/, + /^[0-9a-sA-S]*$/, + /^[0-9a-tA-T]*$/, + /^[0-9a-uA-U]*$/, + /^[0-9a-vA-V]*$/, + /^[0-9a-wA-W]*$/, + /^[0-9a-xA-X]*$/, + /^[0-9a-yA-Y]*$/, + /^[0-9a-zA-Z]*$/, + ]; + + /* + Function: parse + Parse a string into a . + *base* is optional but, if provided, must be from 2 to 36 inclusive. If + *base* is not provided, it will be guessed based on the leading characters + of *s* as follows: + - "0x" or "0X": *base* = 16 + - "0c" or "0C": *base* = 8 + - "0b" or "0B": *base* = 2 + - else: *base* = 10 + If no base is provided, or *base* is 10, the number can be in exponential + form. For example, these are all valid: + > BigInteger.parse("1e9"); // Same as "1000000000" + > BigInteger.parse("1.234*10^3"); // Same as 1234 + > BigInteger.parse("56789 * 10 ** -2"); // Same as 567 + If any characters fall outside the range defined by the radix, an exception + will be thrown. + Parameters: + s - The string to parse. + base - Optional radix (default is to guess based on *s*). + Returns: + a instance. + */ + BigInteger.parse = function (s, base) { + // Expands a number in exponential form to decimal form. + // expandExponential("-13.441*10^5") === "1344100"; + // expandExponential("1.12300e-1") === "0.112300"; + // expandExponential(1000000000000000000000000000000) === "1000000000000000000000000000000"; + function expandExponential(str) { + str = str.replace(/\s*[*xX]\s*10\s*(\^|\*\*)\s*/, 'e'); + + return str.replace(/^([+\-])?(\d+)\.?(\d*)[eE]([+\-]?\d+)$/, function (x, s, n, f, c) { + c = +c; + var l = c < 0; + var i = n.length + c; + x = (l ? n : f).length; + c = (c = Math.abs(c)) >= x ? c - x + l : 0; + var z = new Array(c + 1).join('0'); + var r = n + f; + return ( + (s || '') + + (l ? (r = z + r) : (r += z)).substr(0, (i += l ? z.length : 0)) + + (i < r.length ? '.' + r.substr(i) : '') + ); + }); + } + + s = s.toString(); + if (typeof base === 'undefined' || +base === 10) { + s = expandExponential(s); + } + + var prefixRE; + if (typeof base === 'undefined') { + prefixRE = '0[xcb]'; + } else if (base == 16) { + prefixRE = '0x'; + } else if (base == 8) { + prefixRE = '0c'; + } else if (base == 2) { + prefixRE = '0b'; + } else { + prefixRE = ''; + } + var parts = new RegExp('^([+\\-]?)(' + prefixRE + ')?([0-9a-z]*)(?:\\.\\d*)?$', 'i').exec( + s, + ); + if (parts) { + var sign = parts[1] || '+'; + var baseSection = parts[2] || ''; + var digits = parts[3] || ''; + + if (typeof base === 'undefined') { + // Guess base + if (baseSection === '0x' || baseSection === '0X') { + // Hex + base = 16; + } else if (baseSection === '0c' || baseSection === '0C') { + // Octal + base = 8; + } else if (baseSection === '0b' || baseSection === '0B') { + // Binary + base = 2; + } else { + base = 10; + } + } else if (base < 2 || base > 36) { + throw new Error('Illegal radix ' + base + '.'); + } + + base = +base; + + // Check for digits outside the range + if (!BigInteger.radixRegex[base].test(digits)) { + throw new Error('Bad digit for radix ' + base); + } + + // Strip leading zeros, and convert to array + digits = digits.replace(/^0+/, '').split(''); + if (digits.length === 0) { + return ZERO; + } + + // Get the sign (we know it's not zero) + sign = sign === '-' ? -1 : 1; + + // Optimize 10 + if (base == 10) { + var d = []; + while (digits.length >= BigInteger_base_log10) { + d.push( + parseInt( + digits + .splice( + digits.length - BigInteger.base_log10, + BigInteger.base_log10, + ) + .join(''), + 10, + ), + ); + } + d.push(parseInt(digits.join(''), 10)); + return new BigInteger(d, sign, CONSTRUCT); + } + + // Do the conversion + var d = ZERO; + base = BigInteger.small[base]; + var small = BigInteger.small; + for (var i = 0; i < digits.length; i++) { + d = d.multiply(base).add(small[parseInt(digits[i], 36)]); + } + return new BigInteger(d._d, sign, CONSTRUCT); + } else { + throw new Error('Invalid BigInteger format: ' + s); + } + }; + + /* + Function: add + Add two . + Parameters: + n - The number to add to *this*. Will be converted to a . + Returns: + The numbers added together. + See Also: + , , , + */ + BigInteger.prototype.add = function (n) { + if (this._s === 0) { + return BigInteger(n); + } + + n = BigInteger(n); + if (n._s === 0) { + return this; + } + if (this._s !== n._s) { + n = n.negate(); + return this.subtract(n); + } + + var a = this._d; + var b = n._d; + var al = a.length; + var bl = b.length; + var sum = new Array(Math.max(al, bl) + 1); + var size = Math.min(al, bl); + var carry = 0; + var digit; + + for (var i = 0; i < size; i++) { + digit = a[i] + b[i] + carry; + sum[i] = digit % BigInteger_base; + carry = (digit / BigInteger_base) | 0; + } + if (bl > al) { + a = b; + al = bl; + } + for (i = size; carry && i < al; i++) { + digit = a[i] + carry; + sum[i] = digit % BigInteger_base; + carry = (digit / BigInteger_base) | 0; + } + if (carry) { + sum[i] = carry; + } + + for (; i < al; i++) { + sum[i] = a[i]; + } + + return new BigInteger(sum, this._s, CONSTRUCT); + }; + + /* + Function: negate + Get the additive inverse of a . + Returns: + A with the same magnatude, but with the opposite sign. + See Also: + + */ + BigInteger.prototype.negate = function () { + return new BigInteger(this._d, -this._s | 0, CONSTRUCT); + }; + + /* + Function: abs + Get the absolute value of a . + Returns: + A with the same magnatude, but always positive (or zero). + See Also: + + */ + BigInteger.prototype.abs = function () { + return this._s < 0 ? this.negate() : this; + }; + + /* + Function: subtract + Subtract two . + Parameters: + n - The number to subtract from *this*. Will be converted to a . + Returns: + The *n* subtracted from *this*. + See Also: + , , , + */ + BigInteger.prototype.subtract = function (n) { + if (this._s === 0) { + return BigInteger(n).negate(); + } + + n = BigInteger(n); + if (n._s === 0) { + return this; + } + if (this._s !== n._s) { + n = n.negate(); + return this.add(n); + } + + var m = this; + // negative - negative => -|a| - -|b| => -|a| + |b| => |b| - |a| + if (this._s < 0) { + m = new BigInteger(n._d, 1, CONSTRUCT); + n = new BigInteger(this._d, 1, CONSTRUCT); + } + + // Both are positive => a - b + var sign = m.compareAbs(n); + if (sign === 0) { + return ZERO; + } else if (sign < 0) { + // swap m and n + var t = n; + n = m; + m = t; + } + + // a > b + var a = m._d; + var b = n._d; + var al = a.length; + var bl = b.length; + var diff = new Array(al); // al >= bl since a > b + var borrow = 0; + var i; + var digit; + + for (i = 0; i < bl; i++) { + digit = a[i] - borrow - b[i]; + if (digit < 0) { + digit += BigInteger_base; + borrow = 1; + } else { + borrow = 0; + } + diff[i] = digit; + } + for (i = bl; i < al; i++) { + digit = a[i] - borrow; + if (digit < 0) { + digit += BigInteger_base; + } else { + diff[i++] = digit; + break; + } + diff[i] = digit; + } + for (; i < al; i++) { + diff[i] = a[i]; + } + + return new BigInteger(diff, sign, CONSTRUCT); + }; + + (function () { + function addOne(n, sign) { + var a = n._d; + var sum = a.slice(); + var carry = true; + var i = 0; + + while (true) { + var digit = (a[i] || 0) + 1; + sum[i] = digit % BigInteger_base; + if (digit <= BigInteger_base - 1) { + break; + } + ++i; + } + + return new BigInteger(sum, sign, CONSTRUCT); + } + + function subtractOne(n, sign) { + var a = n._d; + var sum = a.slice(); + var borrow = true; + var i = 0; + + while (true) { + var digit = (a[i] || 0) - 1; + if (digit < 0) { + sum[i] = digit + BigInteger_base; + } else { + sum[i] = digit; + break; + } + ++i; + } + + return new BigInteger(sum, sign, CONSTRUCT); + } + + /* + Function: next + Get the next (add one). + Returns: + *this* + 1. + See Also: + , + */ + BigInteger.prototype.next = function () { + switch (this._s) { + case 0: + return ONE; + case -1: + return subtractOne(this, -1); + // case 1: + default: + return addOne(this, 1); + } + }; + + /* + Function: prev + Get the previous (subtract one). + Returns: + *this* - 1. + See Also: + , + */ + BigInteger.prototype.prev = function () { + switch (this._s) { + case 0: + return M_ONE; + case -1: + return addOne(this, -1); + // case 1: + default: + return subtractOne(this, 1); + } + }; + })(); + + /* + Function: compareAbs + Compare the absolute value of two . + Calling is faster than calling twice, then . + Parameters: + n - The number to compare to *this*. Will be converted to a . + Returns: + -1, 0, or +1 if *|this|* is less than, equal to, or greater than *|n|*. + See Also: + , + */ + BigInteger.prototype.compareAbs = function (n) { + if (this === n) { + return 0; + } + + if (!(n instanceof BigInteger)) { + if (!isFinite(n)) { + return isNaN(n) ? n : -1; + } + n = BigInteger(n); + } + + if (this._s === 0) { + return n._s !== 0 ? -1 : 0; + } + if (n._s === 0) { + return 1; + } + + var l = this._d.length; + var nl = n._d.length; + if (l < nl) { + return -1; + } else if (l > nl) { + return 1; + } + + var a = this._d; + var b = n._d; + for (var i = l - 1; i >= 0; i--) { + if (a[i] !== b[i]) { + return a[i] < b[i] ? -1 : 1; + } + } + + return 0; + }; + + /* + Function: compare + Compare two . + Parameters: + n - The number to compare to *this*. Will be converted to a . + Returns: + -1, 0, or +1 if *this* is less than, equal to, or greater than *n*. + See Also: + , , , + */ + BigInteger.prototype.compare = function (n) { + if (this === n) { + return 0; + } + + n = BigInteger(n); + + if (this._s === 0) { + return -n._s; + } + + if (this._s === n._s) { + // both positive or both negative + var cmp = this.compareAbs(n); + return cmp * this._s; + } else { + return this._s; + } + }; + + /* + Function: isUnit + Return true iff *this* is either 1 or -1. + Returns: + true if *this* compares equal to or . + See Also: + , , , , , + , + */ + BigInteger.prototype.isUnit = function () { + return this === ONE || this === M_ONE || (this._d.length === 1 && this._d[0] === 1); + }; + + /* + Function: multiply + Multiply two . + Parameters: + n - The number to multiply *this* by. Will be converted to a + . + Returns: + The numbers multiplied together. + See Also: + , , , + */ + BigInteger.prototype.multiply = function (n) { + // TODO: Consider adding Karatsuba multiplication for large numbers + if (this._s === 0) { + return ZERO; + } + + n = BigInteger(n); + if (n._s === 0) { + return ZERO; + } + if (this.isUnit()) { + if (this._s < 0) { + return n.negate(); + } + return n; + } + if (n.isUnit()) { + if (n._s < 0) { + return this.negate(); + } + return this; + } + if (this === n) { + return this.square(); + } + + var r = this._d.length >= n._d.length; + var a = (r ? this : n)._d; // a will be longer than b + var b = (r ? n : this)._d; + var al = a.length; + var bl = b.length; + + var pl = al + bl; + var partial = new Array(pl); + var i; + for (i = 0; i < pl; i++) { + partial[i] = 0; + } + + for (i = 0; i < bl; i++) { + var carry = 0; + var bi = b[i]; + var jlimit = al + i; + var digit; + for (var j = i; j < jlimit; j++) { + digit = partial[j] + bi * a[j - i] + carry; + carry = (digit / BigInteger_base) | 0; + partial[j] = digit % BigInteger_base | 0; + } + if (carry) { + digit = partial[j] + carry; + carry = (digit / BigInteger_base) | 0; + partial[j] = digit % BigInteger_base; + } + } + return new BigInteger(partial, this._s * n._s, CONSTRUCT); + }; + + // Multiply a BigInteger by a single-digit native number + // Assumes that this and n are >= 0 + // This is not really intended to be used outside the library itself + BigInteger.prototype.multiplySingleDigit = function (n) { + if (n === 0 || this._s === 0) { + return ZERO; + } + if (n === 1) { + return this; + } + + var digit; + if (this._d.length === 1) { + digit = this._d[0] * n; + if (digit >= BigInteger_base) { + return new BigInteger( + [digit % BigInteger_base | 0, (digit / BigInteger_base) | 0], + 1, + CONSTRUCT, + ); + } + return new BigInteger([digit], 1, CONSTRUCT); + } + + if (n === 2) { + return this.add(this); + } + if (this.isUnit()) { + return new BigInteger([n], 1, CONSTRUCT); + } + + var a = this._d; + var al = a.length; + + var pl = al + 1; + var partial = new Array(pl); + for (var i = 0; i < pl; i++) { + partial[i] = 0; + } + + var carry = 0; + for (var j = 0; j < al; j++) { + digit = n * a[j] + carry; + carry = (digit / BigInteger_base) | 0; + partial[j] = digit % BigInteger_base | 0; + } + if (carry) { + partial[j] = carry; + } + + return new BigInteger(partial, 1, CONSTRUCT); + }; + + /* + Function: square + Multiply a by itself. + This is slightly faster than regular multiplication, since it removes the + duplicated multiplcations. + Returns: + > this.multiply(this) + See Also: + + */ + BigInteger.prototype.square = function () { + // Normally, squaring a 10-digit number would take 100 multiplications. + // Of these 10 are unique diagonals, of the remaining 90 (100-10), 45 are repeated. + // This procedure saves (N*(N-1))/2 multiplications, (e.g., 45 of 100 multiplies). + // Based on code by Gary Darby, Intellitech Systems Inc., www.DelphiForFun.org + + if (this._s === 0) { + return ZERO; + } + if (this.isUnit()) { + return ONE; + } + + var digits = this._d; + var length = digits.length; + var imult1 = new Array(length + length + 1); + var product, carry, k; + var i; + + // Calculate diagonal + for (i = 0; i < length; i++) { + k = i * 2; + product = digits[i] * digits[i]; + carry = (product / BigInteger_base) | 0; + imult1[k] = product % BigInteger_base; + imult1[k + 1] = carry; + } + + // Calculate repeating part + for (i = 0; i < length; i++) { + carry = 0; + k = i * 2 + 1; + for (var j = i + 1; j < length; j++, k++) { + product = digits[j] * digits[i] * 2 + imult1[k] + carry; + carry = (product / BigInteger_base) | 0; + imult1[k] = product % BigInteger_base; + } + k = length + i; + var digit = carry + imult1[k]; + carry = (digit / BigInteger_base) | 0; + imult1[k] = digit % BigInteger_base; + imult1[k + 1] += carry; + } + + return new BigInteger(imult1, 1, CONSTRUCT); + }; + + /* + Function: quotient + Divide two and truncate towards zero. + throws an exception if *n* is zero. + Parameters: + n - The number to divide *this* by. Will be converted to a . + Returns: + The *this* / *n*, truncated to an integer. + See Also: + , , , , + */ + BigInteger.prototype.quotient = function (n) { + return this.divRem(n)[0]; + }; + + /* + Function: divide + Deprecated synonym for . + */ + BigInteger.prototype.divide = BigInteger.prototype.quotient; + + /* + Function: remainder + Calculate the remainder of two . + throws an exception if *n* is zero. + Parameters: + n - The remainder after *this* is divided *this* by *n*. Will be + converted to a . + Returns: + *this* % *n*. + See Also: + , + */ + BigInteger.prototype.remainder = function (n) { + return this.divRem(n)[1]; + }; + + /* + Function: divRem + Calculate the integer quotient and remainder of two . + throws an exception if *n* is zero. + Parameters: + n - The number to divide *this* by. Will be converted to a . + Returns: + A two-element array containing the quotient and the remainder. + > a.divRem(b) + is exactly equivalent to + > [a.quotient(b), a.remainder(b)] + except it is faster, because they are calculated at the same time. + See Also: + , + */ + BigInteger.prototype.divRem = function (n) { + n = BigInteger(n); + if (n._s === 0) { + throw new Error('Divide by zero'); + } + if (this._s === 0) { + return [ZERO, ZERO]; + } + if (n._d.length === 1) { + return this.divRemSmall(n._s * n._d[0]); + } + + // Test for easy cases -- |n1| <= |n2| + switch (this.compareAbs(n)) { + case 0: // n1 == n2 + return [this._s === n._s ? ONE : M_ONE, ZERO]; + case -1: // |n1| < |n2| + return [ZERO, this]; + } + + var sign = this._s * n._s; + var a = n.abs(); + var b_digits = this._d; + var b_index = b_digits.length; + var digits = n._d.length; + var quot = []; + var guess; + + var part = new BigInteger([], 0, CONSTRUCT); + + while (b_index) { + part._d.unshift(b_digits[--b_index]); + part = new BigInteger(part._d, 1, CONSTRUCT); + + if (part.compareAbs(n) < 0) { + quot.push(0); + continue; + } + if (part._s === 0) { + guess = 0; + } else { + var xlen = part._d.length, + ylen = a._d.length; + var highx = part._d[xlen - 1] * BigInteger_base + part._d[xlen - 2]; + var highy = a._d[ylen - 1] * BigInteger_base + a._d[ylen - 2]; + if (part._d.length > a._d.length) { + // The length of part._d can either match a._d length, + // or exceed it by one. + highx = (highx + 1) * BigInteger_base; + } + guess = Math.ceil(highx / highy); + } + do { + var check = a.multiplySingleDigit(guess); + if (check.compareAbs(part) <= 0) { + break; + } + guess--; + } while (guess); + + quot.push(guess); + if (!guess) { + continue; + } + var diff = part.subtract(check); + part._d = diff._d.slice(); + } + + return [ + new BigInteger(quot.reverse(), sign, CONSTRUCT), + new BigInteger(part._d, this._s, CONSTRUCT), + ]; + }; + + // Throws an exception if n is outside of (-BigInteger.base, -1] or + // [1, BigInteger.base). It's not necessary to call this, since the + // other division functions will call it if they are able to. + BigInteger.prototype.divRemSmall = function (n) { + var r; + n = +n; + if (n === 0) { + throw new Error('Divide by zero'); + } + + var n_s = n < 0 ? -1 : 1; + var sign = this._s * n_s; + n = Math.abs(n); + + if (n < 1 || n >= BigInteger_base) { + throw new Error('Argument out of range'); + } + + if (this._s === 0) { + return [ZERO, ZERO]; + } + + if (n === 1 || n === -1) { + return [sign === 1 ? this.abs() : new BigInteger(this._d, sign, CONSTRUCT), ZERO]; + } + + // 2 <= n < BigInteger_base + + // divide a single digit by a single digit + if (this._d.length === 1) { + var q = new BigInteger([(this._d[0] / n) | 0], 1, CONSTRUCT); + r = new BigInteger([this._d[0] % n | 0], 1, CONSTRUCT); + if (sign < 0) { + q = q.negate(); + } + if (this._s < 0) { + r = r.negate(); + } + return [q, r]; + } + + var digits = this._d.slice(); + var quot = new Array(digits.length); + var part = 0; + var diff = 0; + var i = 0; + var guess; + + while (digits.length) { + part = part * BigInteger_base + digits[digits.length - 1]; + if (part < n) { + quot[i++] = 0; + digits.pop(); + diff = BigInteger_base * diff + part; + continue; + } + if (part === 0) { + guess = 0; + } else { + guess = (part / n) | 0; + } + + var check = n * guess; + diff = part - check; + quot[i++] = guess; + if (!guess) { + digits.pop(); + continue; + } + + digits.pop(); + part = diff; + } + + r = new BigInteger([diff], 1, CONSTRUCT); + if (this._s < 0) { + r = r.negate(); + } + return [new BigInteger(quot.reverse(), sign, CONSTRUCT), r]; + }; + + /* + Function: isEven + Return true iff *this* is divisible by two. + Note that is even. + Returns: + true if *this* is even, false otherwise. + See Also: + + */ + BigInteger.prototype.isEven = function () { + var digits = this._d; + return this._s === 0 || digits.length === 0 || digits[0] % 2 === 0; + }; + + /* + Function: isOdd + Return true iff *this* is not divisible by two. + Returns: + true if *this* is odd, false otherwise. + See Also: + + */ + BigInteger.prototype.isOdd = function () { + return !this.isEven(); + }; + + /* + Function: sign + Get the sign of a . + Returns: + * -1 if *this* < 0 + * 0 if *this* == 0 + * +1 if *this* > 0 + See Also: + , , , , + */ + BigInteger.prototype.sign = function () { + return this._s; + }; + + /* + Function: isPositive + Return true iff *this* > 0. + Returns: + true if *this*.compare() == 1. + See Also: + , , , , , + */ + BigInteger.prototype.isPositive = function () { + return this._s > 0; + }; + + /* + Function: isNegative + Return true iff *this* < 0. + Returns: + true if *this*.compare() == -1. + See Also: + , , , , , + */ + BigInteger.prototype.isNegative = function () { + return this._s < 0; + }; + + /* + Function: isZero + Return true iff *this* == 0. + Returns: + true if *this*.compare() == 0. + See Also: + , , , , + */ + BigInteger.prototype.isZero = function () { + return this._s === 0; + }; + + /* + Function: exp10 + Multiply a by a power of 10. + This is equivalent to, but faster than + > if (n >= 0) { + > return this.multiply(BigInteger("1e" + n)); + > } + > else { // n <= 0 + > return this.quotient(BigInteger("1e" + -n)); + > } + Parameters: + n - The power of 10 to multiply *this* by. *n* is converted to a + javascipt number and must be no greater than + (0x7FFFFFFF), or an exception will be thrown. + Returns: + *this* * (10 ** *n*), truncated to an integer if necessary. + See Also: + , + */ + BigInteger.prototype.exp10 = function (n) { + n = +n; + if (n === 0) { + return this; + } + if (Math.abs(n) > Number(MAX_EXP)) { + throw new Error('exponent too large in BigInteger.exp10'); + } + // Optimization for this == 0. This also keeps us from having to trim zeros in the positive n case + if (this._s === 0) { + return ZERO; + } + if (n > 0) { + var k = new BigInteger(this._d.slice(), this._s, CONSTRUCT); + + for (; n >= BigInteger_base_log10; n -= BigInteger_base_log10) { + k._d.unshift(0); + } + if (n == 0) return k; + k._s = 1; + k = k.multiplySingleDigit(Math.pow(10, n)); + return this._s < 0 ? k.negate() : k; + } else if (-n >= this._d.length * BigInteger_base_log10) { + return ZERO; + } else { + var k = new BigInteger(this._d.slice(), this._s, CONSTRUCT); + + for (n = -n; n >= BigInteger_base_log10; n -= BigInteger_base_log10) { + k._d.shift(); + } + return n == 0 ? k : k.divRemSmall(Math.pow(10, n))[0]; + } + }; + + /* + Function: pow + Raise a to a power. + In this implementation, 0**0 is 1. + Parameters: + n - The exponent to raise *this* by. *n* must be no greater than + (0x7FFFFFFF), or an exception will be thrown. + Returns: + *this* raised to the *nth* power. + See Also: + + */ + BigInteger.prototype.pow = function (n) { + if (this.isUnit()) { + if (this._s > 0) { + return this; + } else { + return BigInteger(n).isOdd() ? this : this.negate(); + } + } + + n = BigInteger(n); + if (n._s === 0) { + return ONE; + } else if (n._s < 0) { + if (this._s === 0) { + throw new Error('Divide by zero'); + } else { + return ZERO; + } + } + if (this._s === 0) { + return ZERO; + } + if (n.isUnit()) { + return this; + } + + if (n.compareAbs(MAX_EXP) > 0) { + throw new Error('exponent too large in BigInteger.pow'); + } + var x = this; + var aux = ONE; + var two = BigInteger.small[2]; + + while (n.isPositive()) { + if (n.isOdd()) { + aux = aux.multiply(x); + if (n.isUnit()) { + return aux; + } + } + x = x.square(); + n = n.quotient(two); + } + + return aux; + }; + + /* + Function: modPow + Raise a to a power (mod m). + Because it is reduced by a modulus, is not limited by + like . + Parameters: + exponent - The exponent to raise *this* by. Must be positive. + modulus - The modulus. + Returns: + *this* ^ *exponent* (mod *modulus*). + See Also: + , + */ + BigInteger.prototype.modPow = function (exponent, modulus) { + var result = ONE; + var base = this; + + while (exponent.isPositive()) { + if (exponent.isOdd()) { + result = result.multiply(base).remainder(modulus); + } + + exponent = exponent.quotient(BigInteger.small[2]); + if (exponent.isPositive()) { + base = base.square().remainder(modulus); + } + } + + return result; + }; + + /* + Function: log + Get the natural logarithm of a as a native JavaScript number. + This is equivalent to + > Math.log(this.toJSValue()) + but handles values outside of the native number range. + Returns: + log( *this* ) + See Also: + + */ + BigInteger.prototype.log = function () { + switch (this._s) { + case 0: + return -Infinity; + case -1: + return NaN; + default: // Fall through. + } + + var l = this._d.length; + + if (l * BigInteger_base_log10 < 30) { + return Math.log(this.valueOf()); + } + + var N = Math.ceil(30 / BigInteger_base_log10); + var firstNdigits = this._d.slice(l - N); + return ( + Math.log(new BigInteger(firstNdigits, 1, CONSTRUCT).valueOf()) + + (l - N) * Math.log(BigInteger_base) + ); + }; + + /* + Function: valueOf + Convert a to a native JavaScript integer. + This is called automatically by JavaScipt to convert a to a + native value. + Returns: + > parseInt(this.toString(), 10) + See Also: + , + */ + BigInteger.prototype.valueOf = function () { + return parseInt(this.toString(), 10); + }; + + /* + Function: toJSValue + Convert a to a native JavaScript integer. + This is the same as valueOf, but more explicitly named. + Returns: + > parseInt(this.toString(), 10) + See Also: + , + */ + BigInteger.prototype.toJSValue = function () { + return parseInt(this.toString(), 10); + }; + + /* + Function: lowVal + Author: Lucas Jones + */ + BigInteger.prototype.lowVal = function () { + return this._d[0] || 0; + }; + + var MAX_EXP = BigInteger(0x7fffffff); + // Constant: MAX_EXP + // The largest exponent allowed in and (0x7FFFFFFF or 2147483647). + BigInteger.MAX_EXP = MAX_EXP; + + (function () { + function makeUnary(fn) { + return function (a) { + return fn.call(BigInteger(a)); + }; + } + + function makeBinary(fn) { + return function (a, b) { + return fn.call(BigInteger(a), BigInteger(b)); + }; + } + + function makeTrinary(fn) { + return function (a, b, c) { + return fn.call(BigInteger(a), BigInteger(b), BigInteger(c)); + }; + } + + (function () { + var i, fn; + var unary = + 'toJSValue,isEven,isOdd,sign,isZero,isNegative,abs,isUnit,square,negate,isPositive,toString,next,prev,log'.split( + ',', + ); + var binary = + 'compare,remainder,divRem,subtract,add,quotient,divide,multiply,pow,compareAbs'.split( + ',', + ); + var trinary = ['modPow']; + + for (i = 0; i < unary.length; i++) { + fn = unary[i]; + BigInteger[fn] = makeUnary(BigInteger.prototype[fn]); + } + + for (i = 0; i < binary.length; i++) { + fn = binary[i]; + BigInteger[fn] = makeBinary(BigInteger.prototype[fn]); + } + + for (i = 0; i < trinary.length; i++) { + fn = trinary[i]; + BigInteger[fn] = makeTrinary(BigInteger.prototype[fn]); + } + + BigInteger.exp10 = function (x, n) { + return BigInteger(x).exp10(n); + }; + })(); + })(); + + exports.JSBigInt = BigInteger; // exports.BigInteger changed to exports.JSBigInt +})(typeof exports !== 'undefined' ? exports : this); diff --git a/packages/address-validator/src/crypto/blake256.js b/packages/address-validator/src/crypto/blake256.js new file mode 100644 index 000000000000..a65a8e3d2f6a --- /dev/null +++ b/packages/address-validator/src/crypto/blake256.js @@ -0,0 +1,183 @@ +'use strict'; + +/** + * Credits to https://github.com/cryptocoinjs/blake-hash + */ +Blake256.sigma = [ + [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], + [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], +]; + +Blake256.u256 = [ + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, +]; + +Blake256.padding = new Buffer([ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, +]); + +Blake256.prototype._length_carry = function (arr) { + for (var j = 0; j < arr.length; ++j) { + if (arr[j] < 0x0100000000) break; + arr[j] -= 0x0100000000; + arr[j + 1] += 1; + } +}; + +Blake256.prototype.update = function (data, encoding) { + data = new Buffer(data, encoding); + var block = this._block; + var offset = 0; + + while (this._blockOffset + data.length - offset >= block.length) { + for (var i = this._blockOffset; i < block.length; ) block[i++] = data[offset++]; + + this._length[0] += block.length * 8; + this._length_carry(this._length); + + this._compress(); + this._blockOffset = 0; + } + + while (offset < data.length) block[this._blockOffset++] = data[offset++]; + return this; +}; + +var zo = new Buffer([0x01]); +var oo = new Buffer([0x81]); + +function rot(x, n) { + return ((x << (32 - n)) | (x >>> n)) >>> 0; +} + +function g(v, m, i, a, b, c, d, e) { + var sigma = Blake256.sigma; + var u256 = Blake256.u256; + + v[a] = (v[a] + ((m[sigma[i][e]] ^ u256[sigma[i][e + 1]]) >>> 0) + v[b]) >>> 0; + v[d] = rot(v[d] ^ v[a], 16); + v[c] = (v[c] + v[d]) >>> 0; + v[b] = rot(v[b] ^ v[c], 12); + v[a] = (v[a] + ((m[sigma[i][e + 1]] ^ u256[sigma[i][e]]) >>> 0) + v[b]) >>> 0; + v[d] = rot(v[d] ^ v[a], 8); + v[c] = (v[c] + v[d]) >>> 0; + v[b] = rot(v[b] ^ v[c], 7); +} + +function Blake256() { + this._h = [ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, + 0x5be0cd19, + ]; + + this._s = [0, 0, 0, 0]; + + this._block = new Buffer(64); + this._blockOffset = 0; + this._length = [0, 0]; + + this._nullt = false; + + this._zo = zo; + this._oo = oo; +} + +Blake256.prototype._compress = function () { + var u256 = Blake256.u256; + var v = new Array(16); + var m = new Array(16); + var i; + + for (i = 0; i < 16; ++i) m[i] = this._block.readUInt32BE(i * 4); + for (i = 0; i < 8; ++i) v[i] = this._h[i] >>> 0; + for (i = 8; i < 12; ++i) v[i] = (this._s[i - 8] ^ u256[i - 8]) >>> 0; + for (i = 12; i < 16; ++i) v[i] = u256[i - 8]; + + if (!this._nullt) { + v[12] = (v[12] ^ this._length[0]) >>> 0; + v[13] = (v[13] ^ this._length[0]) >>> 0; + v[14] = (v[14] ^ this._length[1]) >>> 0; + v[15] = (v[15] ^ this._length[1]) >>> 0; + } + + for (i = 0; i < 14; ++i) { + /* column step */ + g(v, m, i, 0, 4, 8, 12, 0); + g(v, m, i, 1, 5, 9, 13, 2); + g(v, m, i, 2, 6, 10, 14, 4); + g(v, m, i, 3, 7, 11, 15, 6); + /* diagonal step */ + g(v, m, i, 0, 5, 10, 15, 8); + g(v, m, i, 1, 6, 11, 12, 10); + g(v, m, i, 2, 7, 8, 13, 12); + g(v, m, i, 3, 4, 9, 14, 14); + } + + for (i = 0; i < 16; ++i) this._h[i % 8] = (this._h[i % 8] ^ v[i]) >>> 0; + for (i = 0; i < 8; ++i) this._h[i] = (this._h[i] ^ this._s[i % 4]) >>> 0; +}; + +Blake256.prototype._padding = function () { + var lo = this._length[0] + this._blockOffset * 8; + var hi = this._length[1]; + if (lo >= 0x0100000000) { + lo -= 0x0100000000; + hi += 1; + } + + var msglen = new Buffer(8); + msglen.writeUInt32BE(hi, 0); + msglen.writeUInt32BE(lo, 4); + + if (this._blockOffset === 55) { + this._length[0] -= 8; + this.update(this._oo); + } else { + if (this._blockOffset < 55) { + if (this._blockOffset === 0) this._nullt = true; + this._length[0] -= (55 - this._blockOffset) * 8; + this.update(Blake256.padding.slice(0, 55 - this._blockOffset)); + } else { + this._length[0] -= (64 - this._blockOffset) * 8; + this.update(Blake256.padding.slice(0, 64 - this._blockOffset)); + this._length[0] -= 55 * 8; + this.update(Blake256.padding.slice(1, 1 + 55)); + this._nullt = true; + } + + this.update(this._zo); + this._length[0] -= 8; + } + + this._length[0] -= 64; + this.update(msglen); +}; + +Blake256.prototype.digest = function (encoding) { + this._padding(); + + var buffer = new Buffer(32); + for (var i = 0; i < 8; ++i) buffer.writeUInt32BE(this._h[i], i * 4); + return buffer.toString(encoding); +}; + +module.exports = Blake256; diff --git a/packages/address-validator/src/crypto/blake2b.js b/packages/address-validator/src/crypto/blake2b.js new file mode 100644 index 000000000000..7acc1e326a98 --- /dev/null +++ b/packages/address-validator/src/crypto/blake2b.js @@ -0,0 +1,320 @@ +'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; diff --git a/packages/address-validator/src/crypto/cnBase58.js b/packages/address-validator/src/crypto/cnBase58.js new file mode 100644 index 000000000000..490a37548a81 --- /dev/null +++ b/packages/address-validator/src/crypto/cnBase58.js @@ -0,0 +1,252 @@ +var JSBigInt = require('./biginteger')['JSBigInt']; + +/** +Copyright (c) 2017, moneroexamples + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Parts of the project are originally copyright (c) 2014-2017, MyMonero.com +*/ + +var cnBase58 = (function () { + var b58 = {}; + + var alphabet_str = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; + var alphabet = []; + for (var i = 0; i < alphabet_str.length; i++) { + alphabet.push(alphabet_str.charCodeAt(i)); + } + var encoded_block_sizes = [0, 2, 3, 5, 6, 7, 9, 10, 11]; + + var alphabet_size = alphabet.length; + var full_block_size = 8; + var full_encoded_block_size = 11; + + var UINT64_MAX = new JSBigInt(2).pow(64); + + function hextobin(hex) { + if (hex.length % 2 !== 0) throw 'Hex string has invalid length!'; + var res = new Uint8Array(hex.length / 2); + for (var i = 0; i < hex.length / 2; ++i) { + res[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16); + } + return res; + } + + function bintohex(bin) { + var out = []; + for (var i = 0; i < bin.length; ++i) { + out.push(('0' + bin[i].toString(16)).slice(-2)); + } + return out.join(''); + } + + function strtobin(str) { + var res = new Uint8Array(str.length); + for (var i = 0; i < str.length; i++) { + res[i] = str.charCodeAt(i); + } + return res; + } + + function bintostr(bin) { + var out = []; + for (var i = 0; i < bin.length; i++) { + out.push(String.fromCharCode(bin[i])); + } + return out.join(''); + } + + function uint8_be_to_64(data) { + if (data.length < 1 || data.length > 8) { + throw 'Invalid input length'; + } + var res = JSBigInt.ZERO; + var twopow8 = new JSBigInt(2).pow(8); + var i = 0; + switch (9 - data.length) { + case 1: + res = res.add(data[i++]); + case 2: + res = res.multiply(twopow8).add(data[i++]); + case 3: + res = res.multiply(twopow8).add(data[i++]); + case 4: + res = res.multiply(twopow8).add(data[i++]); + case 5: + res = res.multiply(twopow8).add(data[i++]); + case 6: + res = res.multiply(twopow8).add(data[i++]); + case 7: + res = res.multiply(twopow8).add(data[i++]); + case 8: + res = res.multiply(twopow8).add(data[i++]); + break; + default: + throw 'Impossible condition'; + } + return res; + } + + function uint64_to_8be(num, size) { + var res = new Uint8Array(size); + if (size < 1 || size > 8) { + throw 'Invalid input length'; + } + var twopow8 = new JSBigInt(2).pow(8); + for (var i = size - 1; i >= 0; i--) { + res[i] = num.remainder(twopow8).toJSValue(); + num = num.divide(twopow8); + } + return res; + } + + b58.encode_block = function (data, buf, index) { + if (data.length < 1 || data.length > full_encoded_block_size) { + throw 'Invalid block length: ' + data.length; + } + var num = uint8_be_to_64(data); + var i = encoded_block_sizes[data.length] - 1; + // while num > 0 + while (num.compare(0) === 1) { + var div = num.divRem(alphabet_size); + // remainder = num % alphabet_size + var remainder = div[1]; + // num = num / alphabet_size + num = div[0]; + buf[index + i] = alphabet[remainder.toJSValue()]; + i--; + } + return buf; + }; + + b58.encode = function (hex) { + var data = hextobin(hex); + if (data.length === 0) { + return ''; + } + var full_block_count = Math.floor(data.length / full_block_size); + var last_block_size = data.length % full_block_size; + var res_size = + full_block_count * full_encoded_block_size + encoded_block_sizes[last_block_size]; + + var res = new Uint8Array(res_size); + var i; + for (i = 0; i < res_size; ++i) { + res[i] = alphabet[0]; + } + for (i = 0; i < full_block_count; i++) { + res = b58.encode_block( + data.subarray(i * full_block_size, i * full_block_size + full_block_size), + res, + i * full_encoded_block_size, + ); + } + if (last_block_size > 0) { + res = b58.encode_block( + data.subarray( + full_block_count * full_block_size, + full_block_count * full_block_size + last_block_size, + ), + res, + full_block_count * full_encoded_block_size, + ); + } + return bintostr(res); + }; + + b58.decode_block = function (data, buf, index) { + if (data.length < 1 || data.length > full_encoded_block_size) { + throw 'Invalid block length: ' + data.length; + } + + var res_size = encoded_block_sizes.indexOf(data.length); + if (res_size <= 0) { + throw 'Invalid block size'; + } + var res_num = new JSBigInt(0); + var order = new JSBigInt(1); + for (var i = data.length - 1; i >= 0; i--) { + var digit = alphabet.indexOf(data[i]); + if (digit < 0) { + throw 'Invalid symbol'; + } + var product = order.multiply(digit).add(res_num); + // if product > UINT64_MAX + if (product.compare(UINT64_MAX) === 1) { + throw 'Overflow'; + } + res_num = product; + order = order.multiply(alphabet_size); + } + if (res_size < full_block_size && new JSBigInt(2).pow(8 * res_size).compare(res_num) <= 0) { + throw 'Overflow 2'; + } + buf.set(uint64_to_8be(res_num, res_size), index); + return buf; + }; + + b58.decode = function (enc) { + enc = strtobin(enc); + if (enc.length === 0) { + return ''; + } + var full_block_count = Math.floor(enc.length / full_encoded_block_size); + var last_block_size = enc.length % full_encoded_block_size; + var last_block_decoded_size = encoded_block_sizes.indexOf(last_block_size); + if (last_block_decoded_size < 0) { + throw 'Invalid encoded length'; + } + var data_size = full_block_count * full_block_size + last_block_decoded_size; + var data = new Uint8Array(data_size); + for (var i = 0; i < full_block_count; i++) { + data = b58.decode_block( + enc.subarray( + i * full_encoded_block_size, + i * full_encoded_block_size + full_encoded_block_size, + ), + data, + i * full_block_size, + ); + } + if (last_block_size > 0) { + data = b58.decode_block( + enc.subarray( + full_block_count * full_encoded_block_size, + full_block_count * full_encoded_block_size + last_block_size, + ), + data, + full_block_count * full_block_size, + ); + } + return bintohex(data); + }; + + return b58; +})(); +module.exports = cnBase58; diff --git a/packages/address-validator/src/crypto/sha3.js b/packages/address-validator/src/crypto/sha3.js new file mode 100644 index 000000000000..5f04ef5e37ff --- /dev/null +++ b/packages/address-validator/src/crypto/sha3.js @@ -0,0 +1,740 @@ +/** + * [js-sha3]{@link https://github.com/emn178/js-sha3} + * + * @version 0.7.0 + * @author Chen, Yi-Cyuan [emn178@gmail.com] + * @copyright Chen, Yi-Cyuan 2015-2017 + * @license MIT + */ +/*jslint bitwise: true */ +'use strict'; + +var ERROR = 'input is invalid type'; +var WINDOW = typeof window === 'object'; +var root = WINDOW ? window : {}; +if (root.JS_SHA3_NO_WINDOW) { + WINDOW = false; +} +var WEB_WORKER = !WINDOW && typeof self === 'object'; +var NODE_JS = + !root.JS_SHA3_NO_NODE_JS && + typeof process === 'object' && + process.versions && + process.versions.node; +if (NODE_JS) { + root = global; +} else if (WEB_WORKER) { + root = self; +} +var ARRAY_BUFFER = !root.JS_SHA3_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined'; +var HEX_CHARS = '0123456789abcdef'.split(''); +var SHAKE_PADDING = [31, 7936, 2031616, 520093696]; +var CSHAKE_PADDING = [4, 1024, 262144, 67108864]; +var KECCAK_PADDING = [1, 256, 65536, 16777216]; +var PADDING = [6, 1536, 393216, 100663296]; +var SHIFT = [0, 8, 16, 24]; +var RC = [ + 1, 0, 32898, 0, 32906, 2147483648, 2147516416, 2147483648, 32907, 0, 2147483649, 0, 2147516545, + 2147483648, 32777, 2147483648, 138, 0, 136, 0, 2147516425, 0, 2147483658, 0, 2147516555, 0, 139, + 2147483648, 32905, 2147483648, 32771, 2147483648, 32770, 2147483648, 128, 2147483648, 32778, 0, + 2147483658, 2147483648, 2147516545, 2147483648, 32896, 2147483648, 2147483649, 0, 2147516424, + 2147483648, +]; +var BITS = [224, 256, 384, 512]; +var SHAKE_BITS = [128, 256]; +var OUTPUT_TYPES = ['hex', 'buffer', 'arrayBuffer', 'array', 'digest']; +var CSHAKE_BYTEPAD = { + 128: 168, + 256: 136, +}; + +if (root.JS_SHA3_NO_NODE_JS || !Array.isArray) { + Array.isArray = function (obj) { + return Object.prototype.toString.call(obj) === '[object Array]'; + }; +} + +if (ARRAY_BUFFER && (root.JS_SHA3_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) { + ArrayBuffer.isView = function (obj) { + return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer; + }; +} + +var createOutputMethod = function (bits, padding, outputType) { + return function (message) { + return new Keccak(bits, padding, bits).update(message)[outputType](); + }; +}; + +var createShakeOutputMethod = function (bits, padding, outputType) { + return function (message, outputBits) { + return new Keccak(bits, padding, outputBits).update(message)[outputType](); + }; +}; + +var createCshakeOutputMethod = function (bits, padding, outputType) { + return function (message, outputBits, n, s) { + return methods['cshake' + bits].update(message, outputBits, n, s)[outputType](); + }; +}; + +var createKmacOutputMethod = function (bits, padding, outputType) { + return function (key, message, outputBits, s) { + return methods['kmac' + bits].update(key, message, outputBits, s)[outputType](); + }; +}; + +var createOutputMethods = function (method, createMethod, bits, padding) { + for (var i = 0; i < OUTPUT_TYPES.length; ++i) { + var type = OUTPUT_TYPES[i]; + method[type] = createMethod(bits, padding, type); + } + return method; +}; + +var createMethod = function (bits, padding) { + var method = createOutputMethod(bits, padding, 'hex'); + method.create = function () { + return new Keccak(bits, padding, bits); + }; + method.update = function (message) { + return method.create().update(message); + }; + return createOutputMethods(method, createOutputMethod, bits, padding); +}; + +var createShakeMethod = function (bits, padding) { + var method = createShakeOutputMethod(bits, padding, 'hex'); + method.create = function (outputBits) { + return new Keccak(bits, padding, outputBits); + }; + method.update = function (message, outputBits) { + return method.create(outputBits).update(message); + }; + return createOutputMethods(method, createShakeOutputMethod, bits, padding); +}; + +var createCshakeMethod = function (bits, padding) { + var w = CSHAKE_BYTEPAD[bits]; + var method = createCshakeOutputMethod(bits, padding, 'hex'); + method.create = function (outputBits, n, s) { + if (!n && !s) { + return methods['shake' + bits].create(outputBits); + } else { + return new Keccak(bits, padding, outputBits).bytepad([n, s], w); + } + }; + method.update = function (message, outputBits, n, s) { + return method.create(outputBits, n, s).update(message); + }; + return createOutputMethods(method, createCshakeOutputMethod, bits, padding); +}; + +var createKmacMethod = function (bits, padding) { + var w = CSHAKE_BYTEPAD[bits]; + var method = createKmacOutputMethod(bits, padding, 'hex'); + method.create = function (key, outputBits, s) { + return new Kmac(bits, padding, outputBits).bytepad(['KMAC', s], w).bytepad([key], w); + }; + method.update = function (key, message, outputBits, s) { + return method.create(key, outputBits, s).update(message); + }; + return createOutputMethods(method, createKmacOutputMethod, bits, padding); +}; + +var algorithms = [ + { name: 'keccak', padding: KECCAK_PADDING, bits: BITS, createMethod: createMethod }, + { name: 'sha3', padding: PADDING, bits: BITS, createMethod: createMethod }, + { name: 'shake', padding: SHAKE_PADDING, bits: SHAKE_BITS, createMethod: createShakeMethod }, + { name: 'cshake', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: createCshakeMethod }, + { name: 'kmac', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: createKmacMethod }, +]; + +var methods = {}, + methodNames = []; + +for (var i = 0; i < algorithms.length; ++i) { + var algorithm = algorithms[i]; + var bits = algorithm.bits; + for (var j = 0; j < bits.length; ++j) { + var methodName = algorithm.name + '_' + bits[j]; + methodNames.push(methodName); + methods[methodName] = algorithm.createMethod(bits[j], algorithm.padding); + if (algorithm.name !== 'sha3') { + var newMethodName = algorithm.name + bits[j]; + methodNames.push(newMethodName); + methods[newMethodName] = methods[methodName]; + } + } +} + +function Keccak(bits, padding, outputBits) { + this.blocks = []; + this.s = []; + this.padding = padding; + this.outputBits = outputBits; + this.reset = true; + this.finalized = false; + this.block = 0; + this.start = 0; + this.blockCount = (1600 - (bits << 1)) >> 5; + this.byteCount = this.blockCount << 2; + this.outputBlocks = outputBits >> 5; + this.extraBytes = (outputBits & 31) >> 3; + + for (var i = 0; i < 50; ++i) { + this.s[i] = 0; + } +} + +Keccak.prototype.update = function (message) { + if (this.finalized) { + return; + } + var notString, + type = typeof message; + if (type !== 'string') { + if (type === 'object') { + if (message === null) { + throw ERROR; + } else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) { + message = new Uint8Array(message); + } else if (!Array.isArray(message)) { + if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) { + throw ERROR; + } + } + } else { + throw ERROR; + } + notString = true; + } + var blocks = this.blocks, + byteCount = this.byteCount, + length = message.length, + blockCount = this.blockCount, + index = 0, + s = this.s, + i, + code; + + while (index < length) { + if (this.reset) { + this.reset = false; + blocks[0] = this.block; + for (i = 1; i < blockCount + 1; ++i) { + blocks[i] = 0; + } + } + if (notString) { + for (i = this.start; index < length && i < byteCount; ++index) { + blocks[i >> 2] |= message[index] << SHIFT[i++ & 3]; + } + } else { + for (i = this.start; index < length && i < byteCount; ++index) { + code = message.charCodeAt(index); + if (code < 0x80) { + blocks[i >> 2] |= code << SHIFT[i++ & 3]; + } else if (code < 0x800) { + blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; + } else if (code < 0xd800 || code >= 0xe000) { + blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; + } else { + code = + 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff)); + blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; + } + } + } + this.lastByteIndex = i; + if (i >= byteCount) { + this.start = i - byteCount; + this.block = blocks[blockCount]; + for (i = 0; i < blockCount; ++i) { + s[i] ^= blocks[i]; + } + f(s); + this.reset = true; + } else { + this.start = i; + } + } + return this; +}; + +Keccak.prototype.encode = function (x, right) { + var o = x & 255, + n = 1; + var bytes = [o]; + x = x >> 8; + o = x & 255; + while (o > 0) { + bytes.unshift(o); + x = x >> 8; + o = x & 255; + ++n; + } + if (right) { + bytes.push(n); + } else { + bytes.unshift(n); + } + this.update(bytes); + return bytes.length; +}; + +Keccak.prototype.encodeString = function (str) { + var notString, + type = typeof str; + if (type !== 'string') { + if (type === 'object') { + if (str === null) { + throw ERROR; + } else if (ARRAY_BUFFER && str.constructor === ArrayBuffer) { + str = new Uint8Array(str); + } else if (!Array.isArray(str)) { + if (!ARRAY_BUFFER || !ArrayBuffer.isView(str)) { + throw ERROR; + } + } + } else { + throw ERROR; + } + notString = true; + } + var bytes = 0, + length = str.length; + if (notString) { + bytes = length; + } else { + for (var i = 0; i < str.length; ++i) { + var code = str.charCodeAt(i); + if (code < 0x80) { + bytes += 1; + } else if (code < 0x800) { + bytes += 2; + } else if (code < 0xd800 || code >= 0xe000) { + bytes += 3; + } else { + code = 0x10000 + (((code & 0x3ff) << 10) | (str.charCodeAt(++i) & 0x3ff)); + bytes += 4; + } + } + } + bytes += this.encode(bytes * 8); + this.update(str); + return bytes; +}; + +Keccak.prototype.bytepad = function (strs, w) { + var bytes = this.encode(w); + for (var i = 0; i < strs.length; ++i) { + bytes += this.encodeString(strs[i]); + } + var paddingBytes = w - (bytes % w); + var zeros = []; + zeros.length = paddingBytes; + this.update(zeros); + return this; +}; + +Keccak.prototype.finalize = function () { + if (this.finalized) { + return; + } + this.finalized = true; + var blocks = this.blocks, + i = this.lastByteIndex, + blockCount = this.blockCount, + s = this.s; + blocks[i >> 2] |= this.padding[i & 3]; + if (this.lastByteIndex === this.byteCount) { + blocks[0] = blocks[blockCount]; + for (i = 1; i < blockCount + 1; ++i) { + blocks[i] = 0; + } + } + blocks[blockCount - 1] |= 0x80000000; + for (i = 0; i < blockCount; ++i) { + s[i] ^= blocks[i]; + } + f(s); +}; + +Keccak.prototype.toString = Keccak.prototype.hex = function () { + this.finalize(); + + var blockCount = this.blockCount, + s = this.s, + outputBlocks = this.outputBlocks, + extraBytes = this.extraBytes, + i = 0, + j = 0; + var hex = '', + block; + while (j < outputBlocks) { + for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) { + block = s[i]; + hex += + HEX_CHARS[(block >> 4) & 0x0f] + + HEX_CHARS[block & 0x0f] + + HEX_CHARS[(block >> 12) & 0x0f] + + HEX_CHARS[(block >> 8) & 0x0f] + + HEX_CHARS[(block >> 20) & 0x0f] + + HEX_CHARS[(block >> 16) & 0x0f] + + HEX_CHARS[(block >> 28) & 0x0f] + + HEX_CHARS[(block >> 24) & 0x0f]; + } + if (j % blockCount === 0) { + f(s); + i = 0; + } + } + if (extraBytes) { + block = s[i]; + hex += HEX_CHARS[(block >> 4) & 0x0f] + HEX_CHARS[block & 0x0f]; + if (extraBytes > 1) { + hex += HEX_CHARS[(block >> 12) & 0x0f] + HEX_CHARS[(block >> 8) & 0x0f]; + } + if (extraBytes > 2) { + hex += HEX_CHARS[(block >> 20) & 0x0f] + HEX_CHARS[(block >> 16) & 0x0f]; + } + } + return hex; +}; + +Keccak.prototype.arrayBuffer = function () { + this.finalize(); + + var blockCount = this.blockCount, + s = this.s, + outputBlocks = this.outputBlocks, + extraBytes = this.extraBytes, + i = 0, + j = 0; + var bytes = this.outputBits >> 3; + var buffer; + if (extraBytes) { + buffer = new ArrayBuffer((outputBlocks + 1) << 2); + } else { + buffer = new ArrayBuffer(bytes); + } + var array = new Uint32Array(buffer); + while (j < outputBlocks) { + for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) { + array[j] = s[i]; + } + if (j % blockCount === 0) { + f(s); + } + } + if (extraBytes) { + array[i] = s[i]; + buffer = buffer.slice(0, bytes); + } + return buffer; +}; + +Keccak.prototype.buffer = Keccak.prototype.arrayBuffer; + +Keccak.prototype.digest = Keccak.prototype.array = function () { + this.finalize(); + + var blockCount = this.blockCount, + s = this.s, + outputBlocks = this.outputBlocks, + extraBytes = this.extraBytes, + i = 0, + j = 0; + var array = [], + offset, + block; + while (j < outputBlocks) { + for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) { + offset = j << 2; + block = s[i]; + array[offset] = block & 0xff; + array[offset + 1] = (block >> 8) & 0xff; + array[offset + 2] = (block >> 16) & 0xff; + array[offset + 3] = (block >> 24) & 0xff; + } + if (j % blockCount === 0) { + f(s); + } + } + if (extraBytes) { + offset = j << 2; + block = s[i]; + array[offset] = block & 0xff; + if (extraBytes > 1) { + array[offset + 1] = (block >> 8) & 0xff; + } + if (extraBytes > 2) { + array[offset + 2] = (block >> 16) & 0xff; + } + } + return array; +}; + +function Kmac(bits, padding, outputBits) { + Keccak.call(this, bits, padding, outputBits); +} + +Kmac.prototype = new Keccak(); + +Kmac.prototype.finalize = function () { + this.encode(this.outputBits, true); + return Keccak.prototype.finalize.call(this); +}; + +var f = function (s) { + var h, + l, + n, + c0, + c1, + c2, + c3, + c4, + c5, + c6, + c7, + c8, + c9, + b0, + b1, + b2, + b3, + b4, + b5, + b6, + b7, + b8, + b9, + b10, + b11, + b12, + b13, + b14, + b15, + b16, + b17, + b18, + b19, + b20, + b21, + b22, + b23, + b24, + b25, + b26, + b27, + b28, + b29, + b30, + b31, + b32, + b33, + b34, + b35, + b36, + b37, + b38, + b39, + b40, + b41, + b42, + b43, + b44, + b45, + b46, + b47, + b48, + b49; + for (n = 0; n < 48; n += 2) { + c0 = s[0] ^ s[10] ^ s[20] ^ s[30] ^ s[40]; + c1 = s[1] ^ s[11] ^ s[21] ^ s[31] ^ s[41]; + c2 = s[2] ^ s[12] ^ s[22] ^ s[32] ^ s[42]; + c3 = s[3] ^ s[13] ^ s[23] ^ s[33] ^ s[43]; + c4 = s[4] ^ s[14] ^ s[24] ^ s[34] ^ s[44]; + c5 = s[5] ^ s[15] ^ s[25] ^ s[35] ^ s[45]; + c6 = s[6] ^ s[16] ^ s[26] ^ s[36] ^ s[46]; + c7 = s[7] ^ s[17] ^ s[27] ^ s[37] ^ s[47]; + c8 = s[8] ^ s[18] ^ s[28] ^ s[38] ^ s[48]; + c9 = s[9] ^ s[19] ^ s[29] ^ s[39] ^ s[49]; + + h = c8 ^ ((c2 << 1) | (c3 >>> 31)); + l = c9 ^ ((c3 << 1) | (c2 >>> 31)); + s[0] ^= h; + s[1] ^= l; + s[10] ^= h; + s[11] ^= l; + s[20] ^= h; + s[21] ^= l; + s[30] ^= h; + s[31] ^= l; + s[40] ^= h; + s[41] ^= l; + h = c0 ^ ((c4 << 1) | (c5 >>> 31)); + l = c1 ^ ((c5 << 1) | (c4 >>> 31)); + s[2] ^= h; + s[3] ^= l; + s[12] ^= h; + s[13] ^= l; + s[22] ^= h; + s[23] ^= l; + s[32] ^= h; + s[33] ^= l; + s[42] ^= h; + s[43] ^= l; + h = c2 ^ ((c6 << 1) | (c7 >>> 31)); + l = c3 ^ ((c7 << 1) | (c6 >>> 31)); + s[4] ^= h; + s[5] ^= l; + s[14] ^= h; + s[15] ^= l; + s[24] ^= h; + s[25] ^= l; + s[34] ^= h; + s[35] ^= l; + s[44] ^= h; + s[45] ^= l; + h = c4 ^ ((c8 << 1) | (c9 >>> 31)); + l = c5 ^ ((c9 << 1) | (c8 >>> 31)); + s[6] ^= h; + s[7] ^= l; + s[16] ^= h; + s[17] ^= l; + s[26] ^= h; + s[27] ^= l; + s[36] ^= h; + s[37] ^= l; + s[46] ^= h; + s[47] ^= l; + h = c6 ^ ((c0 << 1) | (c1 >>> 31)); + l = c7 ^ ((c1 << 1) | (c0 >>> 31)); + s[8] ^= h; + s[9] ^= l; + s[18] ^= h; + s[19] ^= l; + s[28] ^= h; + s[29] ^= l; + s[38] ^= h; + s[39] ^= l; + s[48] ^= h; + s[49] ^= l; + + b0 = s[0]; + b1 = s[1]; + b32 = (s[11] << 4) | (s[10] >>> 28); + b33 = (s[10] << 4) | (s[11] >>> 28); + b14 = (s[20] << 3) | (s[21] >>> 29); + b15 = (s[21] << 3) | (s[20] >>> 29); + b46 = (s[31] << 9) | (s[30] >>> 23); + b47 = (s[30] << 9) | (s[31] >>> 23); + b28 = (s[40] << 18) | (s[41] >>> 14); + b29 = (s[41] << 18) | (s[40] >>> 14); + b20 = (s[2] << 1) | (s[3] >>> 31); + b21 = (s[3] << 1) | (s[2] >>> 31); + b2 = (s[13] << 12) | (s[12] >>> 20); + b3 = (s[12] << 12) | (s[13] >>> 20); + b34 = (s[22] << 10) | (s[23] >>> 22); + b35 = (s[23] << 10) | (s[22] >>> 22); + b16 = (s[33] << 13) | (s[32] >>> 19); + b17 = (s[32] << 13) | (s[33] >>> 19); + b48 = (s[42] << 2) | (s[43] >>> 30); + b49 = (s[43] << 2) | (s[42] >>> 30); + b40 = (s[5] << 30) | (s[4] >>> 2); + b41 = (s[4] << 30) | (s[5] >>> 2); + b22 = (s[14] << 6) | (s[15] >>> 26); + b23 = (s[15] << 6) | (s[14] >>> 26); + b4 = (s[25] << 11) | (s[24] >>> 21); + b5 = (s[24] << 11) | (s[25] >>> 21); + b36 = (s[34] << 15) | (s[35] >>> 17); + b37 = (s[35] << 15) | (s[34] >>> 17); + b18 = (s[45] << 29) | (s[44] >>> 3); + b19 = (s[44] << 29) | (s[45] >>> 3); + b10 = (s[6] << 28) | (s[7] >>> 4); + b11 = (s[7] << 28) | (s[6] >>> 4); + b42 = (s[17] << 23) | (s[16] >>> 9); + b43 = (s[16] << 23) | (s[17] >>> 9); + b24 = (s[26] << 25) | (s[27] >>> 7); + b25 = (s[27] << 25) | (s[26] >>> 7); + b6 = (s[36] << 21) | (s[37] >>> 11); + b7 = (s[37] << 21) | (s[36] >>> 11); + b38 = (s[47] << 24) | (s[46] >>> 8); + b39 = (s[46] << 24) | (s[47] >>> 8); + b30 = (s[8] << 27) | (s[9] >>> 5); + b31 = (s[9] << 27) | (s[8] >>> 5); + b12 = (s[18] << 20) | (s[19] >>> 12); + b13 = (s[19] << 20) | (s[18] >>> 12); + b44 = (s[29] << 7) | (s[28] >>> 25); + b45 = (s[28] << 7) | (s[29] >>> 25); + b26 = (s[38] << 8) | (s[39] >>> 24); + b27 = (s[39] << 8) | (s[38] >>> 24); + b8 = (s[48] << 14) | (s[49] >>> 18); + b9 = (s[49] << 14) | (s[48] >>> 18); + + s[0] = b0 ^ (~b2 & b4); + s[1] = b1 ^ (~b3 & b5); + s[10] = b10 ^ (~b12 & b14); + s[11] = b11 ^ (~b13 & b15); + s[20] = b20 ^ (~b22 & b24); + s[21] = b21 ^ (~b23 & b25); + s[30] = b30 ^ (~b32 & b34); + s[31] = b31 ^ (~b33 & b35); + s[40] = b40 ^ (~b42 & b44); + s[41] = b41 ^ (~b43 & b45); + s[2] = b2 ^ (~b4 & b6); + s[3] = b3 ^ (~b5 & b7); + s[12] = b12 ^ (~b14 & b16); + s[13] = b13 ^ (~b15 & b17); + s[22] = b22 ^ (~b24 & b26); + s[23] = b23 ^ (~b25 & b27); + s[32] = b32 ^ (~b34 & b36); + s[33] = b33 ^ (~b35 & b37); + s[42] = b42 ^ (~b44 & b46); + s[43] = b43 ^ (~b45 & b47); + s[4] = b4 ^ (~b6 & b8); + s[5] = b5 ^ (~b7 & b9); + s[14] = b14 ^ (~b16 & b18); + s[15] = b15 ^ (~b17 & b19); + s[24] = b24 ^ (~b26 & b28); + s[25] = b25 ^ (~b27 & b29); + s[34] = b34 ^ (~b36 & b38); + s[35] = b35 ^ (~b37 & b39); + s[44] = b44 ^ (~b46 & b48); + s[45] = b45 ^ (~b47 & b49); + s[6] = b6 ^ (~b8 & b0); + s[7] = b7 ^ (~b9 & b1); + s[16] = b16 ^ (~b18 & b10); + s[17] = b17 ^ (~b19 & b11); + s[26] = b26 ^ (~b28 & b20); + s[27] = b27 ^ (~b29 & b21); + s[36] = b36 ^ (~b38 & b30); + s[37] = b37 ^ (~b39 & b31); + s[46] = b46 ^ (~b48 & b40); + s[47] = b47 ^ (~b49 & b41); + s[8] = b8 ^ (~b0 & b2); + s[9] = b9 ^ (~b1 & b3); + s[18] = b18 ^ (~b10 & b12); + s[19] = b19 ^ (~b11 & b13); + s[28] = b28 ^ (~b20 & b22); + s[29] = b29 ^ (~b21 & b23); + s[38] = b38 ^ (~b30 & b32); + s[39] = b39 ^ (~b31 & b33); + s[48] = b48 ^ (~b40 & b42); + s[49] = b49 ^ (~b41 & b43); + + s[0] ^= RC[n]; + s[1] ^= RC[n + 1]; + } +}; + +module.exports = methods; diff --git a/packages/address-validator/src/crypto/utils.js b/packages/address-validator/src/crypto/utils.js new file mode 100644 index 000000000000..fac58b2802e5 --- /dev/null +++ b/packages/address-validator/src/crypto/utils.js @@ -0,0 +1,137 @@ +var jsSHA = require('jssha/src/sha256'); +var Blake256 = require('./blake256'); +var keccak256 = require('./sha3')['keccak256']; +var Blake2B = require('./blake2b'); +var base58 = require('./base58'); +var base32 = require('./base32'); +var BigNum = require('browserify-bignum'); +var groestl = require('groestl-hash-js'); + +// Address types, compatible with Trezor +const addressType = { + ADDRESS: 'address', + P2PKH: 'p2pkh', + P2WPKH: 'p2wpkh', + P2WSH: 'p2wsh', + P2SH: 'p2sh', + P2TR: 'p2tr', + WITNESS_UNKNOWN: 'p2w-unknown', +}; + +function numberToHex(number, sizeInBytes) { + return Math.round(number) + .toString(16) + .padStart(sizeInBytes * 2, '0'); +} + +function isHexChar(c) { + if ((c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f') || (c >= '0' && c <= '9')) { + return 1; + } + return 0; +} + +/* Convert a hex char to value */ +function hexChar2byte(c) { + var d = 0; + if (c >= 'A' && c <= 'F') { + d = c.charCodeAt(0) - 'A'.charCodeAt(0) + 10; + } else if (c >= 'a' && c <= 'f') { + d = c.charCodeAt(0) - 'a'.charCodeAt(0) + 10; + } else if (c >= '0' && c <= '9') { + d = c.charCodeAt(0) - '0'.charCodeAt(0); + } + return d; +} + +/* Convert a byte to string */ +function byte2hexStr(byte) { + var hexByteMap = '0123456789ABCDEF'; + var str = ''; + str += hexByteMap.charAt(byte >> 4); + str += hexByteMap.charAt(byte & 0x0f); + return str; +} + +function byteArray2hexStr(byteArray) { + var str = ''; + for (var i = 0; i < byteArray.length - 1; i++) { + str += byte2hexStr(byteArray[i]); + } + str += byte2hexStr(byteArray[i]); + return str; +} + +function hexStr2byteArray(str) { + var byteArray = Array(); + var d = 0; + var i = 0; + var j = 0; + var k = 0; + + for (i = 0; i < str.length; i++) { + var c = str.charAt(i); + if (isHexChar(c)) { + d <<= 4; + d += hexChar2byte(c); + j++; + if (0 === j % 2) { + byteArray[k++] = d; + d = 0; + } + } + } + return byteArray; +} + +module.exports = { + numberToHex, + toHex: function (arrayOfBytes) { + var hex = ''; + for (var i = 0; i < arrayOfBytes.length; i++) { + hex += numberToHex(arrayOfBytes[i], 1); + } + return hex; + }, + sha256: function (payload, format = 'HEX') { + var sha = new jsSHA('SHA-256', format); + sha.update(payload); + return sha.getHash(format); + }, + sha256x2: function (buffer, format = 'HEX') { + return this.sha256(this.sha256(buffer, format), format); + }, + sha256Checksum: function (payload) { + return this.sha256(this.sha256(payload)).substr(0, 8); + }, + blake256: function (hexString) { + return new Blake256().update(hexString, 'hex').digest('hex'); + }, + blake256Checksum: function (payload) { + return this.blake256(this.blake256(payload)).substr(0, 8); + }, + blake2b: function (hexString, outlen) { + return new Blake2B(outlen).update(Buffer.from(hexString, 'hex')).digest('hex'); + }, + keccak256: function (hexString) { + return keccak256(hexString); + }, + keccak256Checksum: function (payload) { + return keccak256(payload).toString().substr(0, 8); + }, + blake2b256: function (hexString) { + return new Blake2B(32).update(Buffer.from(hexString, 'hex'), 32).digest('hex'); + }, + groestl512x2: function (hexString) { + let result = groestl.groestl_2(Buffer.from(hexString, 'hex'), 1, 0).substr(0, 8); + return result; + }, + base58: base58.decode, + byteArray2hexStr: byteArray2hexStr, + hexStr2byteArray: hexStr2byteArray, + bigNumberToBuffer: function (bignumber, size) { + return new BigNum(bignumber).toBuffer({ size, endian: 'big' }); + }, + base32, + addressType, +}; diff --git a/packages/address-validator/src/currencies.js b/packages/address-validator/src/currencies.js new file mode 100644 index 000000000000..9d4f40f35129 --- /dev/null +++ b/packages/address-validator/src/currencies.js @@ -0,0 +1,1505 @@ +var XRPValidator = require('./ripple_validator'); +var ETHValidator = require('./ethereum_validator'); +var BTCValidator = require('./bitcoin_validator'); +var ADAValidator = require('./ada_validator'); +var XMRValidator = require('./monero_validator'); +var LokiValidator = require('./loki_validator'); +var NANOValidator = require('./nano_validator'); +var SCValidator = require('./siacoin_validator'); +var TRXValidator = require('./tron_validator'); +var NEMValidator = require('./nem_validator'); +var LSKValidator = require('./lisk_validator'); +var BCHValidator = require('./bch_validator'); +var XLMValidator = require('./stellar_validator'); +var BinanceValidator = require('./binance_validator'); +var EOSValidator = require('./eos_validator'); +var XTZValidator = require('./tezos_validator'); +var AEValidator = require('./ae_validator'); +var ARDRValidator = require('./ardr_validator'); +var ATOMValidator = require('./atom_validator'); +var HBARValidator = require('./hbar_validator'); +var ICXValidator = require('./icx_validator'); +var IOSTValidator = require('./iost_validator'); +// var IOTAValidator = require('./iota_validator'); +var STEEMValidator = require('./steem_validator'); +var SYSValidator = require('./sys_validator'); +var ZILValidator = require('./zil_validator'); +var NXTValidator = require('./nxt_validator'); + +// defines P2PKH, P2SH and bech32 address types for standard (prod) and testnet networks +var CURRENCIES = [ + { + name: 'Bitcoin', + symbol: 'btc', + segwitHrp: { prod: 'bc', testnet: 'tb', regtest: 'bcrt' }, + addressTypes: { + prod: ['00', '05'], + testnet: ['6f', 'c4', '3c', '26'], + regtest: ['6f', 'c4', '3c', '26'], + }, + validator: BTCValidator, + }, + { + name: 'BitcoinCash', + symbol: 'bch', + regexp: '^[qQpP]{1}[0-9a-zA-Z]{41}$', + addressTypes: { prod: ['00', '05'], testnet: ['6f', 'c4'] }, + validator: BCHValidator, + }, + { + name: 'Bitcoin Diamond', + symbol: 'bcd', + validator: BTCValidator, + addressTypes: { prod: ['00'] }, + }, + { + name: 'Bitcoin SV', + symbol: 'bsv', + regexp: '^[qQ]{1}[0-9a-zA-Z]{41}$', + addressTypes: { prod: ['00', '05'], testnet: ['6f', 'c4'] }, + validator: BCHValidator, + }, + { + name: 'Fujicoin', + symbol: 'fjc', + segwitHrp: { prod: 'fc', testnet: 'tf' }, + addressTypes: { prod: ['24', '10'], testnet: ['4a', 'c4'] }, + validator: BTCValidator, + }, + { + name: 'LiteCoin', + symbol: 'ltc', + segwitHrp: { prod: 'ltc', testnet: 'tltc' }, + addressTypes: { prod: ['30', '32'], testnet: ['6f', 'c4', '3a'] }, + validator: BTCValidator, + }, + { + name: 'PeerCoin', + symbol: 'ppc', + addressTypes: { prod: ['37', '75'], testnet: ['6f', 'c4'] }, + validator: BTCValidator, + }, + { + name: 'DogeCoin', + symbol: 'doge', + addressTypes: { prod: ['1e', '16'], testnet: ['71', 'c4'] }, + validator: BTCValidator, + }, + { + name: 'BeaverCoin', + symbol: 'bvc', + addressTypes: { prod: ['19', '05'], testnet: ['6f', 'c4'] }, + validator: BTCValidator, + }, + { + name: 'FreiCoin', + symbol: 'frc', + addressTypes: { prod: ['00', '05'], testnet: ['6f', 'c4'] }, + validator: BTCValidator, + }, + { + name: 'ProtoShares', + symbol: 'pts', + addressTypes: { prod: ['38', '05'], testnet: ['6f', 'c4'] }, + validator: BTCValidator, + }, + { + name: 'MegaCoin', + symbol: 'mec', + addressTypes: { prod: ['32', '05'], testnet: ['6f', 'c4'] }, + validator: BTCValidator, + }, + { + name: 'PrimeCoin', + symbol: 'xpm', + addressTypes: { prod: ['17', '53'], testnet: ['6f', 'c4'] }, + validator: BTCValidator, + }, + { + name: 'AuroraCoin', + symbol: 'aur', + addressTypes: { prod: ['17', '05'], testnet: ['6f', 'c4'] }, + validator: BTCValidator, + }, + { + name: 'NameCoin', + symbol: 'nmc', + addressTypes: { prod: ['34'], testnet: [] }, + validator: BTCValidator, + }, + { + name: 'NXT', + symbol: 'nxt', + validator: NXTValidator, + }, + { + name: 'BioCoin', + symbol: 'bio', + addressTypes: { prod: ['19', '14'], testnet: ['6f', 'c4'] }, + validator: BTCValidator, + }, + { + name: 'GarliCoin', + symbol: 'grlc', + addressTypes: { prod: ['26', '05'], testnet: ['6f', 'c4'] }, + validator: BTCValidator, + }, + { + name: 'VertCoin', + symbol: 'vtc', + segwitHrp: { prod: 'vtc', testnet: 'tvtc' }, + addressTypes: { prod: ['47', '05'], testnet: ['4a', 'c4', '6f'] }, + validator: BTCValidator, + }, + { + name: 'VeChain', + symbol: 'ven', + validator: ETHValidator, + }, + { + name: 'VeChain Mainnet', + symbol: 'vet', + validator: ETHValidator, + }, + { + name: 'BitcoinGold', + symbol: 'btg', + segwitHrp: { prod: 'btg', testnet: 'tbtg' }, + addressTypes: { prod: ['26', '17'], testnet: ['6f', 'c4'] }, + validator: BTCValidator, + }, + { + name: 'Komodo', + symbol: 'kmd', + addressTypes: { prod: ['3c', '55'], testnet: ['0', '5'] }, + validator: BTCValidator, + }, + { + name: 'BitcoinZ', + symbol: 'btcz', + expectedLength: 26, + addressTypes: { prod: ['1cb8', '1cbd'], testnet: ['1d25', '1cba'] }, + validator: BTCValidator, + }, + { + name: 'BitcoinPrivate', + symbol: 'btcp', + expectedLength: 26, + addressTypes: { prod: ['1325', '13af'], testnet: ['1957', '19e0'] }, + validator: BTCValidator, + }, + { + name: 'Hush', + symbol: 'hush', + expectedLength: 26, + addressTypes: { prod: ['1cb8', '1cbd'], testnet: ['1d25', '1cba'] }, + validator: BTCValidator, + }, + { + name: 'SnowGem', + symbol: 'sng', + expectedLength: 26, + addressTypes: { prod: ['1c28', '1c2d'], testnet: ['1d25', '1cba'] }, + validator: BTCValidator, + }, + { + name: 'ZCash', + symbol: 'zec', + expectedLength: 26, + addressTypes: { prod: ['1cb8', '1cbd'], testnet: ['1d25', '1cba'] }, + validator: BTCValidator, + }, + { + name: 'ZClassic', + symbol: 'zcl', + expectedLength: 26, + addressTypes: { prod: ['1cb8', '1cbd'], testnet: ['1d25', '1cba'] }, + validator: BTCValidator, + }, + { + name: 'ZenCash', + symbol: 'zen', + expectedLength: 26, + addressTypes: { prod: ['2089', '2096'], testnet: ['2092', '2098'] }, + validator: BTCValidator, + }, + { + name: 'VoteCoin', + symbol: 'vot', + expectedLength: 26, + addressTypes: { prod: ['1cb8', '1cbd'], testnet: ['1d25', '1cba'] }, + validator: BTCValidator, + }, + { + name: 'Decred', + symbol: 'dcr', + addressTypes: { prod: ['073f', '071a'], testnet: ['0f21', '0efc'] }, + hashFunction: 'blake256', + expectedLength: 26, + validator: BTCValidator, + }, + { + name: 'GameCredits', + symbol: 'game', + segwitHrp: { prod: 'game', prod: 'tgame' }, + addressTypes: { prod: ['26', '3e'], testnet: ['6f', '3a'] }, + validator: BTCValidator, + }, + { + name: 'PIVX', + symbol: 'pivx', + addressTypes: { prod: ['1e', '0d'], testnet: [] }, + validator: BTCValidator, + }, + { + name: 'SolarCoin', + symbol: 'slr', + addressTypes: { prod: ['12', '05'], testnet: [] }, + validator: BTCValidator, + }, + { + name: 'MonaCoin', + symbol: 'mona', + segwitHrp: { prod: 'mona', prod: 'tmona' }, + addressTypes: { prod: ['32', '37'], testnet: ['6f', '75'] }, + validator: BTCValidator, + }, + { + name: 'DigiByte', + symbol: 'dgb', + segwitHrp: { prod: 'dgb' }, + addressTypes: { prod: ['1e', '3f'], testnet: [] }, + validator: BTCValidator, + }, + { + name: 'Tether', + symbol: 'usdt', + addressTypes: { prod: ['00', '05'], testnet: ['6f', 'c4'] }, + validator: BTCValidator, + }, + { + name: 'Ripple', + symbol: 'xrp', + validator: XRPValidator, + }, + { + name: 'Dash', + symbol: 'dash', + addressTypes: { prod: ['4c', '10'], testnet: ['8c', '13'] }, + validator: BTCValidator, + }, + { + name: 'Neo', + symbol: 'neo', + addressTypes: { prod: ['17'], testnet: [] }, + validator: BTCValidator, + }, + { + name: 'NeoGas', + symbol: 'gas', + addressTypes: { prod: ['17'], testnet: [] }, + validator: BTCValidator, + }, + { + name: 'Qtum', + symbol: 'qtum', + segwitHrp: { prod: 'qc', prod: 'tq' }, + addressTypes: { prod: ['3a', '32'], testnet: ['78', '6e'] }, + validator: BTCValidator, + }, + { + name: 'Waves', + symbol: 'waves', + addressTypes: { prod: ['0157'], testnet: ['0154'] }, + expectedLength: 26, + hashFunction: 'blake256keccak256', + regex: /^[a-zA-Z0-9]{35}$/, + validator: BTCValidator, + }, + { + name: 'Ontology', + symbol: 'ont', + validator: BTCValidator, + addressTypes: { prod: ['17', '41'] }, + }, + { + name: 'Ravencoin', + symbol: 'rvn', + validator: BTCValidator, + addressTypes: { prod: ['3c'] }, + }, + { + name: 'Groestlcoin', + symbol: 'grs', + addressTypes: { prod: ['24', '05'], testnet: ['6f', 'c4'] }, + segwitHrp: { prod: 'grs', testnet: 'tgrs' }, + hashFunction: 'groestl512x2', + validator: BTCValidator, + }, + { + name: 'Ethereum', + symbol: 'eth', + validator: ETHValidator, + }, + { + name: 'EtherZero', + symbol: 'etz', + validator: ETHValidator, + }, + { + name: 'EthereumClassic', + symbol: 'etc', + validator: ETHValidator, + }, + { + name: 'Callisto', + symbol: 'clo', + validator: ETHValidator, + }, + { + name: 'Bankex', + symbol: 'bkx', + validator: ETHValidator, + }, + { + name: 'Cardano', + symbol: 'ada', + segwitHrp: { prod: 'addr', testnet: 'addr_test' }, + validator: ADAValidator, + }, + { + name: 'Monero', + symbol: 'xmr', + addressTypes: { prod: ['18'], testnet: ['53'] }, + subAddressTypes: { prod: ['42'], testnet: ['63'] }, + iAddressTypes: { prod: ['19'], testnet: ['54'] }, + validator: XMRValidator, + }, + { + name: 'Aragon', + symbol: 'ant', + validator: ETHValidator, + }, + { + name: 'Ardor', + symbol: 'ardr', + validator: ARDRValidator, + }, + { + name: 'Basic Attention Token', + symbol: 'bat', + validator: ETHValidator, + }, + { + name: 'Bancor', + symbol: 'bnt', + validator: ETHValidator, + }, + { + name: 'Civic', + symbol: 'cvc', + validator: ETHValidator, + }, + { + name: 'Own', // Rebranded from Chainium + symbol: 'chx', + validator: ETHValidator, + }, + { + name: 'District0x', + symbol: 'dnt', + validator: ETHValidator, + }, + { + name: 'Gnosis', + symbol: 'gno', + validator: ETHValidator, + }, + { + name: 'Golem', + symbol: 'gnt', + validator: ETHValidator, + }, + { + name: 'Matchpool', + symbol: 'gup', + validator: ETHValidator, + }, + { + name: 'Melon', + symbol: 'mln', + validator: ETHValidator, + }, + { + name: 'Numeraire', + symbol: 'nmr', + validator: ETHValidator, + }, + { + name: 'OmiseGO', + symbol: 'omg', + validator: ETHValidator, + }, + { + name: 'TenX', + symbol: 'pay', + validator: ETHValidator, + }, + { + name: 'Ripio Credit Network', + symbol: 'rcn', + validator: ETHValidator, + }, + { + name: 'Augur', + symbol: 'rep', + validator: ETHValidator, + }, + { + name: 'iExec RLC', + symbol: 'rlc', + validator: ETHValidator, + }, + { + name: 'Salt', + symbol: 'salt', + validator: ETHValidator, + }, + { + name: 'Status', + symbol: 'snt', + validator: ETHValidator, + }, + { + name: 'Storj', + symbol: 'storj', + validator: ETHValidator, + }, + { + name: 'STEEM', + symbol: 'steem', + validator: STEEMValidator, + }, + { + name: 'Stratis', + symbol: 'strat', + validator: BTCValidator, + addressTypes: { prod: ['3f'] }, + }, + { + name: 'Syscoin', + symbol: 'sys', + addressTypes: { prod: ['3f'] }, + validator: SYSValidator, + }, + { + name: 'Swarm City', + symbol: 'swt', + validator: ETHValidator, + }, + { + name: 'TrueUSD', + symbol: 'tusd', + validator: ETHValidator, + }, + { + name: 'Wings', + symbol: 'wings', + validator: ETHValidator, + }, + { + name: '0x', + symbol: 'zrx', + validator: ETHValidator, + }, + { + name: 'Expanse', + symbol: 'exp', + validator: ETHValidator, + }, + { + name: 'Viberate', + symbol: 'vib', + validator: ETHValidator, + }, + { + name: 'Odyssey', + symbol: 'ocn', + validator: ETHValidator, + }, + { + name: 'Polymath', + symbol: 'poly', + validator: ETHValidator, + }, + { + name: 'Storm', + symbol: 'storm', + validator: ETHValidator, + }, + { + name: 'FirstBlood', + symbol: '1st', + validator: ETHValidator, + }, + { + name: 'Arcblock', + symbol: 'abt', + validator: ETHValidator, + }, + { + name: 'Abyss Token', + symbol: 'abyss', + validator: ETHValidator, + }, + { + name: 'adToken', + symbol: 'adt', + validator: ETHValidator, + }, + { + name: 'AdEx', + symbol: 'adx', + validator: ETHValidator, + }, + { + name: 'SingularityNET', + symbol: 'agi', + validator: ETHValidator, + }, + { + name: 'Ambrosus', + symbol: 'amb', + validator: ETHValidator, + }, + { + name: 'Ankr', + symbol: 'ankr', + validator: ETHValidator, + }, + { + name: 'AppCoins', + symbol: 'appc', + validator: ETHValidator, + }, + { + name: 'Cosmos', + symbol: 'atom', + validator: ATOMValidator, + }, + { + name: 'Aeron', + symbol: 'arn', + validator: ETHValidator, + }, + { + name: 'Aeternity', + symbol: 'ae', + validator: AEValidator, + }, + { + name: 'ATLANT', + symbol: 'atl', + validator: ETHValidator, + }, + { + name: 'aXpire', + symbol: 'axpr', + validator: ETHValidator, + }, + { + name: 'Band Protocol', + symbol: 'band', + validator: ETHValidator, + }, + { + name: 'Blockmason Credit Protocol', + symbol: 'bcpt', + validator: ETHValidator, + }, + { + name: 'BitDegree', + symbol: 'bdg', + validator: ETHValidator, + }, + { + name: 'BetterBetting', + symbol: 'betr', + validator: ETHValidator, + }, + { + name: 'Bluzelle', + symbol: 'blz', + validator: ETHValidator, + }, + { + name: 'Bread', + symbol: 'brd', + validator: ETHValidator, + }, + { + name: 'Blocktrade Token', + symbol: 'btt', + validator: ETHValidator, + }, + { + name: 'Binance USD', + symbol: 'busd', + validator: ETHValidator, + }, + { + name: 'CryptoBossCoin', + symbol: 'cbc', + validator: ETHValidator, + }, + { + name: 'Blox', + symbol: 'cdt', + validator: ETHValidator, + }, + { + name: 'Celer Network', + symbol: 'celr', + validator: ETHValidator, + }, + { + name: 'Chiliz', + symbol: 'chz', + validator: ETHValidator, + }, + { + name: 'Coinlancer', + symbol: 'cl', + validator: ETHValidator, + }, + { + name: 'Cindicator', + symbol: 'cnd', + validator: ETHValidator, + }, + { + name: 'Cocos-BCX', + symbol: 'cocos', + validator: ETHValidator, + }, + { + name: 'COS', + symbol: 'cos', + validator: ETHValidator, + }, + { + name: 'Cosmo Coin', + symbol: 'cosm', + validator: ETHValidator, + }, + { + name: 'Covesting', + symbol: 'cov', + validator: ETHValidator, + }, + { + name: 'Crypterium', + symbol: 'crpt', + validator: ETHValidator, + }, + { + name: 'Daneel', + symbol: 'dan', + validator: ETHValidator, + }, + { + name: 'Streamr DATAcoin', + symbol: 'data', + validator: ETHValidator, + }, + { + name: 'Dentacoin', + symbol: 'dcn', + validator: ETHValidator, + }, + { + name: 'Dent', + symbol: 'dent', + validator: ETHValidator, + }, + { + name: 'DigixDAO', + symbol: 'dgd', + validator: ETHValidator, + }, + { + name: 'Digitex Futures', + symbol: 'dgtx', + validator: ETHValidator, + }, + { + name: 'Agrello', + symbol: 'dlt', + validator: ETHValidator, + }, + { + name: 'Dock', + symbol: 'dock', + validator: ETHValidator, + }, + { + name: 'DomRaider', + symbol: 'drt', + validator: ETHValidator, + }, + { + name: 'Dusk Network', + symbol: 'dusk', + validator: ETHValidator, + }, + { + name: 'Edgeless', + symbol: 'edg', + validator: ETHValidator, + }, + { + name: 'Eidoo', + symbol: 'edo', + validator: ETHValidator, + }, + { + name: 'Electrify.Asia', + symbol: 'elec', + validator: ETHValidator, + }, + { + name: 'aelf', + symbol: 'elf', + validator: ETHValidator, + }, + { + name: 'Enigma', + symbol: 'eng', + validator: ETHValidator, + }, + { + name: 'STASIS EURO', + symbol: 'eurs', + validator: ETHValidator, + }, + { + name: 'Everex', + symbol: 'evx', + validator: ETHValidator, + }, + { + name: 'FirmaChain', + symbol: 'fct', + validator: ETHValidator, + }, + { + name: 'Fetch.ai', + symbol: 'fet', + validator: ETHValidator, + }, + { + name: 'Fortuna', + symbol: 'fota', + validator: ETHValidator, + }, + { + name: 'Fantom', + symbol: 'ftm', + validator: ETHValidator, + }, + { + name: 'Etherparty', + symbol: 'fuel', + validator: ETHValidator, + }, + { + name: 'Gifto', + symbol: 'gto', + validator: ETHValidator, + }, + { + name: 'Gemini Dollar', + symbol: 'gusd', + validator: ETHValidator, + }, + { + name: 'Genesis Vision', + symbol: 'gvt', + validator: ETHValidator, + }, + { + name: 'Humaniq', + symbol: 'hmq', + validator: ETHValidator, + }, + { + name: 'Holo', + symbol: 'hot', + validator: ETHValidator, + }, + { + name: 'HOQU', + symbol: 'hqx', + validator: ETHValidator, + }, + { + name: 'Huobi Token', + symbol: 'ht', + validator: ETHValidator, + }, + { + name: 'ICON', + symbol: 'icx', + validator: ICXValidator, + }, + { + name: 'Internet of Services', + symbol: 'IOST', + validator: IOSTValidator, + // disable iota validation for now + // }, { + // name: 'Iota', + // symbol: 'iota', + // validator: IOTAValidator, + }, + { + name: 'IHT Real Estate Protocol', + symbol: 'iht', + validator: ETHValidator, + }, + { + name: 'Insolar', + symbol: 'ins', + validator: ETHValidator, + }, + { + name: 'IoTeX', + symbol: 'iotx', + validator: ETHValidator, + }, + { + name: 'BitKan', + symbol: 'kan', + validator: ETHValidator, + }, + { + name: 'Kcash', + symbol: 'kcash', + validator: ETHValidator, + }, + { + name: 'KEY', + symbol: 'key', + validator: ETHValidator, + }, + { + name: 'KickToken', + symbol: 'kick', + validator: ETHValidator, + }, + { + name: 'Kyber Network', + symbol: 'knc', + validator: ETHValidator, + }, + { + name: 'Lambda', + symbol: 'lamb', + validator: ETHValidator, + }, + { + name: 'Aave', + symbol: 'lend', + validator: ETHValidator, + }, + { + name: 'LinkEye', + symbol: 'let', + validator: ETHValidator, + }, + { + name: 'LIFE', + symbol: 'life', + validator: ETHValidator, + }, + { + name: 'LockTrip', + symbol: 'loc', + validator: ETHValidator, + }, + { + name: 'Loopring', + symbol: 'lrc', + validator: ETHValidator, + }, + { + name: 'Lunyr', + symbol: 'lun', + validator: ETHValidator, + }, + { + name: 'Decentraland', + symbol: 'mana', + validator: ETHValidator, + }, + { + name: 'Matic Network', + symbol: 'matic', + validator: ETHValidator, + }, + { + name: 'MCO', + symbol: 'mco', + validator: ETHValidator, + }, + { + name: 'Moeda Loyalty Points', + symbol: 'mda', + validator: ETHValidator, + }, + { + name: 'Measurable Data Token', + symbol: 'mdt', + validator: ETHValidator, + }, + { + name: 'Mainframe', + symbol: 'mft', + validator: ETHValidator, + }, + { + name: 'Mithril', + symbol: 'mith', + validator: ETHValidator, + }, + { + name: 'Molecular Future', + symbol: 'mof', + validator: ETHValidator, + }, + { + name: 'Monetha', + symbol: 'mth', + validator: ETHValidator, + }, + { + name: 'Mysterium', + symbol: 'myst', + validator: ETHValidator, + }, + { + name: 'Nucleus Vision', + symbol: 'ncash', + validator: ETHValidator, + }, + { + name: 'Nexo', + symbol: 'nexo', + validator: ETHValidator, + }, + { + name: 'NAGA', + symbol: 'ngc', + validator: ETHValidator, + }, + { + name: 'Noah Coin', + symbol: 'noah', + validator: ETHValidator, + }, + { + name: 'Pundi X', + symbol: 'npxs', + validator: ETHValidator, + }, + { + name: 'NetKoin', + symbol: 'ntk', + validator: ETHValidator, + }, + { + name: 'OAX', + symbol: 'oax', + validator: ETHValidator, + }, + { + name: 'Menlo One', + symbol: 'one', + validator: ETHValidator, + }, + { + name: 'SoMee.Social', + symbol: 'ong', + validator: ETHValidator, + }, + { + name: 'ORS Group', + symbol: 'ors', + validator: ETHValidator, + }, + { + name: 'OST', + symbol: 'ost', + validator: ETHValidator, + }, + { + name: 'Patron', + symbol: 'pat', + validator: ETHValidator, + }, + { + name: 'Paxos Standard', + symbol: 'pax', + validator: ETHValidator, + }, + { + name: 'Peculium', + symbol: 'pcl', + validator: ETHValidator, + }, + { + name: 'Perlin', + symbol: 'perl', + validator: ETHValidator, + }, + { + name: 'Pillar', + symbol: 'plr', + validator: ETHValidator, + }, + { + name: 'PumaPay', + symbol: 'pma', + validator: ETHValidator, + }, + { + name: 'Po.et', + symbol: 'poe', + validator: ETHValidator, + }, + { + name: 'Power Ledger', + symbol: 'powr', + validator: ETHValidator, + }, + { + name: 'Populous', + symbol: 'ppt', + validator: ETHValidator, + }, + { + name: 'Presearch', + symbol: 'pre', + validator: ETHValidator, + }, + { + name: 'Patientory', + symbol: 'ptoy', + validator: ETHValidator, + }, + { + name: 'QuarkChain', + symbol: 'qkc', + validator: ETHValidator, + }, + { + name: 'Quantstamp', + symbol: 'qsp', + validator: ETHValidator, + }, + { + name: 'Revain', + symbol: 'r', + validator: ETHValidator, + }, + { + name: 'Raiden Network Token', + symbol: 'rdn', + validator: ETHValidator, + }, + { + name: 'Ren', + symbol: 'ren', + validator: ETHValidator, + }, + { + name: 'Request', + symbol: 'req', + validator: ETHValidator, + }, + { + name: 'Refereum', + symbol: 'rfr', + validator: ETHValidator, + }, + { + name: 'SiaCashCoin', + symbol: 'scc', + validator: ETHValidator, + }, + { + name: 'Sentinel', + symbol: 'sent', + validator: ETHValidator, + }, + { + name: 'SkinCoin', + symbol: 'skin', + validator: ETHValidator, + }, + { + name: 'SunContract', + symbol: 'snc', + validator: ETHValidator, + }, + { + name: 'SingularDTV', + symbol: 'sngls', + validator: ETHValidator, + }, + { + name: 'SONM', + symbol: 'snm', + validator: ETHValidator, + }, + { + name: 'All Sports', + symbol: 'soc', + validator: ETHValidator, + }, + { + name: 'SIRIN LABS Token', + symbol: 'srn', + validator: ETHValidator, + }, + { + name: 'Stox', + symbol: 'stx', + validator: ETHValidator, + }, + { + name: 'Substratum', + symbol: 'sub', + validator: ETHValidator, + }, + { + name: 'SwftCoin', + symbol: 'swftc', + validator: ETHValidator, + }, + { + name: 'Lamden', + symbol: 'tau', + validator: ETHValidator, + }, + { + name: 'Telcoin', + symbol: 'tel', + validator: ETHValidator, + }, + { + name: 'Chronobank', + symbol: 'time', + validator: ETHValidator, + }, + { + name: 'Monolith', + symbol: 'tkn', + validator: ETHValidator, + }, + { + name: 'Time New Bank', + symbol: 'tnb', + validator: ETHValidator, + }, + { + name: 'Tierion', + symbol: 'tnt', + validator: ETHValidator, + }, + { + name: 'Tripio', + symbol: 'trio', + validator: ETHValidator, + }, + { + name: 'WeTrust', + symbol: 'trst', + validator: ETHValidator, + }, + { + name: 'USD Coin', + symbol: 'usdc', + validator: ETHValidator, + }, + { + name: 'USDT ERC-20', + symbol: 'usdt20', + validator: ETHValidator, + }, + { + name: 'Utrust', + symbol: 'utk', + validator: ETHValidator, + }, + { + name: 'BLOCKv', + symbol: 'vee', + validator: ETHValidator, + }, + { + name: 'VIBE', + symbol: 'vibe', + validator: ETHValidator, + }, + { + name: 'Tael', + symbol: 'wabi', + validator: ETHValidator, + }, + { + name: 'WePower', + symbol: 'wpr', + validator: ETHValidator, + }, + { + name: 'Waltonchain', + symbol: 'wtc', + validator: ETHValidator, + }, + { + name: 'BlitzPredict', + symbol: 'xbp', + validator: ETHValidator, + }, + { + name: 'CryptoFranc', + symbol: 'xchf', + validator: ETHValidator, + }, + { + name: 'Exchange Union', + symbol: 'xuc', + validator: ETHValidator, + }, + { + name: 'YOU COIN', + symbol: 'you', + validator: ETHValidator, + }, + { + name: 'Zap', + symbol: 'zap', + validator: ETHValidator, + }, + { + name: 'Nano', + symbol: 'nano', + validator: NANOValidator, + }, + { + name: 'RaiBlocks', + symbol: 'xrb', + validator: NANOValidator, + }, + { + name: 'Siacoin', + symbol: 'sc', + validator: SCValidator, + }, + { + name: 'HyperSpace', + symbol: 'xsc', + validator: SCValidator, + }, + { + name: 'Loki', + symbol: 'loki', + addressTypes: { prod: ['114', '116'], testnet: ['156'] }, + subAddressTypes: { prod: ['114', '116'], testnet: ['158'] }, + iAddressTypes: { prod: ['115'], testnet: ['157'] }, + validator: LokiValidator, + }, + { + name: 'LBRY Credits', + symbol: 'lbc', + addressTypes: { prod: ['55'], testnet: [] }, + validator: BTCValidator, + }, + { + name: 'Tron', + symbol: 'trx', + addressTypes: { prod: [0x41], testnet: [0xa0] }, + validator: TRXValidator, + }, + { + name: 'Nem', + symbol: 'xem', + validator: NEMValidator, + }, + { + name: 'Lisk', + symbol: 'lsk', + validator: LSKValidator, + }, + { + name: 'Stellar', + symbol: 'xlm', + validator: XLMValidator, + }, + { + name: 'Scopuly', + symbol: 'sky', + validator: XLMValidator, + }, + { + name: 'BTU Protocol', + symbol: 'btu', + validator: ETHValidator, + }, + { + name: 'Crypto.com Coin', + symbol: 'cro', + validator: ETHValidator, + }, + { + name: 'Multi-collateral DAI', + symbol: 'dai', + validator: ETHValidator, + }, + { + name: 'Enjin Coin', + symbol: 'enj', + validator: ETHValidator, + }, + { + name: 'HedgeTrade', + symbol: 'hedg', + validator: ETHValidator, + }, + { + name: 'Cred', + symbol: 'lba', + validator: ETHValidator, + }, + { + name: 'Chainlink', + symbol: 'link', + validator: ETHValidator, + }, + { + name: 'Loom Network', + symbol: 'loom', + validator: ETHValidator, + }, + { + name: 'Maker', + symbol: 'mkr', + validator: ETHValidator, + }, + { + name: 'Metal', + symbol: 'mtl', + validator: ETHValidator, + }, + { + name: 'Ocean Protocol', + symbol: 'ocean', + validator: ETHValidator, + //}, { + // name: 'PitisCoin', + // symbol: 'pts', # FIXME: symbol collides with ProtoShares + // validator: BTCValidator, + }, + { + name: 'Quant', + symbol: 'qnt', + validator: ETHValidator, + }, + { + name: 'Synthetix Network', + symbol: 'snx', + validator: ETHValidator, + }, + { + name: 'SOLVE', + symbol: 'solve', + validator: ETHValidator, + }, + { + name: 'Spendcoin', + symbol: 'spnd', + validator: ETHValidator, + }, + { + name: 'TEMCO', + symbol: 'temco', + validator: ETHValidator, + }, + { + name: 'Luniverse', + symbol: 'luniverse', + validator: ETHValidator, + }, + { + name: 'Binance Smart Chain', + symbol: 'bsc', + validator: ETHValidator, + }, + { + name: 'Binance', + symbol: 'bnb', + validator: BinanceValidator, + }, + { + name: 'EOS', + symbol: 'eos', + validator: EOSValidator, + }, + { + name: 'Tezos', + symbol: 'xtz', + validator: XTZValidator, + }, + { + name: 'Hedera Hashgraph', + symbol: 'hbar', + validator: HBARValidator, + }, + { + name: 'Verge', + symbol: 'xvg', + addressTypes: { prod: ['1e'], testnet: ['6F'] }, + validator: BTCValidator, + }, + { + name: 'Zilliqa', + symbol: 'zil', + validator: ZILValidator, + }, +]; + +module.exports = { + getByNameOrSymbol: function (currencyNameOrSymbol) { + var nameOrSymbol = currencyNameOrSymbol.toLowerCase(); + return CURRENCIES.find(function (currency) { + return ( + currency.name.toLowerCase() === nameOrSymbol || + currency.symbol.toLowerCase() === nameOrSymbol + ); + }); + }, + getAll: function () { + return CURRENCIES; + }, +}; + +// spit out details for readme.md +// CURRENCIES +// .sort((a, b) => a.name.toUpperCase() > b.name.toUpperCase() ? 1 : -1) +// .forEach(c => console.log(`* ${c.name}/${c.symbol} \`'${c.name}'\` or \`'${c.symbol}'\` `)); + +//spit out keywords for package.json +// CURRENCIES +// .sort((a, b) => a.name.toUpperCase() > b.name.toUpperCase() ? 1 : -1) +// .forEach(c => console.log(`"${c.name}","${c.symbol}",`)); diff --git a/packages/address-validator/src/eos_validator.js b/packages/address-validator/src/eos_validator.js new file mode 100644 index 000000000000..5819e64eb039 --- /dev/null +++ b/packages/address-validator/src/eos_validator.js @@ -0,0 +1,22 @@ +const { addressType } = require('./crypto/utils'); +function isValidEOSAddress(address, currency, networkType) { + var regex = /^[a-z0-9]+$/g; // Must be numbers and lowercase letters only + if (address.search(regex) !== -1 && address.length === 12) { + return true; + } else { + return false; + } +} + +module.exports = { + isValidAddress: function (address, currency, networkType) { + return isValidEOSAddress(address, currency, networkType); + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/ethereum_validator.js b/packages/address-validator/src/ethereum_validator.js new file mode 100644 index 000000000000..e94176079042 --- /dev/null +++ b/packages/address-validator/src/ethereum_validator.js @@ -0,0 +1,44 @@ +const { addressType } = require('./crypto/utils'); +var cryptoUtils = require('./crypto/utils'); + +module.exports = { + isValidAddress: function (address) { + if (!/^0x[0-9a-fA-F]{40}$/.test(address)) { + // Check if it has the basic requirements of an address + return false; + } + + if (/^0x[0-9a-f]{40}$/.test(address) || /^0x?[0-9A-F]{40}$/.test(address)) { + // If it's all small caps or all all caps, return true + return true; + } + + // Otherwise check each case + return this.verifyChecksum(address); + }, + verifyChecksum: function (address) { + // Check each case + address = address.replace('0x', ''); + + var addressHash = cryptoUtils.keccak256(address.toLowerCase()); + + for (var i = 0; i < 40; i++) { + // The nth letter should be uppercase if the nth digit of casemap is 1 + if ( + (parseInt(addressHash[i], 16) > 7 && address[i].toUpperCase() !== address[i]) || + (parseInt(addressHash[i], 16) <= 7 && address[i].toLowerCase() !== address[i]) + ) { + return false; + } + } + + return true; + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/hbar_validator.js b/packages/address-validator/src/hbar_validator.js new file mode 100644 index 000000000000..e889095f8f01 --- /dev/null +++ b/packages/address-validator/src/hbar_validator.js @@ -0,0 +1,23 @@ +const { addressType } = require('./crypto/utils'); +function isValidHBarAddress(address) { + const split = address.split('.'); + if (split[0] !== '0' || split[1] !== '0') { + return false; + } + if (split[2].length <= 6 && /^\d+$/g.test(split[2])) { + return true; + } +} + +module.exports = { + isValidAddress: function (address, currency, networkType) { + return isValidHBarAddress(address); + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/icx_validator.js b/packages/address-validator/src/icx_validator.js new file mode 100644 index 000000000000..fa76c6f85015 --- /dev/null +++ b/packages/address-validator/src/icx_validator.js @@ -0,0 +1,22 @@ +const { addressType } = require('./crypto/utils'); +function isValidICXAddress(address, currency, networkType) { + var regex = /^hx[0-9a-f]{40}$/g; // Begins with hx followed by 40 hex chars + if (address.search(regex) !== -1) { + return true; + } else { + return false; + } +} + +module.exports = { + isValidAddress: function (address, currency, networkType) { + return isValidICXAddress(address, currency, networkType); + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/index.d.ts b/packages/address-validator/src/index.d.ts new file mode 100644 index 000000000000..8658315aeaed --- /dev/null +++ b/packages/address-validator/src/index.d.ts @@ -0,0 +1,26 @@ +declare module '@trezor/address-validator' { + export interface Currency { + name: string; + symbol: string; + } + export type AddressType = + | 'address' + | 'p2pkh' + | 'p2wpkh' + | 'p2wsh' + | 'p2sh' + | 'p2tr' + | 'pw-unknown'; + export function validate( + address: string, + currencyNameOrSymbol?: string, + networkType?: string, + ): boolean; + export function getAddressType( + address: string, + currencyNameOrSymbol?: string, + networkType?: string, + ): AddressType | undefined; + export function getCurrencies(): Currency[]; + export function findCurrency(symbol: string): Currency; +} diff --git a/packages/address-validator/src/index.js b/packages/address-validator/src/index.js new file mode 100644 index 000000000000..c275b6e2085d --- /dev/null +++ b/packages/address-validator/src/index.js @@ -0,0 +1,33 @@ +var currencies = require('./currencies'); +const { addressType } = require('./crypto/utils'); + +var DEFAULT_CURRENCY_NAME = 'bitcoin'; + +module.exports = { + validate: function (address, currencyNameOrSymbol, networkType) { + var currency = currencies.getByNameOrSymbol(currencyNameOrSymbol || DEFAULT_CURRENCY_NAME); + + if (currency && currency.validator) { + return currency.validator.isValidAddress(address, currency, networkType); + } + + throw new Error('Missing validator for currency: ' + currencyNameOrSymbol); + }, + getAddressType: function (address, currencyNameOrSymbol, networkType) { + var currency = currencies.getByNameOrSymbol(currencyNameOrSymbol || DEFAULT_CURRENCY_NAME); + if (!currency || !currency.validator) { + throw new Error('getAddressType: No validator for currency' + currencyNameOrSymbol); + } + if (currency && currency.validator && currency.validator.getAddressType) { + return currency.validator.getAddressType(address, currency, networkType); + } + throw new Error('getAddressType not defined for currency: ' + currencyNameOrSymbol); + }, + getCurrencies: function () { + return currencies.getAll(); + }, + findCurrency: function (symbol) { + return currencies.getByNameOrSymbol(symbol) || null; + }, + addressType, +}; diff --git a/packages/address-validator/src/iost_validator.js b/packages/address-validator/src/iost_validator.js new file mode 100644 index 000000000000..94e5266094eb --- /dev/null +++ b/packages/address-validator/src/iost_validator.js @@ -0,0 +1,15 @@ +const { addressType } = require('./crypto/utils'); +const iostRegex = new RegExp('^[a-z0-9_]{5,11}$'); + +module.exports = { + isValidAddress: function (address, currency, networkType) { + return iostRegex.test(address); + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/iota_validator.js b/packages/address-validator/src/iota_validator.js new file mode 100644 index 000000000000..d922cdbc17f2 --- /dev/null +++ b/packages/address-validator/src/iota_validator.js @@ -0,0 +1,14 @@ +// iota validation is disabled + +// var IOTA = require('@iota/validators') + +// function isValidIotaAddress (address, currency, networkType) { +// var isValid = IOTA.isAddress(address) +// return isValid +// } + +// module.exports = { +// isValidAddress: function (address, currency, networkType) { +// return isValidIotaAddress(address, currency, networkType) +// } +// } diff --git a/packages/address-validator/src/lisk_validator.js b/packages/address-validator/src/lisk_validator.js new file mode 100644 index 000000000000..a2a2cdb3ae13 --- /dev/null +++ b/packages/address-validator/src/lisk_validator.js @@ -0,0 +1,26 @@ +const { addressType } = require('./crypto/utils'); +var cryptoUtils = require('./crypto/utils'); + +var regexp = new RegExp('^[0-9]{1,20}L$'); + +module.exports = { + isValidAddress: function (address) { + return this.getAddressType(address) === addressType.ADDRESS; + }, + + getAddressType: function (address) { + if (!regexp.test(address)) { + return undefined; + } + if (this.verifyAddress(address)) { + return addressType.ADDRESS; + } + }, + + verifyAddress: function (address) { + var BUFFER_SIZE = 8; + var bigNumber = address.substring(0, address.length - 1); + var addressBuffer = cryptoUtils.bigNumberToBuffer(bigNumber); + return Buffer.from(addressBuffer).slice(0, BUFFER_SIZE).equals(addressBuffer); + }, +}; diff --git a/packages/address-validator/src/loki_validator.js b/packages/address-validator/src/loki_validator.js new file mode 100644 index 000000000000..8c052e8e9d35 --- /dev/null +++ b/packages/address-validator/src/loki_validator.js @@ -0,0 +1,74 @@ +const { addressType } = require('./crypto/utils'); +var cryptoUtils = require('./crypto/utils'); +var cnBase58 = require('./crypto/cnBase58'); + +var DEFAULT_NETWORK_TYPE = 'prod'; + +var addressRegTest = new RegExp( + '^L[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{94}$', +); +var integratedAddressRegTest = new RegExp( + '^L[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{105}$', +); + +function validateNetwork(decoded, currency, networkType, addressType) { + var network = currency.addressTypes; + if (addressType == 'integrated') { + network = currency.iAddressTypes; + } else if (addressType == 'subaddress') { + network = currency.subAddressTypes; + } + var at = parseInt(decoded.substr(0, 2), 16).toString(); + + switch (networkType) { + case 'prod': + return network.prod.indexOf(at) >= 0; + case 'testnet': + return network.testnet.indexOf(at) >= 0; + case 'both': + return network.prod.indexOf(at) >= 0 || network.testnet.indexOf(at) >= 0; + default: + return false; + } +} + +function hextobin(hex) { + if (hex.length % 2 !== 0) return null; + var res = new Uint8Array(hex.length / 2); + for (var i = 0; i < hex.length / 2; ++i) { + res[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16); + } + return res; +} + +module.exports = { + isValidAddress: function (address, currency, networkType) { + networkType = networkType || DEFAULT_NETWORK_TYPE; + var addressType = 'standard'; + if (!addressRegTest.test(address)) { + // same regex for mainnet and testnet + if (integratedAddressRegTest.test(address)) { + addressType = 'integrated'; + } else { + return false; + } + } + + var decodedAddrStr = cnBase58.decode(address); + if (!decodedAddrStr) return false; + + if (!validateNetwork(decodedAddrStr, currency, networkType, addressType)) return false; + + var addrChecksum = decodedAddrStr.slice(-8); + var hashChecksum = cryptoUtils.keccak256Checksum(hextobin(decodedAddrStr.slice(0, -8))); + + return addrChecksum === hashChecksum; + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/monero_validator.js b/packages/address-validator/src/monero_validator.js new file mode 100644 index 000000000000..a6a07a073b5f --- /dev/null +++ b/packages/address-validator/src/monero_validator.js @@ -0,0 +1,84 @@ +const { addressType } = require('./crypto/utils'); +var cryptoUtils = require('./crypto/utils'); +var cnBase58 = require('./crypto/cnBase58'); + +var DEFAULT_NETWORK_TYPE = 'prod'; +var testnetRegTest = new RegExp( + `^[A9][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{94}$`, +); +var addressRegTest = new RegExp( + '^4[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{94}$', +); +var subAddressRegTest = new RegExp( + '^8[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{94}$', +); +var integratedAddressRegTest = new RegExp( + '^4[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{105}$', +); + +function validateNetwork(decoded, currency, networkType, addressType) { + var network = currency.addressTypes; + if (addressType == 'integrated') { + network = currency.iAddressTypes; + } else if (addressType == 'subaddress') { + network = currency.subAddressTypes; + } + var at = parseInt(decoded.substr(0, 2), 16).toString(); + + switch (networkType) { + case 'prod': + return network.prod.indexOf(at) >= 0; + case 'testnet': + return network.testnet.indexOf(at) >= 0; + case 'both': + return network.prod.indexOf(at) >= 0 || network.testnet.indexOf(at) >= 0; + default: + return false; + } +} + +function hextobin(hex) { + if (hex.length % 2 !== 0) return null; + var res = new Uint8Array(hex.length / 2); + for (var i = 0; i < hex.length / 2; ++i) { + res[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16); + } + return res; +} + +module.exports = { + isValidAddress: function (address, currency, networkType) { + networkType = networkType || DEFAULT_NETWORK_TYPE; + var addressType = 'standard'; + if (networkType === 'testnet') { + if (!testnetRegTest.test(address)) { + return false; + } + } else if (!addressRegTest.test(address)) { + if (subAddressRegTest.test(address)) { + addressType = 'subaddress'; + } else if (integratedAddressRegTest.test(address)) { + addressType = 'integrated'; + } else { + return false; + } + } + + var decodedAddrStr = cnBase58.decode(address); + if (!decodedAddrStr) return false; + + if (!validateNetwork(decodedAddrStr, currency, networkType, addressType)) return false; + + var addrChecksum = decodedAddrStr.slice(-8); + var hashChecksum = cryptoUtils.keccak256Checksum(hextobin(decodedAddrStr.slice(0, -8))); + + return addrChecksum === hashChecksum; + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/nano_validator.js b/packages/address-validator/src/nano_validator.js new file mode 100644 index 000000000000..f57f4e8e89de --- /dev/null +++ b/packages/address-validator/src/nano_validator.js @@ -0,0 +1,35 @@ +const { addressType } = require('./crypto/utils'); +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; + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/nem_validator.js b/packages/address-validator/src/nem_validator.js new file mode 100644 index 000000000000..1b7c56395bdb --- /dev/null +++ b/packages/address-validator/src/nem_validator.js @@ -0,0 +1,31 @@ +const { addressType } = require('./crypto/utils'); +var cryptoUtils = require('./crypto/utils'); + +/** + * Check if an address is valid + * + * @param {string} _address - An address + * + * @return {boolean} - True if address is valid, false otherwise + */ +var isValidAddress = function (_address) { + var address = _address.toString().toUpperCase().replace(/-/g, ''); + if (!address || address.length !== 40) { + return false; + } + var decoded = cryptoUtils.toHex(cryptoUtils.base32.b32decode(address)); + var stepThreeChecksum = cryptoUtils.keccak256Checksum(Buffer.from(decoded.slice(0, 42), 'hex')); + + return stepThreeChecksum === decoded.slice(42); +}; + +module.exports = { + isValidAddress: isValidAddress, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/nxt_validator.js b/packages/address-validator/src/nxt_validator.js new file mode 100644 index 000000000000..72975ebed154 --- /dev/null +++ b/packages/address-validator/src/nxt_validator.js @@ -0,0 +1,18 @@ +const { addressType } = require('./crypto/utils'); +const nxtRegex = new RegExp('^NXT(-[A-Z0-9]{4}){3}-[A-Z0-9]{5}$'); + +module.exports = { + isValidAddress: function (address, currency, networkType) { + if (!nxtRegex.test(address)) { + return false; + } + return true; + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/ripple_validator.js b/packages/address-validator/src/ripple_validator.js new file mode 100644 index 000000000000..33dd3f36c9e3 --- /dev/null +++ b/packages/address-validator/src/ripple_validator.js @@ -0,0 +1,36 @@ +const { addressType } = require('./crypto/utils'); +var cryptoUtils = require('./crypto/utils'); +var baseX = require('base-x'); + +var ALLOWED_CHARS = 'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz'; + +var codec = baseX(ALLOWED_CHARS); +var regexp = new RegExp('^r[' + ALLOWED_CHARS + ']{27,35}$'); + +module.exports = { + /** + * ripple address validation + */ + isValidAddress: function (address) { + if (regexp.test(address)) { + return this.verifyChecksum(address); + } + + return false; + }, + + verifyChecksum: function (address) { + var bytes = codec.decode(address); + var computedChecksum = cryptoUtils.sha256Checksum(cryptoUtils.toHex(bytes.slice(0, -4))); + var checksum = cryptoUtils.toHex(bytes.slice(-4)); + + return computedChecksum === checksum; + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/siacoin_validator.js b/packages/address-validator/src/siacoin_validator.js new file mode 100644 index 000000000000..a6ab564194db --- /dev/null +++ b/packages/address-validator/src/siacoin_validator.js @@ -0,0 +1,28 @@ +const { addressType } = require('./crypto/utils'); +var cryptoUtils = require('./crypto/utils'); +var isEqual = require('lodash/isEqual'); + +module.exports = { + isValidAddress: function (address) { + if (address.length !== 76) { + // Check if it has the basic requirements of an address + return false; + } + + // Otherwise check each case + return this.verifyChecksum(address); + }, + verifyChecksum: function (address) { + var checksumBytes = address.slice(0, 32 * 2); + var check = address.slice(32 * 2, 38 * 2); + var blakeHash = cryptoUtils.blake2b(checksumBytes, 32).slice(0, 6 * 2); + return isEqual(blakeHash, check); + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/steem_validator.js b/packages/address-validator/src/steem_validator.js new file mode 100644 index 000000000000..cec556979ca8 --- /dev/null +++ b/packages/address-validator/src/steem_validator.js @@ -0,0 +1,33 @@ +const { addressType } = require('./crypto/utils'); +const accountRegex = new RegExp('^[a-z0-9-.]{3,}$'); +const segmentRegex = new RegExp('^[a-z][a-z0-9-]+[a-z0-9]$'); +const doubleDashRegex = new RegExp('--'); + +module.exports = { + isValidAddress: function (address, currency, networkType) { + if (!accountRegex.test(address)) { + return false; + } + let segments = address.split('.'); + for (let i = 0; i < segments.length; i++) { + let segment = segments[i]; + if (segment.length < 3) { + return false; + } + if (!segmentRegex.test(segment)) { + return false; + } + if (doubleDashRegex.test(segment)) { + return false; + } + } + return true; + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/stellar_validator.js b/packages/address-validator/src/stellar_validator.js new file mode 100644 index 000000000000..eed4bdc64793 --- /dev/null +++ b/packages/address-validator/src/stellar_validator.js @@ -0,0 +1,46 @@ +const { addressType } = require('./crypto/utils'); +const baseX = require('base-x'); +const crc = require('crc'); +const cryptoUtils = require('./crypto/utils'); + +const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; + +const base32 = baseX(ALPHABET); +const regexp = new RegExp('^[' + ALPHABET + ']{56}$'); +const ed25519PublicKeyVersionByte = 6 << 3; + +function swap16(number) { + const lower = number & 0xff; + const upper = (number >> 8) & 0xff; + return (lower << 8) | upper; +} + +module.exports = { + isValidAddress: function (address) { + if (regexp.test(address)) { + return this.verifyChecksum(address); + } + + return false; + }, + + verifyChecksum: function (address) { + // based on https://github.com/stellar/js-stellar-base/blob/master/src/strkey.js + const bytes = base32.decode(address); + if (bytes[0] !== ed25519PublicKeyVersionByte) { + return false; + } + + const payload = bytes.slice(0, -2); + const checksum = cryptoUtils.toHex(bytes.slice(-2)); + const computedChecksum = cryptoUtils.numberToHex(swap16(crc.crc16xmodem(payload)), 2); + return computedChecksum === checksum; + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/sys_validator.js b/packages/address-validator/src/sys_validator.js new file mode 100644 index 000000000000..1c284dd984f7 --- /dev/null +++ b/packages/address-validator/src/sys_validator.js @@ -0,0 +1,16 @@ +const { addressType } = require('./crypto/utils'); +const BTCValidator = require('./bitcoin_validator'); +var regexp = new RegExp('^sys1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{39}$'); + +module.exports = { + isValidAddress: function (address, currency, networkType) { + return regexp.test(address) || BTCValidator.isValidAddress(address, currency, networkType); + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/tezos_validator.js b/packages/address-validator/src/tezos_validator.js new file mode 100644 index 000000000000..597d70d0e607 --- /dev/null +++ b/packages/address-validator/src/tezos_validator.js @@ -0,0 +1,45 @@ +const { addressType } = require('./crypto/utils'); +const base58 = require('./crypto/base58'); +const cryptoUtils = require('./crypto/utils'); + +const prefix = new Uint8Array([6, 161, 159]); + +function decodeRaw(buffer) { + let payload = buffer.slice(0, -4); + let checksum = buffer.slice(-4); + let newChecksum = cryptoUtils.hexStr2byteArray( + cryptoUtils.sha256x2(cryptoUtils.byteArray2hexStr(payload)), + ); + + if ( + (checksum[0] ^ newChecksum[0]) | + (checksum[1] ^ newChecksum[1]) | + (checksum[2] ^ newChecksum[2]) | + (checksum[3] ^ newChecksum[3]) + ) + return; + return payload; +} + +const isValidAddress = function (address) { + try { + let buffer = base58.decode(address); + let payload = decodeRaw(buffer); + if (!payload) return false; + payload.slice(prefix.length); + return true; + } catch (e) { + return false; + } +}; + +module.exports = { + isValidAddress, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/tron_validator.js b/packages/address-validator/src/tron_validator.js new file mode 100644 index 000000000000..637a21b0f6d3 --- /dev/null +++ b/packages/address-validator/src/tron_validator.js @@ -0,0 +1,72 @@ +const { addressType } = require('./crypto/utils'); +var cryptoUtils = require('./crypto/utils'); + +function decodeBase58Address(base58Sting) { + if (typeof base58Sting !== 'string') { + return false; + } + if (base58Sting.length <= 4) { + return false; + } + + try { + var address = cryptoUtils.base58(base58Sting); + } catch (e) { + return false; + } + + /*if (base58Sting.length <= 4) { + return false; + }*/ + var len = address.length; + var offset = len - 4; + var checkSum = address.slice(offset); + address = address.slice(0, offset); + var hash0 = cryptoUtils.sha256(cryptoUtils.byteArray2hexStr(address)); + var hash1 = cryptoUtils.hexStr2byteArray(cryptoUtils.sha256(hash0)); + var checkSum1 = hash1.slice(0, 4); + if ( + checkSum[0] === checkSum1[0] && + checkSum[1] === checkSum1[1] && + checkSum[2] === checkSum1[2] && + checkSum[3] === checkSum1[3] + ) { + return address; + } + + return false; +} + +function getEnv(currency, networkType) { + var evn = networkType || 'prod'; + + if (evn !== 'prod' && evn !== 'testnet') evn = 'prod'; + + return currency.addressTypes[evn][0]; +} + +module.exports = { + /** + * tron address validation + */ + isValidAddress: function (mainAddress, currency, networkType) { + var address = decodeBase58Address(mainAddress); + + if (!address) { + return false; + } + + if (address.length !== 21) { + return false; + } + + return getEnv(currency, networkType) === address[0]; + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/src/zil_validator.js b/packages/address-validator/src/zil_validator.js new file mode 100644 index 000000000000..02a08b9a6ebd --- /dev/null +++ b/packages/address-validator/src/zil_validator.js @@ -0,0 +1,24 @@ +const { addressType } = require('./crypto/utils'); +const { bech32 } = require('bech32'); + +const ALLOWED_CHARS = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l'; + +var regexp = new RegExp('^(zil)1([' + ALLOWED_CHARS + ']+)$'); // zil + bech32 separated by '1' + +module.exports = { + isValidAddress: function (address, currency, networkType) { + let match = regexp.exec(address); + if (!match) { + return false; + } + const decoded = bech32.decode(address); + return decoded && decoded.words.length === 32; + }, + + getAddressType: function (address, currency, networkType) { + if (this.isValidAddress(address, currency, networkType)) { + return addressType.ADDRESS; + } + return undefined; + }, +}; diff --git a/packages/address-validator/tests/wallet_address_get_currencies.test.js b/packages/address-validator/tests/wallet_address_get_currencies.test.js new file mode 100644 index 000000000000..e4ab5c2698e2 --- /dev/null +++ b/packages/address-validator/tests/wallet_address_get_currencies.test.js @@ -0,0 +1,33 @@ +var isNode = typeof module !== 'undefined' && typeof module.exports !== 'undefined'; + +var chai = isNode ? require('chai') : window.chai, + expect = chai.expect; + +var WAValidator = isNode ? require('../src') : window.WAValidator; + +describe('WAValidator.getCurrencies()', function () { + it('Should get all currencies', function () { + var currencies = WAValidator.getCurrencies(); + expect(currencies).to.be.ok; + expect(currencies.length).to.be.greaterThan(0); + }); + + it('Should find a specific currency by symbol', function () { + var currency = WAValidator.findCurrency('xrp'); + expect(currency).to.be.ok; + expect(currency.name).to.equal('Ripple'); + expect(currency.symbol).to.equal('xrp'); + }); + + it('Should find a specific currency by name', function () { + var currency = WAValidator.findCurrency('Ripple'); + expect(currency).to.be.ok; + expect(currency.name).to.equal('Ripple'); + expect(currency.symbol).to.equal('xrp'); + }); + + it('Should return null if currency is not found', function () { + var currency = WAValidator.findCurrency('random'); + expect(currency).to.be.null; + }); +}); diff --git a/packages/address-validator/tests/wallet_address_validator.test.js b/packages/address-validator/tests/wallet_address_validator.test.js new file mode 100644 index 000000000000..4eaa69072323 --- /dev/null +++ b/packages/address-validator/tests/wallet_address_validator.test.js @@ -0,0 +1,1638 @@ +var WAValidator = require('../src'); + +const addressType = WAValidator.addressType; + +function isValidAddressType(address, currency, networkType, addressType) { + const type = WAValidator.getAddressType(address, currency, networkType); + expect({ address, addressType: type }).toEqual({ address, addressType }); +} + +function valid(address, currency, networkType) { + var valid = WAValidator.validate(address, currency, networkType); + expect({ address, currency, valid }).toEqual({ address, currency, valid: true }); +} + +function invalid(address, currency, networkType) { + var valid = WAValidator.validate(address, currency, networkType); + expect({ address, currency, valid }).toEqual({ address, currency, valid: false }); +} + +describe('WAValidator.validate()', function () { + describe('valid results', function () { + it('should return true for correct bitcoin addresses', function () { + valid('12KYrjTdVGjFMtaxERSk3gphreJ5US8aUP', 'bitcoin'); + valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'bitcoin'); + valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'BTC'); + valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'Bitcoin'); + valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'btc'); + valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'btc', 'prod'); + valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'btc', 'both'); + valid('15uwigGExiNQxTNr1QSZYPXJMp9Px2YnVU', 'btc', 'prod'); + valid('3FyVFsEyyBPzHjD3qUEgX7Jsn4tcHNZFkn', 'btc', 'prod'); + valid('38mKdURe1zcQyrFqRLzR8PRao3iLGEPVsU', 'btc', 'prod'); + valid('mptPo5AvLzJXi4T82vR6g82fT5uJ6HsQCu', 'btc', 'both'); + valid('1oNLrsHnBcR6dpaBpwz3LSwutbUNkNSjs', 'bitcoin'); + valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'bitcoin', 'testnet'); + valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'bitcoin', 'both'); + + valid('1SQHtwR5oJRKLfiWQ2APsAd9miUc4k2ez'); + valid('116CGDLddrZhMrTwhCVJXtXQpxygTT1kHd'); + + // p2sh addresses + valid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt'); + valid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'bitcoin'); + valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'bitcoin', 'testnet'); + + // regtest + valid('mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q', 'bitcoin', 'regtest'); + valid('ms1B699PA2tAfHTFTwN12Tzxa933WpmuHX', 'bitcoin', 'regtest'); + valid('2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp', 'bitcoin', 'regtest'); + valid('GSa5espVLNseXEfKt46zEdS6jrPkmFghBU', 'bitcoin', 'regtest'); + + valid('bcrt1q8zx9dlztqz9apm7y5gtx8a0tlz57fhncycvun5', 'bitcoin', 'regtest'); + valid( + 'bcrt1pzndg2aenknysnqs0d8gwhg54nqnc6yut2c6as76h4tyqhr8spr6slpjy3x', + 'bitcoin', + 'regtest', + ); + + // segwit addresses + valid('BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4', 'bitcoin'); + invalid( + 'bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx', + 'bitcoin', + ); // valid, but unspendable + invalid('BC1SW50QA3JX3S', 'bitcoin'); // valid, but unspendable + invalid('bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj', 'bitcoin'); // valid, but unspendable + invalid('bc1sw50qgdz25j', 'bitcoin', 'prod'); // valid, but unspendable + valid( + 'tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy', + 'bitcoin', + 'testnet', + ); + + valid( + 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7', + 'bitcoin', + 'testnet', + ); // lowercase L + invalid( + 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7', + 'bitcoin', + 'testnet', + ); // capital L + + invalid('tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty', 'bitcoin'); + invalid('bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5', 'bitcoin'); + invalid('BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2', 'bitcoin'); + invalid('bc1rw5uspcuh', 'bitcoin'); + invalid( + 'bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90', + 'bitcoin', + ); + invalid('BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P', 'bitcoin'); + invalid('bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du', 'bitcoin'); + invalid( + 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv', + 'bitcoin', + 'testnet', + ); + invalid('bc1gmk9yu', 'bitcoin'); + }); + + it('should match the expected bitcoin address type', function () { + isValidAddressType( + '1NSAR5mUUL3qZP29BfFj5jBPR5yWiiZZWi', + 'bitcoin', + 'prod', + addressType.P2PKH, + ); + isValidAddressType( + '3CgkdgWwZ1RJGyHfcYnDe2qGTwaAtifeQw', + 'bitcoin', + 'prod', + addressType.P2SH, + ); + isValidAddressType( + 'bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej', + 'bitcoin', + 'prod', + addressType.P2WSH, + ); + isValidAddressType( + 'bc1qr0c0jscha3tzr7963zz4u2wsezsxvpzkwmrvhg', + 'bitcoin', + 'prod', + addressType.P2WPKH, + ); + isValidAddressType( + 'bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr', + 'bitcoin', + 'prod', + addressType.P2TR, + ); + isValidAddressType( + 'bc1pqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsyjer9e', + 'bitcoin', + 'prod', + addressType.P2TR, + ); + isValidAddressType('BC1SW50QA3JX3S', 'bitcoin', 'prod', addressType.WITNESS_UNKNOWN); // bech32 + isValidAddressType('bc1sw50qgdz25j', 'bitcoin', 'prod', addressType.WITNESS_UNKNOWN); // bech32m ? + isValidAddressType('bc1sw50qgdz25j', 'bitcoin', 'testnet', undefined); + isValidAddressType('qwerty', 'bitcoin', 'prod', undefined); + isValidAddressType( + 'mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q', + 'bitcoin', + 'regtest', + addressType.P2PKH, + ); + isValidAddressType( + 'ms1B699PA2tAfHTFTwN12Tzxa933WpmuHX', + 'bitcoin', + 'regtest', + addressType.P2PKH, + ); + isValidAddressType( + '2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp', + 'bitcoin', + 'regtest', + addressType.P2SH, + ); + isValidAddressType( + 'GSa5espVLNseXEfKt46zEdS6jrPkmFghBU', + 'bitcoin', + 'regtest', + addressType.P2SH, + ); + isValidAddressType( + 'bcrt1q8zx9dlztqz9apm7y5gtx8a0tlz57fhncycvun5', + 'bitcoin', + 'regtest', + addressType.P2WPKH, + ); + isValidAddressType( + 'bcrt1pzndg2aenknysnqs0d8gwhg54nqnc6yut2c6as76h4tyqhr8spr6slpjy3x', + 'bitcoin', + 'regtest', + addressType.P2TR, + ); + }); + + it('should return true for correct bitcoincash addresses', function () { + valid('bitcoincash:qq4v32mtagxac29my6gwj6fd4tmqg8rysu23dax807', 'bch'); + valid('bitcoincash:qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy', 'bch'); + valid('qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy', 'bch'); + valid('bitcoincash:qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy', 'bch', 'testnet'); + valid('qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy', 'bch', 'testnet'); + }); + + it('should match the expected BCH address type', function () { + isValidAddressType( + 'bitcoincash:qq4v32mtagxac29my6gwj6fd4tmqg8rysu23dax807', + 'bch', + 'prod', + addressType.ADDRESS, + ); + isValidAddressType( + 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + 'bch', + 'prod', + undefined, + ); + isValidAddressType( + 'qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy', + 'bch', + 'prod', + addressType.ADDRESS, + ); + isValidAddressType( + 'bc1pqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsyjer9e', + 'bch', + 'prod', + undefined, + ); // BTC address + }); + + it('should return true for correct litecoin addresses', function () { + valid('LVg2kJoFNg45Nbpy53h7Fe1wKyeXVRhMH9', 'litecoin'); + valid('LVg2kJoFNg45Nbpy53h7Fe1wKyeXVRhMH9', 'LTC'); + valid('LTpYZG19YmfvY2bBDYtCKpunVRw7nVgRHW', 'litecoin'); + valid('Lb6wDP2kHGyWC7vrZuZAgV7V4ECyDdH7a6', 'litecoin'); + valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'litecoin', 'testnet'); + + // p2sh addresses + valid('MUWheVyCBf3Fm3WNNXvotQ3Gj8NTSZCBVe', 'litecoin'); + + valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'litecoin', 'testnet'); + valid('QW2SvwjaJU8LD6GSmtm1PHnBG2xPuxwZFy', 'litecoin', 'testnet'); + valid('QjpzxpbLp5pCGsCczMbfh1uhC3P89QZavY', 'litecoin', 'testnet'); + + // segwit + valid('ltc1qajkrze8gc5qdx2ehldsmd596a2gprnn50a53mj3xxvy0zgtdq6gqumv03a', 'litecoin'); + }); + + it('should match the expected litecoin address type', function () { + isValidAddressType( + 'LVg2kJoFNg45Nbpy53h7Fe1wKyeXVRhMH9', + 'litecoin', + 'prod', + addressType.P2PKH, + ); + isValidAddressType( + 'ltc1qajkrze8gc5qdx2ehldsmd596a2gprnn50a53mj3xxvy0zgtdq6gqumv03a', + 'litecoin', + 'prod', + addressType.P2WSH, + ); + }); + + it('should return true for correct peercoin addresses', function () { + valid('PHCEsP6od3WJ8K2WKWEDBYKhH95pc9kiZN', 'peercoin'); + valid('PSbM1pGoE9dnAuVWvpQqTTYVpKZU41dNAz', 'peercoin'); + valid('PUULeHrJL2WujJkorc2RsUAR3SardKUauu', 'peercoin'); + valid('PUULeHrJL2WujJkorc2RsUAR3SardKUauu', 'PPC'); + valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'peercoin', 'testnet'); + + // p2sh addresses + valid('pNms4CaWqgZUxbNZaA1yP2gPr3BYnez9EM', 'peercoin'); + valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'peercoin', 'testnet'); + }); + + it('should return true for correct dogecoin addresses', function () { + valid('DPpJVPpvPNP6i6tMj4rTycAGh8wReTqaSU', 'dogecoin'); + valid('DNzLUN6MyYVS5zf4Xc2yK69V3dXs6Mxia5', 'dogecoin'); + valid('DPS6iZj7roHquvwRYXNBua9QtKPzigUUhM', 'dogecoin'); + valid('DPS6iZj7roHquvwRYXNBua9QtKPzigUUhM', 'DOGE'); + //TODO: NEED A DOGECOIN TESTNET ADDRESS + + //p2sh addresses + valid('A7JjzK9k9x5b2MkkQzqt91WZsuu7wTu6iS', 'dogecoin'); + valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'dogecoin', 'testnet'); + }); + + it('should match the expected dogecoin address type', function () { + isValidAddressType( + 'DMqRVLrhbam3Kcfddpxd6EYvEBbpi3bEpP', + 'dogecoin', + 'prod', + addressType.P2PKH, + ); + isValidAddressType( + 'A7JjzK9k9x5b2MkkQzqt91WZsuu7wTu6iS', + 'dogecoin', + 'prod', + addressType.P2SH, + ); + isValidAddressType('qwerty', 'dogecoin', 'prod', undefined); + }); + + it('should return true for correct beavercoin addresses', function () { + valid('BPPtB4EpPi5wCaGXZuNyKQgng8ya579qUh', 'beavercoin'); + valid('BC1LLYoE4mTCHTJhVYvLGxhRTwAHyWTQ49', 'beavercoin'); + valid('BBuyeg2vjtyFdMNj3LTxuVra4wJMKVAY9C', 'beavercoin'); + valid('BBuyeg2vjtyFdMNj3LTxuVra4wJMKVAY9C', 'BVC'); + valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'beavercoin', 'testnet'); + + // p2sh addresses + valid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'beavercoin'); + valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'beavercoin', 'testnet'); + }); + + it('should return true for correct freicoin addresses', function () { + valid('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', 'freicoin'); + valid('1oNLrsHnBcR6dpaBpwz3LSwutbUNkNSjs', 'freicoin'); + valid('1SQHtwR5oJRKLfiWQ2APsAd9miUc4k2ez', 'freicoin'); + valid('1SQHtwR5oJRKLfiWQ2APsAd9miUc4k2ez', 'FRC'); + valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'freicoin', 'testnet'); + + // p2sh addresse + valid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'freicoin'); + valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'freicoin', 'testnet'); + }); + + it('should return true for correct protoshares addresses', function () { + valid('PaNGELmZgzRQCKeEKM6ifgTqNkC4ceiAWw', 'protoshares'); + valid('Piev8TMX2fT5mFtgxx2TXJaqXP37weMPuD', 'protoshares'); + valid('PgsuLoe9ojRKFGJGVpqqk37gAqNJ4ozboD', 'protoshares'); + valid('PgsuLoe9ojRKFGJGVpqqk37gAqNJ4ozboD', 'PTS'); + valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'protoshares', 'testnet'); + + //p2sh addresses + valid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'protoshares'); + valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'protoshares', 'testnet'); + }); + + it('should return true for correct megacoin addresses', function () { + valid('MWUHaNxjXGZUYTh92i3zuDmsnH1rHSBk5M', 'megacoin'); + valid('MSAkrhRyte7bz999Ga5SqYjzypFFYa2oEb', 'megacoin'); + valid('MLUTAtDQFcfo1QACWocLuufFq5fBDTpCHE', 'megacoin'); + valid('MLUTAtDQFcfo1QACWocLuufFq5fBDTpCHE', 'MEC'); + valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'megacoin', 'testnet'); + + //p2sh addresses + valid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'megacoin'); + valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'megacoin', 'testnet'); + }); + + it('should return true for correct primecoin addresses', function () { + valid('AVKeiZ5JadfWdH2EYVgVRfX4ufoyd4ehuM', 'primecoin'); + valid('AQXBRPyob4dywUJ21RUKrR1xetQCDVenKD', 'primecoin'); + valid('ANHfTZnskKqaBU7oZuSha9SpbHU3YBfeKf', 'primecoin'); + valid('AYdiYMKSGYxLcZNDmqB8jNcck7SQibrfiK', 'primecoin'); + valid('AYdiYMKSGYxLcZNDmqB8jNcck7SQibrfiK', 'XPM'); + valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'primecoin', 'testnet'); + + //p2sh addresses + valid('af5CvTQq7agDh717Wszb5QDbWb7nT2mukP', 'primecoin'); + valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'primecoin', 'testnet'); + }); + + it('should return true for correct auroracoin addresses', function () { + valid('ARM3GLZXF1PDTZ5vz3wh5MVahbK9BHTWAN', 'auroracoin'); + valid('AUtfc6ThCLb7FuEu7QPrWpJuaXaJRPciDF', 'auroracoin'); + valid('AUN1oaj5hjispGnczt8Aruw3TxgGyRqB3V', 'auroracoin'); + valid('AXGcBkGX6NiaDXj85C5dCrhTRUgwxSkKDK', 'auroracoin'); + valid('AXGcBkGX6NiaDXj85C5dCrhTRUgwxSkKDK', 'AUR'); + valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'auroracoin', 'testnet'); + + //p2sh addresses + valid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'auroracoin'); + valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'auroracoin', 'testnet'); + }); + + it('should return true for correct namecoin addresses', function () { + valid('NEpeRmS775fnti8TDgJA28m8KLEfNNRZvT', 'namecoin'); + valid('MyJ691bGJ48RBK2LS8n1U57wcFLFScFXxi', 'namecoin'); + valid('NFY9aw1RXLGtWpeqgNQXprnUcZXyKNinTh', 'namecoin'); + valid('NCPPc7Pzb75CpRPJQPRRh6ouJTq7BCy1H4', 'namecoin'); + valid('NCPPc7Pzb75CpRPJQPRRh6ouJTq7BCy1H4', 'NMC'); + }); + + it('should return true for correct BioCoin addresses', function () { + valid('B7xseoLGk7hEpMDDeSvZDKmmiAMHWiccok', 'biocoin'); + valid('B8zjmYFGhWmiaQSJshfrnefE72xCapCkvo', 'biocoin'); + valid('muH8LL42DiMs8GEQ6Grfi8KUw2uFvuKr1J', 'biocoin', 'testnet'); + valid('muH8LL42DiMs8GEQ6Grfi8KUw2uFvuKr1J', 'BIO', 'testnet'); + valid('B8zjmYFGhWmiaQSJshfrnefE72xCapCkvo', 'BIO'); + }); + + it('should return true for correct Garlicoin addresses', function () { + valid('GU2NtcNotWFiZjTp2Vdgf5CjeMfgsWYCua', 'garlicoin'); + valid('GNWeWaoQ6rv21ZFjJWT9vb91hXUzFTLkru', 'garlicoin'); + valid('mjKbQTkgwzmsL3J86tdVzhyW9pc4NePqTb', 'garlicoin', 'testnet'); + valid('mnYp36NuyRavMKQ9Q9Q6oGqoorAs9p3zYn', 'GRLC', 'testnet'); + valid('GU2NtcNotWFiZjTp2Vdgf5CjeMfgsWYCua', 'GRLC'); + }); + + it('should return true for correct Vertcoin addresses', function () { + valid('3PgeyhEJEnS5CeBu3iFcu3JHVKemeHx1AW', 'VTC'); + valid('353nERPQKhGj4WGzoiWcareA76TPgRCVNA', 'VTC'); + valid('376g4TmL8uQKFYsRFrbv5iz9srmb5bocEt', 'VTC'); + valid('3AMtM4Zk5oNHu9i4jDiwKB6Kg5YEReBsav', 'VTC'); + + valid('VmoMjGf3zgZLy8sk3PMKd3xikZHXWvnYi7', 'vertcoin'); + valid('VmhHwXr3J8xMZpy62WuBGpu3xVvThWzcTQ', 'vertcoin'); + valid('mvww6DEJ18dbyQUukpVQXvLgrNDJazZn1Y', 'vertcoin', 'testnet'); + valid('mn3mdEE6cf1snxVsknNz4GRTdSrWXqYp7c', 'VTC', 'testnet'); + valid('Vri6Q4GgNFfdtcpxD961TotJwaSaYQCaL5', 'VTC'); + valid('vtc1qmzq3erafwvz23yfeu9tu45uz2kx3d7esk0rayg', 'VTC'); + valid('vtc1qhy8eqwqxpyryz4wctus36yl2uu60t0z6ecrvtc', 'VTC'); + valid('vtc1qh9y09s2crkp63mk26u3vrq9q4w3h8ee8gepjgw', 'VTC'); + }); + + it('should return true for correct BitcoinGold addresses', function () { + valid('GW3JrQyHtoVfEFES3Y9JagiX3VSKQStLwj', 'bitcoingold'); + valid('GUDWdeMyAXQbrNFFivAhkJQ1GfBCFdc7JF', 'bitcoingold'); + valid('mvww6DEJ18dbyQUukpVQXvLgrNDJazZn1Y', 'bitcoingold', 'testnet'); + valid('mn3mdEE6cf1snxVsknNz4GRTdSrWXqYp7c', 'BTG', 'testnet'); + valid('GSNFPRsdaM3MXrU5HW1AxgFwmUQC8HXK9F', 'BTG'); + }); + + it('should return true for correct Decred addresses', function () { + valid('Dsesax2GJnMN4wwmWo5rJGq73dDK217Rh85', 'DCR'); + valid('DsYuxtvGRfN8rncXAndtLUpJm55F77K17RA', 'decred'); + valid('DsaXDG2NrJW8g4tFAb8n9MNx81Sn3Qc8AEV', 'decred'); + valid('TsijUgejaRnLKF5WAbpUxNtwKGUiKVeXLr7', 'decred', 'testnet'); + valid('TsZ9QmAoadF12hGvyALp6qvaF4be3BmLqG9', 'dcr', 'testnet'); + }); + + it('should return true for correct Digibyte addresses', function () { + valid('DG2rM2orU2JH5i4ACh3AKNpRTNESdv5xf8', 'DGB'); + valid('DBR2Lj1F17eHGHXgbpae2Wb4m39bDyA1qo', 'DGB'); + valid('D9TDZTR9Z9Mx2NoDJnhqhnYhDLKRAmsL9n', 'digibyte'); + valid('DHRzA1YHA1kFWpz2apRckZJy6KZRyGq4EV', 'digibyte'); + valid('DJ53hTyLBdZp2wMi5BsCS3rtEL1ioYUkva', 'digibyte'); + valid('SRrevBM5bfZNpFJ4MhzaNfkTghYKoTB6LV', 'digibyte'); + valid('SckT6Snbv1WR2VYEuCh3upSPquHN57N314', 'digibyte'); + }); + + it('should return true for correct Ethereum addresses', function () { + valid('0xE37c0D48d68da5c5b14E5c1a9f1CFE802776D9FF', 'ethereum'); + valid('0xa00354276d2fC74ee91e37D085d35748613f4748', 'ethereum'); + valid('0xAff4d6793F584a473348EbA058deb8caad77a288', 'ETH'); + valid('0xc6d9d2cd449a754c494264e1809c50e34d64562b', 'ETH'); + valid('0x52908400098527886E0F7030069857D2E4169EE7', 'ETH'); + valid('0x8617E340B3D01FA5F11F306F4090FD50E238070D', 'ETH'); + valid('0xde709f2102306220921060314715629080e2fb77', 'ETH'); + valid('0x27b1fdb04752bbc536007a920d24acb045561c26', 'ETH'); + valid('0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed', 'ETH'); + valid('0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359', 'ETH'); + valid('0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB', 'ETH'); + valid('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb', 'ETH'); + + valid('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb', 'ethereumclassic'); + valid('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb', 'ETC'); + valid('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb', 'etherzero'); + valid('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb', 'ETZ'); + valid('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb', 'callisto'); + valid('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb', 'CLO'); + }); + + it('should match the expected eip55 address type', function () { + isValidAddressType( + '0xE37c0D48d68da5c5b14E5c1a9f1CFE802776D9FF', + 'ethereum', + 'prod', + addressType.ADDRESS, + ); + isValidAddressType( + '0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb', + 'ethereumclassic', + 'prod', + addressType.ADDRESS, + ); + }); + + it('should return true for correct Ripple addresses', function () { + valid('rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn', 'ripple'); + valid('rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn', 'XRP'); + valid('r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV', 'XRP'); + valid('rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', 'XRP'); + valid('rDTXLQ7ZKZVKz33zJbHjgVShjsBnqMBhmN', 'XRP'); + }); + + it('should match the expected Ripple address type', function () { + isValidAddressType( + 'rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn', + 'Ripple', + 'prod', + addressType.ADDRESS, + ); + isValidAddressType('rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCN', 'Ripple', 'prod', undefined); + }); + + it('should return true for correct dash addresses', function () { + valid('Xx4dYKgz3Zcv6kheaqog3fynaKWjbahb6b', 'dash'); + valid('XcY4WJ6Z2Q8w7vcYER1JypC8s2oa3SQ1b1', 'DASH'); + valid('XqMkVUZnqe3w4xvgdZRtZoe7gMitDudGs4', 'dash'); + valid('yPv7h2i8v3dJjfSH4L3x91JSJszjdbsJJA', 'dash', 'testnet'); + valid('XoAAqv3oUYZ6xRjX3brfbf9PotrGanS6Th', 'dash'); + valid('yP5oXZQXBfBf9FyfZDpFiKDypxuNUKUV2E', 'dash', 'testnet'); + }); + + it('should return true for correct neo addresses', function () { + valid('AR4QmqYENiZAD6oXe7ftm6eDcwtHk7rVTT', 'neo'); + valid('AKDVzYGLczmykdtRaejgvWeZrvdkVEvQ1X', 'NEO'); + }); + + it('should return true for correct neo gas addresses', function () { + valid('AR4QmqYENiZAD6oXe7ftm6eDcwtHk7rVTT', 'neogas'); + }); + + it('should return true for correct qtum addresses', function () { + valid('QNjUiD3bVVZwYTc5AhpeQbS1mfb2guyWhe', 'qtum'); + valid('QVZnSrMwKp6AL4FjUPPnfFgsma6j1DXQXu', 'QTUM'); + valid('MCgyroQse81wuv5RwPpY5DXDNxeafzLFJ8', 'QTUM'); + valid('QQYySVc5WEe3g6PnNFYmspqG5CfSG8rnma', 'QTUM'); + valid('MSvJQBJMZs1dhxz7UAWa2si4iyMD2FHQd5', 'QTUM'); + + valid('qcSLSxN1sngCWSrKFZ6UC7ri4hhVSdq9SU', 'qtum', 'testnet'); + valid('qJnbEdrm9ybjVqDCaX5SWNBHmZy2X7YbPT', 'qtum', 'testnet'); + valid('qchBPDUYswobzpDmY5DsTStt74sTYQtaQv', 'qtum', 'testnet'); + valid('qbgHcqxXYHVJZXHheGpHwLJsB5epDUtWxe', 'qtum', 'testnet'); + valid('qZqqcqCsVtP2U38WWaUnwshHRpefvCa8hX', 'qtum', 'testnet'); + }); + + it('should return true for correct votecoin addresses', function () { + valid('t1U9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'votecoin'); + valid('t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'VOT'); + valid('t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'votecoin', 'testnet'); + }); + + it('should return true for correct bitcoinz addresses', function () { + valid('t1U9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'bitcoinz'); + valid('t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'BTCZ'); + valid('t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'bitcoinz', 'testnet'); + }); + + it('should return true for correct zclassic addresses', function () { + valid('t1U9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'zclassic'); + valid('t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'ZCL'); + valid('t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'zclassic', 'testnet'); + }); + + it('should return true for correct hush addresses', function () { + valid('t1U9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'hush'); + valid('t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'HUSH'); + valid('t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'hush', 'testnet'); + }); + + it('should return true for correct zcash addresses', function () { + valid('t1U9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'zcash'); + valid('t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'ZEC'); + valid('t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'zcash', 'testnet'); + }); + + it('should return true for correct bitcoinprivate addresses', function () { + valid('b1M4XXPFhwMb1SP33yhzn3h9qWXjujkgep4', 'bitcoinprivate'); + //valid('bx....', 'BTCP'); + //valid('nx....', 'bitcoinprivate', 'testnet'); + }); + + it('should return true for correct snowgem addresses', function () { + valid('s1fx7WBkjB4UH6qQjPp6Ysmtr1C1JiTK2Yw', 'snowgem'); + valid('s3d27MhkBRt3ha2UuxhjXaYF4DCnttTMnL1', 'SNG'); + valid('t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'snowgem', 'testnet'); + }); + + it('should return true for correct zencash addresses', function () { + valid('znhiGGfYRepxkBjXYvA2kFrXiC351i9ta4z', 'zencash'); + valid('zssEdGnZCQ9G86LZFtbynMn1hYTVhn6eYCL', 'ZEN'); + valid('ztmWMDLWjbruCJxKmmfAZiT6QAQdiv5F291', 'zencash', 'testnet'); + }); + + it('should return true for correct komodo addresses', function () { + valid('R9R5HirAzqDcWrWGiJEL115dpV3QB3hobH', 'komodo'); + valid('RAvj2KKVUohTu3hVdNJ4U6hQi7TNawpacH', 'KMD'); + //valid('t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'komodo', 'testnet'); + }); + + it('should return true for correct Bankex addresses', function () { + valid('0xeac39e1bc802baae3d4b9cb518f3f60374bbad6c', 'bankex'); + valid('0x45245bc59219eeaaf6cd3f382e078a461ff9de7b', 'BKX'); + valid('0xf40d80FCfa5cdEa0bB1E570c2D52132ac9bC6aEC', 'bankex', 'testnet'); + valid('0x8A7395f281EeCf2B471B689E87Cf4C7fa8bb957d', 'BKX', 'testnet'); + }); + + it('should return true for correct Cardano addresses', function () { + valid('Ae2tdPwUPEYxYNJw1He1esdZYvjmr4NtPzUsGTiqL9zd8ohjZYQcwu6kom7', 'cardano'); + valid( + 'DdzFFzCqrhsfdzUZxvuBkhV8Lpm9p43p9ubh79GCTkxJikAjKh51qhtCFMqUniC5tv5ZExyvSmAte2Du2tGimavSo6qSgXbjiy8qZRTg', + 'ada', + ); + valid('Ae2tdPwUPEZKmwoy3AU3cXb5Chnasj6mvVNxV1H11997q3VW5ihbSfQwGpm', 'ada'); + valid( + '4swhHtxKapQbj3TZEipgtp7NQzcRWDYqCxXYoPQWjGyHmhxS1w1TjUEszCQT1sQucGwmPQMYdv1FYs3d51KgoubviPBf', + 'cardano', + ); + valid( + 'addr1qxnv5u3vrx2t37h3u27qd5ukgcjmrl4f8mu9f5sza3h20cxsfjh80un9kvlggfcdw8fp5kqp9tztqnee9msd0qsafhdsyqclvk', + 'cardano', + ); + valid( + 'ADDR1QXNV5U3VRX2T37H3U27QD5UKGCJMRL4F8MU9F5SZA3H20CXSFJH80UN9KVLGGFCDW8FP5KQP9TZTQNEE9MSD0QSAFHDSYQCLVK', + 'cardano', + ); + valid( + 'addr1qxclz0u9guazk70l9vv3xf67wx3psx3dekasvy43xfvz56qcs6f7ssw2x0fcesudyj8h224rnzkae2lqlnw8f3353t3sjggfx0', + 'cardano', + ); + valid( + 'addr_test1qru5ktsj5zsmhvwv0ep9zuhfu39x3wyt9wxjnsn3cagsyy59ckxhkvuc5xj49rw6zrp443wlygmhv8gwcu38jk6ms6usqd9a9q', + 'cardano', + 'testnet', + ); + }); + + it('should match the expected Cardano address type - mainnet', function () { + isValidAddressType( + 'Ae2tdPwUPEYxYNJw1He1esdZYvjmr4NtPzUsGTiqL9zd8ohjZYQcwu6kom7', + 'cardano', + 'prod', + addressType.ADDRESS, + ); + }); + + it('should match the expected Cardano address type - testnet', function () { + isValidAddressType( + 'addr_test1qru5ktsj5zsmhvwv0ep9zuhfu39x3wyt9wxjnsn3cagsyy59ckxhkvuc5xj49rw6zrp443wlygmhv8gwcu38jk6ms6usqd9a9q', + 'cardano', + 'testnet', + addressType.ADDRESS, + ); + }); + + it('should return true for correct monero addresses', function () { + valid( + '47zQ5LAivg6hNCgijXSEFVLX7mke1bgM6YGLFaANDoJbgXDymcAAZvvMNt2PmMpqEe5qRy2zyfMYXdwpmdyitiFh84xnPG2', + 'monero', + ); + valid( + '48bWuoDG75CXMDHbmPEvUF2hm1vLDic7ZJ7hqRkL65QR9p13AQAX4eEACXNk4YP115Q4KRVZnAvmMBHrcGfv9FvKPZnH6vH', + 'XMR', + ); + valid( + 'A2be3UvzMtkJtxRYgcCbQt2y7Rp2eLVGqNTWfZeankrWimSMM4y7uMP6B9oAZaHsXTj8KFSerkSkkVRuEuEca9QM8VhxCNU', + 'monero', + 'testnet', + ); + + //integrated addresses + valid( + '4Gd4DLiXzBmbVX2FZZ3Cvu6fUaWACup1qDowprUCje1kSP4FmbftiJMSfV8kWZXNqmVwj4m52xqtgFNUudVmsmGkGvkLcCibWfVUfUFVB7', + 'monero', + ); + valid( + '4J5sF94AzXgFgx8LuWc9dcWkJkGkD3cL3L2AuhX6QA9jFvSxxj6QhHqHXqM2b2Go7G8RyDzEbHxYd9G26XUUbuJChipEyBz9fENMU2Ua9b', + 'XMR', + ); + + // subaddress + valid( + '8A9XmWsATrhfedtNhTMNKELwfCwMVAk2iVTdUJdFRb2AC4tV4VeBjsCLYR9cSQTwnvLo4MAuQFMLP6Si4xp6t6BS788db3t', + 'monero', + ); + valid( + '87i7kA61fNvMboXiYWHVygPAggKJPETFqLXXcdH4mQTrECvrTxZMtt6e6owj1k8jUVjNR11eBuBMWHFBtxAwEVcm9dcSUxr', + 'xmr', + ); + }); + + it('should match the expected monero address type', function () { + isValidAddressType( + '47zQ5LAivg6hNCgijXSEFVLX7mke1bgM6YGLFaANDoJbgXDymcAAZvvMNt2PmMpqEe5qRy2zyfMYXdwpmdyitiFh84xnPG2', + 'xmr', + 'prod', + addressType.ADDRESS, + ); + isValidAddressType( + '44643dtxcxjgMWEQLo6mh1c4d9Zxx9GbgK9hEj9iGSiFEryCkbwHyJ3JqxZJRqeC3Hb7ZBLKq5NkaJwR1x95EYnR1bTgN6d', + 'Monero', + 'prod', + undefined, + ); + }); + + it('should return true for correct gamecredits addresses', function () { + valid('GU5BBtW9gxSKvAknvFi9yUaXKUNW9zUN2p', 'game'); + valid('GYxQMVzP6YpzX59QNRYqmJeHNtUMYSZPri', 'game'); + }); + + it('should return true for correct monacoin addresses', function () { + valid('MMN1Q1aRVUzanmg9DJjcRYzQSJQoBeQPui', 'mona'); + valid('PFMzNYnBm5X4c9qJkJPkfgdCyd9fuuy2vT', 'mona'); + valid('PCtN7VUYHW8w4g59BaphrfPs8g7pNgAzxn', 'mona'); + valid('MXCcYFGRmsd4d3CcQugFiqG8uarj5tVu76', 'mona'); + valid('MNK1pGsBf9WdoE54fZM9VFhkeYHW6VUf2u', 'mona'); + }); + + it('should return true for correct pivx addresses', function () { + valid('DJXFW9oJJBUX7QKrG6GKvmTs63MYKzwtpZ', 'pivx'); + valid('DEaYb8EHQgyKvX6VXDS3DZQautJrHBmK3T', 'pivx'); + valid('DDeCGR3QSgqsBxVR23bJvteiyYE34ZmxAc', 'pivx'); + valid('DSqQM8DPpBHHoZXHgRdwmaf6hZPEoZcFkh', 'pivx'); + }); + + it('should return true for correct solarcoin addresses', function () { + valid('8VxVLzwB26E2YZZ82o1NcQe96QSM2z6GwW', 'slr'); + valid('8YW5qcTjeyqX5kESsqu2BUdXiedgssegtQ', 'SolarCoin'); + }); + + it('should return true for correct tether addresses', function () { + valid('3MbYQMMmSkC3AgWkj9FMo5LsPTW1zBTwXL', 'usdt'); + valid('1KdXaqcBeoMAFVAPwTmYvDbEq6RnvNPF6J', 'tether'); + }); + + it('should return true for correct expanse addresses', function () { + valid('0xbab463743603a253bdf1f84975b1a9517505ae05', 'exp'); + valid('0x5d0777cb5d6977873904864c6ab531f4b3261f0b', 'expanse'); + }); + + it('should return true for correct waves addresses', function () { + valid('3P93mVrYnQ4ahaRMYwA2BeWY32eDxTpLVEs', 'waves'); + valid('3P4eeU7v1LMHQFwwT2GW9W99c6vZyytHajj', 'waves'); + + valid('3Myrq5QDgRq3nBVRSSv9UYrP36xTtpJND5y', 'waves', 'testnet'); + valid('3My3KZgFQ3CrVHgz6vGRt8687sH4oAA1qp8', 'waves', 'testnet'); + }); + + 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'); + }); + + it('should return true for correct Aeternity addresses', () => { + valid('ak_AT2bs7LkqwKbPUj5waoqq1E7QYgRzXUbaBanDHXDVsaCJ8gRA', 'ae'); + valid('ak_8QxnP9qXP3NpA4fskYZE7P1GfHzKZAMmoNuok7jJC5NqVYi21', 'ae'); + }); + + it('should match the expected Aeternity address type', function () { + isValidAddressType( + 'ak_AT2bs7LkqwKbPUj5waoqq1E7QYgRzXUbaBanDHXDVsaCJ8gRA', + 'ae', + 'prod', + addressType.ADDRESS, + ); + }); + + it('should return true for correct Ardor addresses', () => { + valid('ARDOR-HFNE-E2VE-SMV3-DCRZ8', 'ardr'); + }); + + it('should return false for correct Ardor addresses', () => { + invalid('AR-HFNE-E2VE-SMV3-DCRZ8', 'ardr'); + }); + + it('should match the expected Ardor address type', function () { + isValidAddressType('ARDOR-HFNE-E2VE-SMV3-DCRZ8', 'ardr', 'prod', addressType.ADDRESS); + isValidAddressType('AR-HFNE-E2VE-SMV3-DCRZ8', 'ardr', 'prod', undefined); + }); + + it('should return true for correct siacoin addresses', function () { + valid( + 'a9b01c85163638682b170d82de02b8bb99ba86092e9ab1b0d25111284fe618e93456915820f1', + 'siacoin', + ); + valid( + 'a9b01c85163638682b170d82de02b8bb99ba86092e9ab1b0d25111284fe618e93456915820f1', + 'siacoin', + ); + valid( + 'ab0c327982abfcc6055a6c9551589167d8a73501aca8769f106371fbc937ad100c955c3b7ba9', + 'siacoin', + ); + valid( + 'ffe1308c044ade30392a0cdc1fd5a4dbe94f9616a95faf888ed36123d9e711557aa497530373', + 'siacoin', + ); + }); + + it('should match the expected Siacoin address type', function () { + isValidAddressType( + 'a9b01c85163638682b170d82de02b8bb99ba86092e9ab1b0d25111284fe618e93456915820f1', + 'siacoin', + 'prod', + addressType.ADDRESS, + ); + isValidAddressType('aaaaaaaaaaaaaaa000000000000000', 'siacoin', 'prod', undefined); + }); + + it('should return true for correct BSC addresses', function () { + valid('0x0590396689ee1d287147e9383fb8dd24532f2006', 'bsc'); + valid('0x07fc5c2bcaa0fa6bdaa4fff897490312c8f33c27', 'binance smart chain'); + }); + + it('should return true for correct Cosmos addresses', () => { + valid('cosmos1xxkueklal9vejv9unqu80w9vptyepfa95pd53u', 'atom'); + }); + + it('should return false for incorrect Cosmos addresses', () => { + invalid('cosmo15v50ymp6n5dn73erkqtmq0u8adpl8d3ujv2e74', 'atom'); + invalid('cosmos25v50ymp6n5dn73erkqtmq0u8adpl8d3ujv2e74', 'atom'); + invalid('cosmos15v50ymp6n5dn73erkQtmq0u8adpl8d3ujv2e74', 'atom'); + }); + + it('should match the expected Cosmos address type', function () { + isValidAddressType( + 'cosmos1xxkueklal9vejv9unqu80w9vptyepfa95pd53u', + 'atom', + 'prod', + addressType.ADDRESS, + ); + isValidAddressType('qwerty', 'atom', 'prod', undefined); + }); + + it('should return true for correct HashGraph addresses', () => { + valid('0.0.10819', 'hbar'); + valid('0.0.13458', 'hbar'); + valid('0.0.16952', 'hbar'); + }); + + it('should return true for incorrect HashGraph addresses', () => { + invalid('1.0.10819', 'hbar'); + }); + + it('should match the expected HBAR address type', function () { + isValidAddressType('0.0.10819', 'hbar', 'prod', addressType.ADDRESS); + isValidAddressType('1.0.10819', 'hbar', 'prod', undefined); + }); + + it('should return true for incorrect ICON addresses', () => { + valid('hxf5a52d659df00ef0517921647516daaf7502a728', 'icx'); + }); + + it('should return false for incorrect ICON addresses', () => { + invalid('gxde8ba8fd110625a0c47ecf29de308b8f5bd20ed6', 'icx'); + invalid('hxde8ba8fd110625a0c47ecf29de308b8f5bd20eD6', 'icx'); + }); + + it('should match the expected ICON address type', function () { + isValidAddressType( + 'hxf5a52d659df00ef0517921647516daaf7502a728', + 'ICON', + 'prod', + addressType.ADDRESS, + ); + isValidAddressType( + 'hxde8ba8fd110625a0c47ecf29de308b8f5bd20eD6', + 'ICON', + 'prod', + undefined, + ); + }); + + it('should return true for correct IOST addresses', () => { + valid('binanceiost', 'iost'); + }); + + it('should return true for correct IOST addresses', () => { + invalid('rekt', 'iost'); + }); + + it('should match the expected IOST address type', function () { + isValidAddressType('binanceiost', 'IOST', 'prod', addressType.ADDRESS); + isValidAddressType('rekt', 'IOST', 'prod', undefined); + }); + + // it('should return true for correct (M)IOTA addresses', () => { + // valid('ABFJCYEFHIV9XJY9XKDNYZGHBPYRYNFMUUNXAMZMFIEYSDKNHNEUSEXQYEWQTDNFETUNRSMEKJUCIKEEWFSWZYVFXD', 'iota') + // }); + + it('should return false for incorrect Ontology addresses', () => { + invalid('AXu57dhdNDnA5drqJUM2KfoMqgaLwmZwow', 'ont'); + invalid('TNVv2v7eKL525gZ2YCmFnsB2FGNG4VeMHd', 'ont'); + invalid('TFYhfePLaZq2Y4BdKAnorm3XjjqTZcc9m4', 'ont'); + invalid('AecjxQsLGsSU3nmx92UuGGbF1fj7EsGrt2', 'ont'); + }); + + it('should return false for incorrect Ravencoin addresses', () => { + invalid('RFnM9d8sjAPn24yJi4VACWWWZjaYyFwd8k', 'rvn'); + }); + + it('should return true for correct STEEM addresses', () => { + valid('disconnect', 'steem'); + }); + + it('should return false for incorrect STEEM addresses', () => { + invalid('meet--crypto8', 'steem'); + invalid('me.etcrypto8', 'steem'); + invalid('met.8etcrypto8', 'steem'); + invalid('me', 'steem'); + invalid('.', 'steem'); + }); + + it('should match the expected STEEM address type', function () { + isValidAddressType('disconnect', 'steem', 'prod', addressType.ADDRESS); + isValidAddressType('me', 'steem', 'prod', undefined); + }); + + it('should return true for correct Stratis addresses', () => { + valid('SY7YwpMGvU42dkFzmFEkGWFr1BEikUwhPT', 'strat'); + }); + + it('should return true for correct Verge addresses', () => { + valid('D9HsosoCM6pxWU4UD3cgHFacmD18Fu34g5', 'xvg'); + }); + + it('should return true for correct Zilliqa addresses', () => { + valid('zil1pk6fe395e9lfkglv0m70daezm5en0t62hty7f7', 'zil'); + }); + + it('should return false for incorrect Zilliqa addresses', () => { + invalid('0xda816e2122a8a39b0926bfa84edd3d42477e9efE', 'zil'); + }); + + it('should match the expected Zilliqa address type', function () { + isValidAddressType( + 'zil1pk6fe395e9lfkglv0m70daezm5en0t62hty7f7', + 'zil', + 'prod', + addressType.ADDRESS, + ); + isValidAddressType( + '0xda816e2122a8a39b0926bfa84edd3d42477e9efE', + 'zil', + 'prod', + undefined, + ); + }); + + it('should return true for incorrect NXT addresses', () => { + valid('NXT-799W-TN9C-GL3Q-D3PXU', 'nxt'); + valid('NXT-TMVC-69YC-SJB4-8YCH7', 'nxt'); + }); + + it('should return false for incorrect NXT addresses', () => { + invalid('NXT-799W-TN9C-GL3Q', 'nxt'); + invalid('NEXT-799W-TN9C-GL3Q', 'nxt'); + }); + + it('should match the expected NXT address type', function () { + isValidAddressType('NXT-799W-TN9C-GL3Q-D3PXU', 'NXT', 'prod', addressType.ADDRESS); + isValidAddressType('NXT-799W-TN9C-GL3Q', 'NXT', 'prod', undefined); + }); + + it('should return true for correct VeChain addresses', () => { + valid('0xA9E5617e2f90427F6db70A3B1d08Fc14706Eb907', 'ven'); + valid('0xb089B15A00528eEB19fcA4565df80d9a111BFCf9', 'ven'); + }); + + it('should return true for correct VeChain Mainnet addresses', () => { + valid('0x1374A7E9d5Ed5CFF9c56a0e57B3d8a836a378715', 'vet'); + valid('0x1374A7E9d5Ed5CFF9c56a0e57B3d8a836a378715', 'vet'); + }); + + it('should return true for correct Syscoin addresses', () => { + valid('SdzKyvhD2Y3xJvGVSfx96NXszq6x9BZX34', 'sys'); + valid('SSSBZDMVxuZyEMW4s6ar79Cf9UKqy6ZCwf', 'sys'); + valid('SUQ4gsnsTUeYJgTLsQ3siryr9HfHp95p12', 'sys'); + valid('SdzKyvhD2Y3xJvGVSfx96NXszq6x9BZX34', 'sys'); + valid('SbmNaK9hVn9BUoPoPtTmXogfGfZd5Mophm', 'sys'); + valid('SQUDdLog219Hpcz6Zss4uXg6xU1pAcnbLF', 'sys'); + valid('STxiBMedbmA28ip1QMooZaTBHxyiwVSCSr', 'sys'); + valid('SV4yxaugDJB6WXT5hNJwN1Pz6M8TjrMmJ6', 'sys'); + }); + + it('should match the expected Syscoin address type', function () { + isValidAddressType( + 'sys1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + 'sys', + 'prod', + addressType.ADDRESS, + ); + isValidAddressType( + 'SdzKyvhD2Y3xJvGVSfx96NXszq6x9BZX34', + 'sys', + 'prod', + addressType.ADDRESS, + ); + isValidAddressType( + 'sus1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + 'sys', + 'prod', + undefined, + ); + }); + + it('should return true for correct loki addresses', function () { + // public + valid( + 'L63ymg8cb5aRz1PhXrEQ22PWw9KBhBS8rMsgqbABhTGFfh53U3Rc2iWCJpCPsHZT5hfyt7fPQa612a5Z1tBnGYEA9h6YHnn', + 'loki', + ); + valid( + 'L5QKRGMNpQU3eCAdjMVTCR631bRKqnW1oEWWBEHAtFJLieA5VvuxyyubCd9FczEEatg8jfy39UJZ13npLJqZG6dtMtM99ha', + 'loki', + ); + // integrated + valid( + 'LK8CGQ17G9R3ys3Xf33wCeViD2B95jgdpjAhcRsjuheJ784dumXn7g3RPAzedWpFq364jJKYL9dkQ8mY66sZG9BiD1xbPb6dpYo7toNRqk', + 'loki', + ); + valid( + 'LK8CGQ17G9R3ys3Xf33wCeViD2B95jgdpjAhcRsjuheJ784dumXn7g3RPAzedWpFq364jJKYL9dkQ8mY66sZG9BiCtWq1AYo1oJTVqgUcQ', + 'loki', + ); + valid( + 'LLhSDqBZdjLQWajr4pBcFkdjL8oGY7MDvfJkKfrQVaokfDMxU6bDVb6h8tsD1jpKpSXbbB1p8RxPbA7fmjvLGjicKLBdQvDMbHA7TWVCUQ', + 'loki', + ); + // subaddress + valid( + 'LW1VMYcvWPZZJ2h1pKGEku2y9WeDiAU2VhgrgVgvjybaRuCdcEkg6FhXjVNSd37Bp7fhYH8tVa5T9VmRaYiWyxYdCpEGBg8', + 'loki', + ); + }); + + it('should return true for correct lbry addresses', function () { + valid('bDb6NmobyDVeNGpizWQQBZkYjKCRQBdKdG', 'LBC'); + valid('bTFXPcV3a8iVDezogvHTHezWZ1mZGWpPDc', 'lbc'); + valid('bK2uEVn6UuwjCTUZ1Dfj5HhWYi9BtqZDDm', 'lbc'); + valid('bNEMVqeUZUqTrYUxud5ehnUhtTAiWDXQ5e', 'lbc'); + }); + + it('should return true for correct trx addresses', function () { + valid('TNDzfERDpxLDS2w1q6yaFC7pzqaSQ3Bg3r', 'trx'); + valid('27bLJCYjbH6MT8DBF9xcrK6yZnm43vx7MNQ', 'trx', 'testnet'); + }); + + it('should return true for correct nem addresses', function () { + valid('NBZMQO7ZPBYNBDUR7F75MAKA2S3DHDCIFG775N3D', 'xem'); + valid('TDWTRGT6GVWCV7GRWFNI45S53PGOJBKNUF3GE6PB', 'xem', 'testnet'); + }); + + it('should match the expected NEM address type', function () { + isValidAddressType( + 'NBZMQO7ZPBYNBDUR7F75MAKA2S3DHDCIFG775N3D', + 'NEM', + 'prod', + addressType.ADDRESS, + ); + isValidAddressType( + 'TDWTRGT6GVWCV7GRWFNI45S53PGOJBKNUF3GE6PB', + 'NEM', + 'testnet', + addressType.ADDRESS, + ); + isValidAddressType('TNDzfERDpxLDS2w1q6yaFC7pzqaSQ3Bg31', 'NEM', 'prod', undefined); + }); + + it('should return true for correct lsk addresses', function () { + valid('469226551L', 'lsk'); + valid('15823701926930889868L', 'Lisk'); + valid('1657699692452120239L', 'lsk'); + valid('555666666999992L', 'lsk'); + valid('6853061742992593192L', 'lsk'); + valid('530464791801L', 'lsk'); + }); + + it('should match the expected lsk address type', function () { + isValidAddressType('469226551L', 'lsk', 'prod', addressType.ADDRESS); + isValidAddressType('469226551l', 'lsk', 'prod', undefined); + }); + + it('should return true for correct bsv addresses', function () { + valid('qzwryn9fxnpqkf7zt878tp2g9cg8kpl65qh2ml0w0r', 'bsv'); + valid('qp65yngy5uds4wxtrkynptal4f76qzmrh52pa3mpaf', 'bsv'); + valid('bitcoincash:qq4v32mtagxac29my6gwj6fd4tmqg8rysu23dax807', 'bsv'); + valid('qq4v32mtagxac29my6gwj6fd4tmqg8rysu23dax807', 'bsv'); + valid('qz97s7ee0rvwlymtxrwafmvs87x6027jwuf3wepug7', 'bsv'); + valid('bitcoincash:qpp32ssez340wfspnt79h6c4xds4fzf3m5j0cplx0l', 'bsv'); + valid('qqg82u7tq2eahs3gkh9m6kjnmjehr69m5v37alepq4', 'bsv'); + valid('bitcoincash:qrwkk9a3es2wu7mdvzh0vekfvjuzysq8tv7r3hcwr5', 'bsv'); + valid('1DrNXqCj2B8FKyx66RAWDkiEJhw2yrvhT3', 'bsv'); + }); + + it('should match the expected bsv address type', function () { + isValidAddressType( + 'qzwryn9fxnpqkf7zt878tp2g9cg8kpl65qh2ml0w0r', + 'bsv', + 'prod', + addressType.ADDRESS, + ); + + // FIXME: this test fails (returns addressType.ADDRESS) - should it return undefined as it's a testnet address? + // isValidAddressType('qzwryn9fxnpqkf7zt878tp2g9cg8kpl65qh2ml0w0r', 'bsv', 'testnet', undefined); + + isValidAddressType('qwerty', 'bsv', 'prod', undefined); + }); + + it('should return true for correct stellar addresses', function () { + valid('GBBM6BKZPEHWYO3E3YKREDPQXMS4VK35YLNU7NFBRI26RAN7GI5POFBB', 'stellar'); + valid('GB7KKHHVYLDIZEKYJPAJUOTBE5E3NJAXPSDZK7O6O44WR3EBRO5HRPVT', 'stellar'); + valid('GD6WVYRVID442Y4JVWFWKWCZKB45UGHJAABBJRS22TUSTWGJYXIUR7N2', 'stellar'); + valid('GBCG42WTVWPO4Q6OZCYI3D6ZSTFSJIXIS6INCIUF23L6VN3ADE4337AP', 'stellar'); + valid('GDFX463YPLCO2EY7NGFMI7SXWWDQAMASGYZXCG2LATOF3PP5NQIUKBPT', 'stellar'); + valid('GBXEODUMM3SJ3QSX2VYUWFU3NRP7BQRC2ERWS7E2LZXDJXL2N66ZQ5PT', 'stellar'); + valid('GAJHORKJKDDEPYCD6URDFODV7CVLJ5AAOJKR6PG2VQOLWFQOF3X7XLOG', 'stellar'); + valid('GACXQEAXYBEZLBMQ2XETOBRO4P66FZAJENDHOQRYPUIXZIIXLKMZEXBJ', 'stellar'); + valid('GDD3XRXU3G4DXHVRUDH7LJM4CD4PDZTVP4QHOO4Q6DELKXUATR657OZV', 'stellar'); + valid('GDTYVCTAUQVPKEDZIBWEJGKBQHB4UGGXI2SXXUEW7LXMD4B7MK37CWLJ', 'stellar'); + valid('GDC5UWE3G6Z4KYOTET5NOCRIVBKWH7MOCSPZPHF4GHQ6XUDD27ACOACD', 'stellar'); + }); + + it('should match the expected stellar address type', function () { + isValidAddressType( + 'GBBM6BKZPEHWYO3E3YKREDPQXMS4VK35YLNU7NFBRI26RAN7GI5POFBB', + 'stellar', + 'prod', + addressType.ADDRESS, + ); + isValidAddressType( + 'SBGWKM3CD4IL47QN6X54N6Y33T3JDNVI6AIJ6CD5IM47HG3IG4O36XCU', + 'stellar', + 'prod', + undefined, + ); + }); + + it('should return true for correct binance address', function () { + valid('bnb1qfmufc2q30cgw82ykjlpfeyauhcf5mad6p5y8t', 'binance'); + valid('bnb1hcqaqelrpd30cvdrwamxw3g2u390qecz0zr9fr', 'binance'); + valid('bnb16hw73zvzmye7x58mqauagf82gd5d3stven24jk', 'binance'); + valid('bnb1xlvns0n2mxh77mzaspn2hgav4rr4m8eerfju38', 'binance'); + valid('bnb16hw73zvzmye7x58mqauagf82gd5d3stven24jk', 'bnb'); + }); + + it('should return false for incorrect binance address', function () { + invalid('lol1qfmufc2q30cgw82ykjlpfeyauhcf5mad6p5y8t', 'binance'); + }); + + it('should return true for correct binance smart chain address', function () { + valid('0x7ae2f5b9e386cd1b50a4550696d957cb4900f03a', 'bsc'); + valid('0x0000000000000000000000000000000000001000', 'Binance Smart Chain'); + }); + + it('should return false for incorrect binance smart chain address', function () { + invalid('bnb1xlvns0n2mxh77mzaspn2hgav4rr4m8eerfju38', 'bsc'); + }); + + it('should return true for correct xtz(tezos) address', function () { + valid('tz1Lhf4J9Qxoe3DZ2nfe8FGDnvVj7oKjnMY6', 'xtz'); + valid('tz1PyxsQ7xVTa5J7gtBeT7pST5Zi5nk5GSjg', 'xtz'); + valid('tz1LcuQHNVQEWP2fZjk1QYZGNrfLDwrT3SyZ', 'xtz'); + valid('tz1Lhf4J9Qxoe3DZ2nfe8FGDnvVj7oKjnMY6', 'xtz'); + valid('tz1RR6wETy9BeXG3Fjk25YmkSMGHxTtKkhpX', 'xtz'); + valid('tz1h3rQ8wBxFd8L9B3d7Jhaawu6Z568XU3xY', 'xtz'); + valid('KT1EM2LvxxFGB3Svh9p9HCP2jEEYyHjABMbK', 'xtz'); + }); + + it('should match the expected xtz(tezor) address type', function () { + isValidAddressType( + 'tz1Lhf4J9Qxoe3DZ2nfe8FGDnvVj7oKjnMY6', + 'xtz', + 'prod', + addressType.ADDRESS, + ); + isValidAddressType('tz1RR6wy9BeXG3Fjk25YmkSMGHxTtKkhpX', 'xtz', 'prod', undefined); + }); + + it('should return true for correct eos addresses', function () { + valid('bittrexacct1', 'eos'); + valid('binancecleos', 'eos'); + valid('123456789012', 'eos'); + }); + + it('should return true for incorrect eos addresses', function () { + invalid('shitcoin', 'eos'); + }); + + it('should match the expected EOS address type', function () { + isValidAddressType('bittrexacct1', 'EOS', 'prod', addressType.ADDRESS); + isValidAddressType('shitcoin', 'EOS', 'prod', undefined); + }); + }); + + describe('invalid results', function () { + function commonTests(currency) { + invalid('', currency); //reject blank + invalid('%%@', currency); //reject invalid base58 string + invalid('1A1zP1ePQGefi2DMPTifTL5SLmv7DivfNa', currency); //reject invalid address + invalid('bd839e4f6fadb293ba580df5dea7814399989983', currency); //reject transaction id's + //testnet + invalid('', currency, 'testnet'); //reject blank + invalid('%%@', currency, 'testnet'); //reject invalid base58 string + invalid('1A1zP1ePQGefi2DMPTifTL5SLmv7DivfNa', currency, 'testnet'); //reject invalid address + invalid('bd839e4f6fadb293ba580df5dea7814399989983', currency, 'testnet'); //reject transaction id's + } + + it('should return false for incorrect bitcoin addresses', function () { + commonTests('bitcoin'); + + // testnet in prod and prod in testnet + invalid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'btc'); + invalid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'bitcoin', 'testnet'); + }); + + it('should return false for incorrect bitcoincash addresses', function () { + commonTests('bitcoincash'); + invalid('12KYrjTdVGjFMtaxERSk3gphreJ5US8aUP', 'bitcoincash'); + invalid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'bitcoincash'); + invalid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'BCH'); + invalid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'bch'); + invalid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'bch', 'prod'); + invalid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'bch', 'both'); + invalid('1oNLrsHnBcR6dpaBpwz3LSwutbUNkNSjs', 'bitcoincash'); + invalid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'bitcoincash', 'testnet'); + invalid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'bitcoincash', 'both'); + // p2sh addresses + invalid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'bitcoincash'); + invalid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'bitcoincash', 'testnet'); + // bitcoincash + invalid('bitcoincash:qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyya', 'bch'); + invalid('qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyya', 'bch'); + }); + + it('should return false for incorrect litecoin addresses', function () { + commonTests('litecoin'); + // do not allow old ltc addresses + invalid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'litecoin'); + invalid('vtc1qmzq3erafwvz23yabc9tu45uz2kx3d7esk0rayg', 'litecoin'); + invalid('ltc1qu7wq0evvgnmyyxcc7xhljavc7duu7js7jxhgjl0p390sy4udvtuq7361dl', 'litecoin'); + }); + + it('should return false for incorrect peercoin addresses', function () { + commonTests('peercoin'); + }); + + it('should return false for incorrect dogecoin addresses', function () { + commonTests('dogecoin'); + }); + + it('should return false for incorrect beavercoin addresses', function () { + commonTests('beavercoin'); + }); + + it('should return false for incorrect freicoin addresses', function () { + commonTests('freicoin'); + }); + + it('should return false for incorrect protoshares addresses', function () { + commonTests('protoshares'); + }); + + it('should return false for incorrect megacoin addresses', function () { + commonTests('megacoin'); + }); + + it('should return false for incorrect primecoin addresses', function () { + commonTests('primecoin'); + }); + + it('should return false for incorrect auroracoin addresses', function () { + commonTests('auroracoin'); + }); + + it('should return false for incorrect namecoin addresses', function () { + commonTests('namecoin'); + }); + + it('should return false for incorrect biocoin addresses', function () { + commonTests('biocoin'); + }); + + it('should return false for incorrect garlicoin addresses', function () { + commonTests('garlicoin'); + }); + + it('should return false for incorrect vertcoin addresses', function () { + commonTests('vertcoin'); + invalid('vtc1qmzq3erafwvz23yabc9tu45uz2kx3d7esk0rayg', 'vertcoin'); + invalid('vtc1qhy8eqwqxpyryz4wctus36yl2uu60t0z6ecrvt', 'vertcoin'); + invalid('vtd1qhy8eqwqxpyryz4wctus36yl2uu60t0z6ecrvtc', 'vertcoin'); + }); + + it('should return false for incorrect bitcoingold addresses', function () { + commonTests('bitcoingold'); + }); + + it('should return false for incorrect decred addresses', function () { + commonTests('decred'); + }); + + it('should return false for incorrect gamecredits addresses', function () { + commonTests('game'); + }); + + it('should return false for incorrect monacoin addresses', function () { + commonTests('mona'); + }); + + it('should return false for incorrect solarcoin addresses', function () { + commonTests('slr'); + }); + + it('should return false for incorrect tether addresses', function () { + commonTests('usdt'); + }); + + it('should return false for incorrect expanse addresses', function () { + commonTests('exp'); + }); + + it('should return false for incorrect usdt addresses', function () { + commonTests('usdt'); + }); + + it('should return false for incorrect bankex addresses', function () { + invalid('1SQHtwR5oJRKLfiWQ2APsAd9miUc4k2ez', 'bankex'); + invalid('116CGDLddrZhMrTwhCVJXtXQpxygTT1kHd', 'BKX'); + invalid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'bankex', 'testnet'); + invalid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'BKX', 'testnet'); + }); + + it('should return false for incorrect digibyte addresses', function () { + commonTests('digibyte'); + }); + + it('should return false for incorrect eip55 addresses', function () { + invalid('6xAff4d6793F584a473348EbA058deb8caad77a288', 'ethereum'); + invalid('0x02fcd51aAbB814FfFe17908fbc888A8975D839A5', 'ethereum'); + invalid('0XD1220A0CF47C7B9BE7A2E6BA89F429762E7B9ADB', 'ethereum'); + invalid('aFf4d6793f584a473348ebA058deb8caad77a2885', 'ethereum'); + invalid('0xff4d6793F584a473', 'ethereum'); + + invalid('0x02fcd51aAbB814FfFe17908fbc888A8975D839A5', 'ethereumclassic'); + invalid('0x02fcd51aAbB814FfFe17908fbc888A8975D839A5', 'etherzero'); + invalid('0x02fcd51aAbB814FfFe17908fbc888A8975D839A5', 'callisto'); + }); + + it('should return false for incorrect ripple addresses', function () { + invalid('rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCN', 'ripple'); + invalid('rDTXLQ7ZKZVKz33zJbHjgVShjsBnqMBhMN', 'XRP'); + invalid('6xAff4d6793F584a473348EbA058deb8ca', 'ripple'); + invalid('DJ53hTyLBdZp2wMi5BsCS3rtEL1ioYUkva', 'ripple'); + }); + + it('should return false for incorrect dash addresses', function () { + commonTests('dash'); + }); + + it('should return false for incorrect neo addresses', function () { + commonTests('neo'); + invalid('AR4QmqYENiZAD6oXe7ftm6eDcwtHk7rVTa', 'neo'); + invalid('AKDVzYGLczmykdtRaejgvWeZrvdkVEvQ10', 'NEO'); + }); + + it('should return false for incorrect qtum addresses', function () { + commonTests('qtum'); + invalid('QNPhBbVhDghASxcUh2vHotQUgNeLRFTcfb', 'qtum'); + invalid('QOPhBbVhDghASxcUh2vHotQUgNeLRFTcfa', 'QTUM'); + invalid('qZqqcqCsVtP2U38ABCUnwshHRpefvCa8hX', 'QTUM', 'testnet'); + }); + + it('should return false for incorrect votecoin addresses', function () { + commonTests('votecoin'); + invalid('t1Y9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'votecoin'); + invalid('t3Yz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'VOT'); + invalid('t2YNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'votecoin', 'testnet'); + }); + + it('should return false for incorrect bitcoinz addresses', function () { + commonTests('bitcoinz'); + invalid('t1Y9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'bitcoinz'); + invalid('t3Yz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'BTCZ'); + invalid('t2YNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'bitcoinz', 'testnet'); + }); + + it('should return false for incorrect zclassic addresses', function () { + commonTests('zclassic'); + invalid('t1Y9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'zclassic'); + invalid('t3Yz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'ZCL'); + invalid('t2YNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'zclassic', 'testnet'); + }); + + it('should return false for incorrect hush addresses', function () { + invalid('t1Y9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'hush'); + invalid('t3Yz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'HUSH'); + invalid('t2YNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'hush', 'testnet'); + }); + + it('should return false for incorrect zcash addresses', function () { + commonTests('zcash'); + invalid('t1Y9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'zcash'); + invalid('t3Yz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'ZEC'); + invalid('t2YNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'zcash', 'testnet'); + }); + + it('should return false for incorrect bitcoinprivate addresses', function () { + commonTests('bitcoinprivate'); + invalid('b1Y4XXPFhwMb1SP33yhzn3h9qWXjujkgep4', 'bitcoinprivate'); + //invalid('bx....', 'BTCP'); + //invalid('nx....', 'bitcoinprivate', 'testnet'); + }); + + it('should return false for incorrect snowgem addresses', function () { + commonTests('snowgem'); + invalid('s1Yx7WBkjB4UH6qQjPp6Ysmtr1C1JiTK2Yw', 'snowgem'); + invalid('s3Y27MhkBRt3ha2UuxhjXaYF4DCnttTMnL1', 'SNG'); + invalid('t2YNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'snowgem', 'testnet'); + }); + + it('should return false for incorrect zencash addresses', function () { + commonTests('zencash'); + invalid('znYiGGfYRepxkBjXYvA2kFrXiC351i9ta4z', 'zencash'); + invalid('zsYEdGnZCQ9G86LZFtbynMn1hYTVhn6eYCL', 'ZEN'); + invalid('ztYWMDLWjbruCJxKmmfAZiT6QAQdiv5F291', 'zencash', 'testnet'); + }); + + it('should return false for incorrect komodo addresses', function () { + commonTests('komodo'); + invalid('R9Y5HirAzqDcWrWGiJEL115dpV3QB3hobH', 'komodo'); + invalid('RAYj2KKVUohTu3hVdNJ4U6hQi7TNawpacH', 'KMD'); + //invalid('t2YNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'komodo', 'testnet'); + }); + + it('should return false for incorrect cardano addresses', function () { + commonTests('cardano'); + invalid('Ae2tdPwUPEYxYNJw1He1esdZYvjmr4NtPzUsGTiqL9zd8ohjZYQcwu6lom7', 'cardano'); + invalid( + 'DdzFFzCqrhsfdzUZxvuBkhV8Lpm9p43p9ubh79GCTkxJikAjKh51qhtCFMqUniC5tv5ZExyvSmAte2Du2tGimavSo6qSgXbjiy8qZRTg1', + 'cardano', + ); + invalid( + 'DdzFFzCqrhsfdzUZxvuBkhV8Lpm9p43p9ubh79GCTkxJikAjKh51qhtCFMqUniC5tv5ZExyvSmAte2Du2tGimavSo6qSgXbjiy8qZRT', + 'ada', + ); + invalid( + 'ADDR1qXNV5U3VRX2T37H3U27QD5UKGCJMRL4F8MU9F5SZA3H20CXSFJH80UN9KVLGGFCDW8FP5KQP9TZTQNEE9MSD0QSAFHDSYQCLVK', + 'cardano', + ); + invalid( + 'addr1qxnv5u3vrx2t37h3u27qd5ukgcjmrl4f8mu9f5sza3h20cxsfjh80un9kvlggfcdw8fp5kqp9tztqnee9msd0qsafhdsyqclvl', + 'cardano', + ); + //invalid('t2YNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'komodo', 'testnet'); + }); + + it('should return false for incorrect monero addresses', function () { + commonTests('monero'); + invalid( + '4AWygwA3hHNE4e4Yr9PtRWJiorXTjZkCi57g4ExYzfXDFFQ8DRFEFyui1dLqVknpqQjGUBdTMbgaFAZaDbrVHdk3GAKBZ3E', + 'monero', + ); + invalid( + '44643dtxcxjgMWEQLo6mh1c4d9Zxx9GbgK9hEj9iGSiFEryCkbwHyJ3JqxZJRqeC3Hb7ZBLKq5NkaJwR1x95EYnR1bTgN6d', + 'xmr', + ); + invalid( + 'A17N9ztrxjQD3v3JJtHGvHVnq6BAbujDNEuensB6PFwBYFpkjAicih8hDtX76HBuEag5NeaCuMZmRMe6eE5NMRGxFTQn8nJ', + 'monero', + 'testnet', + ); + + //integrated + invalid( + '4LNSCKNSTPNbJYkyAEgL966eHJHLDHiq1PpwKoiFBybcSqNGYfLBJApC62uQEeGAFxfYEd29uXBBrJFo7DhKqFVNi3GhmN79EtD5dgycYz', + 'monero', + ); + invalid( + '4JpzTwf3i1GeCV76beVr19179oa8j1L8xNSC1bXMtAxxdf4aTTLqubL8EvXfQmUGKt9MMigFtKy91VtoTTSfg1LU7LocPruT6KcGC9RKJV', + 'xmr', + ); + }); + + it('should return false for incorrect waves addresses', function () { + commonTests('waves'); + invalid('3P93mVrYnQ4ahaRMYwA2BeWY32eDxTpLVEs1', 'waves'); + invalid('3P4eeU7v1LMHQFwwT2GW9W99c6vZyytHaj', 'waves'); + invalid('2P93mVrYnQ4ahaRMYwA2BeWY32eDxTpLVEs', 'waves'); + + invalid('3Myrq5QDgRq3nBVRSSv9UYRP36xTtpJND5y', 'waves', 'testnet'); + invalid('3My3KZgFQ3CrVHgz6vGRt8787sH4oAA1qp8', 'waves', 'testnet'); + }); + + it('should return true for incorrect nano addresses', function () { + valid('nano_1fnrrsrsifdpnkxrwwtfpjx5etcwt7a8hrz6fuqkh6w5i9jdsmo4yjg66iu7', 'nano'); + }); + + 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'); + }); + + it('should match the expected NANO address type', function () { + isValidAddressType( + 'nano_1fnrrsrsifdpnkxrwwtfpjx5etcwt7a8hrz6fuqkh6w5i9jdsmo4yjg66iu7', + 'NANO', + 'prod', + addressType.ADDRESS, + ); + isValidAddressType( + 'xrb_1111111112111111111111111111111111111111111111111111hifc8npp', + 'NANO', + 'prod', + undefined, + ); + }); + + it('should return false for incorrect siacoin addresses', function () { + commonTests('siacoin'); + invalid( + 'ffe1308c044ade30392a0cdc1fd5a4dbe94f9616a95faf888ed36123d9e711557aa497530372', + 'siacoin', + ); + }); + + it('should return false for incorrect lbry addresses', function () { + commonTests('lbc'); + invalid( + 'ffe1308c044ade30392a0cdc1fd5a4dbe94f9616a95faf888ed36123d9e711557aa497530372', + 'lbc', + ); + }); + + it('should return true for correct tron addresses', function () { + valid('TNXoiAJ3dct8Fjg4M9fkLFh9S2v9TXc32G', 'trx'); + }); + + it('should return false for incorrect tron addresses', function () { + commonTests('trx'); + invalid('xrb_1111111112111111111111111111111111111111111111111111hifc8npp', 'trx'); + invalid('TNDzfERDpxLDS2w1q6yaFC7pzqaSQ3Bg31', 'trx'); + }); + + it('should match the expected tron address type', function () { + isValidAddressType( + 'TNXoiAJ3dct8Fjg4M9fkLFh9S2v9TXc32G', + 'tron', + 'prod', + addressType.ADDRESS, + ); + isValidAddressType('TNDzfERDpxLDS2w1q6yaFC7pzqaSQ3Bg31', 'tron', 'prod', undefined); + }); + + it('should return false for incorrect nem addresses', function () { + commonTests('nem'); + invalid('xrb_1111111112111111111111111111111111111111111111111111hifc8npp', 'nem'); + invalid('TNDzfERDpxLDS2w1q6yaFC7pzqaSQ3Bg31', 'nem'); + + invalid('3Myrq5QDgRq3nBVRSSv9UYRP36xTtpJND5y', 'nem', 'testnet'); + invalid('3My3KZgFQ3CrVHgz6vGRt8787sH4oAA1qp8', 'nem', 'testnet'); + }); + //15823701926930889868L + it('should return false for incorrect lsk addresses', function () { + commonTests('lsk'); + invalid('xrb_1111111112111111111111111111111111111111111111111111hifc8npp', 'lsk'); + invalid('TNDzfERDpxLDS2w1q6yaFC7pzqaSQ3Bg31', 'lsk'); + + invalid('158237019269308898689L', 'lsk'); + invalid('158237A192B930C898689L', 'lsk'); + }); + + it('should return false for incorrect bsv addresses', function () { + commonTests('bsv'); + invalid('xrb_1111111112111111111111111111111111111111111111111111hifc8npp', 'bsv'); + invalid('TNDzfERDpxLDS2w1q6yaFC7pzqaSQ3Bg31', 'bsv'); + + invalid('158237019269308898689L', 'bsv'); + invalid('158237A192B930C898689L', 'bsv'); + invalid('bitcoin:qzpuefrpg3kl2ykQe52rxn96pd3Kp4qudywr5pyrsf', 'bsv'); + invalid('pzuefrpg3kl2ykqe52rxn96pd3kp4qudywr5py', 'bsv'); + invalid('rlt2c2wuxr644encp3as0hygtj9djrsaumku3cex5', 'bsv'); + invalid('qra607y4wnkmnpy3wcmrxmltzkrxywcq85c7watpdx09', 'bsv'); + }); + + it('should return false for incorrect stellar addresses', function () { + commonTests('stellar'); + invalid('SBGWKM3CD4IL47QN6X54N6Y33T3JDNVI6AIJ6CD5IM47HG3IG4O36XCU', 'stellar'); + invalid('GBPXX0A5N4JYPESHAADMQKBPWZWQDQ64ZV6ZL2S3LAGW4SY7NTCMWIVL', 'stellar'); + invalid('GCFZB6L25D26RQFDWSSBDEYQ32JHLRMTT44ZYE3DZQUTYOL7WY43PLBG++', 'stellar'); + invalid('GADE5QJ2TY7S5ZB65Q43DFGWYWCPHIYDJ2326KZGAGBN7AE5UY6JVDRRA', 'stellar'); + invalid('GB6OWYST45X57HCJY5XWOHDEBULB6XUROWPIKW77L5DSNANBEQGUPADT2', 'stellar'); + invalid('GB6OWYST45X57HCJY5XWOHDEBULB6XUROWPIKW77L5DSNANBEQGUPADT2T', 'stellar'); + invalid('GDXIIZTKTLVYCBHURXL2UPMTYXOVNI7BRAEFQCP6EZCY4JLKY4VKFNLT', 'stellar'); + invalid('SAB5556L5AN5KSR5WF7UOEFDCIODEWEO7H2UR4S5R62DFTQOGLKOVZDY', 'stellar'); + invalid('gWRYUerEKuz53tstxEuR3NCkiQDcV4wzFHmvLnZmj7PUqxW2wt', 'stellar'); + invalid('g4VPBPrHZkfE8CsjuG2S4yBQNd455UWmk', 'stellar'); + }); + + it('should return false for incorrect binance addresses', function () { + commonTests('binance'); + commonTests('bnb'); + invalid('xrb_1f5e4w33ndqbkx4bw5jtp13kp5xghebfxcmw9hdt1f7goid1s4373w6tjdgu', 'bnb'); + invalid('nano_1f5e4w33ndqbkx4bw5jtp13kp5xghebfxcmw9hdt1f7goid1s4373w6tjdgu', 'bnb'); + invalid('xrb_1111111112111111111111111111111111111111111111111111hifc8npp', 'bnb'); + invalid('nano_111111111111111111111111111111111111111111111111111hifc8npp', 'bnb'); + }); + + it('should return false for incorrect xtz(tezos) address', function () { + commonTests('xtz'); + invalid('SBGWKM3CD4IL47QN6X54N6Y33T3JDNVI6AIJ6CD5IM47HG3IG4O36XCU', 'xtz'); + invalid('GBPXX0A5N4JYPESHAADMQKBPWZWQDQ64ZV6ZL2S3LAGW4SY7NTCMWIVL', 'xtz'); + invalid('GCFZB6L25D26RQFDWSSBDEYQ32JHLRMTT44ZYE3DZQUTYOL7WY43PLBG', 'xtz'); + invalid('tz1RR6wy9BeXG3Fjk25YmkSMGHxTtKkhpX', 'xtz'); + invalid('tz1h3rQ8wBxFd8L9B3d7JhaPQawu6Z568XU3xY', 'xtz'); + invalid('tz1Lhf4J9Qxoe4DZ2nfe8FGDnvVj7oKjnMY6', 'xtz'); + invalid('KT1E2LvxxFGB3Svh9p9HCP2jEEYyHjABMbK', 'xtz'); + }); + + it('should return false for incorrect eos addresses', function () { + commonTests('eos'); + invalid('1234567890123', 'eos'); + invalid('12345678901', 'eos'); + invalid('12345678901@', 'eos'); + }); + + it('should return true for correct groestlcoin addresses', function () { + valid('Foa6yZoKq2r4t3tUFKFcfoXSQjSodZsGx1', 'groestlcoin'); + valid('Fr2Z1bLzqRZByt2WeZwWnpCkA1eBYv83wZ', 'groestlcoin'); + valid('Fr2Z1bLzqRZByt2WeZwWnpCkA1eBYv83wZ', 'GRS'); + valid('Fr2Z1bLzqRZByt2WeZwWnpCkA1eBYv83wZ', 'Groestlcoin'); + valid('Fr2Z1bLzqRZByt2WeZwWnpCkA1eBYv83wZ', 'grs'); + valid('Fr2Z1bLzqRZByt2WeZwWnpCkA1eBYv83wZ', 'grs', 'prod'); + valid('Fr2Z1bLzqRZByt2WeZwWnpCkA1eBYv83wZ', 'grs', 'both'); + valid('FpM19fiGQNjNcaRjFaXVX6Nrewr4gnuuMZ', 'grs', 'prod'); + valid('3FyVFsEyyBPzHjD3qUEgX7Jsn4tcJWiqeN', 'grs', 'prod'); + valid('38mKdURe1zcQyrFqRLzR8PRao3iLFU5hwU', 'grs', 'prod'); + valid('mptPo5AvLzJXi4T82vR6g82fT5uJ9cgfsV', 'grs', 'both'); + valid('FdWcvgskHoXUTqeQRAiuGuh5KQ2EoXv5iM', 'groestlcoin'); + valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWq3SbMQT', 'groestlcoin', 'testnet'); + valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWq3SbMQT', 'groestlcoin', 'both'); + + // p2sh addresses + valid('3NJZLcZEEYBpxYEUGewU4knsQRn1T2Htk2', 'groestlcoin'); + valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfZDahUf', 'groestlcoin', 'testnet'); + + // segwit addresses + valid('grs1q49qls5kklryt95g5xx4p6msycpgjp8ramfc9jq', 'grs'); + valid('grs1qnxt8adg4qk3ljl0qhvp4m0nt56w6ma77vwr2jq', 'grs'); + valid('tgrs1qw4z3xrtgx4f6w7akwpp2xa0gupmkv4yauemmm9', 'grs', 'testnet'); + + invalid('grs1q49qls5kklryt95g5xq4p6msycpgjp8ramfc9jq', 'grs'), + invalid('tgrs1qqjd3qhncsxdyh5gt7hz4k6zzvfguslwxwgv23j', 'grs'); + }); + }); +}); diff --git a/packages/address-validator/tsconfig.json b/packages/address-validator/tsconfig.json new file mode 100644 index 000000000000..c7ebe855e214 --- /dev/null +++ b/packages/address-validator/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { "outDir": "libDev" }, + "references": [] +} diff --git a/packages/suite/package.json b/packages/suite/package.json index 8fd8981024f1..46096603cd68 100644 --- a/packages/suite/package.json +++ b/packages/suite/package.json @@ -55,6 +55,7 @@ "@suite-common/wallet-core": "workspace:*", "@suite-common/wallet-types": "workspace:*", "@suite-common/wallet-utils": "workspace:*", + "@trezor/address-validator": "workspace:*", "@trezor/analytics": "workspace:*", "@trezor/blockchain-link": "workspace:*", "@trezor/blockchain-link-types": "workspace:*", @@ -112,7 +113,6 @@ "redux-thunk": "^2.4.2", "semver": "^7.6.0", "styled-components": "^6.1.8", - "trezor-address-validator": "^0.4.4", "uuid": "^9.0.1", "web3-utils": "^4.2.3", "zxcvbn": "^4.4.2" diff --git a/packages/suite/src/views/wallet/coinmarket/exchange/offers/Offers/SelectedOffer/components/VerifyAddress/index.tsx b/packages/suite/src/views/wallet/coinmarket/exchange/offers/Offers/SelectedOffer/components/VerifyAddress/index.tsx index fb149a3359e3..0eb52129244e 100644 --- a/packages/suite/src/views/wallet/coinmarket/exchange/offers/Offers/SelectedOffer/components/VerifyAddress/index.tsx +++ b/packages/suite/src/views/wallet/coinmarket/exchange/offers/Offers/SelectedOffer/components/VerifyAddress/index.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; import styled from 'styled-components'; import { useForm } from 'react-hook-form'; -import addressValidator from 'trezor-address-validator'; +import addressValidator from '@trezor/address-validator'; import { QuestionTooltip, Translation } from 'src/components/suite'; import { Input, variables, Button } from '@trezor/components'; diff --git a/packages/suite/tsconfig.json b/packages/suite/tsconfig.json index 922574e59f8d..80c01341e1db 100644 --- a/packages/suite/tsconfig.json +++ b/packages/suite/tsconfig.json @@ -83,6 +83,7 @@ { "path": "../../suite-common/wallet-utils" }, + { "path": "../address-validator" }, { "path": "../analytics" }, { "path": "../blockchain-link" }, { "path": "../blockchain-link-types" }, diff --git a/suite-common/wallet-utils/package.json b/suite-common/wallet-utils/package.json index ff917709746a..5377245fd551 100644 --- a/suite-common/wallet-utils/package.json +++ b/suite-common/wallet-utils/package.json @@ -26,6 +26,7 @@ "@suite-common/wallet-config": "workspace:*", "@suite-common/wallet-constants": "workspace:*", "@suite-common/wallet-types": "workspace:*", + "@trezor/address-validator": "workspace:*", "@trezor/blockchain-link": "workspace:*", "@trezor/blockchain-link-types": "workspace:*", "@trezor/blockchain-link-utils": "workspace:*", @@ -35,7 +36,6 @@ "date-fns": "^2.30.0", "react": "18.2.0", "react-hook-form": "^7.50.1", - "trezor-address-validator": "^0.4.4", "web3-utils": "^4.2.3" } } diff --git a/suite-common/wallet-utils/src/validationUtils.ts b/suite-common/wallet-utils/src/validationUtils.ts index fc8a252dc4a6..5d5df5f59eb2 100644 --- a/suite-common/wallet-utils/src/validationUtils.ts +++ b/suite-common/wallet-utils/src/validationUtils.ts @@ -1,5 +1,4 @@ -import addressValidator from 'trezor-address-validator'; - +import addressValidator from '@trezor/address-validator'; import { getTestnetSymbols } from '@suite-common/wallet-config'; import { Account } from '@suite-common/wallet-types'; diff --git a/suite-common/wallet-utils/tsconfig.json b/suite-common/wallet-utils/tsconfig.json index 0981b04e3d36..29c9510e548c 100644 --- a/suite-common/wallet-utils/tsconfig.json +++ b/suite-common/wallet-utils/tsconfig.json @@ -13,6 +13,9 @@ { "path": "../wallet-config" }, { "path": "../wallet-constants" }, { "path": "../wallet-types" }, + { + "path": "../../packages/address-validator" + }, { "path": "../../packages/blockchain-link" }, diff --git a/tsconfig.json b/tsconfig.json index 64f885eefe45..3f60c2ad732e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -113,6 +113,7 @@ { "path": "suite-native/toasts" }, { "path": "suite-native/transactions" }, { "path": "suite-native/video-assets" }, + { "path": "packages/address-validator" }, { "path": "packages/analytics" }, { "path": "packages/auth-server" }, { "path": "packages/blockchain-link" }, diff --git a/yarn.lock b/yarn.lock index ef9b948b7a3b..7576e8dde37c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26,7 +26,7 @@ __metadata: languageName: node linkType: hard -"@ampproject/remapping@npm:^2.1.0, @ampproject/remapping@npm:^2.2.0": +"@ampproject/remapping@npm:^2.1.0": version: 2.2.1 resolution: "@ampproject/remapping@npm:2.2.1" dependencies: @@ -36,6 +36,16 @@ __metadata: languageName: node linkType: hard +"@ampproject/remapping@npm:^2.2.0": + version: 2.2.0 + resolution: "@ampproject/remapping@npm:2.2.0" + dependencies: + "@jridgewell/gen-mapping": "npm:^0.1.0" + "@jridgewell/trace-mapping": "npm:^0.3.9" + checksum: 10/503a58d6e9d645a20debd34fa8df79fb435a79a34b1d487b9ff0be9f20712b1594ce21da16b63af7db8a6b34472212572e53a55613a5a6b3134b23fc74843d04 + languageName: node + linkType: hard + "@aptos-labs/aptos-client@npm:^0.1.0": version: 0.1.0 resolution: "@aptos-labs/aptos-client@npm:0.1.0" @@ -104,7 +114,16 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.18.6, @babel/code-frame@npm:^7.21.4, @babel/code-frame@npm:^7.23.5": +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.7": + version: 7.22.5 + resolution: "@babel/code-frame@npm:7.22.5" + dependencies: + "@babel/highlight": "npm:^7.22.5" + checksum: 10/b1ac7de75859699a9118c5247f489cc943d8d041339323904cd8140592993762f50abc14bc49b6703cb8a94b1aa90d6df2599625825e7ae470c9283b4a6170aa + languageName: node + linkType: hard + +"@babel/code-frame@npm:^7.18.6": version: 7.24.2 resolution: "@babel/code-frame@npm:7.24.2" dependencies: @@ -114,6 +133,16 @@ __metadata: languageName: node linkType: hard +"@babel/code-frame@npm:^7.21.4, @babel/code-frame@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/code-frame@npm:7.23.5" + dependencies: + "@babel/highlight": "npm:^7.23.4" + chalk: "npm:^2.4.2" + checksum: 10/44e58529c9d93083288dc9e649c553c5ba997475a7b0758cc3ddc4d77b8a7d985dbe78cc39c9bbc61f26d50af6da1ddf0a3427eae8cc222a9370619b671ed8f5 + languageName: node + linkType: hard + "@babel/compat-data@npm:^7.20.5, @babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.23.3, @babel/compat-data@npm:^7.23.5": version: 7.23.5 resolution: "@babel/compat-data@npm:7.23.5" @@ -240,7 +269,20 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.22.15, @babel/helper-create-regexp-features-plugin@npm:^7.22.5": +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.22.5" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.22.5" + regexpu-core: "npm:^5.3.1" + semver: "npm:^6.3.0" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/a6c2583918a0b4b66f23a7209ea9f430fc346360376684788c08c13fb31a1a55be6d0f1acd597f2689831045d31aadaee6e45e1f18d819b9088e900928512581 + languageName: node + linkType: hard + +"@babel/helper-create-regexp-features-plugin@npm:^7.22.15": version: 7.22.15 resolution: "@babel/helper-create-regexp-features-plugin@npm:7.22.15" dependencies: @@ -268,7 +310,14 @@ __metadata: languageName: node linkType: hard -"@babel/helper-environment-visitor@npm:^7.18.9, @babel/helper-environment-visitor@npm:^7.22.20": +"@babel/helper-environment-visitor@npm:^7.18.9": + version: 7.22.5 + resolution: "@babel/helper-environment-visitor@npm:7.22.5" + checksum: 10/248532077d732a34cd0844eb7b078ff917c3a8ec81a7f133593f71a860a582f05b60f818dc5049c2212e5baa12289c27889a4b81d56ef409b4863db49646c4b1 + languageName: node + linkType: hard + +"@babel/helper-environment-visitor@npm:^7.22.20": version: 7.22.20 resolution: "@babel/helper-environment-visitor@npm:7.22.20" checksum: 10/d80ee98ff66f41e233f36ca1921774c37e88a803b2f7dca3db7c057a5fea0473804db9fb6729e5dbfd07f4bed722d60f7852035c2c739382e84c335661590b69 @@ -410,6 +459,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-identifier@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-validator-identifier@npm:7.22.5" + checksum: 10/12cb7d4535b3f8d109a446f7bef08d20eebe94fd97b534cd415c936ab342e9634edc5c99961af976bd78bcae6e6ec4b2ab8483d0da2ac5926fbe9f7dd9ab28ab + languageName: node + linkType: hard + "@babel/helper-validator-option@npm:^7.22.15, @babel/helper-validator-option@npm:^7.23.5": version: 7.23.5 resolution: "@babel/helper-validator-option@npm:7.23.5" @@ -451,6 +507,28 @@ __metadata: languageName: node linkType: hard +"@babel/highlight@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/highlight@npm:7.22.5" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.22.5" + chalk: "npm:^2.0.0" + js-tokens: "npm:^4.0.0" + checksum: 10/ff59305c0184648c9cb042638e9d2d184c12df2a112c71359268a982e7ab65cd5236f392ee8eb722a3bf5b5bd155954fdc7b5aacb6b2b1cd5e38dafcbe63cc57 + languageName: node + linkType: hard + +"@babel/highlight@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/highlight@npm:7.23.4" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.22.20" + chalk: "npm:^2.4.2" + js-tokens: "npm:^4.0.0" + checksum: 10/62fef9b5bcea7131df4626d009029b1ae85332042f4648a4ce6e740c3fd23112603c740c45575caec62f260c96b11054d3be5987f4981a5479793579c3aac71f + languageName: node + linkType: hard + "@babel/node@npm:^7.23.9": version: 7.23.9 resolution: "@babel/node@npm:7.23.9" @@ -1795,7 +1873,34 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.17.2, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.20.0, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.4, @babel/runtime@npm:^7.23.5, @babel/runtime@npm:^7.23.8, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.0, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": + version: 7.22.6 + resolution: "@babel/runtime@npm:7.22.6" + dependencies: + regenerator-runtime: "npm:^0.13.11" + checksum: 10/1d2f56797f548b009910bddf3dc04f980a9701193233145dc923f3ea87c8f88121a3c3ef1d449e9cb52a370d7d025a2243c748882d5546ff079ddf5ffe29f240 + languageName: node + linkType: hard + +"@babel/runtime@npm:^7.17.2, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.4, @babel/runtime@npm:^7.23.8, @babel/runtime@npm:^7.23.9": + version: 7.24.0 + resolution: "@babel/runtime@npm:7.24.0" + dependencies: + regenerator-runtime: "npm:^0.14.0" + checksum: 10/8d32c7e116606ea322b89f9fde8ffae6be9503b549dc0d0abb38bd9dc26e87469b9fb7a66964cc089ee558fd0a97d304fb0a3cfec140694764fb0d71b6a6f5e4 + languageName: node + linkType: hard + +"@babel/runtime@npm:^7.18.6": + version: 7.24.4 + resolution: "@babel/runtime@npm:7.24.4" + dependencies: + regenerator-runtime: "npm:^0.14.0" + checksum: 10/8ec8ce2c145bc7e31dd39ab66df124f357f65c11489aefacb30f431bae913b9aaa66aa5efe5321ea2bf8878af3fcee338c87e7599519a952e3a6f83aa1b03308 + languageName: node + linkType: hard + +"@babel/runtime@npm:^7.23.5": version: 7.24.6 resolution: "@babel/runtime@npm:7.24.6" dependencies: @@ -3808,7 +3913,18 @@ __metadata: languageName: node linkType: hard -"@expo/json-file@npm:^8.2.37, @expo/json-file@npm:^8.3.0, @expo/json-file@npm:~8.3.0": +"@expo/json-file@npm:^8.2.37, @expo/json-file@npm:~8.3.0": + version: 8.3.0 + resolution: "@expo/json-file@npm:8.3.0" + dependencies: + "@babel/code-frame": "npm:~7.10.4" + json5: "npm:^2.2.2" + write-file-atomic: "npm:^2.3.0" + checksum: 10/f2b12862f45ce6a47dbea8b93363fcc4eeaa7fc3d280955db7d0780475afaa9407fc208c357d9b3d0f7811c7a8ed3051e693ad408603450e93313407e16f62e4 + languageName: node + linkType: hard + +"@expo/json-file@npm:^8.3.0": version: 8.3.3 resolution: "@expo/json-file@npm:8.3.3" dependencies: @@ -4524,6 +4640,15 @@ __metadata: languageName: node linkType: hard +"@jest/schemas@npm:^29.6.0": + version: 29.6.0 + resolution: "@jest/schemas@npm:29.6.0" + dependencies: + "@sinclair/typebox": "npm:^0.27.8" + checksum: 10/c00511c69cf89138a7d974404d3a5060af375b5a52b9c87215d91873129b382ca11c1ff25bd6d605951404bb381ddce5f8091004a61e76457da35db1f5c51365 + languageName: node + linkType: hard + "@jest/schemas@npm:^29.6.3": version: 29.6.3 resolution: "@jest/schemas@npm:29.6.3" @@ -4568,6 +4693,29 @@ __metadata: languageName: node linkType: hard +"@jest/transform@npm:^29.6.2": + version: 29.6.2 + resolution: "@jest/transform@npm:29.6.2" + dependencies: + "@babel/core": "npm:^7.11.6" + "@jest/types": "npm:^29.6.1" + "@jridgewell/trace-mapping": "npm:^0.3.18" + babel-plugin-istanbul: "npm:^6.1.1" + chalk: "npm:^4.0.0" + convert-source-map: "npm:^2.0.0" + fast-json-stable-stringify: "npm:^2.1.0" + graceful-fs: "npm:^4.2.9" + jest-haste-map: "npm:^29.6.2" + jest-regex-util: "npm:^29.4.3" + jest-util: "npm:^29.6.2" + micromatch: "npm:^4.0.4" + pirates: "npm:^4.0.4" + slash: "npm:^3.0.0" + write-file-atomic: "npm:^4.0.2" + checksum: 10/ab1759672e460bdcc2950ab6fcc2509b40c87d022164492363553ebb5efb0ce67a1721c0aaf5dd00370d20771cb234360bd03635d72354b0fd3e959355becbd7 + languageName: node + linkType: hard + "@jest/transform@npm:^29.7.0": version: 29.7.0 resolution: "@jest/transform@npm:29.7.0" @@ -4618,6 +4766,16 @@ __metadata: languageName: node linkType: hard +"@jridgewell/gen-mapping@npm:^0.1.0": + version: 0.1.1 + resolution: "@jridgewell/gen-mapping@npm:0.1.1" + dependencies: + "@jridgewell/set-array": "npm:^1.0.0" + "@jridgewell/sourcemap-codec": "npm:^1.4.10" + checksum: 10/ba76fae1d8ea52b181474518c705a8eac36405dfc836fb07e9c25730a84d29e05fd6d954f121057742639f3128a24ea45d205c9c989efd464d1114671c19fa6c + languageName: node + linkType: hard + "@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2": version: 0.3.2 resolution: "@jridgewell/gen-mapping@npm:0.3.2" @@ -4636,13 +4794,23 @@ __metadata: languageName: node linkType: hard -"@jridgewell/set-array@npm:^1.0.1": +"@jridgewell/set-array@npm:^1.0.0, @jridgewell/set-array@npm:^1.0.1": version: 1.1.2 resolution: "@jridgewell/set-array@npm:1.1.2" checksum: 10/69a84d5980385f396ff60a175f7177af0b8da4ddb81824cb7016a9ef914eee9806c72b6b65942003c63f7983d4f39a5c6c27185bbca88eb4690b62075602e28e languageName: node linkType: hard +"@jridgewell/source-map@npm:^0.3.2": + version: 0.3.2 + resolution: "@jridgewell/source-map@npm:0.3.2" + dependencies: + "@jridgewell/gen-mapping": "npm:^0.3.0" + "@jridgewell/trace-mapping": "npm:^0.3.9" + checksum: 10/1aaa42075bac32a551708025da0c07b11c11fb05ccd10fb70df2cb0db88773338ab0f33f175d9865379cb855bb3b1cda478367747a1087309fda40a7b9214bfa + languageName: node + linkType: hard + "@jridgewell/source-map@npm:^0.3.3": version: 0.3.5 resolution: "@jridgewell/source-map@npm:0.3.5" @@ -7194,13 +7362,20 @@ __metadata: languageName: node linkType: hard -"@scure/base@npm:^1.1.3, @scure/base@npm:~1.1.0, @scure/base@npm:~1.1.4": +"@scure/base@npm:^1.1.3, @scure/base@npm:~1.1.4": version: 1.1.5 resolution: "@scure/base@npm:1.1.5" checksum: 10/543fa9991c6378b6a0d5ab7f1e27b30bb9c1e860d3ac81119b4213cfdf0ad7b61be004e06506e89de7ce0cec9391c17f5c082bb34c3b617a2ee6a04129f52481 languageName: node linkType: hard +"@scure/base@npm:~1.1.0": + version: 1.1.1 + resolution: "@scure/base@npm:1.1.1" + checksum: 10/9aaa525ac25215cbe1bde00733a2fd25e99f03793aa1fd2961c567bb62b60c8a3a485a7cb5d748c41604fca79d149de19b05e64449b770c0a04b9ae38d0b5b2b + languageName: node + linkType: hard + "@scure/bip32@npm:1.3.3, @scure/bip32@npm:^1.3.1": version: 1.3.3 resolution: "@scure/bip32@npm:1.3.3" @@ -7353,6 +7528,13 @@ __metadata: languageName: node linkType: hard +"@sentry/cli-darwin@npm:2.27.0": + version: 2.27.0 + resolution: "@sentry/cli-darwin@npm:2.27.0" + conditions: os=darwin + languageName: node + linkType: hard + "@sentry/cli-darwin@npm:2.30.4": version: 2.30.4 resolution: "@sentry/cli-darwin@npm:2.30.4" @@ -7360,6 +7542,13 @@ __metadata: languageName: node linkType: hard +"@sentry/cli-linux-arm64@npm:2.27.0": + version: 2.27.0 + resolution: "@sentry/cli-linux-arm64@npm:2.27.0" + conditions: (os=linux | os=freebsd) & cpu=arm64 + languageName: node + linkType: hard + "@sentry/cli-linux-arm64@npm:2.30.4": version: 2.30.4 resolution: "@sentry/cli-linux-arm64@npm:2.30.4" @@ -7367,6 +7556,13 @@ __metadata: languageName: node linkType: hard +"@sentry/cli-linux-arm@npm:2.27.0": + version: 2.27.0 + resolution: "@sentry/cli-linux-arm@npm:2.27.0" + conditions: (os=linux | os=freebsd) & cpu=arm + languageName: node + linkType: hard + "@sentry/cli-linux-arm@npm:2.30.4": version: 2.30.4 resolution: "@sentry/cli-linux-arm@npm:2.30.4" @@ -7374,6 +7570,13 @@ __metadata: languageName: node linkType: hard +"@sentry/cli-linux-i686@npm:2.27.0": + version: 2.27.0 + resolution: "@sentry/cli-linux-i686@npm:2.27.0" + conditions: (os=linux | os=freebsd) & (cpu=x86 | cpu=ia32) + languageName: node + linkType: hard + "@sentry/cli-linux-i686@npm:2.30.4": version: 2.30.4 resolution: "@sentry/cli-linux-i686@npm:2.30.4" @@ -7381,6 +7584,13 @@ __metadata: languageName: node linkType: hard +"@sentry/cli-linux-x64@npm:2.27.0": + version: 2.27.0 + resolution: "@sentry/cli-linux-x64@npm:2.27.0" + conditions: (os=linux | os=freebsd) & cpu=x64 + languageName: node + linkType: hard + "@sentry/cli-linux-x64@npm:2.30.4": version: 2.30.4 resolution: "@sentry/cli-linux-x64@npm:2.30.4" @@ -7388,6 +7598,13 @@ __metadata: languageName: node linkType: hard +"@sentry/cli-win32-i686@npm:2.27.0": + version: 2.27.0 + resolution: "@sentry/cli-win32-i686@npm:2.27.0" + conditions: os=win32 & (cpu=x86 | cpu=ia32) + languageName: node + linkType: hard + "@sentry/cli-win32-i686@npm:2.30.4": version: 2.30.4 resolution: "@sentry/cli-win32-i686@npm:2.30.4" @@ -7395,6 +7612,13 @@ __metadata: languageName: node linkType: hard +"@sentry/cli-win32-x64@npm:2.27.0": + version: 2.27.0 + resolution: "@sentry/cli-win32-x64@npm:2.27.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@sentry/cli-win32-x64@npm:2.30.4": version: 2.30.4 resolution: "@sentry/cli-win32-x64@npm:2.30.4" @@ -7402,7 +7626,7 @@ __metadata: languageName: node linkType: hard -"@sentry/cli@npm:2.30.4, @sentry/cli@npm:^2.22.3": +"@sentry/cli@npm:2.30.4": version: 2.30.4 resolution: "@sentry/cli@npm:2.30.4" dependencies: @@ -7439,6 +7663,43 @@ __metadata: languageName: node linkType: hard +"@sentry/cli@npm:^2.22.3": + version: 2.27.0 + resolution: "@sentry/cli@npm:2.27.0" + dependencies: + "@sentry/cli-darwin": "npm:2.27.0" + "@sentry/cli-linux-arm": "npm:2.27.0" + "@sentry/cli-linux-arm64": "npm:2.27.0" + "@sentry/cli-linux-i686": "npm:2.27.0" + "@sentry/cli-linux-x64": "npm:2.27.0" + "@sentry/cli-win32-i686": "npm:2.27.0" + "@sentry/cli-win32-x64": "npm:2.27.0" + https-proxy-agent: "npm:^5.0.0" + node-fetch: "npm:^2.6.7" + progress: "npm:^2.0.3" + proxy-from-env: "npm:^1.1.0" + which: "npm:^2.0.2" + dependenciesMeta: + "@sentry/cli-darwin": + optional: true + "@sentry/cli-linux-arm": + optional: true + "@sentry/cli-linux-arm64": + optional: true + "@sentry/cli-linux-i686": + optional: true + "@sentry/cli-linux-x64": + optional: true + "@sentry/cli-win32-i686": + optional: true + "@sentry/cli-win32-x64": + optional: true + bin: + sentry-cli: bin/sentry-cli + checksum: 10/7ccebc0866136008161151fc328373480040fd601a7f5f093612a4d4b3587bc047a6aaeae1ad37924289e834065074f5f3fcac21f73d35a74bb901d5f5246248 + languageName: node + linkType: hard + "@sentry/core@npm:7.113.0, @sentry/core@npm:^7.100.1": version: 7.113.0 resolution: "@sentry/core@npm:7.113.0" @@ -7656,7 +7917,7 @@ __metadata: languageName: node linkType: hard -"@sideway/formula@npm:^3.0.1": +"@sideway/formula@npm:^3.0.0, @sideway/formula@npm:^3.0.1": version: 3.0.1 resolution: "@sideway/formula@npm:3.0.1" checksum: 10/8d3ee7f80df4e5204b2cbe92a2a711ca89684965a5c9eb3b316b7051212d3522e332a65a0bb2a07cc708fcd1d0b27fcb30f43ff0bcd5089d7006c7160a89eefe @@ -8921,6 +9182,7 @@ __metadata: "@suite-common/wallet-config": "workspace:*" "@suite-common/wallet-constants": "workspace:*" "@suite-common/wallet-types": "workspace:*" + "@trezor/address-validator": "workspace:*" "@trezor/blockchain-link": "workspace:*" "@trezor/blockchain-link-types": "workspace:*" "@trezor/blockchain-link-utils": "workspace:*" @@ -8930,7 +9192,6 @@ __metadata: date-fns: "npm:^2.30.0" react: "npm:18.2.0" react-hook-form: "npm:^7.50.1" - trezor-address-validator: "npm:^0.4.4" web3-utils: "npm:^4.2.3" languageName: unknown linkType: soft @@ -10381,6 +10642,23 @@ __metadata: languageName: node linkType: hard +"@trezor/address-validator@workspace:*, @trezor/address-validator@workspace:packages/address-validator": + version: 0.0.0-use.local + resolution: "@trezor/address-validator@workspace:packages/address-validator" + dependencies: + base-x: "npm:^3.0.7" + bech32: "npm:^2.0.0" + browserify-bignum: "npm:^1.3.0-2" + cbor-js: "npm:^0.1.0" + crc: "npm:^3.8.0" + groestl-hash-js: "npm:1.0.0" + jest-environment-jsdom: "npm:29.7.0" + jssha: "npm:2.3.1" + lodash: "npm:^4.17.15" + rimraf: "npm:^5.0.5" + languageName: unknown + linkType: soft + "@trezor/analytics@workspace:*, @trezor/analytics@workspace:packages/analytics": version: 0.0.0-use.local resolution: "@trezor/analytics@workspace:packages/analytics" @@ -11309,6 +11587,7 @@ __metadata: "@suite-common/wallet-utils": "workspace:*" "@testing-library/react": "npm:14.2.1" "@testing-library/user-event": "npm:14.5.2" + "@trezor/address-validator": "workspace:*" "@trezor/analytics": "workspace:*" "@trezor/blockchain-link": "workspace:*" "@trezor/blockchain-link-types": "workspace:*" @@ -11390,7 +11669,6 @@ __metadata: styled-components: "npm:^6.1.8" stylelint: "npm:^16.2.1" stylelint-config-standard: "npm:^36.0.0" - trezor-address-validator: "npm:^0.4.4" typescript-styled-plugin: "npm:^0.18.3" uuid: "npm:^9.0.1" web3-utils: "npm:^4.2.3" @@ -12038,7 +12316,14 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:*, @types/estree@npm:1.0.5, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.5": +"@types/estree@npm:*, @types/estree@npm:^1.0.0": + version: 1.0.1 + resolution: "@types/estree@npm:1.0.1" + checksum: 10/f252569c002506c61ad913e778aa69415908078c46c78c901ccad77bc66cd34f1e1b9babefb8ff0d27c07a15fb0824755edd7bb3fa7ea828f32ae0fe5faa9962 + languageName: node + linkType: hard + +"@types/estree@npm:1.0.5, @types/estree@npm:^1.0.5": version: 1.0.5 resolution: "@types/estree@npm:1.0.5" checksum: 10/7de6d928dd4010b0e20c6919e1a6c27b61f8d4567befa89252055fad503d587ecb9a1e3eab1b1901f923964d7019796db810b7fd6430acb26c32866d126fd408 @@ -12325,7 +12610,14 @@ __metadata: languageName: node linkType: hard -"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.11, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.6, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.11, @types/json-schema@npm:^7.0.6, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": + version: 7.0.11 + resolution: "@types/json-schema@npm:7.0.11" + checksum: 10/e50864a93f4dcb9de64c0c605d836f5416341c824d7a8cde1aa15a5fc68bed44b33cdcb2e04e5098339e9121848378f2d0cc5b124dec41c89203c6f67d6f344a + languageName: node + linkType: hard + +"@types/json-schema@npm:^7.0.12": version: 7.0.14 resolution: "@types/json-schema@npm:7.0.14" checksum: 10/84b5efed51984c077f9cb7c5a3dcb8d8288ce1ae8825952b173c3506a0cfc90bc961d7f2a8847c440310d02bbd570cf918ac463d8310b0c9dce2252baa1ba4e0 @@ -13018,13 +13310,20 @@ __metadata: languageName: node linkType: hard -"@types/w3c-web-usb@npm:^1.0.10, @types/w3c-web-usb@npm:^1.0.6": +"@types/w3c-web-usb@npm:^1.0.10": version: 1.0.10 resolution: "@types/w3c-web-usb@npm:1.0.10" checksum: 10/6ac6786a0788f0846a48b103ab06ca5fde5eb95674217b522420a2f6157bee3e181a961c1b7011940f497c55f4f5cc46129657d881fdd8112b48764089679ad6 languageName: node linkType: hard +"@types/w3c-web-usb@npm:^1.0.6": + version: 1.0.6 + resolution: "@types/w3c-web-usb@npm:1.0.6" + checksum: 10/c8cf57876abbd018f145feaecc2f5316bef30e7976b0f0078918a4c26569dba8c934dc2b1e39e187f55069cee757ceff1914561c16bd2bcd5cc3e2ae88f5d58a + languageName: node + linkType: hard + "@types/web@npm:^0.0.138": version: 0.0.138 resolution: "@types/web@npm:0.0.138" @@ -13939,7 +14238,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.0.0, acorn@npm:^8.0.4, acorn@npm:^8.1.0, acorn@npm:^8.10.0, acorn@npm:^8.11.3, acorn@npm:^8.4.1, acorn@npm:^8.7.1, acorn@npm:^8.8.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": +"acorn@npm:^8.0.0, acorn@npm:^8.10.0, acorn@npm:^8.11.3, acorn@npm:^8.8.2, acorn@npm:^8.9.0": version: 8.11.3 resolution: "acorn@npm:8.11.3" bin: @@ -13948,6 +14247,15 @@ __metadata: languageName: node linkType: hard +"acorn@npm:^8.0.4, acorn@npm:^8.1.0, acorn@npm:^8.4.1, acorn@npm:^8.5.0, acorn@npm:^8.7.1, acorn@npm:^8.8.1": + version: 8.8.2 + resolution: "acorn@npm:8.8.2" + bin: + acorn: bin/acorn + checksum: 10/b4e77d56d24d3e11a45d9ac8ae661b4e14a4af04ae33edbf1e6bf910887e5bb352cc60e9ea06a0944880e6b658f58c095d3b54e88e1921cb9319608b51085dd7 + languageName: node + linkType: hard + "address@npm:^1.0.1": version: 1.2.1 resolution: "address@npm:1.2.1" @@ -14847,7 +15155,7 @@ __metadata: languageName: node linkType: hard -"babel-jest@npm:29.7.0, babel-jest@npm:^29.2.1, babel-jest@npm:^29.7.0": +"babel-jest@npm:29.7.0, babel-jest@npm:^29.7.0": version: 29.7.0 resolution: "babel-jest@npm:29.7.0" dependencies: @@ -14864,6 +15172,23 @@ __metadata: languageName: node linkType: hard +"babel-jest@npm:^29.2.1": + version: 29.6.2 + resolution: "babel-jest@npm:29.6.2" + dependencies: + "@jest/transform": "npm:^29.6.2" + "@types/babel__core": "npm:^7.1.14" + babel-plugin-istanbul: "npm:^6.1.1" + babel-preset-jest: "npm:^29.5.0" + chalk: "npm:^4.0.0" + graceful-fs: "npm:^4.2.9" + slash: "npm:^3.0.0" + peerDependencies: + "@babel/core": ^7.8.0 + checksum: 10/d1860f1c0ede72c3c246906e7ded535e25b1f8b4ac39a74e6d555ec7dd5f0ae7541cf0bc172588f9fed4a11a64eed9eda9688d23403577b36a9e97dc609b9b0a + languageName: node + linkType: hard + "babel-loader@npm:^9.0.0, babel-loader@npm:^9.1.3": version: 9.1.3 resolution: "babel-loader@npm:9.1.3" @@ -14897,6 +15222,18 @@ __metadata: languageName: node linkType: hard +"babel-plugin-jest-hoist@npm:^29.5.0": + version: 29.5.0 + resolution: "babel-plugin-jest-hoist@npm:29.5.0" + dependencies: + "@babel/template": "npm:^7.3.3" + "@babel/types": "npm:^7.3.3" + "@types/babel__core": "npm:^7.1.14" + "@types/babel__traverse": "npm:^7.0.6" + checksum: 10/18066c177da855f478178bd2a48fa1c131d31f15c04af8c732bb4c7eb5c952fde8ac9b11133e5ddd5b74aed92c6a833fbfde51cc5dec1f7169bf865b548da680 + languageName: node + linkType: hard + "babel-plugin-jest-hoist@npm:^29.6.3": version: 29.6.3 resolution: "babel-plugin-jest-hoist@npm:29.6.3" @@ -15040,6 +15377,18 @@ __metadata: languageName: node linkType: hard +"babel-preset-jest@npm:^29.5.0": + version: 29.5.0 + resolution: "babel-preset-jest@npm:29.5.0" + dependencies: + babel-plugin-jest-hoist: "npm:^29.5.0" + babel-preset-current-node-syntax: "npm:^1.0.0" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/5566ca2762766c9319b4973d018d2fa08c0fcf6415c72cc54f4c8e7199e851ea8f5e6c6730f03ed7ed44fc8beefa959dd15911f2647dee47c615ff4faeddb1ad + languageName: node + linkType: hard + "babel-preset-jest@npm:^29.6.3": version: 29.6.3 resolution: "babel-preset-jest@npm:29.6.3" @@ -15357,6 +15706,26 @@ __metadata: languageName: node linkType: hard +"body-parser@npm:1.20.1": + version: 1.20.1 + resolution: "body-parser@npm:1.20.1" + dependencies: + bytes: "npm:3.1.2" + content-type: "npm:~1.0.4" + debug: "npm:2.6.9" + depd: "npm:2.0.0" + destroy: "npm:1.2.0" + http-errors: "npm:2.0.0" + iconv-lite: "npm:0.4.24" + on-finished: "npm:2.4.1" + qs: "npm:6.11.0" + raw-body: "npm:2.5.1" + type-is: "npm:~1.6.18" + unpipe: "npm:1.0.0" + checksum: 10/5f8d128022a2fb8b6e7990d30878a0182f300b70e46b3f9d358a9433ad6275f0de46add6d63206da3637c01c3b38b6111a7480f7e7ac2e9f7b989f6133fe5510 + languageName: node + linkType: hard + "body-parser@npm:1.20.2, body-parser@npm:^1.16.0, body-parser@npm:^1.19.0": version: 1.20.2 resolution: "body-parser@npm:1.20.2" @@ -16330,7 +16699,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^2.0.1, chalk@npm:^2.4.1, chalk@npm:^2.4.2": +"chalk@npm:^2.0.0, chalk@npm:^2.0.1, chalk@npm:^2.4.1, chalk@npm:^2.4.2": version: 2.4.2 resolution: "chalk@npm:2.4.2" dependencies: @@ -16472,7 +16841,7 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:^3.3.0, chokidar@npm:^3.4.0, chokidar@npm:^3.5.1, chokidar@npm:^3.5.3": +"chokidar@npm:^3.3.0": version: 3.6.0 resolution: "chokidar@npm:3.6.0" dependencies: @@ -16491,6 +16860,25 @@ __metadata: languageName: node linkType: hard +"chokidar@npm:^3.4.0, chokidar@npm:^3.5.1, chokidar@npm:^3.5.3": + version: 3.5.3 + resolution: "chokidar@npm:3.5.3" + dependencies: + anymatch: "npm:~3.1.2" + braces: "npm:~3.0.2" + fsevents: "npm:~2.3.2" + glob-parent: "npm:~5.1.2" + is-binary-path: "npm:~2.1.0" + is-glob: "npm:~4.0.1" + normalize-path: "npm:~3.0.0" + readdirp: "npm:~3.6.0" + dependenciesMeta: + fsevents: + optional: true + checksum: 10/863e3ff78ee7a4a24513d2a416856e84c8e4f5e60efbe03e8ab791af1a183f569b62fc6f6b8044e2804966cb81277ddbbc1dc374fba3265bd609ea8efd62f5b3 + languageName: node + linkType: hard + "chownr@npm:^1.1.1, chownr@npm:^1.1.4": version: 1.1.4 resolution: "chownr@npm:1.1.4" @@ -17364,6 +17752,13 @@ __metadata: languageName: node linkType: hard +"cookie@npm:0.5.0": + version: 0.5.0 + resolution: "cookie@npm:0.5.0" + checksum: 10/aae7911ddc5f444a9025fbd979ad1b5d60191011339bce48e555cb83343d0f98b865ff5c4d71fecdfb8555a5cafdc65632f6fce172f32aaf6936830a883a0380 + languageName: node + linkType: hard + "cookie@npm:0.6.0, cookie@npm:^0.6.0": version: 0.6.0 resolution: "cookie@npm:0.6.0" @@ -18123,7 +18518,16 @@ __metadata: languageName: node linkType: hard -"d3-array@npm:2 - 3, d3-array@npm:2.10.0 - 3, d3-array@npm:2.5.0 - 3, d3-array@npm:3, d3-array@npm:^3.1.6, d3-array@npm:^3.2.0": +"d3-array@npm:2 - 3, d3-array@npm:2.10.0 - 3, d3-array@npm:^3.1.6": + version: 3.2.2 + resolution: "d3-array@npm:3.2.2" + dependencies: + internmap: "npm:1 - 2" + checksum: 10/e940c7b77e5fbb8520a3b914b8121e668d12b58f1fbd15be83d819802b73da43540422fe66d17feec04e3280255b3aa5fac452f12b7f37f2378531a8bbb233bc + languageName: node + linkType: hard + +"d3-array@npm:2.5.0 - 3, d3-array@npm:3, d3-array@npm:^3.2.0": version: 3.2.4 resolution: "d3-array@npm:3.2.4" dependencies: @@ -18568,7 +18972,14 @@ __metadata: languageName: node linkType: hard -"dayjs@npm:^1.10.4, dayjs@npm:^1.11.7, dayjs@npm:^1.8.15": +"dayjs@npm:^1.10.4, dayjs@npm:^1.8.15": + version: 1.11.5 + resolution: "dayjs@npm:1.11.5" + checksum: 10/cee1c2ed5f74ba31eb30ea985e36eb8f0e10c2afedb8d480a316776bd6655c731aa9d21766c44d64c3e04eb30983b40fec9566902af832768e94335306da9485 + languageName: node + linkType: hard + +"dayjs@npm:^1.11.7": version: 1.11.10 resolution: "dayjs@npm:1.11.10" checksum: 10/27e8f5bc01c0a76f36c656e62ab7f08c2e7b040b09e613cd4844abf03fb258e0350f0a83b02c887b84d771c1f11e092deda0beef8c6df2a1afbc3f6c1fade279 @@ -19476,7 +19887,14 @@ __metadata: languageName: node linkType: hard -"dotenv@npm:^16.0.0, dotenv@npm:^16.0.3, dotenv@npm:^16.3.1, dotenv@npm:^16.4.1, dotenv@npm:^16.4.4, dotenv@npm:~16.4.5": +"dotenv@npm:^16.0.0, dotenv@npm:^16.3.1, dotenv@npm:^16.4.1": + version: 16.4.1 + resolution: "dotenv@npm:16.4.1" + checksum: 10/8da20250633703686961004df3ea81b1f81e16fbe873372050676f54ca4053172d0589aae902e683eb575884d56b6bc89fe48bbac5e1e0bef606a061389ca33c + languageName: node + linkType: hard + +"dotenv@npm:^16.0.3, dotenv@npm:^16.4.4, dotenv@npm:~16.4.5": version: 16.4.5 resolution: "dotenv@npm:16.4.5" checksum: 10/55a3134601115194ae0f924e54473459ed0d9fc340ae610b676e248cca45aa7c680d86365318ea964e6da4e2ea80c4514c1adab5adb43d6867fb57ff068f95c8 @@ -19897,7 +20315,7 @@ __metadata: languageName: node linkType: hard -"envinfo@npm:^7.10.0, envinfo@npm:^7.7.3": +"envinfo@npm:^7.10.0": version: 7.11.0 resolution: "envinfo@npm:7.11.0" bin: @@ -19906,6 +20324,15 @@ __metadata: languageName: node linkType: hard +"envinfo@npm:^7.7.3": + version: 7.8.1 + resolution: "envinfo@npm:7.8.1" + bin: + envinfo: dist/cli.js + checksum: 10/e7a2d71c7dfe398a4ffda0e844e242d2183ef2627f98e74e4cd71edd2af691c8707a2b34aacef92538c27b3daf9a360d32202f33c0a9f27f767c4e1c6ba8b522 + languageName: node + linkType: hard + "eol@npm:^0.9.1": version: 0.9.1 resolution: "eol@npm:0.9.1" @@ -21715,7 +22142,7 @@ __metadata: languageName: node linkType: hard -"express@npm:^4.14.0, express@npm:^4.17.3, express@npm:^4.18.2, express@npm:^4.19.2": +"express@npm:^4.14.0, express@npm:^4.18.2, express@npm:^4.19.2": version: 4.19.2 resolution: "express@npm:4.19.2" dependencies: @@ -21754,6 +22181,45 @@ __metadata: languageName: node linkType: hard +"express@npm:^4.17.3": + version: 4.18.2 + resolution: "express@npm:4.18.2" + dependencies: + accepts: "npm:~1.3.8" + array-flatten: "npm:1.1.1" + body-parser: "npm:1.20.1" + content-disposition: "npm:0.5.4" + content-type: "npm:~1.0.4" + cookie: "npm:0.5.0" + cookie-signature: "npm:1.0.6" + debug: "npm:2.6.9" + depd: "npm:2.0.0" + encodeurl: "npm:~1.0.2" + escape-html: "npm:~1.0.3" + etag: "npm:~1.8.1" + finalhandler: "npm:1.2.0" + fresh: "npm:0.5.2" + http-errors: "npm:2.0.0" + merge-descriptors: "npm:1.0.1" + methods: "npm:~1.1.2" + on-finished: "npm:2.4.1" + parseurl: "npm:~1.3.3" + path-to-regexp: "npm:0.1.7" + proxy-addr: "npm:~2.0.7" + qs: "npm:6.11.0" + range-parser: "npm:~1.2.1" + safe-buffer: "npm:5.2.1" + send: "npm:0.18.0" + serve-static: "npm:1.15.0" + setprototypeof: "npm:1.2.0" + statuses: "npm:2.0.1" + type-is: "npm:~1.6.18" + utils-merge: "npm:1.0.1" + vary: "npm:~1.1.2" + checksum: 10/869ae89ed6ff4bed7b373079dc58e5dddcf2915a2669b36037ff78c99d675ae930e5fe052b35c24f56557d28a023bb1cbe3e2f2fb87eaab96a1cedd7e597809d + languageName: node + linkType: hard + "ext@npm:^1.1.2": version: 1.7.0 resolution: "ext@npm:1.7.0" @@ -22494,7 +22960,17 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.15.0, follow-redirects@npm:^1.15.4": +"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.15.0": + version: 1.15.2 + resolution: "follow-redirects@npm:1.15.2" + peerDependenciesMeta: + debug: + optional: true + checksum: 10/8be0d39919770054812537d376850ccde0b4762b0501c440bd08724971a078123b55f57704f2984e0664fecc0c86adea85add63295804d9dce401cd9604c91d3 + languageName: node + linkType: hard + +"follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.15.4": version: 1.15.6 resolution: "follow-redirects@npm:1.15.6" peerDependenciesMeta: @@ -23196,7 +23672,22 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.0.0, glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": +"glob@npm:^10.0.0": + version: 10.3.3 + resolution: "glob@npm:10.3.3" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^2.0.3" + minimatch: "npm:^9.0.1" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + path-scurry: "npm:^1.10.1" + bin: + glob: dist/cjs/src/bin.js + checksum: 10/0d1a59dff5d5d7085f9c1e3b0c9c3a7e3a199a013ef8f800c0886e3cfe6f8e293f7847081021a97f96616bf778c053c6937382675f369ec8231c8b95d3ba11e2 + languageName: node + linkType: hard + +"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": version: 10.3.10 resolution: "glob@npm:10.3.10" dependencies: @@ -24597,13 +25088,20 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.0.0, ignore@npm:^5.0.4, ignore@npm:^5.1.1, ignore@npm:^5.2.0, ignore@npm:^5.2.4, ignore@npm:^5.3.0": +"ignore@npm:^5.0.0, ignore@npm:^5.2.4, ignore@npm:^5.3.0": version: 5.3.1 resolution: "ignore@npm:5.3.1" checksum: 10/0a884c2fbc8c316f0b9f92beaf84464253b73230a4d4d286697be45fca081199191ca33e1c2e82d9e5f851f5e9a48a78e25a35c951e7eb41e59f150db3530065 languageName: node linkType: hard +"ignore@npm:^5.0.4, ignore@npm:^5.1.1, ignore@npm:^5.2.0": + version: 5.2.4 + resolution: "ignore@npm:5.2.4" + checksum: 10/4f7caf5d2005da21a382d4bd1d2aa741a3bed51de185c8562dd7f899a81a620ac4fd0619b06f7029a38ae79e4e4c134399db3bd0192c703c3ef54bb82df3086c + languageName: node + linkType: hard + "image-size@npm:^1.0.2": version: 1.1.1 resolution: "image-size@npm:1.1.1" @@ -25486,7 +25984,20 @@ __metadata: languageName: node linkType: hard -"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.12, is-typed-array@npm:^1.1.3, is-typed-array@npm:^1.1.9": +"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.3": + version: 1.1.10 + resolution: "is-typed-array@npm:1.1.10" + dependencies: + available-typed-arrays: "npm:^1.0.5" + call-bind: "npm:^1.0.2" + for-each: "npm:^0.3.3" + gopd: "npm:^1.0.1" + has-tostringtag: "npm:^1.0.0" + checksum: 10/2392b2473bbc994f5c30d6848e32bab3cab6c80b795aaec3020baf5419ff7df38fc11b3a043eb56d50f842394c578dbb204a7a29398099f895cf111c5b27f327 + languageName: node + linkType: hard + +"is-typed-array@npm:^1.1.12, is-typed-array@npm:^1.1.9": version: 1.1.12 resolution: "is-typed-array@npm:1.1.12" dependencies: @@ -25746,6 +26257,19 @@ __metadata: languageName: node linkType: hard +"jackspeak@npm:^2.0.3": + version: 2.2.0 + resolution: "jackspeak@npm:2.2.0" + dependencies: + "@isaacs/cliui": "npm:^8.0.2" + "@pkgjs/parseargs": "npm:^0.11.0" + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 10/9fc9c6d28abccaf064a82be1a70d50004e582ba3ed790a84732c9ce275cbc748ff22df2027e549161eff1653235ff4e971c789a51b903a428003a462c058f5e5 + languageName: node + linkType: hard + "jackspeak@npm:^2.3.5": version: 2.3.6 resolution: "jackspeak@npm:2.3.6" @@ -25982,6 +26506,27 @@ __metadata: languageName: node linkType: hard +"jest-environment-jsdom@npm:29.7.0": + version: 29.7.0 + resolution: "jest-environment-jsdom@npm:29.7.0" + dependencies: + "@jest/environment": "npm:^29.7.0" + "@jest/fake-timers": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/jsdom": "npm:^20.0.0" + "@types/node": "npm:*" + jest-mock: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jsdom: "npm:^20.0.0" + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + checksum: 10/23bbfc9bca914baef4b654f7983175a4d49b0f515a5094ebcb8f819f28ec186f53c0ba06af1855eac04bab1457f4ea79dae05f70052cf899863e8096daa6e0f5 + languageName: node + linkType: hard + "jest-environment-jsdom@npm:^29.2.1": version: 29.6.2 resolution: "jest-environment-jsdom@npm:29.6.2" @@ -26046,6 +26591,29 @@ __metadata: languageName: node linkType: hard +"jest-haste-map@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-haste-map@npm:29.6.2" + dependencies: + "@jest/types": "npm:^29.6.1" + "@types/graceful-fs": "npm:^4.1.3" + "@types/node": "npm:*" + anymatch: "npm:^3.0.3" + fb-watchman: "npm:^2.0.0" + fsevents: "npm:^2.3.2" + graceful-fs: "npm:^4.2.9" + jest-regex-util: "npm:^29.4.3" + jest-util: "npm:^29.6.2" + jest-worker: "npm:^29.6.2" + micromatch: "npm:^4.0.4" + walker: "npm:^1.0.8" + dependenciesMeta: + fsevents: + optional: true + checksum: 10/855d2c94979ad0795d5ef31cc81ccf40d2c2f6abd63de34a89e8b12e6b1cf7b9ae875f7479b783b7a2e9f55502ad1d241d483c103bed85a75c2b10eaafea3634 + languageName: node + linkType: hard + "jest-haste-map@npm:^29.7.0": version: 29.7.0 resolution: "jest-haste-map@npm:29.7.0" @@ -26157,6 +26725,13 @@ __metadata: languageName: node linkType: hard +"jest-regex-util@npm:^29.4.3": + version: 29.4.3 + resolution: "jest-regex-util@npm:29.4.3" + checksum: 10/96fc7fc28cd4dd73a63c13a526202c4bd8b351d4e5b68b1a2a2c88da3308c2a16e26feaa593083eb0bac38cca1aa9dd05025412e7de013ba963fb8e66af22b8a + languageName: node + linkType: hard + "jest-resolve-dependencies@npm:^29.7.0": version: 29.7.0 resolution: "jest-resolve-dependencies@npm:29.7.0" @@ -26271,7 +26846,7 @@ __metadata: languageName: node linkType: hard -"jest-util@npm:^29.0.0, jest-util@npm:^29.6.2, jest-util@npm:^29.7.0": +"jest-util@npm:^29.0.0, jest-util@npm:^29.7.0": version: 29.7.0 resolution: "jest-util@npm:29.7.0" dependencies: @@ -26285,6 +26860,20 @@ __metadata: languageName: node linkType: hard +"jest-util@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-util@npm:29.6.2" + dependencies: + "@jest/types": "npm:^29.6.1" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + ci-info: "npm:^3.2.0" + graceful-fs: "npm:^4.2.9" + picomatch: "npm:^2.2.3" + checksum: 10/95d510b7bbac6976c71bf9c8f2e861cdc6c47dca0a70c470ebce6fa2afef3fecd73772efdffc04e7aad89602ab388c2f1ee1cb27c505210d767f0731da65c13b + languageName: node + linkType: hard + "jest-validate@npm:^29.6.3, jest-validate@npm:^29.7.0": version: 29.7.0 resolution: "jest-validate@npm:29.7.0" @@ -26371,6 +26960,18 @@ __metadata: languageName: node linkType: hard +"jest-worker@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-worker@npm:29.6.2" + dependencies: + "@types/node": "npm:*" + jest-util: "npm:^29.6.2" + merge-stream: "npm:^2.0.0" + supports-color: "npm:^8.0.0" + checksum: 10/7564896d0e61fdd202652c1ce17e1c20ef01dcbf313471dd83e687efa424e82745cc4d7ebf19ba8342327fa62971107c0e507a654e0041f310b4d53bee82584f + languageName: node + linkType: hard + "jest-worker@npm:^29.6.3, jest-worker@npm:^29.7.0": version: 29.7.0 resolution: "jest-worker@npm:29.7.0" @@ -26418,7 +27019,7 @@ __metadata: languageName: node linkType: hard -"joi@npm:^17.11.0, joi@npm:^17.2.1": +"joi@npm:^17.11.0": version: 17.11.0 resolution: "joi@npm:17.11.0" dependencies: @@ -26431,6 +27032,19 @@ __metadata: languageName: node linkType: hard +"joi@npm:^17.2.1": + version: 17.6.3 + resolution: "joi@npm:17.6.3" + dependencies: + "@hapi/hoek": "npm:^9.0.0" + "@hapi/topo": "npm:^5.0.0" + "@sideway/address": "npm:^4.1.3" + "@sideway/formula": "npm:^3.0.0" + "@sideway/pinpoint": "npm:^2.0.0" + checksum: 10/0cd00de7a27caf3a2139daed4f804870a7a425e350b092444151be656fa9e2373877f55c1cc41b26c27f9b0a94fb416a2eddf800c43b8b7c1d3705540a1e4618 + languageName: node + linkType: hard + "join-component@npm:^1.1.0": version: 1.1.0 resolution: "join-component@npm:1.1.0" @@ -27755,13 +28369,20 @@ __metadata: languageName: node linkType: hard -"lines-and-columns@npm:^2.0.3, lines-and-columns@npm:~2.0.3": +"lines-and-columns@npm:^2.0.3": version: 2.0.4 resolution: "lines-and-columns@npm:2.0.4" checksum: 10/81ac2f943f5428a46bd4ea2561c74ba674a107d8e6cc70cd317d16892a36ff3ba0dc6e599aca8b6f8668d26c85288394c6edf7a40e985ca843acab3701b80d4c languageName: node linkType: hard +"lines-and-columns@npm:~2.0.3": + version: 2.0.3 + resolution: "lines-and-columns@npm:2.0.3" + checksum: 10/b5bb0d6ee2f82ae834ceddc9251af2060c30db476673e9c817c34c00bed58e0c5d90a6866b64afe7bdcb2c5eb1b418a5b1ee631d2592dc8ff381540901fa4da6 + languageName: node + linkType: hard + "linkify-it@npm:^5.0.0": version: 5.0.0 resolution: "linkify-it@npm:5.0.0" @@ -28197,7 +28818,7 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.0.0, lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": +"lru-cache@npm:^10.0.0, lru-cache@npm:^10.0.1": version: 10.2.2 resolution: "lru-cache@npm:10.2.2" checksum: 10/ff1a496d30b5eaec2c9079080965bb0cede203cf878371f7033a007f1e54cd4aa13cc8abf7ccec4c994a83a22ed5476e83a55bb57cc07e6c1547a42937e42c37 @@ -28239,6 +28860,13 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^9.1.1 || ^10.0.0": + version: 10.0.0 + resolution: "lru-cache@npm:10.0.0" + checksum: 10/590e00d6ccd76a1ada056585be3fd6dbddda395fc9359390cff38669c69c3fa1792dd6c4c46a9b1b411f032cd2e979d9e664f1628163292ecdfeada98c3da1f3 + languageName: node + linkType: hard + "lru-queue@npm:^0.1.0": version: 0.1.0 resolution: "lru-queue@npm:0.1.0" @@ -28275,7 +28903,16 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.1, magic-string@npm:^0.30.10, magic-string@npm:^0.30.5": +"magic-string@npm:^0.30.1, magic-string@npm:^0.30.5": + version: 0.30.8 + resolution: "magic-string@npm:0.30.8" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.4.15" + checksum: 10/72ab63817af600e92c19dc8489c1aa4a9599da00cfd59b2319709bd48fb0cf533fdf354bf140ac86e598dbd63e6b2cc83647fe8448f864a3eb6061c62c94e784 + languageName: node + linkType: hard + +"magic-string@npm:^0.30.10": version: 0.30.10 resolution: "magic-string@npm:0.30.10" dependencies: @@ -28950,7 +29587,7 @@ __metadata: languageName: node linkType: hard -"mdast-util-to-string@npm:^3.0.0, mdast-util-to-string@npm:^3.1.0": +"mdast-util-to-string@npm:^3.0.0": version: 3.2.0 resolution: "mdast-util-to-string@npm:3.2.0" dependencies: @@ -28959,6 +29596,13 @@ __metadata: languageName: node linkType: hard +"mdast-util-to-string@npm:^3.1.0": + version: 3.1.0 + resolution: "mdast-util-to-string@npm:3.1.0" + checksum: 10/3e72cde3f56e28ba17734af1ba200039fe6faba1fdfb0cf35f8cc5afc86335a43978a2b01d74a2843e347f453f441e37d2b897967e63cc4854be1054c30258e0 + languageName: node + linkType: hard + "mdast-util-to-string@npm:^4.0.0": version: 4.0.0 resolution: "mdast-util-to-string@npm:4.0.0" @@ -29404,7 +30048,7 @@ __metadata: languageName: node linkType: hard -"micromark-core-commonmark@npm:^1.0.0, micromark-core-commonmark@npm:^1.0.1": +"micromark-core-commonmark@npm:^1.0.0": version: 1.1.0 resolution: "micromark-core-commonmark@npm:1.1.0" dependencies: @@ -29428,6 +30072,30 @@ __metadata: languageName: node linkType: hard +"micromark-core-commonmark@npm:^1.0.1": + version: 1.0.6 + resolution: "micromark-core-commonmark@npm:1.0.6" + dependencies: + decode-named-character-reference: "npm:^1.0.0" + micromark-factory-destination: "npm:^1.0.0" + micromark-factory-label: "npm:^1.0.0" + micromark-factory-space: "npm:^1.0.0" + micromark-factory-title: "npm:^1.0.0" + micromark-factory-whitespace: "npm:^1.0.0" + micromark-util-character: "npm:^1.0.0" + micromark-util-chunked: "npm:^1.0.0" + micromark-util-classify-character: "npm:^1.0.0" + micromark-util-html-tag-name: "npm:^1.0.0" + micromark-util-normalize-identifier: "npm:^1.0.0" + micromark-util-resolve-all: "npm:^1.0.0" + micromark-util-subtokenize: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.1" + uvu: "npm:^0.5.0" + checksum: 10/20daa4b78b88afea7658c2bd428c830734c72fbb2184c1f0761bb4c1e5fcf266509e7d46ad5f7b2a2aeb32cd17951788733cad458632457b52397534d930030a + languageName: node + linkType: hard + "micromark-core-commonmark@npm:^2.0.0": version: 2.0.0 resolution: "micromark-core-commonmark@npm:2.0.0" @@ -30450,7 +31118,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:9.0.3, minimatch@npm:^9.0.0, minimatch@npm:^9.0.1, minimatch@npm:^9.0.3": +"minimatch@npm:9.0.3, minimatch@npm:^9.0.0, minimatch@npm:^9.0.3": version: 9.0.3 resolution: "minimatch@npm:9.0.3" dependencies: @@ -30477,6 +31145,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^9.0.1": + version: 9.0.1 + resolution: "minimatch@npm:9.0.1" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10/b4e98f4dc740dcf33999a99af23ae6e5e1c47632f296dc95cb649a282150f92378d41434bf64af4ea2e5975255a757d031c3bf014bad9214544ac57d97f3ba63 + languageName: node + linkType: hard + "minimist@npm:^1.1.3, minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:^1.2.8": version: 1.2.8 resolution: "minimist@npm:1.2.8" @@ -30577,7 +31254,14 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.3, minipass@npm:^7.0.4": +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.4": + version: 7.0.4 + resolution: "minipass@npm:7.0.4" + checksum: 10/e864bd02ceb5e0707696d58f7ce3a0b89233f0d686ef0d447a66db705c0846a8dc6f34865cd85256c1472ff623665f616b90b8ff58058b2ad996c5de747d2d18 + languageName: node + linkType: hard + +"minipass@npm:^7.0.3": version: 7.1.2 resolution: "minipass@npm:7.1.2" checksum: 10/c25f0ee8196d8e6036661104bacd743785b2599a21de5c516b32b3fa2b83113ac89a2358465bc04956baab37ffb956ae43be679b2262bf7be15fce467ccd7950 @@ -31265,7 +31949,7 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:2.7.0, node-fetch@npm:^2.0.0, node-fetch@npm:^2.2.0, node-fetch@npm:^2.5.0, node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.11, node-fetch@npm:^2.6.12, node-fetch@npm:^2.6.6, node-fetch@npm:^2.6.7, node-fetch@npm:^2.7.0": +"node-fetch@npm:2.7.0, node-fetch@npm:^2.5.0, node-fetch@npm:^2.6.12, node-fetch@npm:^2.6.6, node-fetch@npm:^2.7.0": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" dependencies: @@ -31279,6 +31963,20 @@ __metadata: languageName: node linkType: hard +"node-fetch@npm:^2.0.0, node-fetch@npm:^2.2.0, node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.11, node-fetch@npm:^2.6.7": + version: 2.6.12 + resolution: "node-fetch@npm:2.6.12" + dependencies: + whatwg-url: "npm:^5.0.0" + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: 10/370ed4d906edad9709a81b54a0141d37d2973a27dc80c723d8ac14afcec6dc67bc6c70986a96992b64ec75d08159cc4b65ce6aa9063941168ea5ac73b24df9f8 + languageName: node + linkType: hard + "node-forge@npm:^1, node-forge@npm:^1.2.1, node-forge@npm:^1.3.1": version: 1.3.1 resolution: "node-forge@npm:1.3.1" @@ -33383,7 +34081,17 @@ __metadata: languageName: node linkType: hard -"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.15, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4, postcss-selector-parser@npm:^6.0.6": +"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4": + version: 6.0.11 + resolution: "postcss-selector-parser@npm:6.0.11" + dependencies: + cssesc: "npm:^3.0.0" + util-deprecate: "npm:^1.0.2" + checksum: 10/14d2c77e533a7b0688f35c909c07f74a9f3cc8d7aea19fd4042093c2df96d6d1ca0d41fcf0ecea28e8560e09913e8a58e5d95a6504cea31c71e23acb80927bab + languageName: node + linkType: hard + +"postcss-selector-parser@npm:^6.0.15, postcss-selector-parser@npm:^6.0.6": version: 6.0.15 resolution: "postcss-selector-parser@npm:6.0.15" dependencies: @@ -33569,7 +34277,7 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^29.0.0, pretty-format@npm:^29.0.3, pretty-format@npm:^29.5.0, pretty-format@npm:^29.7.0": +"pretty-format@npm:^29.0.0, pretty-format@npm:^29.7.0": version: 29.7.0 resolution: "pretty-format@npm:29.7.0" dependencies: @@ -33580,6 +34288,17 @@ __metadata: languageName: node linkType: hard +"pretty-format@npm:^29.0.3, pretty-format@npm:^29.5.0": + version: 29.6.2 + resolution: "pretty-format@npm:29.6.2" + dependencies: + "@jest/schemas": "npm:^29.6.0" + ansi-styles: "npm:^5.0.0" + react-is: "npm:^18.0.0" + checksum: 10/5db1faf52552341e5026fd72f847d88116b08f758ef904f1635415b53ec2a193a0114fdede9f55a2c1174fa6eca896531f860db6f208c5698a52a5c354bb6f8d + languageName: node + linkType: hard + "pretty-hrtime@npm:^1.0.3": version: 1.0.3 resolution: "pretty-hrtime@npm:1.0.3" @@ -34178,6 +34897,18 @@ __metadata: languageName: node linkType: hard +"raw-body@npm:2.5.1": + version: 2.5.1 + resolution: "raw-body@npm:2.5.1" + dependencies: + bytes: "npm:3.1.2" + http-errors: "npm:2.0.0" + iconv-lite: "npm:0.4.24" + unpipe: "npm:1.0.0" + checksum: 10/280bedc12db3490ecd06f740bdcf66093a07535374b51331242382c0e130bb273ebb611b7bc4cba1b4b4e016cc7b1f4b05a6df885a6af39c2bc3b94c02291c84 + languageName: node + linkType: hard + "raw-body@npm:2.5.2": version: 2.5.2 resolution: "raw-body@npm:2.5.2" @@ -35074,7 +35805,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.0.2, readable-stream@npm:^3.0.6, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0, readable-stream@npm:^3.6.2": +"readable-stream@npm:^3.0.2, readable-stream@npm:^3.6.2": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" dependencies: @@ -35085,6 +35816,17 @@ __metadata: languageName: node linkType: hard +"readable-stream@npm:^3.0.6, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0": + version: 3.6.0 + resolution: "readable-stream@npm:3.6.0" + dependencies: + inherits: "npm:^2.0.3" + string_decoder: "npm:^1.1.1" + util-deprecate: "npm:^1.0.1" + checksum: 10/b80b3e6a7fafb1c79de7db541de357f4a5ee73bd70c21672f5a7c840d27bb27bdb0151e7ba2fd82c4a888df22ce0c501b0d9f3e4dfe51688876701c437d59536 + languageName: node + linkType: hard + "readable-stream@npm:^4.0.0": version: 4.5.2 resolution: "readable-stream@npm:4.5.2" @@ -35354,7 +36096,7 @@ __metadata: languageName: node linkType: hard -"regenerator-runtime@npm:^0.13.2": +"regenerator-runtime@npm:^0.13.11, regenerator-runtime@npm:^0.13.2": version: 0.13.11 resolution: "regenerator-runtime@npm:0.13.11" checksum: 10/d493e9e118abef5b099c78170834f18540c4933cedf9bfabc32d3af94abfb59a7907bd7950259cbab0a929ebca7db77301e8024e5121e6482a82f78283dfd20c @@ -35866,7 +36608,20 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.1.5, resolve@npm:^1.1.6, resolve@npm:^1.1.7, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.0, resolve@npm:^1.22.1, resolve@npm:^1.22.2, resolve@npm:^1.22.3, resolve@npm:^1.22.4, resolve@npm:^1.9.0": +"resolve@npm:^1.1.5, resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:^1.9.0": + version: 1.22.3 + resolution: "resolve@npm:1.22.3" + dependencies: + is-core-module: "npm:^2.12.0" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10/3d733800d5f7525df912e9c4a68ee14574f42fa3676651debe6d2f6f55f8eef35626ad6330745da52943d695760f1ac7ee85b2c24f48be111f744aba7cb2e06d + languageName: node + linkType: hard + +"resolve@npm:^1.1.7, resolve@npm:^1.22.0, resolve@npm:^1.22.2, resolve@npm:^1.22.3, resolve@npm:^1.22.4": version: 1.22.8 resolution: "resolve@npm:1.22.8" dependencies: @@ -35908,7 +36663,20 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@npm%3A^1.1.5#optional!builtin, resolve@patch:resolve@npm%3A^1.1.6#optional!builtin, resolve@patch:resolve@npm%3A^1.1.7#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin, resolve@patch:resolve@npm%3A^1.22.2#optional!builtin, resolve@patch:resolve@npm%3A^1.22.3#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin, resolve@patch:resolve@npm%3A^1.9.0#optional!builtin": +"resolve@patch:resolve@npm%3A^1.1.5#optional!builtin, resolve@patch:resolve@npm%3A^1.1.6#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin, resolve@patch:resolve@npm%3A^1.9.0#optional!builtin": + version: 1.22.3 + resolution: "resolve@patch:resolve@npm%3A1.22.3#optional!builtin::version=1.22.3&hash=c3c19d" + dependencies: + is-core-module: "npm:^2.12.0" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10/b775dffbad4d4ed3ae498a37d33a96282d64de50955f7642258aeaa2886e419598f4dfe837c0e31bcc6eb448287c1578e899dffe49eca76ef393bf8605a3b543 + languageName: node + linkType: hard + +"resolve@patch:resolve@npm%3A^1.1.7#optional!builtin, resolve@patch:resolve@npm%3A^1.22.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.2#optional!builtin, resolve@patch:resolve@npm%3A^1.22.3#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" dependencies: @@ -36018,7 +36786,7 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:^3.0.2": +"rimraf@npm:^3.0.0, rimraf@npm:^3.0.2": version: 3.0.2 resolution: "rimraf@npm:3.0.2" dependencies: @@ -36830,7 +37598,14 @@ __metadata: languageName: node linkType: hard -"shell-quote@npm:^1.6.1, shell-quote@npm:^1.7.2, shell-quote@npm:^1.7.3, shell-quote@npm:^1.8.1": +"shell-quote@npm:^1.6.1, shell-quote@npm:^1.7.3": + version: 1.7.3 + resolution: "shell-quote@npm:1.7.3" + checksum: 10/0ab00c37c84ea3ac13d5f0d45c6850701254fd1d6653d0604a48973ba3911ad0dd9f414672253a01f68fe48bb651a7138317ed4543b75ce4192c1d610e453d4c + languageName: node + linkType: hard + +"shell-quote@npm:^1.7.2, shell-quote@npm:^1.8.1": version: 1.8.1 resolution: "shell-quote@npm:1.8.1" checksum: 10/af19ab5a1ec30cb4b2f91fd6df49a7442d5c4825a2e269b3712eded10eedd7f9efeaab96d57829880733fc55bcdd8e9b1d8589b4befb06667c731d08145e274d @@ -38492,7 +39267,7 @@ __metadata: languageName: node linkType: hard -"tar@npm:^6.0.5, tar@npm:^6.1.11, tar@npm:^6.1.12, tar@npm:^6.1.13, tar@npm:^6.1.2, tar@npm:^6.2.0": +"tar@npm:^6.0.5, tar@npm:^6.1.11, tar@npm:^6.1.13, tar@npm:^6.1.2, tar@npm:^6.2.0": version: 6.2.1 resolution: "tar@npm:6.2.1" dependencies: @@ -38506,6 +39281,20 @@ __metadata: languageName: node linkType: hard +"tar@npm:^6.1.12": + version: 6.2.0 + resolution: "tar@npm:6.2.0" + dependencies: + chownr: "npm:^2.0.0" + fs-minipass: "npm:^2.0.0" + minipass: "npm:^5.0.0" + minizlib: "npm:^2.1.1" + mkdirp: "npm:^1.0.3" + yallist: "npm:^4.0.0" + checksum: 10/2042bbb14830b5cd0d584007db0eb0a7e933e66d1397e72a4293768d2332449bc3e312c266a0887ec20156dea388d8965e53b4fc5097f42d78593549016da089 + languageName: node + linkType: hard + "tar@npm:^7.0.1": version: 7.0.1 resolution: "tar@npm:7.0.1" @@ -38638,7 +39427,29 @@ __metadata: languageName: node linkType: hard -"terser-webpack-plugin@npm:^5.3.1, terser-webpack-plugin@npm:^5.3.10, terser-webpack-plugin@npm:^5.3.9": +"terser-webpack-plugin@npm:^5.3.1, terser-webpack-plugin@npm:^5.3.9": + version: 5.3.9 + resolution: "terser-webpack-plugin@npm:5.3.9" + dependencies: + "@jridgewell/trace-mapping": "npm:^0.3.17" + jest-worker: "npm:^27.4.5" + schema-utils: "npm:^3.1.1" + serialize-javascript: "npm:^6.0.1" + terser: "npm:^5.16.8" + peerDependencies: + webpack: ^5.1.0 + peerDependenciesMeta: + "@swc/core": + optional: true + esbuild: + optional: true + uglify-js: + optional: true + checksum: 10/339737a407e034b7a9d4a66e31d84d81c10433e41b8eae2ca776f0e47c2048879be482a9aa08e8c27565a2a949bc68f6e07f451bf4d9aa347dd61b3d000f5353 + languageName: node + linkType: hard + +"terser-webpack-plugin@npm:^5.3.10": version: 5.3.10 resolution: "terser-webpack-plugin@npm:5.3.10" dependencies: @@ -38674,6 +39485,20 @@ __metadata: languageName: node linkType: hard +"terser@npm:^5.16.8": + version: 5.17.4 + resolution: "terser@npm:5.17.4" + dependencies: + "@jridgewell/source-map": "npm:^0.3.2" + acorn: "npm:^8.5.0" + commander: "npm:^2.20.0" + source-map-support: "npm:~0.5.20" + bin: + terser: bin/terser + checksum: 10/3b2b82e8cf93a40502a5abbac42b531f356c34f5b2090cd122a21f4596561a8fc743988ee2d07f44449c70b498db3d70712810ad80806496807e44b9d65abf1c + languageName: node + linkType: hard + "test-exclude@npm:^6.0.0": version: 6.0.0 resolution: "test-exclude@npm:6.0.0" @@ -38922,7 +39747,16 @@ __metadata: languageName: node linkType: hard -"tmp@npm:^0.2.0, tmp@npm:^0.2.1, tmp@npm:^0.2.3, tmp@npm:~0.2.1": +"tmp@npm:^0.2.0, tmp@npm:^0.2.1, tmp@npm:~0.2.1": + version: 0.2.1 + resolution: "tmp@npm:0.2.1" + dependencies: + rimraf: "npm:^3.0.0" + checksum: 10/445148d72df3ce99356bc89a7857a0c5c3b32958697a14e50952c6f7cf0a8016e746ababe9a74c1aa52f04c526661992f14659eba34d3c6701d49ba2f3cf781b + languageName: node + linkType: hard + +"tmp@npm:^0.2.3": version: 0.2.3 resolution: "tmp@npm:0.2.3" checksum: 10/7b13696787f159c9754793a83aa79a24f1522d47b87462ddb57c18ee93ff26c74cbb2b8d9138f571d2e0e765c728fb2739863a672b280528512c6d83d511c6fa @@ -39082,22 +39916,6 @@ __metadata: languageName: node linkType: hard -"trezor-address-validator@npm:^0.4.4": - version: 0.4.4 - resolution: "trezor-address-validator@npm:0.4.4" - dependencies: - base-x: "npm:^3.0.7" - bech32: "npm:^2.0.0" - browserify-bignum: "npm:^1.3.0-2" - cbor-js: "npm:^0.1.0" - crc: "npm:^3.8.0" - groestl-hash-js: "npm:1.0.0" - jssha: "npm:2.3.1" - lodash: "npm:^4.17.15" - checksum: 10/8f30bf4e2136cae746988b4761f07684b80250e82caeadcefdeaabb9e4e7bef9d3baaba48424a294870cc95735519b8feb5169ded87dec0a38cae2641b6f5edd - languageName: node - linkType: hard - "trezor-suite@workspace:.": version: 0.0.0-use.local resolution: "trezor-suite@workspace:." @@ -40017,7 +40835,7 @@ __metadata: languageName: node linkType: hard -"unist-util-visit-parents@npm:^5.0.0, unist-util-visit-parents@npm:^5.1.1": +"unist-util-visit-parents@npm:^5.0.0": version: 5.1.3 resolution: "unist-util-visit-parents@npm:5.1.3" dependencies: @@ -40027,6 +40845,16 @@ __metadata: languageName: node linkType: hard +"unist-util-visit-parents@npm:^5.1.1": + version: 5.1.1 + resolution: "unist-util-visit-parents@npm:5.1.1" + dependencies: + "@types/unist": "npm:^2.0.0" + unist-util-is: "npm:^5.0.0" + checksum: 10/2c15cdfca1a58f29df67d856e58773d8fb49ad2ff89ad7bba335189118fd07b919b3af0b76f6d6a9774c1915596283b799f3fa38cfa80e1e57514162063e62ac + languageName: node + linkType: hard + "unist-util-visit-parents@npm:^6.0.0": version: 6.0.1 resolution: "unist-util-visit-parents@npm:6.0.1" @@ -41529,7 +42357,7 @@ __metadata: languageName: node linkType: hard -"webpack-merge@npm:^5.10.0, webpack-merge@npm:^5.7.3, webpack-merge@npm:^5.9.0": +"webpack-merge@npm:^5.10.0": version: 5.10.0 resolution: "webpack-merge@npm:5.10.0" dependencies: @@ -41540,6 +42368,16 @@ __metadata: languageName: node linkType: hard +"webpack-merge@npm:^5.7.3, webpack-merge@npm:^5.9.0": + version: 5.9.0 + resolution: "webpack-merge@npm:5.9.0" + dependencies: + clone-deep: "npm:^4.0.1" + wildcard: "npm:^2.0.0" + checksum: 10/d23dd1f0bad0b9821bf58443d2d29097d65cd9353046c2d8a6d7b57877ec19cf64be57cc7ef2a371a15cf9264fe6eaf8dea4015dc87487e664ffab2a28329d56 + languageName: node + linkType: hard + "webpack-nano@npm:^1.1.1": version: 1.1.1 resolution: "webpack-nano@npm:1.1.1" @@ -41838,7 +42676,7 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.2, which-typed-array@npm:^1.1.9": +"which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.13": version: 1.1.13 resolution: "which-typed-array@npm:1.1.13" dependencies: @@ -41851,6 +42689,20 @@ __metadata: languageName: node linkType: hard +"which-typed-array@npm:^1.1.2, which-typed-array@npm:^1.1.9": + version: 1.1.9 + resolution: "which-typed-array@npm:1.1.9" + dependencies: + available-typed-arrays: "npm:^1.0.5" + call-bind: "npm:^1.0.2" + for-each: "npm:^0.3.3" + gopd: "npm:^1.0.1" + has-tostringtag: "npm:^1.0.0" + is-typed-array: "npm:^1.1.10" + checksum: 10/90ef760a09dcffc479138a6bc77fd2933a81a41d531f4886ae212f6edb54a0645a43a6c24de2c096aea910430035ac56b3d22a06f3d64e5163fa178d0f24e08e + languageName: node + linkType: hard + "which@npm:^1.2.1, which@npm:^1.2.14, which@npm:^1.2.4, which@npm:^1.2.9, which@npm:^1.3.1": version: 1.3.1 resolution: "which@npm:1.3.1" @@ -42056,7 +42908,37 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.11.0, ws@npm:^8.12.1, ws@npm:^8.13.0, ws@npm:^8.16.0, ws@npm:^8.17.1, ws@npm:^8.2.3, ws@npm:^8.5.0": +"ws@npm:^8.11.0, ws@npm:^8.13.0, ws@npm:^8.2.3": + version: 8.13.0 + resolution: "ws@npm:8.13.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10/1769532b6fdab9ff659f0b17810e7501831d34ecca23fd179ee64091dd93a51f42c59f6c7bb4c7a384b6c229aca8076fb312aa35626257c18081511ef62a161d + languageName: node + linkType: hard + +"ws@npm:^8.12.1, ws@npm:^8.16.0, ws@npm:^8.5.0": + version: 8.16.0 + resolution: "ws@npm:8.16.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10/7c511c59e979bd37b63c3aea4a8e4d4163204f00bd5633c053b05ed67835481995f61a523b0ad2b603566f9a89b34cb4965cb9fab9649fbfebd8f740cea57f17 + languageName: node + linkType: hard + +"ws@npm:^8.17.1": version: 8.17.1 resolution: "ws@npm:8.17.1" peerDependencies: @@ -42285,7 +43167,7 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.0.0, yaml@npm:^2.2.1, yaml@npm:^2.2.2, yaml@npm:^2.3.4": +"yaml@npm:^2.0.0, yaml@npm:^2.2.1, yaml@npm:^2.3.4": version: 2.4.1 resolution: "yaml@npm:2.4.1" bin: @@ -42294,6 +43176,13 @@ __metadata: languageName: node linkType: hard +"yaml@npm:^2.2.2": + version: 2.2.2 + resolution: "yaml@npm:2.2.2" + checksum: 10/991384bf875dd1df9ab8e3393d6db7010d222eef4e750f17590b5d3d96d3f3ad49420f58fff6a3896321fb64d08f4bb3b4edf0d337fdfd6e960119ef5aa0527c + languageName: node + linkType: hard + "yargs-parser@npm:21.1.1, yargs-parser@npm:^21.0.0, yargs-parser@npm:^21.0.1, yargs-parser@npm:^21.1.1": version: 21.1.1 resolution: "yargs-parser@npm:21.1.1" @@ -42439,13 +43328,20 @@ __metadata: languageName: node linkType: hard -"zod@npm:^3.21.4, zod@npm:^3.22.3": +"zod@npm:^3.21.4": version: 3.23.4 resolution: "zod@npm:3.23.4" checksum: 10/29117ce59f16af155d9a3aab024d18e858e55b4b51c1f848772516ec6f019e617a0cdaf4c6e20f15154360a9f4c160056aba34502ec68072c8f0af31dfd653d6 languageName: node linkType: hard +"zod@npm:^3.22.3": + version: 3.22.4 + resolution: "zod@npm:3.22.4" + checksum: 10/73622ca36a916f785cf528fe612a884b3e0f183dbe6b33365a7d0fc92abdbedf7804c5e2bd8df0a278e1472106d46674281397a3dd800fa9031dc3429758c6ac + languageName: node + linkType: hard + "zwitch@npm:^2.0.0, zwitch@npm:^2.0.4": version: 2.0.4 resolution: "zwitch@npm:2.0.4"