├── .editorconfig ├── .gitignore ├── .snyk ├── .travis.yml ├── .vscode └── launch.json ├── LICENSE ├── README.md ├── dist ├── wallet-address-validator.js └── wallet-address-validator.min.js ├── index.html ├── karma.conf.js ├── package-lock.json ├── package.json ├── src ├── ada_validator.js ├── ae_validator.js ├── ardr_validator.js ├── atom_validator.js ├── bch_validator.js ├── binance_validator.js ├── bitcoin_validator.js ├── crypto │ ├── base32.js │ ├── base58.js │ ├── bech32.js │ ├── biginteger.js │ ├── blake256.js │ ├── blake2b.js │ ├── cnBase58.js │ ├── sha3.js │ └── utils.js ├── currencies.js ├── eos_validator.js ├── ethereum_validator.js ├── hbar_validator.js ├── icx_validator.js ├── iost_validator.js ├── iota_validator.js ├── lisk_validator.js ├── loki_validator.js ├── monero_validator.js ├── nano_validator.js ├── nem_validator.js ├── nxt_validator.js ├── ripple_validator.js ├── siacoin_validator.js ├── solana_validator.js ├── steem_validator.js ├── stellar_validator.js ├── sys_validator.js ├── tezos_validator.js ├── tron_validator.js ├── wallet_address_validator.d.ts ├── wallet_address_validator.js └── zil_validator.js ├── test ├── wallet_address_get_currencies.js └── wallet_address_validator.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bower_components 3 | .idea 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /.snyk: -------------------------------------------------------------------------------- 1 | # Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. 2 | version: v1.13.3 3 | ignore: {} 4 | patch: {} 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | addons: 3 | chrome: stable 4 | language: node_js 5 | node_js: 6 | - "8" 7 | - "10" 8 | - "stable" 9 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "yarn test:node", 9 | "request": "launch", 10 | "runtimeArgs": [ 11 | "test:node", 12 | ], 13 | "runtimeExecutable": "yarn", 14 | "skipFiles": [ 15 | "/**" 16 | ], 17 | "type": "pwa-node" 18 | }, 19 | { 20 | "type": "node", 21 | "request": "launch", 22 | "name": "Mocha Tests", 23 | "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", 24 | "args": [ 25 | "-u", 26 | "tdd", 27 | "--timeout", 28 | "999999", 29 | "--colors", 30 | "${workspaceFolder}/test" 31 | ], 32 | "internalConsoleOptions": "openOnSessionStart" 33 | } 34 | ] 35 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Roman Shtylman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # trezor-address-validator 2 | Simple wallet address validator for validating Bitcoin and other altcoins addresses in **Node.js and browser**. 3 | 4 | Forked from [ryanralph/altcoin-address](https://github.com/ryanralph/altcoin-address). 5 | 6 | **File size is ~65 kB (minifed and gzipped)**. 7 | 8 | ## Installation 9 | 10 | ### NPM 11 | ``` 12 | npm install trezor-address-validator 13 | ``` 14 | 15 | ### Browser 16 | ```html 17 | 18 | ``` 19 | 20 | ## API 21 | 22 | ##### validate (address [, currency = 'bitcoin'[, networkType = 'prod']]) 23 | 24 | ###### Parameters 25 | * address - Wallet address to validate. 26 | * currency - Optional. Currency name or symbol, e.g. `'bitcoin'` (default), `'litecoin'` or `'LTC'` 27 | * networkType - Optional. Use `'prod'` (default) to enforce standard address, `'testnet'` to enforce testnet address and `'both'` to enforce nothing. 28 | 29 | > Returns true if the address (string) is a valid wallet address for the crypto currency specified, see below for supported currencies. 30 | 31 | 32 | ##### getAddressType (address [, currency = 'bitcoin'[, networkType = 'prod']]) 33 | 34 | ###### Parameters 35 | * address - Wallet address to validate. 36 | * currency - Optional. Currency name or symbol, e.g. `'bitcoin'` (default), `'litecoin'` or `'LTC'` 37 | * networkType - Optional. Use `'prod'` (default) to enforce standard address, `'testnet'` to enforce testnet address and `'both'` to enforce nothing. 38 | 39 | > Returns address type (`'address' | 'p2pkh' | 'p2wpkh' | 'p2wsh' | 'p2sh' | 'p2tr' | 'pw-unknown'`) of the address or `undefined` if the address is invalid. 40 | ### Supported crypto currencies 41 | 42 | * 0x/zrx `'0x'` or `'zrx'` 43 | * Aave/lend `'Aave'` or `'lend'` 44 | * Abyss Token/abyss `'Abyss Token'` or `'abyss'` 45 | * AdEx/adx `'AdEx'` or `'adx'` 46 | * adToken/adt `'adToken'` or `'adt'` 47 | * aelf/elf `'aelf'` or `'elf'` 48 | * Aeron/arn `'Aeron'` or `'arn'` 49 | * Aeternity/ae `'Aeternity'` or `'ae'` 50 | * Agrello/dlt `'Agrello'` or `'dlt'` 51 | * All Sports/soc `'All Sports'` or `'soc'` 52 | * Ambrosus/amb `'Ambrosus'` or `'amb'` 53 | * Ankr/ankr `'Ankr'` or `'ankr'` 54 | * AppCoins/appc `'AppCoins'` or `'appc'` 55 | * Aragon/ant `'Aragon'` or `'ant'` 56 | * Arcblock/abt `'Arcblock'` or `'abt'` 57 | * Ardor/ardr `'Ardor'` or `'ardr'` 58 | * ATLANT/atl `'ATLANT'` or `'atl'` 59 | * Augur/rep `'Augur'` or `'rep'` 60 | * AuroraCoin/aur `'AuroraCoin'` or `'aur'` 61 | * aXpire/axpr `'aXpire'` or `'axpr'` 62 | * Bancor/bnt `'Bancor'` or `'bnt'` 63 | * Band Protocol/band `'Band Protocol'` or `'band'` 64 | * Bankex/bkx `'Bankex'` or `'bkx'` 65 | * Basic Attention Token/bat `'Basic Attention Token'` or `'bat'` 66 | * BeaverCoin/bvc `'BeaverCoin'` or `'bvc'` 67 | * BetterBetting/betr `'BetterBetting'` or `'betr'` 68 | * Binance/bnb `'Binance'` or `'bnb'` 69 | * Binance Smart Chain/bsc `'Binance Smart Chain'` or `'bsc'` 70 | * Binance USD/busd `'Binance USD'` or `'busd'` 71 | * BioCoin/bio `'BioCoin'` or `'bio'` 72 | * Bitcoin/btc `'Bitcoin'` or `'btc'` 73 | * Bitcoin Diamond/bcd `'Bitcoin Diamond'` or `'bcd'` 74 | * Bitcoin SV/bsv `'Bitcoin SV'` or `'bsv'` 75 | * BitcoinCash/bch `'BitcoinCash'` or `'bch'` 76 | * BitcoinGold/btg `'BitcoinGold'` or `'btg'` 77 | * BitcoinPrivate/btcp `'BitcoinPrivate'` or `'btcp'` 78 | * BitcoinZ/btcz `'BitcoinZ'` or `'btcz'` 79 | * BitDegree/bdg `'BitDegree'` or `'bdg'` 80 | * BitKan/kan `'BitKan'` or `'kan'` 81 | * BlitzPredict/xbp `'BlitzPredict'` or `'xbp'` 82 | * Blockmason Credit Protocol/bcpt `'Blockmason Credit Protocol'` or `'bcpt'` 83 | * Blocktrade Token/btt `'Blocktrade Token'` or `'btt'` 84 | * BLOCKv/vee `'BLOCKv'` or `'vee'` 85 | * Blox/cdt `'Blox'` or `'cdt'` 86 | * Bluzelle/blz `'Bluzelle'` or `'blz'` 87 | * Bread/brd `'Bread'` or `'brd'` 88 | * BTU Protocol/btu `'BTU Protocol'` or `'btu'` 89 | * Callisto/clo `'Callisto'` or `'clo'` 90 | * Cardano/ada `'Cardano'` or `'ada'` 91 | * Celer Network/celr `'Celer Network'` or `'celr'` 92 | * Chainlink/link `'Chainlink'` or `'link'` 93 | * Chiliz/chz `'Chiliz'` or `'chz'` 94 | * Chronobank/time `'Chronobank'` or `'time'` 95 | * Cindicator/cnd `'Cindicator'` or `'cnd'` 96 | * Civic/cvc `'Civic'` or `'cvc'` 97 | * Cocos-BCX/cocos `'Cocos-BCX'` or `'cocos'` 98 | * Coinlancer/cl `'Coinlancer'` or `'cl'` 99 | * COS/cos `'COS'` or `'cos'` 100 | * Cosmo Coin/cosm `'Cosmo Coin'` or `'cosm'` 101 | * Cosmos/atom `'Cosmos'` or `'atom'` 102 | * Covesting/cov `'Covesting'` or `'cov'` 103 | * Cred/lba `'Cred'` or `'lba'` 104 | * Crypterium/crpt `'Crypterium'` or `'crpt'` 105 | * Crypto.com Coin/cro `'Crypto.com Coin'` or `'cro'` 106 | * CryptoBossCoin/cbc `'CryptoBossCoin'` or `'cbc'` 107 | * CryptoFranc/xchf `'CryptoFranc'` or `'xchf'` 108 | * Daneel/dan `'Daneel'` or `'dan'` 109 | * Dash/dash `'Dash'` or `'dash'` 110 | * Decentraland/mana `'Decentraland'` or `'mana'` 111 | * Decred/dcr `'Decred'` or `'dcr'` 112 | * Dent/dent `'Dent'` or `'dent'` 113 | * Dentacoin/dcn `'Dentacoin'` or `'dcn'` 114 | * DigiByte/dgb `'DigiByte'` or `'dgb'` 115 | * Digitex Futures/dgtx `'Digitex Futures'` or `'dgtx'` 116 | * DigixDAO/dgd `'DigixDAO'` or `'dgd'` 117 | * District0x/dnt `'District0x'` or `'dnt'` 118 | * Dock/dock `'Dock'` or `'dock'` 119 | * DogeCoin/doge `'DogeCoin'` or `'doge'` 120 | * DomRaider/drt `'DomRaider'` or `'drt'` 121 | * Dusk Network/dusk `'Dusk Network'` or `'dusk'` 122 | * Edgeless/edg `'Edgeless'` or `'edg'` 123 | * Eidoo/edo `'Eidoo'` or `'edo'` 124 | * Electrify.Asia/elec `'Electrify.Asia'` or `'elec'` 125 | * Enigma/eng `'Enigma'` or `'eng'` 126 | * Enjin Coin/enj `'Enjin Coin'` or `'enj'` 127 | * EOS/eos `'EOS'` or `'eos'` 128 | * Ethereum/eth `'Ethereum'` or `'eth'` 129 | * EthereumClassic/etc `'EthereumClassic'` or `'etc'` 130 | * Etherparty/fuel `'Etherparty'` or `'fuel'` 131 | * EtherZero/etz `'EtherZero'` or `'etz'` 132 | * Everex/evx `'Everex'` or `'evx'` 133 | * Exchange Union/xuc `'Exchange Union'` or `'xuc'` 134 | * Expanse/exp `'Expanse'` or `'exp'` 135 | * Fantom/ftm `'Fantom'` or `'ftm'` 136 | * Fetch.ai/fet `'Fetch.ai'` or `'fet'` 137 | * FirmaChain/fct `'FirmaChain'` or `'fct'` 138 | * FirstBlood/1st `'FirstBlood'` or `'1st'` 139 | * Fortuna/fota `'Fortuna'` or `'fota'` 140 | * FreiCoin/frc `'FreiCoin'` or `'frc'` 141 | * GameCredits/game `'GameCredits'` or `'game'` 142 | * GarliCoin/grlc `'GarliCoin'` or `'grlc'` 143 | * Gemini Dollar/gusd `'Gemini Dollar'` or `'gusd'` 144 | * Genesis Vision/gvt `'Genesis Vision'` or `'gvt'` 145 | * Gifto/gto `'Gifto'` or `'gto'` 146 | * Gnosis/gno `'Gnosis'` or `'gno'` 147 | * Golem/gnt `'Golem'` or `'gnt'` 148 | * Groestlcoin/grs `'Groestlcoin'` or `'grs'` 149 | * Hedera Hashgraph/hbar `'Hedera Hashgraph'` or `'hbar'` 150 | * HedgeTrade/hedg `'HedgeTrade'` or `'hedg'` 151 | * Holo/hot `'Holo'` or `'hot'` 152 | * HOQU/hqx `'HOQU'` or `'hqx'` 153 | * Humaniq/hmq `'Humaniq'` or `'hmq'` 154 | * Huobi Token/ht `'Huobi Token'` or `'ht'` 155 | * Hush/hush `'Hush'` or `'hush'` 156 | * HyperSpace/xsc `'HyperSpace'` or `'xsc'` 157 | * ICON/icx `'ICON'` or `'icx'` 158 | * iExec RLC/rlc `'iExec RLC'` or `'rlc'` 159 | * IHT Real Estate Protocol/iht `'IHT Real Estate Protocol'` or `'iht'` 160 | * Insolar/ins `'Insolar'` or `'ins'` 161 | * Internet of Services/IOST `'Internet of Services'` or `'IOST'` 162 | * Iota/iota `'Iota'` or `'iota'` 163 | * IoTeX/iotx `'IoTeX'` or `'iotx'` 164 | * Kcash/kcash `'Kcash'` or `'kcash'` 165 | * KEY/key `'KEY'` or `'key'` 166 | * KickToken/kick `'KickToken'` or `'kick'` 167 | * Komodo/kmd `'Komodo'` or `'kmd'` 168 | * Kyber Network/knc `'Kyber Network'` or `'knc'` 169 | * Lambda/lamb `'Lambda'` or `'lamb'` 170 | * Lamden/tau `'Lamden'` or `'tau'` 171 | * LBRY Credits/lbc `'LBRY Credits'` or `'lbc'` 172 | * LIFE/life `'LIFE'` or `'life'` 173 | * LinkEye/let `'LinkEye'` or `'let'` 174 | * Lisk/lsk `'Lisk'` or `'lsk'` 175 | * LiteCoin/ltc `'LiteCoin'` or `'ltc'` 176 | * LockTrip/loc `'LockTrip'` or `'loc'` 177 | * Loki/loki `'Loki'` or `'loki'` 178 | * Loom Network/loom `'Loom Network'` or `'loom'` 179 | * Loopring/lrc `'Loopring'` or `'lrc'` 180 | * Luniverse/luniverse `'Luniverse'` or `'luniverse'` 181 | * Lunyr/lun `'Lunyr'` or `'lun'` 182 | * Mainframe/mft `'Mainframe'` or `'mft'` 183 | * Maker/mkr `'Maker'` or `'mkr'` 184 | * Matchpool/gup `'Matchpool'` or `'gup'` 185 | * Matic Network/matic `'Matic Network'` or `'matic'` 186 | * MCO/mco `'MCO'` or `'mco'` 187 | * Measurable Data Token/mdt `'Measurable Data Token'` or `'mdt'` 188 | * MegaCoin/mec `'MegaCoin'` or `'mec'` 189 | * Melon/mln `'Melon'` or `'mln'` 190 | * Menlo One/one `'Menlo One'` or `'one'` 191 | * Metal/mtl `'Metal'` or `'mtl'` 192 | * Mithril/mith `'Mithril'` or `'mith'` 193 | * Moeda Loyalty Points/mda `'Moeda Loyalty Points'` or `'mda'` 194 | * Molecular Future/mof `'Molecular Future'` or `'mof'` 195 | * MonaCoin/mona `'MonaCoin'` or `'mona'` 196 | * Monero/xmr `'Monero'` or `'xmr'` 197 | * Monetha/mth `'Monetha'` or `'mth'` 198 | * Monolith/tkn `'Monolith'` or `'tkn'` 199 | * Multi-collateral DAI/dai `'Multi-collateral DAI'` or `'dai'` 200 | * Mysterium/myst `'Mysterium'` or `'myst'` 201 | * NAGA/ngc `'NAGA'` or `'ngc'` 202 | * NameCoin/nmc `'NameCoin'` or `'nmc'` 203 | * Nano/nano `'Nano'` or `'nano'` 204 | * Nem/xem `'Nem'` or `'xem'` 205 | * Neo/neo `'Neo'` or `'neo'` 206 | * NeoGas/gas `'NeoGas'` or `'gas'` 207 | * NetKoin/ntk `'NetKoin'` or `'ntk'` 208 | * Nexo/nexo `'Nexo'` or `'nexo'` 209 | * Noah Coin/noah `'Noah Coin'` or `'noah'` 210 | * Nucleus Vision/ncash `'Nucleus Vision'` or `'ncash'` 211 | * Numeraire/nmr `'Numeraire'` or `'nmr'` 212 | * NXT/nxt `'NXT'` or `'nxt'` 213 | * OAX/oax `'OAX'` or `'oax'` 214 | * Ocean Protocol/ocean `'Ocean Protocol'` or `'ocean'` 215 | * Odyssey/ocn `'Odyssey'` or `'ocn'` 216 | * OmiseGO/omg `'OmiseGO'` or `'omg'` 217 | * Ontology/ont `'Ontology'` or `'ont'` 218 | * ORS Group/ors `'ORS Group'` or `'ors'` 219 | * OST/ost `'OST'` or `'ost'` 220 | * Own/chx `'Own'` or `'chx'` 221 | * Patientory/ptoy `'Patientory'` or `'ptoy'` 222 | * Patron/pat `'Patron'` or `'pat'` 223 | * Paxos Standard/pax `'Paxos Standard'` or `'pax'` 224 | * Peculium/pcl `'Peculium'` or `'pcl'` 225 | * PeerCoin/ppc `'PeerCoin'` or `'ppc'` 226 | * Perlin/perl `'Perlin'` or `'perl'` 227 | * Pillar/plr `'Pillar'` or `'plr'` 228 | * PIVX/pivx `'PIVX'` or `'pivx'` 229 | * Po.et/poe `'Po.et'` or `'poe'` 230 | * Polymath/poly `'Polymath'` or `'poly'` 231 | * Populous/ppt `'Populous'` or `'ppt'` 232 | * Power Ledger/powr `'Power Ledger'` or `'powr'` 233 | * Presearch/pre `'Presearch'` or `'pre'` 234 | * PrimeCoin/xpm `'PrimeCoin'` or `'xpm'` 235 | * ProtoShares/pts `'ProtoShares'` or `'pts'` 236 | * PumaPay/pma `'PumaPay'` or `'pma'` 237 | * Pundi X/npxs `'Pundi X'` or `'npxs'` 238 | * Qtum/qtum `'Qtum'` or `'qtum'` 239 | * Quant/qnt `'Quant'` or `'qnt'` 240 | * Quantstamp/qsp `'Quantstamp'` or `'qsp'` 241 | * QuarkChain/qkc `'QuarkChain'` or `'qkc'` 242 | * RaiBlocks/xrb `'RaiBlocks'` or `'xrb'` 243 | * Raiden Network Token/rdn `'Raiden Network Token'` or `'rdn'` 244 | * Ravencoin/rvn `'Ravencoin'` or `'rvn'` 245 | * Refereum/rfr `'Refereum'` or `'rfr'` 246 | * Ren/ren `'Ren'` or `'ren'` 247 | * Request/req `'Request'` or `'req'` 248 | * Revain/r `'Revain'` or `'r'` 249 | * Ripio Credit Network/rcn `'Ripio Credit Network'` or `'rcn'` 250 | * Ripple/xrp `'Ripple'` or `'xrp'` 251 | * Salt/salt `'Salt'` or `'salt'` 252 | * Scopuly/sky `'Scopuly'` or `'sky'` 253 | * Sentinel/sent `'Sentinel'` or `'sent'` 254 | * SiaCashCoin/scc `'SiaCashCoin'` or `'scc'` 255 | * Siacoin/sc `'Siacoin'` or `'sc'` 256 | * SingularDTV/sngls `'SingularDTV'` or `'sngls'` 257 | * SingularityNET/agi `'SingularityNET'` or `'agi'` 258 | * SIRIN LABS Token/srn `'SIRIN LABS Token'` or `'srn'` 259 | * SkinCoin/skin `'SkinCoin'` or `'skin'` 260 | * SnowGem/sng `'SnowGem'` or `'sng'` 261 | * Solana/sol `'Solana'` or `'sol'` 262 | * SolarCoin/slr `'SolarCoin'` or `'slr'` 263 | * SOLVE/solve `'SOLVE'` or `'solve'` 264 | * SoMee.Social/ong `'SoMee.Social'` or `'ong'` 265 | * SONM/snm `'SONM'` or `'snm'` 266 | * Spendcoin/spnd `'Spendcoin'` or `'spnd'` 267 | * STASIS EURO/eurs `'STASIS EURO'` or `'eurs'` 268 | * Status/snt `'Status'` or `'snt'` 269 | * STEEM/steem `'STEEM'` or `'steem'` 270 | * Stellar/xlm `'Stellar'` or `'xlm'` 271 | * Storj/storj `'Storj'` or `'storj'` 272 | * Storm/storm `'Storm'` or `'storm'` 273 | * Stox/stx `'Stox'` or `'stx'` 274 | * Stratis/strat `'Stratis'` or `'strat'` 275 | * Streamr DATAcoin/data `'Streamr DATAcoin'` or `'data'` 276 | * Substratum/sub `'Substratum'` or `'sub'` 277 | * SunContract/snc `'SunContract'` or `'snc'` 278 | * Swarm City/swt `'Swarm City'` or `'swt'` 279 | * SwftCoin/swftc `'SwftCoin'` or `'swftc'` 280 | * Synthetix Network/snx `'Synthetix Network'` or `'snx'` 281 | * Syscoin/sys `'Syscoin'` or `'sys'` 282 | * Tael/wabi `'Tael'` or `'wabi'` 283 | * Telcoin/tel `'Telcoin'` or `'tel'` 284 | * TEMCO/temco `'TEMCO'` or `'temco'` 285 | * TenX/pay `'TenX'` or `'pay'` 286 | * Tether/usdt `'Tether'` or `'usdt'` 287 | * Tezos/xtz `'Tezos'` or `'xtz'` 288 | * Tierion/tnt `'Tierion'` or `'tnt'` 289 | * Time New Bank/tnb `'Time New Bank'` or `'tnb'` 290 | * Tripio/trio `'Tripio'` or `'trio'` 291 | * Tron/trx `'Tron'` or `'trx'` 292 | * TrueUSD/tusd `'TrueUSD'` or `'tusd'` 293 | * USD Coin/usdc `'USD Coin'` or `'usdc'` 294 | * USDT ERC-20/usdt20 `'USDT ERC-20'` or `'usdt20'` 295 | * Utrust/utk `'Utrust'` or `'utk'` 296 | * VeChain/ven `'VeChain'` or `'ven'` 297 | * VeChain Mainnet/vet `'VeChain Mainnet'` or `'vet'` 298 | * Verge/xvg `'Verge'` or `'xvg'` 299 | * VertCoin/vtc `'VertCoin'` or `'vtc'` 300 | * VIBE/vibe `'VIBE'` or `'vibe'` 301 | * Viberate/vib `'Viberate'` or `'vib'` 302 | * VoteCoin/vot `'VoteCoin'` or `'vot'` 303 | * Waltonchain/wtc `'Waltonchain'` or `'wtc'` 304 | * Waves/waves `'Waves'` or `'waves'` 305 | * WePower/wpr `'WePower'` or `'wpr'` 306 | * WeTrust/trst `'WeTrust'` or `'trst'` 307 | * Wings/wings `'Wings'` or `'wings'` 308 | * YOU COIN/you `'YOU COIN'` or `'you'` 309 | * Zap/zap `'Zap'` or `'zap'` 310 | * ZCash/zec `'ZCash'` or `'zec'` 311 | * ZClassic/zcl `'ZClassic'` or `'zcl'` 312 | * ZenCash/zen `'ZenCash'` or `'zen'` 313 | * Zilliqa/zil `'Zilliqa'` or `'zil'` 314 | 315 | ### Usage example 316 | 317 | #### Node 318 | ```javascript 319 | var WAValidator = require('trezor-address-validator'); 320 | 321 | var valid = WAValidator.validate('1KFzzGtDdnq5hrwxXGjwVnKzRbvf8WVxck', 'BTC'); 322 | if(valid) 323 | console.log('This is a valid address'); 324 | else 325 | console.log('Address INVALID'); 326 | 327 | // This will log 'This is a valid address' to the console. 328 | ``` 329 | 330 | ```javascript 331 | var WAValidator = require('trezor-address-validator'); 332 | 333 | var valid = WAValidator.validate('1KFzzGtDdnq5hrwxXGjwVnKzRbvf8WVxck', 'litecoin', 'testnet'); 334 | if(valid) 335 | console.log('This is a valid address'); 336 | else 337 | console.log('Address INVALID'); 338 | 339 | // As this is a invalid litecoin address 'Address INVALID' will be logged to console. 340 | ``` 341 | 342 | ```javascript 343 | var WAValidator = require('trezor-address-validator'); 344 | 345 | var currency = WAValidator.findCurrency('xrp'); 346 | if(currency) 347 | console.log('This currency exists'); 348 | else 349 | console.log('Currency INVALID'); 350 | 351 | // As this is a valid currency symbol 'This currency exists' will be logged to console. 352 | ``` 353 | 354 | ```javascript 355 | var WAValidator = require('trezor-address-validator'); 356 | 357 | var currency = WAValidator.findCurrency('random'); 358 | if(currency) 359 | console.log('This currency exists'); 360 | else 361 | console.log('Currency INVALID'); 362 | 363 | // As this is not a valid currency symbol 'Currency INVALID' will be logged to console. 364 | ``` 365 | #### Browser 366 | ```html 367 | 368 | ``` 369 | 370 | ```javascript 371 | // WAValidator is exposed as a global (window.WAValidator) 372 | var valid = WAValidator.validate('1KFzzGtDdnq5hrwxXGjwVnKzRbvf8WVxck', 'bitcoin'); 373 | if(valid) 374 | alert('This is a valid address'); 375 | else 376 | alert('Address INVALID'); 377 | 378 | // This should show a pop up with text 'This is a valid address'. 379 | ``` 380 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | module.exports = function (config) { 3 | config.set({ 4 | basePath: '', 5 | 6 | frameworks: ['mocha', 'chai'], 7 | 8 | files: [ 9 | 'dist/wallet-address-validator.min.js', 10 | 'test/**/*.js' 11 | ], 12 | 13 | reporters: ['progress'], 14 | 15 | port: 9876, 16 | 17 | colors: true, 18 | 19 | logLevel: config.LOG_INFO, 20 | 21 | browsers: ['ChromeHeadless'], 22 | 23 | singleRun: true, 24 | 25 | concurrency: Infinity 26 | }) 27 | }; 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "trezor-address-validator", 3 | "description": "Multicoin address validator for Bitcoin and other altcoins.", 4 | "keywords": [ 5 | "ada", 6 | "btc", 7 | "bitcoin", 8 | "bitcoin cash", 9 | "litecoin", 10 | "decred", 11 | "dogecoin", 12 | "ethereum", 13 | "ripple", 14 | "dash", 15 | "neo", 16 | "gas", 17 | "komodo", 18 | "zcash", 19 | "qtum", 20 | "trx", 21 | "nem", 22 | "waves", 23 | "altcoin", 24 | "bankex", 25 | "monero", 26 | "segwit", 27 | "crypto", 28 | "address", 29 | "wallet", 30 | "validator", 31 | "vertcoin", 32 | "nano", 33 | "raiblocks", 34 | "javascript", 35 | "browser", 36 | "nodejs" 37 | ], 38 | "version": "0.4.4", 39 | "author": "Martin ", 40 | "homepage": "https://github.com/trezor/trezor-address-validator", 41 | "license": "MIT", 42 | "repository": { 43 | "type": "git", 44 | "url": "https://github.com/trezor/trezor-address-validator.git" 45 | }, 46 | "main": "src/wallet_address_validator", 47 | "engines": { 48 | "node": "*" 49 | }, 50 | "scripts": { 51 | "bundle": "browserify src/wallet_address_validator.js --standalone WAValidator --outfile dist/wallet-address-validator.js", 52 | "minify": "uglifyjs -c -m -o dist/wallet-address-validator.min.js -- dist/wallet-address-validator.js", 53 | "test:node": "mocha test", 54 | "test:browser": "npm run bundle && npm run minify && karma start", 55 | "test": "npm run test:node && npm run test:browser", 56 | "start": "npm run bundle && npm run minify && npm test" 57 | }, 58 | "dependencies": { 59 | "base-x": "^3.0.7", 60 | "bech32": "^2.0.0", 61 | "browserify-bignum": "^1.3.0-2", 62 | "cbor-js": "^0.1.0", 63 | "crc": "^3.8.0", 64 | "groestl-hash-js": "1.0.0", 65 | "jssha": "2.3.1", 66 | "lodash": "^4.17.15" 67 | }, 68 | "devDependencies": { 69 | "browserify": "^16.5.0", 70 | "chai": "^4.2.0", 71 | "karma": "^4.4.1", 72 | "karma-chai": "^0.1.0", 73 | "karma-chrome-launcher": "^3.1.0", 74 | "karma-mocha": "^1.3.0", 75 | "mocha": "^7.0.0", 76 | "uglify-es": "^3.3.9" 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/ada_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | var cbor = require('cbor-js'); 3 | var CRC = require('crc'); 4 | var base58 = require('./crypto/base58'); 5 | var { bech32 } = require('bech32'); 6 | 7 | var DEFAULT_NETWORK_TYPE = 'prod'; 8 | 9 | function getDecoded(address) { 10 | try { 11 | var decoded = base58.decode(address); 12 | return cbor.decode(new Uint8Array(decoded).buffer); 13 | } catch (e) { 14 | // if decoding fails, assume invalid address 15 | return null; 16 | } 17 | } 18 | 19 | function isValidLegacyAddress(address) { 20 | var decoded = getDecoded(address); 21 | 22 | if (!decoded || (!Array.isArray(decoded) && decoded.length != 2)) { 23 | return false; 24 | } 25 | 26 | var tagged = decoded[0]; 27 | var validCrc = decoded[1]; 28 | if (typeof (validCrc) != 'number') { 29 | return false; 30 | } 31 | 32 | // get crc of the payload 33 | var crc = CRC.crc32(tagged); 34 | 35 | return crc == validCrc; 36 | } 37 | 38 | // it is not possible to use bitcoin ./crypto/segwit_addr library, the cardano address is too long for that 39 | function isValidBech32Address(address, currency, networkType) { 40 | if (!currency.segwitHrp) { 41 | return false; 42 | } 43 | var hrp = currency.segwitHrp[networkType]; 44 | if (!hrp) { 45 | return false; 46 | } 47 | 48 | try { 49 | var dec = bech32.decode(address, networkType === 'prod' ? 103 : 108); 50 | } catch (err) { 51 | return false; 52 | } 53 | 54 | if (dec === null || dec.prefix !== hrp || dec.words.length < 1 || dec.words[0] > 16) { 55 | return false; 56 | } 57 | 58 | return true; 59 | } 60 | 61 | module.exports = { 62 | isValidAddress: function (address, currency, networkType) { 63 | networkType = networkType || DEFAULT_NETWORK_TYPE; 64 | return isValidLegacyAddress(address) 65 | || isValidBech32Address(address, currency, networkType); 66 | }, 67 | getAddressType: function(address, currency, networkType) { 68 | if (this.isValidAddress(address, currency, networkType)) { 69 | return addressType.ADDRESS; 70 | } 71 | return undefined; 72 | }, 73 | }; 74 | -------------------------------------------------------------------------------- /src/ae_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | var base58 = require('./crypto/base58') 3 | 4 | const ALLOWED_CHARS = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' 5 | 6 | var regexp = new RegExp('^(ak_)([' + ALLOWED_CHARS + ']+)$') // Begins with ak_ followed by 7 | 8 | module.exports = { 9 | isValidAddress: function (address, currency, networkType) { 10 | let match = regexp.exec(address) 11 | if (match !== null) { 12 | return this.verifyChecksum(match[2]) 13 | } else { 14 | return false 15 | } 16 | }, 17 | 18 | verifyChecksum: function (address) { 19 | var decoded = base58.decode(address) 20 | decoded.splice(-4, 4) // remove last 4 elements. Why is base 58 adding them? 21 | return decoded.length === 32 22 | }, 23 | 24 | getAddressType: function(address, currency, networkType) { 25 | if (this.isValidAddress(address, currency, networkType)) { 26 | return addressType.ADDRESS; 27 | } 28 | return undefined; 29 | }, 30 | } 31 | -------------------------------------------------------------------------------- /src/ardr_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | const ardorRegex = new RegExp('^ARDOR(-[A-Z0-9]{4}){3}(-[A-Z0-9]{5})$') 3 | 4 | module.exports = { 5 | isValidAddress: function (address, currency, networkType) { 6 | if (!ardorRegex.test(address)) { 7 | return false 8 | } 9 | 10 | return true 11 | }, 12 | 13 | getAddressType: function(address, currency, networkType) { 14 | if (this.isValidAddress(address, currency, networkType)) { 15 | return addressType.ADDRESS; 16 | } 17 | return undefined; 18 | }, 19 | } 20 | 21 | -------------------------------------------------------------------------------- /src/atom_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | const { bech32 } = require('bech32'); 3 | 4 | const ALLOWED_CHARS = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l' 5 | 6 | var regexp = new RegExp('^(cosmos)1([' + ALLOWED_CHARS + ']+)$') // cosmos + bech32 separated by '1' 7 | 8 | module.exports = { 9 | isValidAddress: function (address, currency, networkType) { 10 | return regexp.exec(address) !== null; 11 | }, 12 | 13 | verifyChecksum: function (address) { 14 | const decoded = bech32.decode(address); 15 | return decoded && decoded.words.length === 32; 16 | }, 17 | 18 | getAddressType: function(address, currency, networkType) { 19 | if (this.isValidAddress(address)) { 20 | return addressType.ADDRESS; 21 | } 22 | return undefined; 23 | }, 24 | } 25 | 26 | -------------------------------------------------------------------------------- /src/bch_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | var cryptoUtils = require('./crypto/utils'); 3 | var BTCValidator = require('./bitcoin_validator'); 4 | 5 | var GENERATOR = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]; 6 | 7 | function polymod(values) { 8 | var chk = 1; 9 | for (var p = 0; p < values.length; ++p) { 10 | var top = chk >> 25; 11 | chk = ((chk & 0x1ffffff) << 5) ^ values[p]; 12 | for (var i = 0; i < 5; ++i) { 13 | if ((top >> i) & 1) { 14 | chk ^= GENERATOR[i]; 15 | } 16 | } 17 | } 18 | return chk; 19 | } 20 | 21 | function hrpExpand(hrp) { 22 | var ret = []; 23 | var p; 24 | for (p = 0; p < hrp.length; ++p) { 25 | ret.push(hrp.charCodeAt(p) >> 5); 26 | } 27 | ret.push(0); 28 | for (p = 0; p < hrp.length; ++p) { 29 | ret.push(hrp.charCodeAt(p) & 31); 30 | } 31 | return ret; 32 | } 33 | 34 | function verifyChecksum(hrp, data) { 35 | return polymod(hrpExpand(hrp).concat(data)) === 1; 36 | } 37 | 38 | function validateAddress(address, currency, networkType) { 39 | var prefix = 'bitcoincash'; 40 | var regexp = new RegExp(currency.regexp); 41 | var raw_address; 42 | 43 | var res = address.split(':'); 44 | if (res.length > 2) { 45 | return false; 46 | } 47 | if (res.length === 1) { 48 | raw_address = address 49 | } else { 50 | if (res[0] !== 'bitcoincash') { 51 | return false; 52 | } 53 | raw_address = res[1]; 54 | } 55 | 56 | if (!regexp.test(raw_address)) { 57 | return false; 58 | } 59 | 60 | if (raw_address.toLowerCase() != raw_address && raw_address.toUpperCase() != raw_address) { 61 | return false; 62 | } 63 | 64 | var decoded = cryptoUtils.base32.b32decode(raw_address); 65 | if (networkType === 'testnet') { 66 | prefix = 'bchtest'; 67 | } 68 | 69 | try { 70 | if (verifyChecksum(prefix, decoded)) { 71 | return false; 72 | } 73 | } catch (e) { 74 | return false; 75 | } 76 | 77 | return true; 78 | } 79 | 80 | module.exports = { 81 | isValidAddress: function (address, currency, networkType) { 82 | return validateAddress(address, currency, networkType) || 83 | (currency.symbol !== 'bch' && BTCValidator.isValidAddress(address, currency, networkType)); 84 | }, 85 | getAddressType: function(address, currency, networkType) { 86 | networkType = networkType || DEFAULT_NETWORK_TYPE; 87 | if (this.isValidAddress(address, currency, networkType)) { 88 | return addressType.ADDRESS; 89 | } 90 | return undefined; 91 | } 92 | } -------------------------------------------------------------------------------- /src/binance_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | module.exports = { 3 | isValidAddress: function (address) { 4 | var binanceAddress = address.slice(address.indexOf('bnb')); 5 | if (binanceAddress.length !== 42) { 6 | return false; 7 | } 8 | return true; 9 | }, 10 | 11 | getAddressType: function(address, currency, networkType) { 12 | if (this.isValidAddress(address, currency, networkType)) { 13 | return addressType.ADDRESS; 14 | } 15 | return undefined; 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /src/bitcoin_validator.js: -------------------------------------------------------------------------------- 1 | var bech32 = require('./crypto/bech32'); 2 | var base58 = require('./crypto/base58'); 3 | var cryptoUtils = require('./crypto/utils'); 4 | const { addressType } = require('./crypto/utils'); 5 | 6 | var DEFAULT_NETWORK_TYPE = 'prod'; 7 | 8 | function getDecoded(address) { 9 | try { 10 | return base58.decode(address); 11 | } catch (e) { 12 | // if decoding fails, assume invalid address 13 | return null; 14 | } 15 | } 16 | 17 | function getChecksum(hashFunction, payload) { 18 | // Each currency may implement different hashing algorithm 19 | switch (hashFunction) { 20 | // blake then keccak hash chain 21 | case 'blake256keccak256': 22 | var blake = cryptoUtils.blake2b256(payload); 23 | return cryptoUtils.keccak256Checksum(Buffer.from(blake, 'hex')); 24 | case 'blake256': 25 | return cryptoUtils.blake256Checksum(payload); 26 | case 'keccak256': 27 | return cryptoUtils.keccak256Checksum(payload); 28 | case 'groestl512x2': 29 | return cryptoUtils.groestl512x2(payload); 30 | case 'sha256': 31 | default: 32 | return cryptoUtils.sha256Checksum(payload); 33 | } 34 | } 35 | 36 | function getAddressType(address, currency) { 37 | currency = currency || {}; 38 | // should be 25 bytes per btc address spec and 26 decred 39 | var expectedLength = currency.expectedLength || 25; 40 | var hashFunction = currency.hashFunction || 'sha256'; 41 | var decoded = getDecoded(address); 42 | 43 | if (decoded) { 44 | var length = decoded.length; 45 | 46 | if (length !== expectedLength) { 47 | return null; 48 | } 49 | 50 | if(currency.regex) { 51 | if(!currency.regex.test(address)) { 52 | return null; 53 | } 54 | } 55 | 56 | var checksum = cryptoUtils.toHex(decoded.slice(length - 4, length)), 57 | body = cryptoUtils.toHex(decoded.slice(0, length - 4)), 58 | goodChecksum = getChecksum(hashFunction, body); 59 | 60 | return checksum === goodChecksum ? cryptoUtils.toHex(decoded.slice(0, expectedLength - 24)) : null; 61 | } 62 | 63 | return null; 64 | } 65 | 66 | function getOutputIndex(address, currency, networkType) { 67 | const addressType = getAddressType(address, currency); 68 | if (addressType) { 69 | const correctAddressTypes = 70 | currency.addressTypes[networkType] || 71 | Object.keys(currency.addressTypes).reduce((all, key) => { 72 | return all.concat(currency.addressTypes[key]); 73 | }, []); 74 | return correctAddressTypes.indexOf(addressType); 75 | } 76 | return null; 77 | } 78 | 79 | function isValidPayToPublicKeyHashAddress(address, currency, networkType) { 80 | return getOutputIndex(address, currency, networkType) === 0; 81 | } 82 | 83 | function isValidPayToScriptHashAddress(address, currency, networkType) { 84 | return getOutputIndex(address, currency, networkType) > 0; 85 | } 86 | 87 | function isValidPayToWitnessScriptHashAddress(address, currency, networkType) { 88 | try { 89 | const hrp = currency.segwitHrp[networkType]; 90 | const decoded = bech32.decode(hrp, address); 91 | return decoded && decoded.version === 0 && decoded.program.length === 32; 92 | } catch (err) { 93 | return null; 94 | } 95 | } 96 | 97 | function isValidPayToWitnessPublicKeyHashAddress(address, currency, networkType) { 98 | try { 99 | const hrp = currency.segwitHrp[networkType]; 100 | const decoded = bech32.decode(hrp, address); 101 | return decoded && decoded.version === 0 && decoded.program.length === 20; 102 | } catch (err) { 103 | return null; 104 | } 105 | } 106 | 107 | function isValidPayToTaprootAddress(address, currency, networkType) { 108 | try { 109 | const hrp = currency.segwitHrp[networkType]; 110 | decoded = bech32.decode(hrp, address, true); 111 | return decoded && decoded.version === 1 && decoded.program.length === 32; 112 | } catch (err) {} 113 | return null; 114 | } 115 | 116 | function isValidSegwitAddress(address, currency, networkType) { 117 | if (!currency.segwitHrp) { 118 | return false; 119 | } 120 | var hrp = currency.segwitHrp[networkType]; 121 | if (!hrp) { 122 | return false; 123 | } 124 | // try bech32 first 125 | let ret = bech32.decode(hrp, address, false); 126 | if (ret) { 127 | if (ret.version === 0 || ret.program.length === 20 || ret.program.length === 32) { 128 | return false; 129 | } else { 130 | return address.toLowerCase() === bech32.encode(hrp, ret.version, ret.program, false); 131 | } 132 | } 133 | // then try bech32m 134 | ret = bech32.decode(hrp, address, true); 135 | if (ret) { 136 | if (ret.version > 1 || ret.program.length !== 32) { 137 | return address.toLowerCase() === bech32.encode(hrp, ret.version, ret.program, true); 138 | } 139 | } 140 | return false; 141 | } 142 | 143 | module.exports = { 144 | isValidAddress: function (address, currency, networkType) { 145 | networkType = networkType || DEFAULT_NETWORK_TYPE; 146 | const addrType = this.getAddressType(address, currency, networkType); 147 | // Though WITNESS_UNKNOWN is a valid address, it's not spendable - so we mark it as invalid 148 | return addrType !== undefined && addrType !== addressType.WITNESS_UNKNOWN; 149 | }, 150 | getAddressType: function(address, currency, networkType) { 151 | networkType = networkType || DEFAULT_NETWORK_TYPE; 152 | if (isValidPayToPublicKeyHashAddress(address, currency, networkType)) { 153 | return addressType.P2PKH; 154 | } 155 | if (isValidPayToScriptHashAddress(address, currency, networkType)) { 156 | return addressType.P2SH; 157 | } 158 | if (isValidPayToWitnessScriptHashAddress(address, currency, networkType)) { 159 | return addressType.P2WSH; 160 | } 161 | if (isValidPayToWitnessPublicKeyHashAddress(address, currency, networkType)) { 162 | return addressType.P2WPKH; 163 | } 164 | if (isValidPayToTaprootAddress(address, currency, networkType)) { 165 | return addressType.P2TR; 166 | } 167 | if (isValidSegwitAddress(address, currency, networkType)) { 168 | return addressType.WITNESS_UNKNOWN; 169 | } 170 | return undefined; 171 | }, 172 | }; 173 | -------------------------------------------------------------------------------- /src/crypto/base32.js: -------------------------------------------------------------------------------- 1 | var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 2 | 3 | /** 4 | * Encode a string to base32 5 | */ 6 | var b32encode = function(s) { 7 | var parts = []; 8 | var quanta = Math.floor((s.length / 5)); 9 | var leftover = s.length % 5; 10 | 11 | if (leftover != 0) { 12 | for (var i = 0; i < (5 - leftover); i++) { 13 | s += '\x00'; 14 | } 15 | quanta += 1; 16 | } 17 | 18 | for (var i = 0; i < quanta; i++) { 19 | parts.push(alphabet.charAt(s.charCodeAt(i * 5) >> 3)); 20 | parts.push(alphabet.charAt(((s.charCodeAt(i * 5) & 0x07) << 2) | (s.charCodeAt(i * 5 + 1) >> 6))); 21 | parts.push(alphabet.charAt(((s.charCodeAt(i * 5 + 1) & 0x3F) >> 1))); 22 | parts.push(alphabet.charAt(((s.charCodeAt(i * 5 + 1) & 0x01) << 4) | (s.charCodeAt(i * 5 + 2) >> 4))); 23 | parts.push(alphabet.charAt(((s.charCodeAt(i * 5 + 2) & 0x0F) << 1) | (s.charCodeAt(i * 5 + 3) >> 7))); 24 | parts.push(alphabet.charAt(((s.charCodeAt(i * 5 + 3) & 0x7F) >> 2))); 25 | parts.push(alphabet.charAt(((s.charCodeAt(i * 5 + 3) & 0x03) << 3) | (s.charCodeAt(i * 5 + 4) >> 5))); 26 | parts.push(alphabet.charAt(((s.charCodeAt(i * 5 + 4) & 0x1F)))); 27 | } 28 | 29 | var replace = 0; 30 | if (leftover == 1) replace = 6; 31 | else if (leftover == 2) replace = 4; 32 | else if (leftover == 3) replace = 3; 33 | else if (leftover == 4) replace = 1; 34 | 35 | for (var i = 0; i < replace; i++) parts.pop(); 36 | for (var i = 0; i < replace; i++) parts.push("="); 37 | 38 | return parts.join(""); 39 | } 40 | 41 | /** 42 | * Decode a base32 string. 43 | * This is made specifically for our use, deals only with proper strings 44 | */ 45 | var b32decode = function(s) { 46 | var r = new ArrayBuffer(s.length * 5 / 8); 47 | var b = new Uint8Array(r); 48 | for (var j = 0; j < s.length / 8; j++) { 49 | var v = [0, 0, 0, 0, 0, 0, 0, 0]; 50 | for (var i = 0; i < 8; ++i) { 51 | v[i] = alphabet.indexOf(s[j * 8 + i]); 52 | } 53 | var i = 0; 54 | b[j * 5 + 0] = (v[i + 0] << 3) | (v[i + 1] >> 2); 55 | b[j * 5 + 1] = ((v[i + 1] & 0x3) << 6) | (v[i + 2] << 1) | (v[i + 3] >> 4); 56 | b[j * 5 + 2] = ((v[i + 3] & 0xf) << 4) | (v[i + 4] >> 1); 57 | b[j * 5 + 3] = ((v[i + 4] & 0x1) << 7) | (v[i + 5] << 2) | (v[i + 6] >> 3); 58 | b[j * 5 + 4] = ((v[i + 6] & 0x7) << 5) | (v[i + 7]); 59 | } 60 | return b; 61 | } 62 | 63 | module.exports = { 64 | b32decode: b32decode, 65 | b32encode: b32encode 66 | }; -------------------------------------------------------------------------------- /src/crypto/base58.js: -------------------------------------------------------------------------------- 1 | // Base58 encoding/decoding 2 | // Originally written by Mike Hearn for BitcoinJ 3 | // Copyright (c) 2011 Google Inc 4 | // Ported to JavaScript by Stefan Thomas 5 | // Merged Buffer refactorings from base58-native by Stephen Pair 6 | // Copyright (c) 2013 BitPay Inc 7 | 8 | var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; 9 | var ALPHABET_MAP = {}; 10 | for (var i = 0; i < ALPHABET.length; ++i) { 11 | ALPHABET_MAP[ALPHABET.charAt(i)] = i; 12 | } 13 | var BASE = ALPHABET.length; 14 | 15 | module.exports = { 16 | decode: function(string) { 17 | if (string.length === 0) return []; 18 | 19 | var i, j, bytes = [0]; 20 | for (i = 0; i < string.length; ++i) { 21 | var c = string[i]; 22 | if (!(c in ALPHABET_MAP)) throw new Error('Non-base58 character'); 23 | 24 | for (j = 0; j < bytes.length; ++j) bytes[j] *= BASE 25 | bytes[0] += ALPHABET_MAP[c]; 26 | 27 | var carry = 0; 28 | for (j = 0; j < bytes.length; ++j) { 29 | bytes[j] += carry; 30 | carry = bytes[j] >> 8; 31 | bytes[j] &= 0xff 32 | } 33 | 34 | while (carry) { 35 | bytes.push(carry & 0xff); 36 | carry >>= 8; 37 | } 38 | } 39 | // deal with leading zeros 40 | for (i = 0; string[i] === '1' && i < string.length - 1; ++i){ 41 | bytes.push(0); 42 | } 43 | 44 | return bytes.reverse(); 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /src/crypto/bech32.js: -------------------------------------------------------------------------------- 1 | const { bech32, bech32m } = require('bech32'); 2 | 3 | function convertbits(data, frombits, tobits, pad) { 4 | var acc = 0; 5 | var bits = 0; 6 | var ret = []; 7 | var maxv = (1 << tobits) - 1; 8 | for (var p = 0; p < data.length; ++p) { 9 | var value = data[p]; 10 | if (value < 0 || (value >> frombits) !== 0) { 11 | return null; 12 | } 13 | acc = (acc << frombits) | value; 14 | bits += frombits; 15 | while (bits >= tobits) { 16 | bits -= tobits; 17 | ret.push((acc >> bits) & maxv); 18 | } 19 | } 20 | if (pad) { 21 | if (bits > 0) { 22 | ret.push((acc << (tobits - bits)) & maxv); 23 | } 24 | } else if (bits >= frombits || ((acc << (tobits - bits)) & maxv)) { 25 | return null; 26 | } 27 | return ret; 28 | } 29 | 30 | function decode(hrp, addr, m = false) { 31 | let dec; 32 | try { 33 | if (m) { 34 | dec = bech32m.decode(addr); 35 | } else { 36 | dec = bech32.decode(addr); 37 | } 38 | } catch (err) { 39 | return null; 40 | } 41 | if ( 42 | dec === null || 43 | dec.prefix !== hrp || 44 | dec.words.length < 1 || 45 | dec.words[0] > 16 46 | ) { 47 | return null; 48 | } 49 | var res = convertbits(dec.words.slice(1), 5, 8, false); 50 | if (res === null || res.length < 2 || res.length > 40) { 51 | return null; 52 | } 53 | return { version: dec.words[0], program: res }; 54 | } 55 | 56 | function encode(hrp, version, program, m = false) { 57 | var ret; 58 | if (m) { 59 | ret = bech32m.encode(hrp, [version].concat(convertbits(program, 8, 5, true))); 60 | } else { 61 | ret = bech32.encode( hrp, [version].concat(convertbits(program, 8, 5, true))); 62 | } 63 | if (decode(hrp, ret, m) === null) { 64 | return null; 65 | } 66 | return ret; 67 | } 68 | 69 | module.exports = { decode, encode }; -------------------------------------------------------------------------------- /src/crypto/biginteger.js: -------------------------------------------------------------------------------- 1 | /* 2 | JavaScript BigInteger library version 0.9.1 3 | http://silentmatt.com/biginteger/ 4 | Copyright (c) 2009 Matthew Crumley 5 | Copyright (c) 2010,2011 by John Tobey 6 | Licensed under the MIT license. 7 | Support for arbitrary internal representation base was added by 8 | Vitaly Magerya. 9 | */ 10 | 11 | /* 12 | File: biginteger.js 13 | Exports: 14 | 15 | */ 16 | (function(exports) { 17 | "use strict"; 18 | /* 19 | Class: BigInteger 20 | An arbitrarily-large integer. 21 | objects should be considered immutable. None of the "built-in" 22 | methods modify *this* or their arguments. All properties should be 23 | considered private. 24 | All the methods of instances can be called "statically". The 25 | static versions are convenient if you don't already have a 26 | object. 27 | As an example, these calls are equivalent. 28 | > BigInteger(4).multiply(5); // returns BigInteger(20); 29 | > BigInteger.multiply(4, 5); // returns BigInteger(20); 30 | > var a = 42; 31 | > var a = BigInteger.toJSValue("0b101010"); // Not completely useless... 32 | */ 33 | 34 | var CONSTRUCT = {}; // Unique token to call "private" version of constructor 35 | 36 | /* 37 | Constructor: BigInteger() 38 | Convert a value to a . 39 | Although is the constructor for objects, it is 40 | best not to call it as a constructor. If *n* is a object, it is 41 | simply returned as-is. Otherwise, is equivalent to 42 | without a radix argument. 43 | > var n0 = BigInteger(); // Same as 44 | > var n1 = BigInteger("123"); // Create a new with value 123 45 | > var n2 = BigInteger(123); // Create a new with value 123 46 | > var n3 = BigInteger(n2); // Return n2, unchanged 47 | The constructor form only takes an array and a sign. *n* must be an 48 | array of numbers in little-endian order, where each digit is between 0 49 | and BigInteger.base. The second parameter sets the sign: -1 for 50 | negative, +1 for positive, or 0 for zero. The array is *not copied and 51 | may be modified*. If the array contains only zeros, the sign parameter 52 | is ignored and is forced to zero. 53 | > new BigInteger([5], -1): create a new BigInteger with value -5 54 | Parameters: 55 | n - Value to convert to a . 56 | Returns: 57 | A value. 58 | See Also: 59 | , 60 | */ 61 | function BigInteger(n, s, token) { 62 | 63 | if (token !== CONSTRUCT) { 64 | if (n instanceof BigInteger) { 65 | return n; 66 | } 67 | else if (typeof n === "undefined") { 68 | return ZERO; 69 | } 70 | return BigInteger.parse(n); 71 | } 72 | 73 | n = n || []; // Provide the nullary constructor for subclasses. 74 | while (n.length && !n[n.length - 1]) { 75 | --n.length; 76 | } 77 | this._d = n; 78 | this._s = n.length ? (s || 1) : 0; 79 | } 80 | 81 | BigInteger._construct = function(n, s) { 82 | return new BigInteger(n, s, CONSTRUCT); 83 | }; 84 | 85 | // Base-10 speedup hacks in parse, toString, exp10 and log functions 86 | // require base to be a power of 10. 10^7 is the largest such power 87 | // that won't cause a precision loss when digits are multiplied. 88 | var BigInteger_base = 10000000; 89 | var BigInteger_base_log10 = 7; 90 | 91 | BigInteger.base = BigInteger_base; 92 | BigInteger.base_log10 = BigInteger_base_log10; 93 | 94 | var ZERO = new BigInteger([], 0, CONSTRUCT); 95 | // Constant: ZERO 96 | // 0. 97 | BigInteger.ZERO = ZERO; 98 | 99 | var ONE = new BigInteger([1], 1, CONSTRUCT); 100 | // Constant: ONE 101 | // 1. 102 | BigInteger.ONE = ONE; 103 | 104 | var M_ONE = new BigInteger(ONE._d, -1, CONSTRUCT); 105 | // Constant: M_ONE 106 | // -1. 107 | BigInteger.M_ONE = M_ONE; 108 | 109 | // Constant: _0 110 | // Shortcut for . 111 | BigInteger._0 = ZERO; 112 | 113 | // Constant: _1 114 | // Shortcut for . 115 | BigInteger._1 = ONE; 116 | 117 | /* 118 | Constant: small 119 | Array of from 0 to 36. 120 | These are used internally for parsing, but useful when you need a "small" 121 | . 122 | See Also: 123 | , , <_0>, <_1> 124 | */ 125 | BigInteger.small = [ 126 | ZERO, 127 | ONE, 128 | /* Assuming BigInteger_base > 36 */ 129 | new BigInteger( [2], 1, CONSTRUCT), 130 | new BigInteger( [3], 1, CONSTRUCT), 131 | new BigInteger( [4], 1, CONSTRUCT), 132 | new BigInteger( [5], 1, CONSTRUCT), 133 | new BigInteger( [6], 1, CONSTRUCT), 134 | new BigInteger( [7], 1, CONSTRUCT), 135 | new BigInteger( [8], 1, CONSTRUCT), 136 | new BigInteger( [9], 1, CONSTRUCT), 137 | new BigInteger([10], 1, CONSTRUCT), 138 | new BigInteger([11], 1, CONSTRUCT), 139 | new BigInteger([12], 1, CONSTRUCT), 140 | new BigInteger([13], 1, CONSTRUCT), 141 | new BigInteger([14], 1, CONSTRUCT), 142 | new BigInteger([15], 1, CONSTRUCT), 143 | new BigInteger([16], 1, CONSTRUCT), 144 | new BigInteger([17], 1, CONSTRUCT), 145 | new BigInteger([18], 1, CONSTRUCT), 146 | new BigInteger([19], 1, CONSTRUCT), 147 | new BigInteger([20], 1, CONSTRUCT), 148 | new BigInteger([21], 1, CONSTRUCT), 149 | new BigInteger([22], 1, CONSTRUCT), 150 | new BigInteger([23], 1, CONSTRUCT), 151 | new BigInteger([24], 1, CONSTRUCT), 152 | new BigInteger([25], 1, CONSTRUCT), 153 | new BigInteger([26], 1, CONSTRUCT), 154 | new BigInteger([27], 1, CONSTRUCT), 155 | new BigInteger([28], 1, CONSTRUCT), 156 | new BigInteger([29], 1, CONSTRUCT), 157 | new BigInteger([30], 1, CONSTRUCT), 158 | new BigInteger([31], 1, CONSTRUCT), 159 | new BigInteger([32], 1, CONSTRUCT), 160 | new BigInteger([33], 1, CONSTRUCT), 161 | new BigInteger([34], 1, CONSTRUCT), 162 | new BigInteger([35], 1, CONSTRUCT), 163 | new BigInteger([36], 1, CONSTRUCT) 164 | ]; 165 | 166 | // Used for parsing/radix conversion 167 | BigInteger.digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""); 168 | 169 | /* 170 | Method: toString 171 | Convert a to a string. 172 | When *base* is greater than 10, letters are upper case. 173 | Parameters: 174 | base - Optional base to represent the number in (default is base 10). 175 | Must be between 2 and 36 inclusive, or an Error will be thrown. 176 | Returns: 177 | The string representation of the . 178 | */ 179 | BigInteger.prototype.toString = function(base) { 180 | base = +base || 10; 181 | if (base < 2 || base > 36) { 182 | throw new Error("illegal radix " + base + "."); 183 | } 184 | if (this._s === 0) { 185 | return "0"; 186 | } 187 | if (base === 10) { 188 | var str = this._s < 0 ? "-" : ""; 189 | str += this._d[this._d.length - 1].toString(); 190 | for (var i = this._d.length - 2; i >= 0; i--) { 191 | var group = this._d[i].toString(); 192 | while (group.length < BigInteger_base_log10) group = '0' + group; 193 | str += group; 194 | } 195 | return str; 196 | } 197 | else { 198 | var numerals = BigInteger.digits; 199 | base = BigInteger.small[base]; 200 | var sign = this._s; 201 | 202 | var n = this.abs(); 203 | var digits = []; 204 | var digit; 205 | 206 | while (n._s !== 0) { 207 | var divmod = n.divRem(base); 208 | n = divmod[0]; 209 | digit = divmod[1]; 210 | // TODO: This could be changed to unshift instead of reversing at the end. 211 | // Benchmark both to compare speeds. 212 | digits.push(numerals[digit.valueOf()]); 213 | } 214 | return (sign < 0 ? "-" : "") + digits.reverse().join(""); 215 | } 216 | }; 217 | 218 | // Verify strings for parsing 219 | BigInteger.radixRegex = [ 220 | /^$/, 221 | /^$/, 222 | /^[01]*$/, 223 | /^[012]*$/, 224 | /^[0-3]*$/, 225 | /^[0-4]*$/, 226 | /^[0-5]*$/, 227 | /^[0-6]*$/, 228 | /^[0-7]*$/, 229 | /^[0-8]*$/, 230 | /^[0-9]*$/, 231 | /^[0-9aA]*$/, 232 | /^[0-9abAB]*$/, 233 | /^[0-9abcABC]*$/, 234 | /^[0-9a-dA-D]*$/, 235 | /^[0-9a-eA-E]*$/, 236 | /^[0-9a-fA-F]*$/, 237 | /^[0-9a-gA-G]*$/, 238 | /^[0-9a-hA-H]*$/, 239 | /^[0-9a-iA-I]*$/, 240 | /^[0-9a-jA-J]*$/, 241 | /^[0-9a-kA-K]*$/, 242 | /^[0-9a-lA-L]*$/, 243 | /^[0-9a-mA-M]*$/, 244 | /^[0-9a-nA-N]*$/, 245 | /^[0-9a-oA-O]*$/, 246 | /^[0-9a-pA-P]*$/, 247 | /^[0-9a-qA-Q]*$/, 248 | /^[0-9a-rA-R]*$/, 249 | /^[0-9a-sA-S]*$/, 250 | /^[0-9a-tA-T]*$/, 251 | /^[0-9a-uA-U]*$/, 252 | /^[0-9a-vA-V]*$/, 253 | /^[0-9a-wA-W]*$/, 254 | /^[0-9a-xA-X]*$/, 255 | /^[0-9a-yA-Y]*$/, 256 | /^[0-9a-zA-Z]*$/ 257 | ]; 258 | 259 | /* 260 | Function: parse 261 | Parse a string into a . 262 | *base* is optional but, if provided, must be from 2 to 36 inclusive. If 263 | *base* is not provided, it will be guessed based on the leading characters 264 | of *s* as follows: 265 | - "0x" or "0X": *base* = 16 266 | - "0c" or "0C": *base* = 8 267 | - "0b" or "0B": *base* = 2 268 | - else: *base* = 10 269 | If no base is provided, or *base* is 10, the number can be in exponential 270 | form. For example, these are all valid: 271 | > BigInteger.parse("1e9"); // Same as "1000000000" 272 | > BigInteger.parse("1.234*10^3"); // Same as 1234 273 | > BigInteger.parse("56789 * 10 ** -2"); // Same as 567 274 | If any characters fall outside the range defined by the radix, an exception 275 | will be thrown. 276 | Parameters: 277 | s - The string to parse. 278 | base - Optional radix (default is to guess based on *s*). 279 | Returns: 280 | a instance. 281 | */ 282 | BigInteger.parse = function(s, base) { 283 | // Expands a number in exponential form to decimal form. 284 | // expandExponential("-13.441*10^5") === "1344100"; 285 | // expandExponential("1.12300e-1") === "0.112300"; 286 | // expandExponential(1000000000000000000000000000000) === "1000000000000000000000000000000"; 287 | function expandExponential(str) { 288 | str = str.replace(/\s*[*xX]\s*10\s*(\^|\*\*)\s*/, "e"); 289 | 290 | return str.replace(/^([+\-])?(\d+)\.?(\d*)[eE]([+\-]?\d+)$/, function(x, s, n, f, c) { 291 | c = +c; 292 | var l = c < 0; 293 | var i = n.length + c; 294 | x = (l ? n : f).length; 295 | c = ((c = Math.abs(c)) >= x ? c - x + l : 0); 296 | var z = (new Array(c + 1)).join("0"); 297 | var r = n + f; 298 | return (s || "") + (l ? r = z + r : r += z).substr(0, i += l ? z.length : 0) + (i < r.length ? "." + r.substr(i) : ""); 299 | }); 300 | } 301 | 302 | s = s.toString(); 303 | if (typeof base === "undefined" || +base === 10) { 304 | s = expandExponential(s); 305 | } 306 | 307 | var prefixRE; 308 | if (typeof base === "undefined") { 309 | prefixRE = '0[xcb]'; 310 | } 311 | else if (base == 16) { 312 | prefixRE = '0x'; 313 | } 314 | else if (base == 8) { 315 | prefixRE = '0c'; 316 | } 317 | else if (base == 2) { 318 | prefixRE = '0b'; 319 | } 320 | else { 321 | prefixRE = ''; 322 | } 323 | var parts = new RegExp('^([+\\-]?)(' + prefixRE + ')?([0-9a-z]*)(?:\\.\\d*)?$', 'i').exec(s); 324 | if (parts) { 325 | var sign = parts[1] || "+"; 326 | var baseSection = parts[2] || ""; 327 | var digits = parts[3] || ""; 328 | 329 | if (typeof base === "undefined") { 330 | // Guess base 331 | if (baseSection === "0x" || baseSection === "0X") { // Hex 332 | base = 16; 333 | } 334 | else if (baseSection === "0c" || baseSection === "0C") { // Octal 335 | base = 8; 336 | } 337 | else if (baseSection === "0b" || baseSection === "0B") { // Binary 338 | base = 2; 339 | } 340 | else { 341 | base = 10; 342 | } 343 | } 344 | else if (base < 2 || base > 36) { 345 | throw new Error("Illegal radix " + base + "."); 346 | } 347 | 348 | base = +base; 349 | 350 | // Check for digits outside the range 351 | if (!(BigInteger.radixRegex[base].test(digits))) { 352 | throw new Error("Bad digit for radix " + base); 353 | } 354 | 355 | // Strip leading zeros, and convert to array 356 | digits = digits.replace(/^0+/, "").split(""); 357 | if (digits.length === 0) { 358 | return ZERO; 359 | } 360 | 361 | // Get the sign (we know it's not zero) 362 | sign = (sign === "-") ? -1 : 1; 363 | 364 | // Optimize 10 365 | if (base == 10) { 366 | var d = []; 367 | while (digits.length >= BigInteger_base_log10) { 368 | d.push(parseInt(digits.splice(digits.length-BigInteger.base_log10, BigInteger.base_log10).join(''), 10)); 369 | } 370 | d.push(parseInt(digits.join(''), 10)); 371 | return new BigInteger(d, sign, CONSTRUCT); 372 | } 373 | 374 | // Do the conversion 375 | var d = ZERO; 376 | base = BigInteger.small[base]; 377 | var small = BigInteger.small; 378 | for (var i = 0; i < digits.length; i++) { 379 | d = d.multiply(base).add(small[parseInt(digits[i], 36)]); 380 | } 381 | return new BigInteger(d._d, sign, CONSTRUCT); 382 | } 383 | else { 384 | throw new Error("Invalid BigInteger format: " + s); 385 | } 386 | }; 387 | 388 | /* 389 | Function: add 390 | Add two . 391 | Parameters: 392 | n - The number to add to *this*. Will be converted to a . 393 | Returns: 394 | The numbers added together. 395 | See Also: 396 | , , , 397 | */ 398 | BigInteger.prototype.add = function(n) { 399 | if (this._s === 0) { 400 | return BigInteger(n); 401 | } 402 | 403 | n = BigInteger(n); 404 | if (n._s === 0) { 405 | return this; 406 | } 407 | if (this._s !== n._s) { 408 | n = n.negate(); 409 | return this.subtract(n); 410 | } 411 | 412 | var a = this._d; 413 | var b = n._d; 414 | var al = a.length; 415 | var bl = b.length; 416 | var sum = new Array(Math.max(al, bl) + 1); 417 | var size = Math.min(al, bl); 418 | var carry = 0; 419 | var digit; 420 | 421 | for (var i = 0; i < size; i++) { 422 | digit = a[i] + b[i] + carry; 423 | sum[i] = digit % BigInteger_base; 424 | carry = (digit / BigInteger_base) | 0; 425 | } 426 | if (bl > al) { 427 | a = b; 428 | al = bl; 429 | } 430 | for (i = size; carry && i < al; i++) { 431 | digit = a[i] + carry; 432 | sum[i] = digit % BigInteger_base; 433 | carry = (digit / BigInteger_base) | 0; 434 | } 435 | if (carry) { 436 | sum[i] = carry; 437 | } 438 | 439 | for ( ; i < al; i++) { 440 | sum[i] = a[i]; 441 | } 442 | 443 | return new BigInteger(sum, this._s, CONSTRUCT); 444 | }; 445 | 446 | /* 447 | Function: negate 448 | Get the additive inverse of a . 449 | Returns: 450 | A with the same magnatude, but with the opposite sign. 451 | See Also: 452 | 453 | */ 454 | BigInteger.prototype.negate = function() { 455 | return new BigInteger(this._d, (-this._s) | 0, CONSTRUCT); 456 | }; 457 | 458 | /* 459 | Function: abs 460 | Get the absolute value of a . 461 | Returns: 462 | A with the same magnatude, but always positive (or zero). 463 | See Also: 464 | 465 | */ 466 | BigInteger.prototype.abs = function() { 467 | return (this._s < 0) ? this.negate() : this; 468 | }; 469 | 470 | /* 471 | Function: subtract 472 | Subtract two . 473 | Parameters: 474 | n - The number to subtract from *this*. Will be converted to a . 475 | Returns: 476 | The *n* subtracted from *this*. 477 | See Also: 478 | , , , 479 | */ 480 | BigInteger.prototype.subtract = function(n) { 481 | if (this._s === 0) { 482 | return BigInteger(n).negate(); 483 | } 484 | 485 | n = BigInteger(n); 486 | if (n._s === 0) { 487 | return this; 488 | } 489 | if (this._s !== n._s) { 490 | n = n.negate(); 491 | return this.add(n); 492 | } 493 | 494 | var m = this; 495 | // negative - negative => -|a| - -|b| => -|a| + |b| => |b| - |a| 496 | if (this._s < 0) { 497 | m = new BigInteger(n._d, 1, CONSTRUCT); 498 | n = new BigInteger(this._d, 1, CONSTRUCT); 499 | } 500 | 501 | // Both are positive => a - b 502 | var sign = m.compareAbs(n); 503 | if (sign === 0) { 504 | return ZERO; 505 | } 506 | else if (sign < 0) { 507 | // swap m and n 508 | var t = n; 509 | n = m; 510 | m = t; 511 | } 512 | 513 | // a > b 514 | var a = m._d; 515 | var b = n._d; 516 | var al = a.length; 517 | var bl = b.length; 518 | var diff = new Array(al); // al >= bl since a > b 519 | var borrow = 0; 520 | var i; 521 | var digit; 522 | 523 | for (i = 0; i < bl; i++) { 524 | digit = a[i] - borrow - b[i]; 525 | if (digit < 0) { 526 | digit += BigInteger_base; 527 | borrow = 1; 528 | } 529 | else { 530 | borrow = 0; 531 | } 532 | diff[i] = digit; 533 | } 534 | for (i = bl; i < al; i++) { 535 | digit = a[i] - borrow; 536 | if (digit < 0) { 537 | digit += BigInteger_base; 538 | } 539 | else { 540 | diff[i++] = digit; 541 | break; 542 | } 543 | diff[i] = digit; 544 | } 545 | for ( ; i < al; i++) { 546 | diff[i] = a[i]; 547 | } 548 | 549 | return new BigInteger(diff, sign, CONSTRUCT); 550 | }; 551 | 552 | (function() { 553 | function addOne(n, sign) { 554 | var a = n._d; 555 | var sum = a.slice(); 556 | var carry = true; 557 | var i = 0; 558 | 559 | while (true) { 560 | var digit = (a[i] || 0) + 1; 561 | sum[i] = digit % BigInteger_base; 562 | if (digit <= BigInteger_base - 1) { 563 | break; 564 | } 565 | ++i; 566 | } 567 | 568 | return new BigInteger(sum, sign, CONSTRUCT); 569 | } 570 | 571 | function subtractOne(n, sign) { 572 | var a = n._d; 573 | var sum = a.slice(); 574 | var borrow = true; 575 | var i = 0; 576 | 577 | while (true) { 578 | var digit = (a[i] || 0) - 1; 579 | if (digit < 0) { 580 | sum[i] = digit + BigInteger_base; 581 | } 582 | else { 583 | sum[i] = digit; 584 | break; 585 | } 586 | ++i; 587 | } 588 | 589 | return new BigInteger(sum, sign, CONSTRUCT); 590 | } 591 | 592 | /* 593 | Function: next 594 | Get the next (add one). 595 | Returns: 596 | *this* + 1. 597 | See Also: 598 | , 599 | */ 600 | BigInteger.prototype.next = function() { 601 | switch (this._s) { 602 | case 0: 603 | return ONE; 604 | case -1: 605 | return subtractOne(this, -1); 606 | // case 1: 607 | default: 608 | return addOne(this, 1); 609 | } 610 | }; 611 | 612 | /* 613 | Function: prev 614 | Get the previous (subtract one). 615 | Returns: 616 | *this* - 1. 617 | See Also: 618 | , 619 | */ 620 | BigInteger.prototype.prev = function() { 621 | switch (this._s) { 622 | case 0: 623 | return M_ONE; 624 | case -1: 625 | return addOne(this, -1); 626 | // case 1: 627 | default: 628 | return subtractOne(this, 1); 629 | } 630 | }; 631 | })(); 632 | 633 | /* 634 | Function: compareAbs 635 | Compare the absolute value of two . 636 | Calling is faster than calling twice, then . 637 | Parameters: 638 | n - The number to compare to *this*. Will be converted to a . 639 | Returns: 640 | -1, 0, or +1 if *|this|* is less than, equal to, or greater than *|n|*. 641 | See Also: 642 | , 643 | */ 644 | BigInteger.prototype.compareAbs = function(n) { 645 | if (this === n) { 646 | return 0; 647 | } 648 | 649 | if (!(n instanceof BigInteger)) { 650 | if (!isFinite(n)) { 651 | return(isNaN(n) ? n : -1); 652 | } 653 | n = BigInteger(n); 654 | } 655 | 656 | if (this._s === 0) { 657 | return (n._s !== 0) ? -1 : 0; 658 | } 659 | if (n._s === 0) { 660 | return 1; 661 | } 662 | 663 | var l = this._d.length; 664 | var nl = n._d.length; 665 | if (l < nl) { 666 | return -1; 667 | } 668 | else if (l > nl) { 669 | return 1; 670 | } 671 | 672 | var a = this._d; 673 | var b = n._d; 674 | for (var i = l-1; i >= 0; i--) { 675 | if (a[i] !== b[i]) { 676 | return a[i] < b[i] ? -1 : 1; 677 | } 678 | } 679 | 680 | return 0; 681 | }; 682 | 683 | /* 684 | Function: compare 685 | Compare two . 686 | Parameters: 687 | n - The number to compare to *this*. Will be converted to a . 688 | Returns: 689 | -1, 0, or +1 if *this* is less than, equal to, or greater than *n*. 690 | See Also: 691 | , , , 692 | */ 693 | BigInteger.prototype.compare = function(n) { 694 | if (this === n) { 695 | return 0; 696 | } 697 | 698 | n = BigInteger(n); 699 | 700 | if (this._s === 0) { 701 | return -n._s; 702 | } 703 | 704 | if (this._s === n._s) { // both positive or both negative 705 | var cmp = this.compareAbs(n); 706 | return cmp * this._s; 707 | } 708 | else { 709 | return this._s; 710 | } 711 | }; 712 | 713 | /* 714 | Function: isUnit 715 | Return true iff *this* is either 1 or -1. 716 | Returns: 717 | true if *this* compares equal to or . 718 | See Also: 719 | , , , , , 720 | , 721 | */ 722 | BigInteger.prototype.isUnit = function() { 723 | return this === ONE || 724 | this === M_ONE || 725 | (this._d.length === 1 && this._d[0] === 1); 726 | }; 727 | 728 | /* 729 | Function: multiply 730 | Multiply two . 731 | Parameters: 732 | n - The number to multiply *this* by. Will be converted to a 733 | . 734 | Returns: 735 | The numbers multiplied together. 736 | See Also: 737 | , , , 738 | */ 739 | BigInteger.prototype.multiply = function(n) { 740 | // TODO: Consider adding Karatsuba multiplication for large numbers 741 | if (this._s === 0) { 742 | return ZERO; 743 | } 744 | 745 | n = BigInteger(n); 746 | if (n._s === 0) { 747 | return ZERO; 748 | } 749 | if (this.isUnit()) { 750 | if (this._s < 0) { 751 | return n.negate(); 752 | } 753 | return n; 754 | } 755 | if (n.isUnit()) { 756 | if (n._s < 0) { 757 | return this.negate(); 758 | } 759 | return this; 760 | } 761 | if (this === n) { 762 | return this.square(); 763 | } 764 | 765 | var r = (this._d.length >= n._d.length); 766 | var a = (r ? this : n)._d; // a will be longer than b 767 | var b = (r ? n : this)._d; 768 | var al = a.length; 769 | var bl = b.length; 770 | 771 | var pl = al + bl; 772 | var partial = new Array(pl); 773 | var i; 774 | for (i = 0; i < pl; i++) { 775 | partial[i] = 0; 776 | } 777 | 778 | for (i = 0; i < bl; i++) { 779 | var carry = 0; 780 | var bi = b[i]; 781 | var jlimit = al + i; 782 | var digit; 783 | for (var j = i; j < jlimit; j++) { 784 | digit = partial[j] + bi * a[j - i] + carry; 785 | carry = (digit / BigInteger_base) | 0; 786 | partial[j] = (digit % BigInteger_base) | 0; 787 | } 788 | if (carry) { 789 | digit = partial[j] + carry; 790 | carry = (digit / BigInteger_base) | 0; 791 | partial[j] = digit % BigInteger_base; 792 | } 793 | } 794 | return new BigInteger(partial, this._s * n._s, CONSTRUCT); 795 | }; 796 | 797 | // Multiply a BigInteger by a single-digit native number 798 | // Assumes that this and n are >= 0 799 | // This is not really intended to be used outside the library itself 800 | BigInteger.prototype.multiplySingleDigit = function(n) { 801 | if (n === 0 || this._s === 0) { 802 | return ZERO; 803 | } 804 | if (n === 1) { 805 | return this; 806 | } 807 | 808 | var digit; 809 | if (this._d.length === 1) { 810 | digit = this._d[0] * n; 811 | if (digit >= BigInteger_base) { 812 | return new BigInteger([(digit % BigInteger_base)|0, 813 | (digit / BigInteger_base)|0], 1, CONSTRUCT); 814 | } 815 | return new BigInteger([digit], 1, CONSTRUCT); 816 | } 817 | 818 | if (n === 2) { 819 | return this.add(this); 820 | } 821 | if (this.isUnit()) { 822 | return new BigInteger([n], 1, CONSTRUCT); 823 | } 824 | 825 | var a = this._d; 826 | var al = a.length; 827 | 828 | var pl = al + 1; 829 | var partial = new Array(pl); 830 | for (var i = 0; i < pl; i++) { 831 | partial[i] = 0; 832 | } 833 | 834 | var carry = 0; 835 | for (var j = 0; j < al; j++) { 836 | digit = n * a[j] + carry; 837 | carry = (digit / BigInteger_base) | 0; 838 | partial[j] = (digit % BigInteger_base) | 0; 839 | } 840 | if (carry) { 841 | partial[j] = carry; 842 | } 843 | 844 | return new BigInteger(partial, 1, CONSTRUCT); 845 | }; 846 | 847 | /* 848 | Function: square 849 | Multiply a by itself. 850 | This is slightly faster than regular multiplication, since it removes the 851 | duplicated multiplcations. 852 | Returns: 853 | > this.multiply(this) 854 | See Also: 855 | 856 | */ 857 | BigInteger.prototype.square = function() { 858 | // Normally, squaring a 10-digit number would take 100 multiplications. 859 | // Of these 10 are unique diagonals, of the remaining 90 (100-10), 45 are repeated. 860 | // This procedure saves (N*(N-1))/2 multiplications, (e.g., 45 of 100 multiplies). 861 | // Based on code by Gary Darby, Intellitech Systems Inc., www.DelphiForFun.org 862 | 863 | if (this._s === 0) { 864 | return ZERO; 865 | } 866 | if (this.isUnit()) { 867 | return ONE; 868 | } 869 | 870 | var digits = this._d; 871 | var length = digits.length; 872 | var imult1 = new Array(length + length + 1); 873 | var product, carry, k; 874 | var i; 875 | 876 | // Calculate diagonal 877 | for (i = 0; i < length; i++) { 878 | k = i * 2; 879 | product = digits[i] * digits[i]; 880 | carry = (product / BigInteger_base) | 0; 881 | imult1[k] = product % BigInteger_base; 882 | imult1[k + 1] = carry; 883 | } 884 | 885 | // Calculate repeating part 886 | for (i = 0; i < length; i++) { 887 | carry = 0; 888 | k = i * 2 + 1; 889 | for (var j = i + 1; j < length; j++, k++) { 890 | product = digits[j] * digits[i] * 2 + imult1[k] + carry; 891 | carry = (product / BigInteger_base) | 0; 892 | imult1[k] = product % BigInteger_base; 893 | } 894 | k = length + i; 895 | var digit = carry + imult1[k]; 896 | carry = (digit / BigInteger_base) | 0; 897 | imult1[k] = digit % BigInteger_base; 898 | imult1[k + 1] += carry; 899 | } 900 | 901 | return new BigInteger(imult1, 1, CONSTRUCT); 902 | }; 903 | 904 | /* 905 | Function: quotient 906 | Divide two and truncate towards zero. 907 | throws an exception if *n* is zero. 908 | Parameters: 909 | n - The number to divide *this* by. Will be converted to a . 910 | Returns: 911 | The *this* / *n*, truncated to an integer. 912 | See Also: 913 | , , , , 914 | */ 915 | BigInteger.prototype.quotient = function(n) { 916 | return this.divRem(n)[0]; 917 | }; 918 | 919 | /* 920 | Function: divide 921 | Deprecated synonym for . 922 | */ 923 | BigInteger.prototype.divide = BigInteger.prototype.quotient; 924 | 925 | /* 926 | Function: remainder 927 | Calculate the remainder of two . 928 | throws an exception if *n* is zero. 929 | Parameters: 930 | n - The remainder after *this* is divided *this* by *n*. Will be 931 | converted to a . 932 | Returns: 933 | *this* % *n*. 934 | See Also: 935 | , 936 | */ 937 | BigInteger.prototype.remainder = function(n) { 938 | return this.divRem(n)[1]; 939 | }; 940 | 941 | /* 942 | Function: divRem 943 | Calculate the integer quotient and remainder of two . 944 | throws an exception if *n* is zero. 945 | Parameters: 946 | n - The number to divide *this* by. Will be converted to a . 947 | Returns: 948 | A two-element array containing the quotient and the remainder. 949 | > a.divRem(b) 950 | is exactly equivalent to 951 | > [a.quotient(b), a.remainder(b)] 952 | except it is faster, because they are calculated at the same time. 953 | See Also: 954 | , 955 | */ 956 | BigInteger.prototype.divRem = function(n) { 957 | n = BigInteger(n); 958 | if (n._s === 0) { 959 | throw new Error("Divide by zero"); 960 | } 961 | if (this._s === 0) { 962 | return [ZERO, ZERO]; 963 | } 964 | if (n._d.length === 1) { 965 | return this.divRemSmall(n._s * n._d[0]); 966 | } 967 | 968 | // Test for easy cases -- |n1| <= |n2| 969 | switch (this.compareAbs(n)) { 970 | case 0: // n1 == n2 971 | return [this._s === n._s ? ONE : M_ONE, ZERO]; 972 | case -1: // |n1| < |n2| 973 | return [ZERO, this]; 974 | } 975 | 976 | var sign = this._s * n._s; 977 | var a = n.abs(); 978 | var b_digits = this._d; 979 | var b_index = b_digits.length; 980 | var digits = n._d.length; 981 | var quot = []; 982 | var guess; 983 | 984 | var part = new BigInteger([], 0, CONSTRUCT); 985 | 986 | while (b_index) { 987 | part._d.unshift(b_digits[--b_index]); 988 | part = new BigInteger(part._d, 1, CONSTRUCT); 989 | 990 | if (part.compareAbs(n) < 0) { 991 | quot.push(0); 992 | continue; 993 | } 994 | if (part._s === 0) { 995 | guess = 0; 996 | } 997 | else { 998 | var xlen = part._d.length, ylen = a._d.length; 999 | var highx = part._d[xlen-1]*BigInteger_base + part._d[xlen-2]; 1000 | var highy = a._d[ylen-1]*BigInteger_base + a._d[ylen-2]; 1001 | if (part._d.length > a._d.length) { 1002 | // The length of part._d can either match a._d length, 1003 | // or exceed it by one. 1004 | highx = (highx+1)*BigInteger_base; 1005 | } 1006 | guess = Math.ceil(highx/highy); 1007 | } 1008 | do { 1009 | var check = a.multiplySingleDigit(guess); 1010 | if (check.compareAbs(part) <= 0) { 1011 | break; 1012 | } 1013 | guess--; 1014 | } while (guess); 1015 | 1016 | quot.push(guess); 1017 | if (!guess) { 1018 | continue; 1019 | } 1020 | var diff = part.subtract(check); 1021 | part._d = diff._d.slice(); 1022 | } 1023 | 1024 | return [new BigInteger(quot.reverse(), sign, CONSTRUCT), 1025 | new BigInteger(part._d, this._s, CONSTRUCT)]; 1026 | }; 1027 | 1028 | // Throws an exception if n is outside of (-BigInteger.base, -1] or 1029 | // [1, BigInteger.base). It's not necessary to call this, since the 1030 | // other division functions will call it if they are able to. 1031 | BigInteger.prototype.divRemSmall = function(n) { 1032 | var r; 1033 | n = +n; 1034 | if (n === 0) { 1035 | throw new Error("Divide by zero"); 1036 | } 1037 | 1038 | var n_s = n < 0 ? -1 : 1; 1039 | var sign = this._s * n_s; 1040 | n = Math.abs(n); 1041 | 1042 | if (n < 1 || n >= BigInteger_base) { 1043 | throw new Error("Argument out of range"); 1044 | } 1045 | 1046 | if (this._s === 0) { 1047 | return [ZERO, ZERO]; 1048 | } 1049 | 1050 | if (n === 1 || n === -1) { 1051 | return [(sign === 1) ? this.abs() : new BigInteger(this._d, sign, CONSTRUCT), ZERO]; 1052 | } 1053 | 1054 | // 2 <= n < BigInteger_base 1055 | 1056 | // divide a single digit by a single digit 1057 | if (this._d.length === 1) { 1058 | var q = new BigInteger([(this._d[0] / n) | 0], 1, CONSTRUCT); 1059 | r = new BigInteger([(this._d[0] % n) | 0], 1, CONSTRUCT); 1060 | if (sign < 0) { 1061 | q = q.negate(); 1062 | } 1063 | if (this._s < 0) { 1064 | r = r.negate(); 1065 | } 1066 | return [q, r]; 1067 | } 1068 | 1069 | var digits = this._d.slice(); 1070 | var quot = new Array(digits.length); 1071 | var part = 0; 1072 | var diff = 0; 1073 | var i = 0; 1074 | var guess; 1075 | 1076 | while (digits.length) { 1077 | part = part * BigInteger_base + digits[digits.length - 1]; 1078 | if (part < n) { 1079 | quot[i++] = 0; 1080 | digits.pop(); 1081 | diff = BigInteger_base * diff + part; 1082 | continue; 1083 | } 1084 | if (part === 0) { 1085 | guess = 0; 1086 | } 1087 | else { 1088 | guess = (part / n) | 0; 1089 | } 1090 | 1091 | var check = n * guess; 1092 | diff = part - check; 1093 | quot[i++] = guess; 1094 | if (!guess) { 1095 | digits.pop(); 1096 | continue; 1097 | } 1098 | 1099 | digits.pop(); 1100 | part = diff; 1101 | } 1102 | 1103 | r = new BigInteger([diff], 1, CONSTRUCT); 1104 | if (this._s < 0) { 1105 | r = r.negate(); 1106 | } 1107 | return [new BigInteger(quot.reverse(), sign, CONSTRUCT), r]; 1108 | }; 1109 | 1110 | /* 1111 | Function: isEven 1112 | Return true iff *this* is divisible by two. 1113 | Note that is even. 1114 | Returns: 1115 | true if *this* is even, false otherwise. 1116 | See Also: 1117 | 1118 | */ 1119 | BigInteger.prototype.isEven = function() { 1120 | var digits = this._d; 1121 | return this._s === 0 || digits.length === 0 || (digits[0] % 2) === 0; 1122 | }; 1123 | 1124 | /* 1125 | Function: isOdd 1126 | Return true iff *this* is not divisible by two. 1127 | Returns: 1128 | true if *this* is odd, false otherwise. 1129 | See Also: 1130 | 1131 | */ 1132 | BigInteger.prototype.isOdd = function() { 1133 | return !this.isEven(); 1134 | }; 1135 | 1136 | /* 1137 | Function: sign 1138 | Get the sign of a . 1139 | Returns: 1140 | * -1 if *this* < 0 1141 | * 0 if *this* == 0 1142 | * +1 if *this* > 0 1143 | See Also: 1144 | , , , , 1145 | */ 1146 | BigInteger.prototype.sign = function() { 1147 | return this._s; 1148 | }; 1149 | 1150 | /* 1151 | Function: isPositive 1152 | Return true iff *this* > 0. 1153 | Returns: 1154 | true if *this*.compare() == 1. 1155 | See Also: 1156 | , , , , , 1157 | */ 1158 | BigInteger.prototype.isPositive = function() { 1159 | return this._s > 0; 1160 | }; 1161 | 1162 | /* 1163 | Function: isNegative 1164 | Return true iff *this* < 0. 1165 | Returns: 1166 | true if *this*.compare() == -1. 1167 | See Also: 1168 | , , , , , 1169 | */ 1170 | BigInteger.prototype.isNegative = function() { 1171 | return this._s < 0; 1172 | }; 1173 | 1174 | /* 1175 | Function: isZero 1176 | Return true iff *this* == 0. 1177 | Returns: 1178 | true if *this*.compare() == 0. 1179 | See Also: 1180 | , , , , 1181 | */ 1182 | BigInteger.prototype.isZero = function() { 1183 | return this._s === 0; 1184 | }; 1185 | 1186 | /* 1187 | Function: exp10 1188 | Multiply a by a power of 10. 1189 | This is equivalent to, but faster than 1190 | > if (n >= 0) { 1191 | > return this.multiply(BigInteger("1e" + n)); 1192 | > } 1193 | > else { // n <= 0 1194 | > return this.quotient(BigInteger("1e" + -n)); 1195 | > } 1196 | Parameters: 1197 | n - The power of 10 to multiply *this* by. *n* is converted to a 1198 | javascipt number and must be no greater than 1199 | (0x7FFFFFFF), or an exception will be thrown. 1200 | Returns: 1201 | *this* * (10 ** *n*), truncated to an integer if necessary. 1202 | See Also: 1203 | , 1204 | */ 1205 | BigInteger.prototype.exp10 = function(n) { 1206 | n = +n; 1207 | if (n === 0) { 1208 | return this; 1209 | } 1210 | if (Math.abs(n) > Number(MAX_EXP)) { 1211 | throw new Error("exponent too large in BigInteger.exp10"); 1212 | } 1213 | // Optimization for this == 0. This also keeps us from having to trim zeros in the positive n case 1214 | if (this._s === 0) { 1215 | return ZERO; 1216 | } 1217 | if (n > 0) { 1218 | var k = new BigInteger(this._d.slice(), this._s, CONSTRUCT); 1219 | 1220 | for (; n >= BigInteger_base_log10; n -= BigInteger_base_log10) { 1221 | k._d.unshift(0); 1222 | } 1223 | if (n == 0) 1224 | return k; 1225 | k._s = 1; 1226 | k = k.multiplySingleDigit(Math.pow(10, n)); 1227 | return (this._s < 0 ? k.negate() : k); 1228 | } else if (-n >= this._d.length*BigInteger_base_log10) { 1229 | return ZERO; 1230 | } else { 1231 | var k = new BigInteger(this._d.slice(), this._s, CONSTRUCT); 1232 | 1233 | for (n = -n; n >= BigInteger_base_log10; n -= BigInteger_base_log10) { 1234 | k._d.shift(); 1235 | } 1236 | return (n == 0) ? k : k.divRemSmall(Math.pow(10, n))[0]; 1237 | } 1238 | }; 1239 | 1240 | /* 1241 | Function: pow 1242 | Raise a to a power. 1243 | In this implementation, 0**0 is 1. 1244 | Parameters: 1245 | n - The exponent to raise *this* by. *n* must be no greater than 1246 | (0x7FFFFFFF), or an exception will be thrown. 1247 | Returns: 1248 | *this* raised to the *nth* power. 1249 | See Also: 1250 | 1251 | */ 1252 | BigInteger.prototype.pow = function(n) { 1253 | if (this.isUnit()) { 1254 | if (this._s > 0) { 1255 | return this; 1256 | } 1257 | else { 1258 | return BigInteger(n).isOdd() ? this : this.negate(); 1259 | } 1260 | } 1261 | 1262 | n = BigInteger(n); 1263 | if (n._s === 0) { 1264 | return ONE; 1265 | } 1266 | else if (n._s < 0) { 1267 | if (this._s === 0) { 1268 | throw new Error("Divide by zero"); 1269 | } 1270 | else { 1271 | return ZERO; 1272 | } 1273 | } 1274 | if (this._s === 0) { 1275 | return ZERO; 1276 | } 1277 | if (n.isUnit()) { 1278 | return this; 1279 | } 1280 | 1281 | if (n.compareAbs(MAX_EXP) > 0) { 1282 | throw new Error("exponent too large in BigInteger.pow"); 1283 | } 1284 | var x = this; 1285 | var aux = ONE; 1286 | var two = BigInteger.small[2]; 1287 | 1288 | while (n.isPositive()) { 1289 | if (n.isOdd()) { 1290 | aux = aux.multiply(x); 1291 | if (n.isUnit()) { 1292 | return aux; 1293 | } 1294 | } 1295 | x = x.square(); 1296 | n = n.quotient(two); 1297 | } 1298 | 1299 | return aux; 1300 | }; 1301 | 1302 | /* 1303 | Function: modPow 1304 | Raise a to a power (mod m). 1305 | Because it is reduced by a modulus, is not limited by 1306 | like . 1307 | Parameters: 1308 | exponent - The exponent to raise *this* by. Must be positive. 1309 | modulus - The modulus. 1310 | Returns: 1311 | *this* ^ *exponent* (mod *modulus*). 1312 | See Also: 1313 | , 1314 | */ 1315 | BigInteger.prototype.modPow = function(exponent, modulus) { 1316 | var result = ONE; 1317 | var base = this; 1318 | 1319 | while (exponent.isPositive()) { 1320 | if (exponent.isOdd()) { 1321 | result = result.multiply(base).remainder(modulus); 1322 | } 1323 | 1324 | exponent = exponent.quotient(BigInteger.small[2]); 1325 | if (exponent.isPositive()) { 1326 | base = base.square().remainder(modulus); 1327 | } 1328 | } 1329 | 1330 | return result; 1331 | }; 1332 | 1333 | /* 1334 | Function: log 1335 | Get the natural logarithm of a as a native JavaScript number. 1336 | This is equivalent to 1337 | > Math.log(this.toJSValue()) 1338 | but handles values outside of the native number range. 1339 | Returns: 1340 | log( *this* ) 1341 | See Also: 1342 | 1343 | */ 1344 | BigInteger.prototype.log = function() { 1345 | switch (this._s) { 1346 | case 0: return -Infinity; 1347 | case -1: return NaN; 1348 | default: // Fall through. 1349 | } 1350 | 1351 | var l = this._d.length; 1352 | 1353 | if (l*BigInteger_base_log10 < 30) { 1354 | return Math.log(this.valueOf()); 1355 | } 1356 | 1357 | var N = Math.ceil(30/BigInteger_base_log10); 1358 | var firstNdigits = this._d.slice(l - N); 1359 | return Math.log((new BigInteger(firstNdigits, 1, CONSTRUCT)).valueOf()) + (l - N) * Math.log(BigInteger_base); 1360 | }; 1361 | 1362 | /* 1363 | Function: valueOf 1364 | Convert a to a native JavaScript integer. 1365 | This is called automatically by JavaScipt to convert a to a 1366 | native value. 1367 | Returns: 1368 | > parseInt(this.toString(), 10) 1369 | See Also: 1370 | , 1371 | */ 1372 | BigInteger.prototype.valueOf = function() { 1373 | return parseInt(this.toString(), 10); 1374 | }; 1375 | 1376 | /* 1377 | Function: toJSValue 1378 | Convert a to a native JavaScript integer. 1379 | This is the same as valueOf, but more explicitly named. 1380 | Returns: 1381 | > parseInt(this.toString(), 10) 1382 | See Also: 1383 | , 1384 | */ 1385 | BigInteger.prototype.toJSValue = function() { 1386 | return parseInt(this.toString(), 10); 1387 | }; 1388 | 1389 | 1390 | /* 1391 | Function: lowVal 1392 | Author: Lucas Jones 1393 | */ 1394 | BigInteger.prototype.lowVal = function () { 1395 | return this._d[0] || 0; 1396 | }; 1397 | 1398 | var MAX_EXP = BigInteger(0x7FFFFFFF); 1399 | // Constant: MAX_EXP 1400 | // The largest exponent allowed in and (0x7FFFFFFF or 2147483647). 1401 | BigInteger.MAX_EXP = MAX_EXP; 1402 | 1403 | (function() { 1404 | function makeUnary(fn) { 1405 | return function(a) { 1406 | return fn.call(BigInteger(a)); 1407 | }; 1408 | } 1409 | 1410 | function makeBinary(fn) { 1411 | return function(a, b) { 1412 | return fn.call(BigInteger(a), BigInteger(b)); 1413 | }; 1414 | } 1415 | 1416 | function makeTrinary(fn) { 1417 | return function(a, b, c) { 1418 | return fn.call(BigInteger(a), BigInteger(b), BigInteger(c)); 1419 | }; 1420 | } 1421 | 1422 | (function() { 1423 | var i, fn; 1424 | var unary = "toJSValue,isEven,isOdd,sign,isZero,isNegative,abs,isUnit,square,negate,isPositive,toString,next,prev,log".split(","); 1425 | var binary = "compare,remainder,divRem,subtract,add,quotient,divide,multiply,pow,compareAbs".split(","); 1426 | var trinary = ["modPow"]; 1427 | 1428 | for (i = 0; i < unary.length; i++) { 1429 | fn = unary[i]; 1430 | BigInteger[fn] = makeUnary(BigInteger.prototype[fn]); 1431 | } 1432 | 1433 | for (i = 0; i < binary.length; i++) { 1434 | fn = binary[i]; 1435 | BigInteger[fn] = makeBinary(BigInteger.prototype[fn]); 1436 | } 1437 | 1438 | for (i = 0; i < trinary.length; i++) { 1439 | fn = trinary[i]; 1440 | BigInteger[fn] = makeTrinary(BigInteger.prototype[fn]); 1441 | } 1442 | 1443 | BigInteger.exp10 = function(x, n) { 1444 | return BigInteger(x).exp10(n); 1445 | }; 1446 | })(); 1447 | })(); 1448 | 1449 | exports.JSBigInt = BigInteger; // exports.BigInteger changed to exports.JSBigInt 1450 | })(typeof exports !== 'undefined' ? exports : this); -------------------------------------------------------------------------------- /src/crypto/blake256.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Credits to https://github.com/cryptocoinjs/blake-hash 5 | */ 6 | Blake256.sigma = [ 7 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 8 | [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], 9 | [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4], 10 | [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8], 11 | [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13], 12 | [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9], 13 | [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11], 14 | [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10], 15 | [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5], 16 | [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0], 17 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 18 | [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], 19 | [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4], 20 | [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8], 21 | [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13], 22 | [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9] 23 | ] 24 | 25 | Blake256.u256 = [ 26 | 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 27 | 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 28 | 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 29 | 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917 30 | ] 31 | 32 | Blake256.padding = new Buffer([ 33 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 41 | ]) 42 | 43 | Blake256.prototype._length_carry = function (arr) { 44 | for (var j = 0; j < arr.length; ++j) { 45 | if (arr[j] < 0x0100000000) break 46 | arr[j] -= 0x0100000000 47 | arr[j + 1] += 1 48 | } 49 | } 50 | 51 | Blake256.prototype.update = function (data, encoding) { 52 | data = new Buffer(data, encoding); 53 | var block = this._block 54 | var offset = 0 55 | 56 | while (this._blockOffset + data.length - offset >= block.length) { 57 | for (var i = this._blockOffset; i < block.length;) block[i++] = data[offset++] 58 | 59 | this._length[0] += block.length * 8 60 | this._length_carry(this._length) 61 | 62 | this._compress() 63 | this._blockOffset = 0 64 | } 65 | 66 | while (offset < data.length) block[this._blockOffset++] = data[offset++] 67 | return this; 68 | } 69 | 70 | var zo = new Buffer([0x01]) 71 | var oo = new Buffer([0x81]) 72 | 73 | function rot (x, n) { 74 | return ((x << (32 - n)) | (x >>> n)) >>> 0 75 | } 76 | 77 | function g (v, m, i, a, b, c, d, e) { 78 | var sigma = Blake256.sigma 79 | var u256 = Blake256.u256 80 | 81 | v[a] = (v[a] + ((m[sigma[i][e]] ^ u256[sigma[i][e + 1]]) >>> 0) + v[b]) >>> 0 82 | v[d] = rot(v[d] ^ v[a], 16) 83 | v[c] = (v[c] + v[d]) >>> 0 84 | v[b] = rot(v[b] ^ v[c], 12) 85 | v[a] = (v[a] + ((m[sigma[i][e + 1]] ^ u256[sigma[i][e]]) >>> 0) + v[b]) >>> 0 86 | v[d] = rot(v[d] ^ v[a], 8) 87 | v[c] = (v[c] + v[d]) >>> 0 88 | v[b] = rot(v[b] ^ v[c], 7) 89 | } 90 | 91 | function Blake256 () { 92 | this._h = [ 93 | 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 94 | 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 95 | ] 96 | 97 | this._s = [0, 0, 0, 0] 98 | 99 | this._block = new Buffer(64) 100 | this._blockOffset = 0 101 | this._length = [0, 0] 102 | 103 | this._nullt = false 104 | 105 | this._zo = zo 106 | this._oo = oo 107 | } 108 | 109 | Blake256.prototype._compress = function () { 110 | var u256 = Blake256.u256 111 | var v = new Array(16) 112 | var m = new Array(16) 113 | var i 114 | 115 | for (i = 0; i < 16; ++i) m[i] = this._block.readUInt32BE(i * 4) 116 | for (i = 0; i < 8; ++i) v[i] = this._h[i] >>> 0 117 | for (i = 8; i < 12; ++i) v[i] = (this._s[i - 8] ^ u256[i - 8]) >>> 0 118 | for (i = 12; i < 16; ++i) v[i] = u256[i - 8] 119 | 120 | if (!this._nullt) { 121 | v[12] = (v[12] ^ this._length[0]) >>> 0 122 | v[13] = (v[13] ^ this._length[0]) >>> 0 123 | v[14] = (v[14] ^ this._length[1]) >>> 0 124 | v[15] = (v[15] ^ this._length[1]) >>> 0 125 | } 126 | 127 | for (i = 0; i < 14; ++i) { 128 | /* column step */ 129 | g(v, m, i, 0, 4, 8, 12, 0) 130 | g(v, m, i, 1, 5, 9, 13, 2) 131 | g(v, m, i, 2, 6, 10, 14, 4) 132 | g(v, m, i, 3, 7, 11, 15, 6) 133 | /* diagonal step */ 134 | g(v, m, i, 0, 5, 10, 15, 8) 135 | g(v, m, i, 1, 6, 11, 12, 10) 136 | g(v, m, i, 2, 7, 8, 13, 12) 137 | g(v, m, i, 3, 4, 9, 14, 14) 138 | } 139 | 140 | for (i = 0; i < 16; ++i) this._h[i % 8] = (this._h[i % 8] ^ v[i]) >>> 0 141 | for (i = 0; i < 8; ++i) this._h[i] = (this._h[i] ^ this._s[i % 4]) >>> 0 142 | } 143 | 144 | Blake256.prototype._padding = function () { 145 | var lo = this._length[0] + this._blockOffset * 8 146 | var hi = this._length[1] 147 | if (lo >= 0x0100000000) { 148 | lo -= 0x0100000000 149 | hi += 1 150 | } 151 | 152 | var msglen = new Buffer(8) 153 | msglen.writeUInt32BE(hi, 0) 154 | msglen.writeUInt32BE(lo, 4) 155 | 156 | if (this._blockOffset === 55) { 157 | this._length[0] -= 8 158 | this.update(this._oo) 159 | } else { 160 | if (this._blockOffset < 55) { 161 | if (this._blockOffset === 0) this._nullt = true 162 | this._length[0] -= (55 - this._blockOffset) * 8 163 | this.update(Blake256.padding.slice(0, 55 - this._blockOffset)) 164 | } else { 165 | this._length[0] -= (64 - this._blockOffset) * 8 166 | this.update(Blake256.padding.slice(0, 64 - this._blockOffset)) 167 | this._length[0] -= 55 * 8 168 | this.update(Blake256.padding.slice(1, 1 + 55)) 169 | this._nullt = true 170 | } 171 | 172 | this.update(this._zo) 173 | this._length[0] -= 8 174 | } 175 | 176 | this._length[0] -= 64 177 | this.update(msglen) 178 | } 179 | 180 | Blake256.prototype.digest = function (encoding) { 181 | this._padding() 182 | 183 | var buffer = new Buffer(32) 184 | for (var i = 0; i < 8; ++i) buffer.writeUInt32BE(this._h[i], i * 4) 185 | return buffer.toString(encoding); 186 | } 187 | 188 | module.exports = Blake256; -------------------------------------------------------------------------------- /src/crypto/blake2b.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Credits to https://github.com/emilbayes/blake2b 5 | * 6 | * Copyright (c) 2017, Emil Bay github@tixz.dk 7 | * 8 | * 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. 9 | * 10 | * 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. 11 | */ 12 | 13 | // 64-bit unsigned addition 14 | // Sets v[a,a+1] += v[b,b+1] 15 | // v should be a Uint32Array 16 | function ADD64AA (v, a, b) { 17 | var o0 = v[a] + v[b] 18 | var o1 = v[a + 1] + v[b + 1] 19 | if (o0 >= 0x100000000) { 20 | o1++ 21 | } 22 | v[a] = o0 23 | v[a + 1] = o1 24 | } 25 | 26 | // 64-bit unsigned addition 27 | // Sets v[a,a+1] += b 28 | // b0 is the low 32 bits of b, b1 represents the high 32 bits 29 | function ADD64AC (v, a, b0, b1) { 30 | var o0 = v[a] + b0 31 | if (b0 < 0) { 32 | o0 += 0x100000000 33 | } 34 | var o1 = v[a + 1] + b1 35 | if (o0 >= 0x100000000) { 36 | o1++ 37 | } 38 | v[a] = o0 39 | v[a + 1] = o1 40 | } 41 | 42 | // Little-endian byte access 43 | function B2B_GET32 (arr, i) { 44 | return (arr[i] ^ 45 | (arr[i + 1] << 8) ^ 46 | (arr[i + 2] << 16) ^ 47 | (arr[i + 3] << 24)) 48 | } 49 | 50 | // G Mixing function 51 | // The ROTRs are inlined for speed 52 | function B2B_G (a, b, c, d, ix, iy) { 53 | var x0 = m[ix] 54 | var x1 = m[ix + 1] 55 | var y0 = m[iy] 56 | var y1 = m[iy + 1] 57 | 58 | ADD64AA(v, a, b) // v[a,a+1] += v[b,b+1] ... in JS we must store a uint64 as two uint32s 59 | ADD64AC(v, a, x0, x1) // v[a, a+1] += x ... x0 is the low 32 bits of x, x1 is the high 32 bits 60 | 61 | // v[d,d+1] = (v[d,d+1] xor v[a,a+1]) rotated to the right by 32 bits 62 | var xor0 = v[d] ^ v[a] 63 | var xor1 = v[d + 1] ^ v[a + 1] 64 | v[d] = xor1 65 | v[d + 1] = xor0 66 | 67 | ADD64AA(v, c, d) 68 | 69 | // v[b,b+1] = (v[b,b+1] xor v[c,c+1]) rotated right by 24 bits 70 | xor0 = v[b] ^ v[c] 71 | xor1 = v[b + 1] ^ v[c + 1] 72 | v[b] = (xor0 >>> 24) ^ (xor1 << 8) 73 | v[b + 1] = (xor1 >>> 24) ^ (xor0 << 8) 74 | 75 | ADD64AA(v, a, b) 76 | ADD64AC(v, a, y0, y1) 77 | 78 | // v[d,d+1] = (v[d,d+1] xor v[a,a+1]) rotated right by 16 bits 79 | xor0 = v[d] ^ v[a] 80 | xor1 = v[d + 1] ^ v[a + 1] 81 | v[d] = (xor0 >>> 16) ^ (xor1 << 16) 82 | v[d + 1] = (xor1 >>> 16) ^ (xor0 << 16) 83 | 84 | ADD64AA(v, c, d) 85 | 86 | // v[b,b+1] = (v[b,b+1] xor v[c,c+1]) rotated right by 63 bits 87 | xor0 = v[b] ^ v[c] 88 | xor1 = v[b + 1] ^ v[c + 1] 89 | v[b] = (xor1 >>> 31) ^ (xor0 << 1) 90 | v[b + 1] = (xor0 >>> 31) ^ (xor1 << 1) 91 | } 92 | 93 | // Initialization Vector 94 | var BLAKE2B_IV32 = new Uint32Array([ 95 | 0xF3BCC908, 0x6A09E667, 0x84CAA73B, 0xBB67AE85, 96 | 0xFE94F82B, 0x3C6EF372, 0x5F1D36F1, 0xA54FF53A, 97 | 0xADE682D1, 0x510E527F, 0x2B3E6C1F, 0x9B05688C, 98 | 0xFB41BD6B, 0x1F83D9AB, 0x137E2179, 0x5BE0CD19 99 | ]) 100 | 101 | var SIGMA8 = [ 102 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 103 | 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3, 104 | 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4, 105 | 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8, 106 | 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13, 107 | 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9, 108 | 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11, 109 | 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10, 110 | 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5, 111 | 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0, 112 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 113 | 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 114 | ] 115 | 116 | // These are offsets into a uint64 buffer. 117 | // Multiply them all by 2 to make them offsets into a uint32 buffer, 118 | // because this is Javascript and we don't have uint64s 119 | var SIGMA82 = new Uint8Array(SIGMA8.map(function (x) { return x * 2 })) 120 | 121 | // Compression function. 'last' flag indicates last block. 122 | // Note we're representing 16 uint64s as 32 uint32s 123 | var v = new Uint32Array(32) 124 | var m = new Uint32Array(32) 125 | function blake2bCompress (ctx, last) { 126 | var i = 0 127 | 128 | // init work variables 129 | for (i = 0; i < 16; i++) { 130 | v[i] = ctx.h[i] 131 | v[i + 16] = BLAKE2B_IV32[i] 132 | } 133 | 134 | // low 64 bits of offset 135 | v[24] = v[24] ^ ctx.t 136 | v[25] = v[25] ^ (ctx.t / 0x100000000) 137 | // high 64 bits not supported, offset may not be higher than 2**53-1 138 | 139 | // last block flag set ? 140 | if (last) { 141 | v[28] = ~v[28] 142 | v[29] = ~v[29] 143 | } 144 | 145 | // get little-endian words 146 | for (i = 0; i < 32; i++) { 147 | m[i] = B2B_GET32(ctx.b, 4 * i) 148 | } 149 | 150 | // twelve rounds of mixing 151 | for (i = 0; i < 12; i++) { 152 | B2B_G(0, 8, 16, 24, SIGMA82[i * 16 + 0], SIGMA82[i * 16 + 1]) 153 | B2B_G(2, 10, 18, 26, SIGMA82[i * 16 + 2], SIGMA82[i * 16 + 3]) 154 | B2B_G(4, 12, 20, 28, SIGMA82[i * 16 + 4], SIGMA82[i * 16 + 5]) 155 | B2B_G(6, 14, 22, 30, SIGMA82[i * 16 + 6], SIGMA82[i * 16 + 7]) 156 | B2B_G(0, 10, 20, 30, SIGMA82[i * 16 + 8], SIGMA82[i * 16 + 9]) 157 | B2B_G(2, 12, 22, 24, SIGMA82[i * 16 + 10], SIGMA82[i * 16 + 11]) 158 | B2B_G(4, 14, 16, 26, SIGMA82[i * 16 + 12], SIGMA82[i * 16 + 13]) 159 | B2B_G(6, 8, 18, 28, SIGMA82[i * 16 + 14], SIGMA82[i * 16 + 15]) 160 | } 161 | 162 | for (i = 0; i < 16; i++) { 163 | ctx.h[i] = ctx.h[i] ^ v[i] ^ v[i + 16] 164 | } 165 | } 166 | 167 | // reusable parameter_block 168 | var parameter_block = new Uint8Array([ 169 | 0, 0, 0, 0, // 0: outlen, keylen, fanout, depth 170 | 0, 0, 0, 0, // 4: leaf length, sequential mode 171 | 0, 0, 0, 0, // 8: node offset 172 | 0, 0, 0, 0, // 12: node offset 173 | 0, 0, 0, 0, // 16: node depth, inner length, rfu 174 | 0, 0, 0, 0, // 20: rfu 175 | 0, 0, 0, 0, // 24: rfu 176 | 0, 0, 0, 0, // 28: rfu 177 | 0, 0, 0, 0, // 32: salt 178 | 0, 0, 0, 0, // 36: salt 179 | 0, 0, 0, 0, // 40: salt 180 | 0, 0, 0, 0, // 44: salt 181 | 0, 0, 0, 0, // 48: personal 182 | 0, 0, 0, 0, // 52: personal 183 | 0, 0, 0, 0, // 56: personal 184 | 0, 0, 0, 0 // 60: personal 185 | ]) 186 | 187 | // Creates a BLAKE2b hashing context 188 | // Requires an output length between 1 and 64 bytes 189 | // Takes an optional Uint8Array key 190 | function Blake2b (outlen, key, salt, personal) { 191 | // zero out parameter_block before usage 192 | parameter_block.fill(0) 193 | // state, 'param block' 194 | 195 | this.b = new Uint8Array(128) 196 | this.h = new Uint32Array(16) 197 | this.t = 0 // input count 198 | this.c = 0 // pointer within buffer 199 | this.outlen = outlen // output length in bytes 200 | 201 | parameter_block[0] = outlen 202 | if (key) parameter_block[1] = key.length 203 | parameter_block[2] = 1 // fanout 204 | parameter_block[3] = 1 // depth 205 | 206 | if (salt) parameter_block.set(salt, 32) 207 | if (personal) parameter_block.set(personal, 48) 208 | 209 | // initialize hash state 210 | for (var i = 0; i < 16; i++) { 211 | this.h[i] = BLAKE2B_IV32[i] ^ B2B_GET32(parameter_block, i * 4) 212 | } 213 | 214 | // key the hash, if applicable 215 | if (key) { 216 | blake2bUpdate(this, key) 217 | // at the end 218 | this.c = 128 219 | } 220 | } 221 | 222 | Blake2b.prototype.update = function (input) { 223 | blake2bUpdate(this, input) 224 | return this 225 | } 226 | 227 | Blake2b.prototype.digest = function (out) { 228 | var buf = (!out || out === 'binary' || out === 'hex') ? new Uint8Array(this.outlen) : out 229 | blake2bFinal(this, buf) 230 | if (out === 'hex') return hexSlice(buf) 231 | return buf 232 | } 233 | 234 | Blake2b.prototype.final = Blake2b.prototype.digest 235 | 236 | // Updates a BLAKE2b streaming hash 237 | // Requires hash context and Uint8Array (byte array) 238 | function blake2bUpdate (ctx, input) { 239 | for (var i = 0; i < input.length; i++) { 240 | if (ctx.c === 128) { // buffer full ? 241 | ctx.t += ctx.c // add counters 242 | blake2bCompress(ctx, false) // compress (not last) 243 | ctx.c = 0 // counter to zero 244 | } 245 | ctx.b[ctx.c++] = input[i] 246 | } 247 | } 248 | 249 | // Completes a BLAKE2b streaming hash 250 | // Returns a Uint8Array containing the message digest 251 | function blake2bFinal (ctx, out) { 252 | ctx.t += ctx.c // mark last block offset 253 | 254 | while (ctx.c < 128) { // fill up with zeros 255 | ctx.b[ctx.c++] = 0 256 | } 257 | blake2bCompress(ctx, true) // final block flag = 1 258 | 259 | for (var i = 0; i < ctx.outlen; i++) { 260 | out[i] = ctx.h[i >> 2] >> (8 * (i & 3)) 261 | } 262 | return out 263 | } 264 | 265 | function hexSlice (buf) { 266 | var str = '' 267 | for (var i = 0; i < buf.length; i++) str += toHex(buf[i]) 268 | return str 269 | } 270 | 271 | function toHex (n) { 272 | if (n < 16) return '0' + n.toString(16) 273 | return n.toString(16) 274 | } 275 | 276 | module.exports = Blake2b; 277 | -------------------------------------------------------------------------------- /src/crypto/cnBase58.js: -------------------------------------------------------------------------------- 1 | var JSBigInt = require('./biginteger')['JSBigInt']; 2 | 3 | /** 4 | Copyright (c) 2017, moneroexamples 5 | 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | 11 | 1. Redistributions of source code must retain the above copyright notice, this 12 | list of conditions and the following disclaimer. 13 | 14 | 2. Redistributions in binary form must reproduce the above copyright notice, 15 | this list of conditions and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | 3. Neither the name of the copyright holder nor the names of its contributors 19 | may be used to endorse or promote products derived from this software without 20 | specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 23 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | Parts of the project are originally copyright (c) 2014-2017, MyMonero.com 34 | */ 35 | 36 | var cnBase58 = (function () { 37 | var b58 = {}; 38 | 39 | var alphabet_str = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; 40 | var alphabet = []; 41 | for (var i = 0; i < alphabet_str.length; i++) { 42 | alphabet.push(alphabet_str.charCodeAt(i)); 43 | } 44 | var encoded_block_sizes = [0, 2, 3, 5, 6, 7, 9, 10, 11]; 45 | 46 | var alphabet_size = alphabet.length; 47 | var full_block_size = 8; 48 | var full_encoded_block_size = 11; 49 | 50 | var UINT64_MAX = new JSBigInt(2).pow(64); 51 | 52 | function hextobin(hex) { 53 | if (hex.length % 2 !== 0) throw "Hex string has invalid length!"; 54 | var res = new Uint8Array(hex.length / 2); 55 | for (var i = 0; i < hex.length / 2; ++i) { 56 | res[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16); 57 | } 58 | return res; 59 | } 60 | 61 | function bintohex(bin) { 62 | var out = []; 63 | for (var i = 0; i < bin.length; ++i) { 64 | out.push(("0" + bin[i].toString(16)).slice(-2)); 65 | } 66 | return out.join(""); 67 | } 68 | 69 | function strtobin(str) { 70 | var res = new Uint8Array(str.length); 71 | for (var i = 0; i < str.length; i++) { 72 | res[i] = str.charCodeAt(i); 73 | } 74 | return res; 75 | } 76 | 77 | function bintostr(bin) { 78 | var out = []; 79 | for (var i = 0; i < bin.length; i++) { 80 | out.push(String.fromCharCode(bin[i])); 81 | } 82 | return out.join(""); 83 | } 84 | 85 | function uint8_be_to_64(data) { 86 | if (data.length < 1 || data.length > 8) { 87 | throw "Invalid input length"; 88 | } 89 | var res = JSBigInt.ZERO; 90 | var twopow8 = new JSBigInt(2).pow(8); 91 | var i = 0; 92 | switch (9 - data.length) { 93 | case 1: 94 | res = res.add(data[i++]); 95 | case 2: 96 | res = res.multiply(twopow8).add(data[i++]); 97 | case 3: 98 | res = res.multiply(twopow8).add(data[i++]); 99 | case 4: 100 | res = res.multiply(twopow8).add(data[i++]); 101 | case 5: 102 | res = res.multiply(twopow8).add(data[i++]); 103 | case 6: 104 | res = res.multiply(twopow8).add(data[i++]); 105 | case 7: 106 | res = res.multiply(twopow8).add(data[i++]); 107 | case 8: 108 | res = res.multiply(twopow8).add(data[i++]); 109 | break; 110 | default: 111 | throw "Impossible condition"; 112 | } 113 | return res; 114 | } 115 | 116 | function uint64_to_8be(num, size) { 117 | var res = new Uint8Array(size); 118 | if (size < 1 || size > 8) { 119 | throw "Invalid input length"; 120 | } 121 | var twopow8 = new JSBigInt(2).pow(8); 122 | for (var i = size - 1; i >= 0; i--) { 123 | res[i] = num.remainder(twopow8).toJSValue(); 124 | num = num.divide(twopow8); 125 | } 126 | return res; 127 | } 128 | 129 | b58.encode_block = function (data, buf, index) { 130 | if (data.length < 1 || data.length > full_encoded_block_size) { 131 | throw "Invalid block length: " + data.length; 132 | } 133 | var num = uint8_be_to_64(data); 134 | var i = encoded_block_sizes[data.length] - 1; 135 | // while num > 0 136 | while (num.compare(0) === 1) { 137 | var div = num.divRem(alphabet_size); 138 | // remainder = num % alphabet_size 139 | var remainder = div[1]; 140 | // num = num / alphabet_size 141 | num = div[0]; 142 | buf[index + i] = alphabet[remainder.toJSValue()]; 143 | i--; 144 | } 145 | return buf; 146 | }; 147 | 148 | b58.encode = function (hex) { 149 | var data = hextobin(hex); 150 | if (data.length === 0) { 151 | return ""; 152 | } 153 | var full_block_count = Math.floor(data.length / full_block_size); 154 | var last_block_size = data.length % full_block_size; 155 | var res_size = full_block_count * full_encoded_block_size + encoded_block_sizes[last_block_size]; 156 | 157 | var res = new Uint8Array(res_size); 158 | var i; 159 | for (i = 0; i < res_size; ++i) { 160 | res[i] = alphabet[0]; 161 | } 162 | for (i = 0; i < full_block_count; i++) { 163 | res = b58.encode_block(data.subarray(i * full_block_size, i * full_block_size + full_block_size), res, i * full_encoded_block_size); 164 | } 165 | if (last_block_size > 0) { 166 | 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) 167 | } 168 | return bintostr(res); 169 | }; 170 | 171 | b58.decode_block = function (data, buf, index) { 172 | if (data.length < 1 || data.length > full_encoded_block_size) { 173 | throw "Invalid block length: " + data.length; 174 | } 175 | 176 | var res_size = encoded_block_sizes.indexOf(data.length); 177 | if (res_size <= 0) { 178 | throw "Invalid block size"; 179 | } 180 | var res_num = new JSBigInt(0); 181 | var order = new JSBigInt(1); 182 | for (var i = data.length - 1; i >= 0; i--) { 183 | var digit = alphabet.indexOf(data[i]); 184 | if (digit < 0) { 185 | throw "Invalid symbol"; 186 | } 187 | var product = order.multiply(digit).add(res_num); 188 | // if product > UINT64_MAX 189 | if (product.compare(UINT64_MAX) === 1) { 190 | throw "Overflow"; 191 | } 192 | res_num = product; 193 | order = order.multiply(alphabet_size); 194 | } 195 | if (res_size < full_block_size && (new JSBigInt(2).pow(8 * res_size).compare(res_num) <= 0)) { 196 | throw "Overflow 2"; 197 | } 198 | buf.set(uint64_to_8be(res_num, res_size), index); 199 | return buf; 200 | }; 201 | 202 | b58.decode = function (enc) { 203 | enc = strtobin(enc); 204 | if (enc.length === 0) { 205 | return ""; 206 | } 207 | var full_block_count = Math.floor(enc.length / full_encoded_block_size); 208 | var last_block_size = enc.length % full_encoded_block_size; 209 | var last_block_decoded_size = encoded_block_sizes.indexOf(last_block_size); 210 | if (last_block_decoded_size < 0) { 211 | throw "Invalid encoded length"; 212 | } 213 | var data_size = full_block_count * full_block_size + last_block_decoded_size; 214 | var data = new Uint8Array(data_size); 215 | for (var i = 0; i < full_block_count; i++) { 216 | 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); 217 | } 218 | if (last_block_size > 0) { 219 | 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); 220 | } 221 | return bintohex(data); 222 | }; 223 | 224 | return b58; 225 | })(); 226 | module.exports = cnBase58; -------------------------------------------------------------------------------- /src/crypto/sha3.js: -------------------------------------------------------------------------------- 1 | /** 2 | * [js-sha3]{@link https://github.com/emn178/js-sha3} 3 | * 4 | * @version 0.7.0 5 | * @author Chen, Yi-Cyuan [emn178@gmail.com] 6 | * @copyright Chen, Yi-Cyuan 2015-2017 7 | * @license MIT 8 | */ 9 | /*jslint bitwise: true */ 10 | 'use strict'; 11 | 12 | var ERROR = 'input is invalid type'; 13 | var WINDOW = typeof window === 'object'; 14 | var root = WINDOW ? window : {}; 15 | if (root.JS_SHA3_NO_WINDOW) { 16 | WINDOW = false; 17 | } 18 | var WEB_WORKER = !WINDOW && typeof self === 'object'; 19 | var NODE_JS = !root.JS_SHA3_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node; 20 | if (NODE_JS) { 21 | root = global; 22 | } else if (WEB_WORKER) { 23 | root = self; 24 | } 25 | var ARRAY_BUFFER = !root.JS_SHA3_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined'; 26 | var HEX_CHARS = '0123456789abcdef'.split(''); 27 | var SHAKE_PADDING = [31, 7936, 2031616, 520093696]; 28 | var CSHAKE_PADDING = [4, 1024, 262144, 67108864]; 29 | var KECCAK_PADDING = [1, 256, 65536, 16777216]; 30 | var PADDING = [6, 1536, 393216, 100663296]; 31 | var SHIFT = [0, 8, 16, 24]; 32 | var RC = [1, 0, 32898, 0, 32906, 2147483648, 2147516416, 2147483648, 32907, 0, 2147483649, 33 | 0, 2147516545, 2147483648, 32777, 2147483648, 138, 0, 136, 0, 2147516425, 0, 34 | 2147483658, 0, 2147516555, 0, 139, 2147483648, 32905, 2147483648, 32771, 35 | 2147483648, 32770, 2147483648, 128, 2147483648, 32778, 0, 2147483658, 2147483648, 36 | 2147516545, 2147483648, 32896, 2147483648, 2147483649, 0, 2147516424, 2147483648]; 37 | var BITS = [224, 256, 384, 512]; 38 | var SHAKE_BITS = [128, 256]; 39 | var OUTPUT_TYPES = ['hex', 'buffer', 'arrayBuffer', 'array', 'digest']; 40 | var CSHAKE_BYTEPAD = { 41 | '128': 168, 42 | '256': 136 43 | }; 44 | 45 | if (root.JS_SHA3_NO_NODE_JS || !Array.isArray) { 46 | Array.isArray = function (obj) { 47 | return Object.prototype.toString.call(obj) === '[object Array]'; 48 | }; 49 | } 50 | 51 | if (ARRAY_BUFFER && (root.JS_SHA3_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) { 52 | ArrayBuffer.isView = function (obj) { 53 | return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer; 54 | }; 55 | } 56 | 57 | var createOutputMethod = function (bits, padding, outputType) { 58 | return function (message) { 59 | return new Keccak(bits, padding, bits).update(message)[outputType](); 60 | }; 61 | }; 62 | 63 | var createShakeOutputMethod = function (bits, padding, outputType) { 64 | return function (message, outputBits) { 65 | return new Keccak(bits, padding, outputBits).update(message)[outputType](); 66 | }; 67 | }; 68 | 69 | var createCshakeOutputMethod = function (bits, padding, outputType) { 70 | return function (message, outputBits, n, s) { 71 | return methods['cshake' + bits].update(message, outputBits, n, s)[outputType](); 72 | }; 73 | }; 74 | 75 | var createKmacOutputMethod = function (bits, padding, outputType) { 76 | return function (key, message, outputBits, s) { 77 | return methods['kmac' + bits].update(key, message, outputBits, s)[outputType](); 78 | }; 79 | }; 80 | 81 | var createOutputMethods = function (method, createMethod, bits, padding) { 82 | for (var i = 0; i < OUTPUT_TYPES.length; ++i) { 83 | var type = OUTPUT_TYPES[i]; 84 | method[type] = createMethod(bits, padding, type); 85 | } 86 | return method; 87 | }; 88 | 89 | var createMethod = function (bits, padding) { 90 | var method = createOutputMethod(bits, padding, 'hex'); 91 | method.create = function () { 92 | return new Keccak(bits, padding, bits); 93 | }; 94 | method.update = function (message) { 95 | return method.create().update(message); 96 | }; 97 | return createOutputMethods(method, createOutputMethod, bits, padding); 98 | }; 99 | 100 | var createShakeMethod = function (bits, padding) { 101 | var method = createShakeOutputMethod(bits, padding, 'hex'); 102 | method.create = function (outputBits) { 103 | return new Keccak(bits, padding, outputBits); 104 | }; 105 | method.update = function (message, outputBits) { 106 | return method.create(outputBits).update(message); 107 | }; 108 | return createOutputMethods(method, createShakeOutputMethod, bits, padding); 109 | }; 110 | 111 | var createCshakeMethod = function (bits, padding) { 112 | var w = CSHAKE_BYTEPAD[bits]; 113 | var method = createCshakeOutputMethod(bits, padding, 'hex'); 114 | method.create = function (outputBits, n, s) { 115 | if (!n && !s) { 116 | return methods['shake' + bits].create(outputBits); 117 | } else { 118 | return new Keccak(bits, padding, outputBits).bytepad([n, s], w); 119 | } 120 | }; 121 | method.update = function (message, outputBits, n, s) { 122 | return method.create(outputBits, n, s).update(message); 123 | }; 124 | return createOutputMethods(method, createCshakeOutputMethod, bits, padding); 125 | }; 126 | 127 | var createKmacMethod = function (bits, padding) { 128 | var w = CSHAKE_BYTEPAD[bits]; 129 | var method = createKmacOutputMethod(bits, padding, 'hex'); 130 | method.create = function (key, outputBits, s) { 131 | return new Kmac(bits, padding, outputBits).bytepad(['KMAC', s], w).bytepad([key], w); 132 | }; 133 | method.update = function (key, message, outputBits, s) { 134 | return method.create(key, outputBits, s).update(message); 135 | }; 136 | return createOutputMethods(method, createKmacOutputMethod, bits, padding); 137 | }; 138 | 139 | var algorithms = [ 140 | { name: 'keccak', padding: KECCAK_PADDING, bits: BITS, createMethod: createMethod }, 141 | { name: 'sha3', padding: PADDING, bits: BITS, createMethod: createMethod }, 142 | { name: 'shake', padding: SHAKE_PADDING, bits: SHAKE_BITS, createMethod: createShakeMethod }, 143 | { name: 'cshake', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: createCshakeMethod }, 144 | { name: 'kmac', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: createKmacMethod } 145 | ]; 146 | 147 | var methods = {}, methodNames = []; 148 | 149 | for (var i = 0; i < algorithms.length; ++i) { 150 | var algorithm = algorithms[i]; 151 | var bits = algorithm.bits; 152 | for (var j = 0; j < bits.length; ++j) { 153 | var methodName = algorithm.name + '_' + bits[j]; 154 | methodNames.push(methodName); 155 | methods[methodName] = algorithm.createMethod(bits[j], algorithm.padding); 156 | if (algorithm.name !== 'sha3') { 157 | var newMethodName = algorithm.name + bits[j]; 158 | methodNames.push(newMethodName); 159 | methods[newMethodName] = methods[methodName]; 160 | } 161 | } 162 | } 163 | 164 | function Keccak(bits, padding, outputBits) { 165 | this.blocks = []; 166 | this.s = []; 167 | this.padding = padding; 168 | this.outputBits = outputBits; 169 | this.reset = true; 170 | this.finalized = false; 171 | this.block = 0; 172 | this.start = 0; 173 | this.blockCount = (1600 - (bits << 1)) >> 5; 174 | this.byteCount = this.blockCount << 2; 175 | this.outputBlocks = outputBits >> 5; 176 | this.extraBytes = (outputBits & 31) >> 3; 177 | 178 | for (var i = 0; i < 50; ++i) { 179 | this.s[i] = 0; 180 | } 181 | } 182 | 183 | Keccak.prototype.update = function (message) { 184 | if (this.finalized) { 185 | return; 186 | } 187 | var notString, type = typeof message; 188 | if (type !== 'string') { 189 | if (type === 'object') { 190 | if (message === null) { 191 | throw ERROR; 192 | } else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) { 193 | message = new Uint8Array(message); 194 | } else if (!Array.isArray(message)) { 195 | if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) { 196 | throw ERROR; 197 | } 198 | } 199 | } else { 200 | throw ERROR; 201 | } 202 | notString = true; 203 | } 204 | var blocks = this.blocks, byteCount = this.byteCount, length = message.length, 205 | blockCount = this.blockCount, index = 0, s = this.s, i, code; 206 | 207 | while (index < length) { 208 | if (this.reset) { 209 | this.reset = false; 210 | blocks[0] = this.block; 211 | for (i = 1; i < blockCount + 1; ++i) { 212 | blocks[i] = 0; 213 | } 214 | } 215 | if (notString) { 216 | for (i = this.start; index < length && i < byteCount; ++index) { 217 | blocks[i >> 2] |= message[index] << SHIFT[i++ & 3]; 218 | } 219 | } else { 220 | for (i = this.start; index < length && i < byteCount; ++index) { 221 | code = message.charCodeAt(index); 222 | if (code < 0x80) { 223 | blocks[i >> 2] |= code << SHIFT[i++ & 3]; 224 | } else if (code < 0x800) { 225 | blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3]; 226 | blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; 227 | } else if (code < 0xd800 || code >= 0xe000) { 228 | blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3]; 229 | blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; 230 | blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; 231 | } else { 232 | code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff)); 233 | blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3]; 234 | blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3]; 235 | blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; 236 | blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; 237 | } 238 | } 239 | } 240 | this.lastByteIndex = i; 241 | if (i >= byteCount) { 242 | this.start = i - byteCount; 243 | this.block = blocks[blockCount]; 244 | for (i = 0; i < blockCount; ++i) { 245 | s[i] ^= blocks[i]; 246 | } 247 | f(s); 248 | this.reset = true; 249 | } else { 250 | this.start = i; 251 | } 252 | } 253 | return this; 254 | }; 255 | 256 | Keccak.prototype.encode = function (x, right) { 257 | var o = x & 255, n = 1; 258 | var bytes = [o]; 259 | x = x >> 8; 260 | o = x & 255; 261 | while (o > 0) { 262 | bytes.unshift(o); 263 | x = x >> 8; 264 | o = x & 255; 265 | ++n; 266 | } 267 | if (right) { 268 | bytes.push(n); 269 | } else { 270 | bytes.unshift(n); 271 | } 272 | this.update(bytes); 273 | return bytes.length; 274 | }; 275 | 276 | Keccak.prototype.encodeString = function (str) { 277 | var notString, type = typeof str; 278 | if (type !== 'string') { 279 | if (type === 'object') { 280 | if (str === null) { 281 | throw ERROR; 282 | } else if (ARRAY_BUFFER && str.constructor === ArrayBuffer) { 283 | str = new Uint8Array(str); 284 | } else if (!Array.isArray(str)) { 285 | if (!ARRAY_BUFFER || !ArrayBuffer.isView(str)) { 286 | throw ERROR; 287 | } 288 | } 289 | } else { 290 | throw ERROR; 291 | } 292 | notString = true; 293 | } 294 | var bytes = 0, length = str.length; 295 | if (notString) { 296 | bytes = length; 297 | } else { 298 | for (var i = 0; i < str.length; ++i) { 299 | var code = str.charCodeAt(i); 300 | if (code < 0x80) { 301 | bytes += 1; 302 | } else if (code < 0x800) { 303 | bytes += 2; 304 | } else if (code < 0xd800 || code >= 0xe000) { 305 | bytes += 3; 306 | } else { 307 | code = 0x10000 + (((code & 0x3ff) << 10) | (str.charCodeAt(++i) & 0x3ff)); 308 | bytes += 4; 309 | } 310 | } 311 | } 312 | bytes += this.encode(bytes * 8); 313 | this.update(str); 314 | return bytes; 315 | }; 316 | 317 | Keccak.prototype.bytepad = function (strs, w) { 318 | var bytes = this.encode(w); 319 | for (var i = 0; i < strs.length; ++i) { 320 | bytes += this.encodeString(strs[i]); 321 | } 322 | var paddingBytes = w - bytes % w; 323 | var zeros = []; 324 | zeros.length = paddingBytes; 325 | this.update(zeros); 326 | return this; 327 | }; 328 | 329 | Keccak.prototype.finalize = function () { 330 | if (this.finalized) { 331 | return; 332 | } 333 | this.finalized = true; 334 | var blocks = this.blocks, i = this.lastByteIndex, blockCount = this.blockCount, s = this.s; 335 | blocks[i >> 2] |= this.padding[i & 3]; 336 | if (this.lastByteIndex === this.byteCount) { 337 | blocks[0] = blocks[blockCount]; 338 | for (i = 1; i < blockCount + 1; ++i) { 339 | blocks[i] = 0; 340 | } 341 | } 342 | blocks[blockCount - 1] |= 0x80000000; 343 | for (i = 0; i < blockCount; ++i) { 344 | s[i] ^= blocks[i]; 345 | } 346 | f(s); 347 | }; 348 | 349 | Keccak.prototype.toString = Keccak.prototype.hex = function () { 350 | this.finalize(); 351 | 352 | var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks, 353 | extraBytes = this.extraBytes, i = 0, j = 0; 354 | var hex = '', block; 355 | while (j < outputBlocks) { 356 | for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) { 357 | block = s[i]; 358 | hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F] + 359 | HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F] + 360 | HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F] + 361 | HEX_CHARS[(block >> 28) & 0x0F] + HEX_CHARS[(block >> 24) & 0x0F]; 362 | } 363 | if (j % blockCount === 0) { 364 | f(s); 365 | i = 0; 366 | } 367 | } 368 | if (extraBytes) { 369 | block = s[i]; 370 | hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F]; 371 | if (extraBytes > 1) { 372 | hex += HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F]; 373 | } 374 | if (extraBytes > 2) { 375 | hex += HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F]; 376 | } 377 | } 378 | return hex; 379 | }; 380 | 381 | Keccak.prototype.arrayBuffer = function () { 382 | this.finalize(); 383 | 384 | var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks, 385 | extraBytes = this.extraBytes, i = 0, j = 0; 386 | var bytes = this.outputBits >> 3; 387 | var buffer; 388 | if (extraBytes) { 389 | buffer = new ArrayBuffer((outputBlocks + 1) << 2); 390 | } else { 391 | buffer = new ArrayBuffer(bytes); 392 | } 393 | var array = new Uint32Array(buffer); 394 | while (j < outputBlocks) { 395 | for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) { 396 | array[j] = s[i]; 397 | } 398 | if (j % blockCount === 0) { 399 | f(s); 400 | } 401 | } 402 | if (extraBytes) { 403 | array[i] = s[i]; 404 | buffer = buffer.slice(0, bytes); 405 | } 406 | return buffer; 407 | }; 408 | 409 | Keccak.prototype.buffer = Keccak.prototype.arrayBuffer; 410 | 411 | Keccak.prototype.digest = Keccak.prototype.array = function () { 412 | this.finalize(); 413 | 414 | var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks, 415 | extraBytes = this.extraBytes, i = 0, j = 0; 416 | var array = [], offset, block; 417 | while (j < outputBlocks) { 418 | for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) { 419 | offset = j << 2; 420 | block = s[i]; 421 | array[offset] = block & 0xFF; 422 | array[offset + 1] = (block >> 8) & 0xFF; 423 | array[offset + 2] = (block >> 16) & 0xFF; 424 | array[offset + 3] = (block >> 24) & 0xFF; 425 | } 426 | if (j % blockCount === 0) { 427 | f(s); 428 | } 429 | } 430 | if (extraBytes) { 431 | offset = j << 2; 432 | block = s[i]; 433 | array[offset] = block & 0xFF; 434 | if (extraBytes > 1) { 435 | array[offset + 1] = (block >> 8) & 0xFF; 436 | } 437 | if (extraBytes > 2) { 438 | array[offset + 2] = (block >> 16) & 0xFF; 439 | } 440 | } 441 | return array; 442 | }; 443 | 444 | function Kmac(bits, padding, outputBits) { 445 | Keccak.call(this, bits, padding, outputBits); 446 | } 447 | 448 | Kmac.prototype = new Keccak(); 449 | 450 | Kmac.prototype.finalize = function () { 451 | this.encode(this.outputBits, true); 452 | return Keccak.prototype.finalize.call(this); 453 | }; 454 | 455 | var f = function (s) { 456 | var h, l, n, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, 457 | b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17, 458 | b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31, b32, b33, 459 | b34, b35, b36, b37, b38, b39, b40, b41, b42, b43, b44, b45, b46, b47, b48, b49; 460 | for (n = 0; n < 48; n += 2) { 461 | c0 = s[0] ^ s[10] ^ s[20] ^ s[30] ^ s[40]; 462 | c1 = s[1] ^ s[11] ^ s[21] ^ s[31] ^ s[41]; 463 | c2 = s[2] ^ s[12] ^ s[22] ^ s[32] ^ s[42]; 464 | c3 = s[3] ^ s[13] ^ s[23] ^ s[33] ^ s[43]; 465 | c4 = s[4] ^ s[14] ^ s[24] ^ s[34] ^ s[44]; 466 | c5 = s[5] ^ s[15] ^ s[25] ^ s[35] ^ s[45]; 467 | c6 = s[6] ^ s[16] ^ s[26] ^ s[36] ^ s[46]; 468 | c7 = s[7] ^ s[17] ^ s[27] ^ s[37] ^ s[47]; 469 | c8 = s[8] ^ s[18] ^ s[28] ^ s[38] ^ s[48]; 470 | c9 = s[9] ^ s[19] ^ s[29] ^ s[39] ^ s[49]; 471 | 472 | h = c8 ^ ((c2 << 1) | (c3 >>> 31)); 473 | l = c9 ^ ((c3 << 1) | (c2 >>> 31)); 474 | s[0] ^= h; 475 | s[1] ^= l; 476 | s[10] ^= h; 477 | s[11] ^= l; 478 | s[20] ^= h; 479 | s[21] ^= l; 480 | s[30] ^= h; 481 | s[31] ^= l; 482 | s[40] ^= h; 483 | s[41] ^= l; 484 | h = c0 ^ ((c4 << 1) | (c5 >>> 31)); 485 | l = c1 ^ ((c5 << 1) | (c4 >>> 31)); 486 | s[2] ^= h; 487 | s[3] ^= l; 488 | s[12] ^= h; 489 | s[13] ^= l; 490 | s[22] ^= h; 491 | s[23] ^= l; 492 | s[32] ^= h; 493 | s[33] ^= l; 494 | s[42] ^= h; 495 | s[43] ^= l; 496 | h = c2 ^ ((c6 << 1) | (c7 >>> 31)); 497 | l = c3 ^ ((c7 << 1) | (c6 >>> 31)); 498 | s[4] ^= h; 499 | s[5] ^= l; 500 | s[14] ^= h; 501 | s[15] ^= l; 502 | s[24] ^= h; 503 | s[25] ^= l; 504 | s[34] ^= h; 505 | s[35] ^= l; 506 | s[44] ^= h; 507 | s[45] ^= l; 508 | h = c4 ^ ((c8 << 1) | (c9 >>> 31)); 509 | l = c5 ^ ((c9 << 1) | (c8 >>> 31)); 510 | s[6] ^= h; 511 | s[7] ^= l; 512 | s[16] ^= h; 513 | s[17] ^= l; 514 | s[26] ^= h; 515 | s[27] ^= l; 516 | s[36] ^= h; 517 | s[37] ^= l; 518 | s[46] ^= h; 519 | s[47] ^= l; 520 | h = c6 ^ ((c0 << 1) | (c1 >>> 31)); 521 | l = c7 ^ ((c1 << 1) | (c0 >>> 31)); 522 | s[8] ^= h; 523 | s[9] ^= l; 524 | s[18] ^= h; 525 | s[19] ^= l; 526 | s[28] ^= h; 527 | s[29] ^= l; 528 | s[38] ^= h; 529 | s[39] ^= l; 530 | s[48] ^= h; 531 | s[49] ^= l; 532 | 533 | b0 = s[0]; 534 | b1 = s[1]; 535 | b32 = (s[11] << 4) | (s[10] >>> 28); 536 | b33 = (s[10] << 4) | (s[11] >>> 28); 537 | b14 = (s[20] << 3) | (s[21] >>> 29); 538 | b15 = (s[21] << 3) | (s[20] >>> 29); 539 | b46 = (s[31] << 9) | (s[30] >>> 23); 540 | b47 = (s[30] << 9) | (s[31] >>> 23); 541 | b28 = (s[40] << 18) | (s[41] >>> 14); 542 | b29 = (s[41] << 18) | (s[40] >>> 14); 543 | b20 = (s[2] << 1) | (s[3] >>> 31); 544 | b21 = (s[3] << 1) | (s[2] >>> 31); 545 | b2 = (s[13] << 12) | (s[12] >>> 20); 546 | b3 = (s[12] << 12) | (s[13] >>> 20); 547 | b34 = (s[22] << 10) | (s[23] >>> 22); 548 | b35 = (s[23] << 10) | (s[22] >>> 22); 549 | b16 = (s[33] << 13) | (s[32] >>> 19); 550 | b17 = (s[32] << 13) | (s[33] >>> 19); 551 | b48 = (s[42] << 2) | (s[43] >>> 30); 552 | b49 = (s[43] << 2) | (s[42] >>> 30); 553 | b40 = (s[5] << 30) | (s[4] >>> 2); 554 | b41 = (s[4] << 30) | (s[5] >>> 2); 555 | b22 = (s[14] << 6) | (s[15] >>> 26); 556 | b23 = (s[15] << 6) | (s[14] >>> 26); 557 | b4 = (s[25] << 11) | (s[24] >>> 21); 558 | b5 = (s[24] << 11) | (s[25] >>> 21); 559 | b36 = (s[34] << 15) | (s[35] >>> 17); 560 | b37 = (s[35] << 15) | (s[34] >>> 17); 561 | b18 = (s[45] << 29) | (s[44] >>> 3); 562 | b19 = (s[44] << 29) | (s[45] >>> 3); 563 | b10 = (s[6] << 28) | (s[7] >>> 4); 564 | b11 = (s[7] << 28) | (s[6] >>> 4); 565 | b42 = (s[17] << 23) | (s[16] >>> 9); 566 | b43 = (s[16] << 23) | (s[17] >>> 9); 567 | b24 = (s[26] << 25) | (s[27] >>> 7); 568 | b25 = (s[27] << 25) | (s[26] >>> 7); 569 | b6 = (s[36] << 21) | (s[37] >>> 11); 570 | b7 = (s[37] << 21) | (s[36] >>> 11); 571 | b38 = (s[47] << 24) | (s[46] >>> 8); 572 | b39 = (s[46] << 24) | (s[47] >>> 8); 573 | b30 = (s[8] << 27) | (s[9] >>> 5); 574 | b31 = (s[9] << 27) | (s[8] >>> 5); 575 | b12 = (s[18] << 20) | (s[19] >>> 12); 576 | b13 = (s[19] << 20) | (s[18] >>> 12); 577 | b44 = (s[29] << 7) | (s[28] >>> 25); 578 | b45 = (s[28] << 7) | (s[29] >>> 25); 579 | b26 = (s[38] << 8) | (s[39] >>> 24); 580 | b27 = (s[39] << 8) | (s[38] >>> 24); 581 | b8 = (s[48] << 14) | (s[49] >>> 18); 582 | b9 = (s[49] << 14) | (s[48] >>> 18); 583 | 584 | s[0] = b0 ^ (~b2 & b4); 585 | s[1] = b1 ^ (~b3 & b5); 586 | s[10] = b10 ^ (~b12 & b14); 587 | s[11] = b11 ^ (~b13 & b15); 588 | s[20] = b20 ^ (~b22 & b24); 589 | s[21] = b21 ^ (~b23 & b25); 590 | s[30] = b30 ^ (~b32 & b34); 591 | s[31] = b31 ^ (~b33 & b35); 592 | s[40] = b40 ^ (~b42 & b44); 593 | s[41] = b41 ^ (~b43 & b45); 594 | s[2] = b2 ^ (~b4 & b6); 595 | s[3] = b3 ^ (~b5 & b7); 596 | s[12] = b12 ^ (~b14 & b16); 597 | s[13] = b13 ^ (~b15 & b17); 598 | s[22] = b22 ^ (~b24 & b26); 599 | s[23] = b23 ^ (~b25 & b27); 600 | s[32] = b32 ^ (~b34 & b36); 601 | s[33] = b33 ^ (~b35 & b37); 602 | s[42] = b42 ^ (~b44 & b46); 603 | s[43] = b43 ^ (~b45 & b47); 604 | s[4] = b4 ^ (~b6 & b8); 605 | s[5] = b5 ^ (~b7 & b9); 606 | s[14] = b14 ^ (~b16 & b18); 607 | s[15] = b15 ^ (~b17 & b19); 608 | s[24] = b24 ^ (~b26 & b28); 609 | s[25] = b25 ^ (~b27 & b29); 610 | s[34] = b34 ^ (~b36 & b38); 611 | s[35] = b35 ^ (~b37 & b39); 612 | s[44] = b44 ^ (~b46 & b48); 613 | s[45] = b45 ^ (~b47 & b49); 614 | s[6] = b6 ^ (~b8 & b0); 615 | s[7] = b7 ^ (~b9 & b1); 616 | s[16] = b16 ^ (~b18 & b10); 617 | s[17] = b17 ^ (~b19 & b11); 618 | s[26] = b26 ^ (~b28 & b20); 619 | s[27] = b27 ^ (~b29 & b21); 620 | s[36] = b36 ^ (~b38 & b30); 621 | s[37] = b37 ^ (~b39 & b31); 622 | s[46] = b46 ^ (~b48 & b40); 623 | s[47] = b47 ^ (~b49 & b41); 624 | s[8] = b8 ^ (~b0 & b2); 625 | s[9] = b9 ^ (~b1 & b3); 626 | s[18] = b18 ^ (~b10 & b12); 627 | s[19] = b19 ^ (~b11 & b13); 628 | s[28] = b28 ^ (~b20 & b22); 629 | s[29] = b29 ^ (~b21 & b23); 630 | s[38] = b38 ^ (~b30 & b32); 631 | s[39] = b39 ^ (~b31 & b33); 632 | s[48] = b48 ^ (~b40 & b42); 633 | s[49] = b49 ^ (~b41 & b43); 634 | 635 | s[0] ^= RC[n]; 636 | s[1] ^= RC[n + 1]; 637 | } 638 | }; 639 | 640 | module.exports = methods; 641 | -------------------------------------------------------------------------------- /src/crypto/utils.js: -------------------------------------------------------------------------------- 1 | var jsSHA = require('jssha/src/sha256'); 2 | var Blake256 = require('./blake256'); 3 | var keccak256 = require('./sha3')['keccak256']; 4 | var Blake2B = require('./blake2b'); 5 | var base58 = require('./base58'); 6 | var base32 = require('./base32'); 7 | var BigNum = require('browserify-bignum'); 8 | var groestl = require('groestl-hash-js'); 9 | 10 | // Address types, compatible with Trezor 11 | const addressType = { 12 | ADDRESS: 'address', 13 | P2PKH: 'p2pkh', 14 | P2WPKH: 'p2wpkh', 15 | P2WSH: 'p2wsh', 16 | P2SH: 'p2sh', 17 | P2TR: 'p2tr', 18 | WITNESS_UNKNOWN: 'p2w-unknown', 19 | }; 20 | 21 | function numberToHex(number, sizeInBytes) { 22 | return Math.round(number).toString(16).padStart(sizeInBytes * 2, '0'); 23 | } 24 | 25 | function isHexChar(c) { 26 | if ((c >= 'A' && c <= 'F') || 27 | (c >= 'a' && c <= 'f') || 28 | (c >= '0' && c <= '9')) { 29 | return 1; 30 | } 31 | return 0; 32 | } 33 | 34 | /* Convert a hex char to value */ 35 | function hexChar2byte(c) { 36 | var d = 0; 37 | if (c >= 'A' && c <= 'F') { 38 | d = c.charCodeAt(0) - 'A'.charCodeAt(0) + 10; 39 | } 40 | else if (c >= 'a' && c <= 'f') { 41 | d = c.charCodeAt(0) - 'a'.charCodeAt(0) + 10; 42 | } 43 | else if (c >= '0' && c <= '9') { 44 | d = c.charCodeAt(0) - '0'.charCodeAt(0); 45 | } 46 | return d; 47 | } 48 | 49 | /* Convert a byte to string */ 50 | function byte2hexStr(byte) { 51 | var hexByteMap = "0123456789ABCDEF"; 52 | var str = ""; 53 | str += hexByteMap.charAt(byte >> 4); 54 | str += hexByteMap.charAt(byte & 0x0f); 55 | return str; 56 | } 57 | 58 | function byteArray2hexStr(byteArray) { 59 | var str = ""; 60 | for (var i = 0; i < (byteArray.length - 1); i++) { 61 | str += byte2hexStr(byteArray[i]); 62 | } 63 | str += byte2hexStr(byteArray[i]); 64 | return str; 65 | } 66 | 67 | function hexStr2byteArray(str) { 68 | var byteArray = Array(); 69 | var d = 0; 70 | var i = 0; 71 | var j = 0; 72 | var k = 0; 73 | 74 | for (i = 0; i < str.length; i++) { 75 | var c = str.charAt(i); 76 | if (isHexChar(c)) { 77 | d <<= 4; 78 | d += hexChar2byte(c); 79 | j++; 80 | if (0 === (j % 2)) { 81 | byteArray[k++] = d; 82 | d = 0; 83 | } 84 | } 85 | } 86 | return byteArray; 87 | } 88 | 89 | module.exports = { 90 | numberToHex, 91 | toHex: function (arrayOfBytes) { 92 | var hex = ''; 93 | for (var i = 0; i < arrayOfBytes.length; i++) { 94 | hex += numberToHex(arrayOfBytes[i], 1); 95 | } 96 | return hex; 97 | }, 98 | sha256: function (payload, format = 'HEX') { 99 | var sha = new jsSHA('SHA-256', format); 100 | sha.update(payload); 101 | return sha.getHash(format); 102 | }, 103 | sha256x2: function (buffer, format = 'HEX') { 104 | return this.sha256(this.sha256(buffer, format), format); 105 | }, 106 | sha256Checksum: function (payload) { 107 | return this.sha256(this.sha256(payload)).substr(0, 8); 108 | }, 109 | blake256: function (hexString) { 110 | return new Blake256().update(hexString, 'hex').digest('hex'); 111 | }, 112 | blake256Checksum: function (payload) { 113 | return this.blake256(this.blake256(payload)).substr(0, 8); 114 | }, 115 | blake2b: function (hexString, outlen) { 116 | return new Blake2B(outlen).update(Buffer.from(hexString, 'hex')).digest('hex'); 117 | }, 118 | keccak256: function (hexString) { 119 | return keccak256(hexString); 120 | }, 121 | keccak256Checksum: function (payload) { 122 | return keccak256(payload).toString().substr(0, 8); 123 | }, 124 | blake2b256: function (hexString) { 125 | return new Blake2B(32).update(Buffer.from(hexString, 'hex'), 32).digest('hex'); 126 | }, 127 | groestl512x2: function (hexString) { 128 | let result = groestl.groestl_2(Buffer.from(hexString, 'hex'), 1, 0).substr(0, 8); 129 | return result; 130 | }, 131 | base58: base58.decode, 132 | byteArray2hexStr: byteArray2hexStr, 133 | hexStr2byteArray: hexStr2byteArray, 134 | bigNumberToBuffer: function(bignumber, size){ 135 | return new BigNum(bignumber).toBuffer({ size, endian: 'big' }); 136 | }, 137 | base32, 138 | addressType, 139 | } 140 | -------------------------------------------------------------------------------- /src/currencies.js: -------------------------------------------------------------------------------- 1 | var XRPValidator = require('./ripple_validator'); 2 | var ETHValidator = require('./ethereum_validator'); 3 | var BTCValidator = require('./bitcoin_validator'); 4 | var ADAValidator = require('./ada_validator'); 5 | var XMRValidator = require('./monero_validator'); 6 | var LokiValidator = require('./loki_validator'); 7 | var NANOValidator = require('./nano_validator'); 8 | var SCValidator = require('./siacoin_validator'); 9 | var TRXValidator = require('./tron_validator'); 10 | var NEMValidator = require('./nem_validator'); 11 | var LSKValidator = require('./lisk_validator'); 12 | var BCHValidator = require('./bch_validator'); 13 | var XLMValidator = require('./stellar_validator'); 14 | var BinanceValidator = require('./binance_validator'); 15 | var EOSValidator = require('./eos_validator'); 16 | var XTZValidator = require('./tezos_validator'); 17 | var AEValidator = require('./ae_validator'); 18 | var ARDRValidator = require('./ardr_validator'); 19 | var ATOMValidator = require('./atom_validator'); 20 | var HBARValidator = require('./hbar_validator'); 21 | var ICXValidator = require('./icx_validator'); 22 | var IOSTValidator = require('./iost_validator'); 23 | // var IOTAValidator = require('./iota_validator'); 24 | var STEEMValidator = require('./steem_validator'); 25 | var SYSValidator = require('./sys_validator'); 26 | var ZILValidator = require('./zil_validator'); 27 | var NXTValidator = require('./nxt_validator'); 28 | var SOLValidator = require('./solana_validator'); 29 | 30 | // defines P2PKH, P2SH and bech32 address types for standard (prod) and testnet networks 31 | var CURRENCIES = [ 32 | { 33 | name: 'Bitcoin', 34 | symbol: 'btc', 35 | segwitHrp: { prod: 'bc', testnet: 'tb', regtest: 'bcrt' }, 36 | addressTypes: { prod: ['00', '05'], testnet: ['6f', 'c4', '3c', '26'], regtest: ['6f', 'c4', '3c', '26'] }, 37 | validator: BTCValidator, 38 | }, { 39 | name: 'BitcoinCash', 40 | symbol: 'bch', 41 | regexp: '^[qQpP]{1}[0-9a-zA-Z]{41}$', 42 | addressTypes: { prod: ['00', '05'], testnet: ['6f', 'c4'] }, 43 | validator: BCHValidator, 44 | }, { 45 | name: 'Bitcoin Diamond', 46 | symbol: 'bcd', 47 | validator: BTCValidator, 48 | addressTypes: { prod: ['00'] } 49 | }, { 50 | name: 'Bitcoin SV', 51 | symbol: 'bsv', 52 | regexp: '^[qQ]{1}[0-9a-zA-Z]{41}$', 53 | addressTypes: { prod: ['00', '05'], testnet: ['6f', 'c4'] }, 54 | validator: BCHValidator, 55 | }, { 56 | name: 'Fujicoin', 57 | symbol: 'fjc', 58 | segwitHrp: { prod: 'fc', testnet: 'tf' }, 59 | addressTypes: { prod: ['24', '10'], testnet: ['4a', 'c4'] }, 60 | validator: BTCValidator, 61 | }, { 62 | name: 'LiteCoin', 63 | symbol: 'ltc', 64 | segwitHrp: { prod: 'ltc', testnet: 'tltc' }, 65 | addressTypes: { prod: ['30', '32'], testnet: ['6f', 'c4', '3a'] }, 66 | validator: BTCValidator, 67 | }, { 68 | name: 'PeerCoin', 69 | symbol: 'ppc', 70 | addressTypes: { prod: ['37', '75'], testnet: ['6f', 'c4'] }, 71 | validator: BTCValidator, 72 | }, { 73 | name: 'DogeCoin', 74 | symbol: 'doge', 75 | addressTypes: { prod: ['1e', '16'], testnet: ['71', 'c4'] }, 76 | validator: BTCValidator, 77 | }, { 78 | name: 'BeaverCoin', 79 | symbol: 'bvc', 80 | addressTypes: { prod: ['19', '05'], testnet: ['6f', 'c4'] }, 81 | validator: BTCValidator, 82 | }, { 83 | name: 'FreiCoin', 84 | symbol: 'frc', 85 | addressTypes: { prod: ['00', '05'], testnet: ['6f', 'c4'] }, 86 | validator: BTCValidator, 87 | }, { 88 | name: 'ProtoShares', 89 | symbol: 'pts', 90 | addressTypes: { prod: ['38', '05'], testnet: ['6f', 'c4'] }, 91 | validator: BTCValidator, 92 | }, { 93 | name: 'MegaCoin', 94 | symbol: 'mec', 95 | addressTypes: { prod: ['32', '05'], testnet: ['6f', 'c4'] }, 96 | validator: BTCValidator, 97 | }, { 98 | name: 'PrimeCoin', 99 | symbol: 'xpm', 100 | addressTypes: { prod: ['17', '53'], testnet: ['6f', 'c4'] }, 101 | validator: BTCValidator, 102 | }, { 103 | name: 'AuroraCoin', 104 | symbol: 'aur', 105 | addressTypes: { prod: ['17', '05'], testnet: ['6f', 'c4'] }, 106 | validator: BTCValidator, 107 | }, { 108 | name: 'NameCoin', 109 | symbol: 'nmc', 110 | addressTypes: { prod: ['34'], testnet: [] }, 111 | validator: BTCValidator, 112 | }, { 113 | name: 'NXT', 114 | symbol: 'nxt', 115 | validator: NXTValidator, 116 | }, { 117 | name: 'BioCoin', 118 | symbol: 'bio', 119 | addressTypes: { prod: ['19', '14'], testnet: ['6f', 'c4'] }, 120 | validator: BTCValidator, 121 | }, { 122 | name: 'GarliCoin', 123 | symbol: 'grlc', 124 | addressTypes: { prod: ['26', '05'], testnet: ['6f', 'c4'] }, 125 | validator: BTCValidator, 126 | }, { 127 | name: 'VertCoin', 128 | symbol: 'vtc', 129 | segwitHrp: { prod: 'vtc', testnet: 'tvtc' }, 130 | addressTypes: { prod: ['47', '05'], testnet: ['4a', 'c4', '6f'] }, 131 | validator: BTCValidator, 132 | }, { 133 | name: 'VeChain', 134 | symbol: 'ven', 135 | validator: ETHValidator, 136 | }, { 137 | name: 'VeChain Mainnet', 138 | symbol: 'vet', 139 | validator: ETHValidator, 140 | }, { 141 | name: 'BitcoinGold', 142 | symbol: 'btg', 143 | segwitHrp: { prod: 'btg', testnet: 'tbtg' }, 144 | addressTypes: { prod: ['26', '17'], testnet: ['6f', 'c4'] }, 145 | validator: BTCValidator, 146 | }, { 147 | name: 'Komodo', 148 | symbol: 'kmd', 149 | addressTypes: { prod: ['3c', '55'], testnet: ['0', '5'] }, 150 | validator: BTCValidator, 151 | }, { 152 | name: 'BitcoinZ', 153 | symbol: 'btcz', 154 | expectedLength: 26, 155 | addressTypes: { prod: ['1cb8', '1cbd'], testnet: ['1d25', '1cba'] }, 156 | validator: BTCValidator, 157 | }, { 158 | name: 'BitcoinPrivate', 159 | symbol: 'btcp', 160 | expectedLength: 26, 161 | addressTypes: { prod: ['1325', '13af'], testnet: ['1957', '19e0'] }, 162 | validator: BTCValidator, 163 | }, { 164 | name: 'Hush', 165 | symbol: 'hush', 166 | expectedLength: 26, 167 | addressTypes: { prod: ['1cb8', '1cbd'], testnet: ['1d25', '1cba'] }, 168 | validator: BTCValidator, 169 | }, { 170 | name: 'SnowGem', 171 | symbol: 'sng', 172 | expectedLength: 26, 173 | addressTypes: { prod: ['1c28', '1c2d'], testnet: ['1d25', '1cba'] }, 174 | validator: BTCValidator, 175 | }, { 176 | name: 'ZCash', 177 | symbol: 'zec', 178 | expectedLength: 26, 179 | addressTypes: { prod: ['1cb8', '1cbd'], testnet: ['1d25', '1cba'] }, 180 | validator: BTCValidator, 181 | }, { 182 | name: 'ZClassic', 183 | symbol: 'zcl', 184 | expectedLength: 26, 185 | addressTypes: { prod: ['1cb8', '1cbd'], testnet: ['1d25', '1cba'] }, 186 | validator: BTCValidator, 187 | }, { 188 | name: 'ZenCash', 189 | symbol: 'zen', 190 | expectedLength: 26, 191 | addressTypes: { prod: ['2089', '2096'], testnet: ['2092', '2098'] }, 192 | validator: BTCValidator, 193 | }, { 194 | name: 'VoteCoin', 195 | symbol: 'vot', 196 | expectedLength: 26, 197 | addressTypes: { prod: ['1cb8', '1cbd'], testnet: ['1d25', '1cba'] }, 198 | validator: BTCValidator, 199 | }, { 200 | name: 'Decred', 201 | symbol: 'dcr', 202 | addressTypes: { prod: ['073f', '071a'], testnet: ['0f21', '0efc'] }, 203 | hashFunction: 'blake256', 204 | expectedLength: 26, 205 | validator: BTCValidator, 206 | }, { 207 | name: 'GameCredits', 208 | symbol: 'game', 209 | segwitHrp: { prod: 'game', prod: 'tgame' }, 210 | addressTypes: { prod: ['26', '3e'], testnet: ['6f', '3a'] }, 211 | validator: BTCValidator, 212 | }, { 213 | name: 'PIVX', 214 | symbol: 'pivx', 215 | addressTypes: { prod: ['1e', '0d'], testnet: [] }, 216 | validator: BTCValidator, 217 | }, { 218 | name: 'SolarCoin', 219 | symbol: 'slr', 220 | addressTypes: { prod: ['12', '05'], testnet: [] }, 221 | validator: BTCValidator, 222 | }, { 223 | name: 'MonaCoin', 224 | symbol: 'mona', 225 | segwitHrp: { prod: 'mona', prod: 'tmona' }, 226 | addressTypes: { prod: ['32', '37'], testnet: ['6f', '75'] }, 227 | validator: BTCValidator, 228 | }, { 229 | name: 'DigiByte', 230 | symbol: 'dgb', 231 | segwitHrp: { prod: 'dgb' }, 232 | addressTypes: { prod: ['1e', '3f'], testnet: [] }, 233 | validator: BTCValidator, 234 | }, { 235 | name: 'Tether', 236 | symbol: 'usdt', 237 | addressTypes: { prod: ['00', '05'], testnet: ['6f', 'c4'] }, 238 | validator: BTCValidator, 239 | }, { 240 | name: 'Ripple', 241 | symbol: 'xrp', 242 | validator: XRPValidator, 243 | }, { 244 | name: 'Dash', 245 | symbol: 'dash', 246 | addressTypes: { prod: ['4c', '10'], testnet: ['8c', '13'] }, 247 | validator: BTCValidator, 248 | }, { 249 | name: 'Neo', 250 | symbol: 'neo', 251 | addressTypes: { prod: ['17'], testnet: [] }, 252 | validator: BTCValidator, 253 | }, { 254 | name: 'NeoGas', 255 | symbol: 'gas', 256 | addressTypes: { prod: ['17'], testnet: [] }, 257 | validator: BTCValidator, 258 | }, { 259 | name: 'Qtum', 260 | symbol: 'qtum', 261 | segwitHrp: { prod: 'qc', prod: 'tq' }, 262 | addressTypes: { prod: ['3a', '32'], testnet: ['78', '6e'] }, 263 | validator: BTCValidator, 264 | }, { 265 | name: 'Waves', 266 | symbol: 'waves', 267 | addressTypes: { prod: ['0157'], testnet: ['0154'] }, 268 | expectedLength: 26, 269 | hashFunction: 'blake256keccak256', 270 | regex: /^[a-zA-Z0-9]{35}$/, 271 | validator: BTCValidator, 272 | }, { 273 | name: 'Ontology', 274 | symbol: 'ont', 275 | validator: BTCValidator, 276 | addressTypes: { prod: ['17', '41'] } 277 | }, { 278 | name: 'Ravencoin', 279 | symbol: 'rvn', 280 | validator: BTCValidator, 281 | addressTypes: { prod: ['3c'] } 282 | }, { 283 | name: 'Groestlcoin', 284 | symbol: 'grs', 285 | addressTypes: { prod: ['24', '05'], testnet: ['6f', 'c4'] }, 286 | segwitHrp: { prod: 'grs', testnet: 'tgrs' }, 287 | hashFunction: 'groestl512x2', 288 | validator: BTCValidator 289 | }, { 290 | name: 'Ethereum', 291 | symbol: 'eth', 292 | validator: ETHValidator, 293 | }, { 294 | name: 'EtherZero', 295 | symbol: 'etz', 296 | validator: ETHValidator, 297 | }, { 298 | name: 'EthereumClassic', 299 | symbol: 'etc', 300 | validator: ETHValidator, 301 | }, { 302 | name: 'Callisto', 303 | symbol: 'clo', 304 | validator: ETHValidator, 305 | }, { 306 | name: 'Bankex', 307 | symbol: 'bkx', 308 | validator: ETHValidator, 309 | }, { 310 | name: 'Cardano', 311 | symbol: 'ada', 312 | segwitHrp: { prod: 'addr', testnet: 'addr_test' }, 313 | validator: ADAValidator, 314 | }, { 315 | name: 'Monero', 316 | symbol: 'xmr', 317 | addressTypes: { prod: ['18'], testnet: ['53'] }, 318 | subAddressTypes: { prod: ['42'], testnet: ['63'] }, 319 | iAddressTypes: { prod: ['19'], testnet: ['54'] }, 320 | validator: XMRValidator, 321 | }, { 322 | name: 'Aragon', 323 | symbol: 'ant', 324 | validator: ETHValidator, 325 | }, { 326 | name: 'Ardor', 327 | symbol: 'ardr', 328 | validator: ARDRValidator, 329 | }, { 330 | name: 'Basic Attention Token', 331 | symbol: 'bat', 332 | validator: ETHValidator, 333 | }, { 334 | name: 'Bancor', 335 | symbol: 'bnt', 336 | validator: ETHValidator, 337 | }, { 338 | name: 'Civic', 339 | symbol: 'cvc', 340 | validator: ETHValidator, 341 | }, { 342 | name: 'Own', // Rebranded from Chainium 343 | symbol: 'chx', 344 | validator: ETHValidator, 345 | }, { 346 | name: 'District0x', 347 | symbol: 'dnt', 348 | validator: ETHValidator, 349 | }, { 350 | name: 'Gnosis', 351 | symbol: 'gno', 352 | validator: ETHValidator, 353 | }, { 354 | name: 'Golem', 355 | symbol: 'gnt', 356 | validator: ETHValidator, 357 | }, { 358 | name: 'Matchpool', 359 | symbol: 'gup', 360 | validator: ETHValidator, 361 | }, { 362 | name: 'Melon', 363 | symbol: 'mln', 364 | validator: ETHValidator, 365 | }, { 366 | name: 'Numeraire', 367 | symbol: 'nmr', 368 | validator: ETHValidator, 369 | }, { 370 | name: 'OmiseGO', 371 | symbol: 'omg', 372 | validator: ETHValidator, 373 | }, { 374 | name: 'TenX', 375 | symbol: 'pay', 376 | validator: ETHValidator, 377 | }, { 378 | name: 'Ripio Credit Network', 379 | symbol: 'rcn', 380 | validator: ETHValidator, 381 | }, { 382 | name: 'Augur', 383 | symbol: 'rep', 384 | validator: ETHValidator, 385 | }, { 386 | name: 'iExec RLC', 387 | symbol: 'rlc', 388 | validator: ETHValidator, 389 | }, { 390 | name: 'Salt', 391 | symbol: 'salt', 392 | validator: ETHValidator, 393 | }, { 394 | name: 'Status', 395 | symbol: 'snt', 396 | validator: ETHValidator, 397 | }, { 398 | name: 'Storj', 399 | symbol: 'storj', 400 | validator: ETHValidator, 401 | }, { 402 | name: 'STEEM', 403 | symbol: 'steem', 404 | validator: STEEMValidator 405 | }, { 406 | name: 'Stratis', 407 | symbol: 'strat', 408 | validator: BTCValidator, 409 | addressTypes: { prod: ['3f'] } 410 | }, { 411 | name: 'Syscoin', 412 | symbol: 'sys', 413 | addressTypes: { prod: ['3f'] }, 414 | validator: SYSValidator 415 | }, { 416 | name: 'Swarm City', 417 | symbol: 'swt', 418 | validator: ETHValidator, 419 | }, { 420 | name: 'TrueUSD', 421 | symbol: 'tusd', 422 | validator: ETHValidator, 423 | }, { 424 | name: 'Wings', 425 | symbol: 'wings', 426 | validator: ETHValidator, 427 | }, { 428 | name: '0x', 429 | symbol: 'zrx', 430 | validator: ETHValidator, 431 | }, { 432 | name: 'Expanse', 433 | symbol: 'exp', 434 | validator: ETHValidator, 435 | }, { 436 | name: 'Viberate', 437 | symbol: 'vib', 438 | validator: ETHValidator, 439 | }, { 440 | name: 'Odyssey', 441 | symbol: 'ocn', 442 | validator: ETHValidator, 443 | }, { 444 | name: 'Polymath', 445 | symbol: 'poly', 446 | validator: ETHValidator, 447 | }, { 448 | name: 'Storm', 449 | symbol: 'storm', 450 | validator: ETHValidator, 451 | }, { 452 | name: 'FirstBlood', 453 | symbol: '1st', 454 | validator: ETHValidator, 455 | }, { 456 | name: 'Arcblock', 457 | symbol: 'abt', 458 | validator: ETHValidator, 459 | }, { 460 | name: 'Abyss Token', 461 | symbol: 'abyss', 462 | validator: ETHValidator, 463 | }, { 464 | name: 'adToken', 465 | symbol: 'adt', 466 | validator: ETHValidator, 467 | }, { 468 | name: 'AdEx', 469 | symbol: 'adx', 470 | validator: ETHValidator, 471 | }, { 472 | name: 'SingularityNET', 473 | symbol: 'agi', 474 | validator: ETHValidator, 475 | }, { 476 | name: 'Ambrosus', 477 | symbol: 'amb', 478 | validator: ETHValidator, 479 | }, { 480 | name: 'Ankr', 481 | symbol: 'ankr', 482 | validator: ETHValidator, 483 | }, { 484 | name: 'AppCoins', 485 | symbol: 'appc', 486 | validator: ETHValidator, 487 | }, { 488 | name: 'Cosmos', 489 | symbol: 'atom', 490 | validator: ATOMValidator, 491 | }, { 492 | name: 'Aeron', 493 | symbol: 'arn', 494 | validator: ETHValidator, 495 | }, { 496 | name: 'Aeternity', 497 | symbol: 'ae', 498 | validator: AEValidator, 499 | }, { 500 | name: 'ATLANT', 501 | symbol: 'atl', 502 | validator: ETHValidator, 503 | }, { 504 | name: 'aXpire', 505 | symbol: 'axpr', 506 | validator: ETHValidator, 507 | }, { 508 | name: 'Band Protocol', 509 | symbol: 'band', 510 | validator: ETHValidator, 511 | }, { 512 | name: 'Blockmason Credit Protocol', 513 | symbol: 'bcpt', 514 | validator: ETHValidator, 515 | }, { 516 | name: 'BitDegree', 517 | symbol: 'bdg', 518 | validator: ETHValidator, 519 | }, { 520 | name: 'BetterBetting', 521 | symbol: 'betr', 522 | validator: ETHValidator, 523 | }, { 524 | name: 'Bluzelle', 525 | symbol: 'blz', 526 | validator: ETHValidator, 527 | }, { 528 | name: 'Bread', 529 | symbol: 'brd', 530 | validator: ETHValidator, 531 | }, { 532 | name: 'Blocktrade Token', 533 | symbol: 'btt', 534 | validator: ETHValidator, 535 | }, { 536 | name: 'Binance USD', 537 | symbol: 'busd', 538 | validator: ETHValidator, 539 | }, { 540 | name: 'CryptoBossCoin', 541 | symbol: 'cbc', 542 | validator: ETHValidator, 543 | }, { 544 | name: 'Blox', 545 | symbol: 'cdt', 546 | validator: ETHValidator, 547 | }, { 548 | name: 'Celer Network', 549 | symbol: 'celr', 550 | validator: ETHValidator, 551 | }, { 552 | name: 'Chiliz', 553 | symbol: 'chz', 554 | validator: ETHValidator, 555 | }, { 556 | name: 'Coinlancer', 557 | symbol: 'cl', 558 | validator: ETHValidator, 559 | }, { 560 | name: 'Cindicator', 561 | symbol: 'cnd', 562 | validator: ETHValidator, 563 | }, { 564 | name: 'Cocos-BCX', 565 | symbol: 'cocos', 566 | validator: ETHValidator, 567 | }, { 568 | name: 'COS', 569 | symbol: 'cos', 570 | validator: ETHValidator, 571 | }, { 572 | name: 'Cosmo Coin', 573 | symbol: 'cosm', 574 | validator: ETHValidator, 575 | }, { 576 | name: 'Covesting', 577 | symbol: 'cov', 578 | validator: ETHValidator, 579 | }, { 580 | name: 'Crypterium', 581 | symbol: 'crpt', 582 | validator: ETHValidator, 583 | }, { 584 | name: 'Daneel', 585 | symbol: 'dan', 586 | validator: ETHValidator, 587 | }, { 588 | name: 'Streamr DATAcoin', 589 | symbol: 'data', 590 | validator: ETHValidator, 591 | }, { 592 | name: 'Dentacoin', 593 | symbol: 'dcn', 594 | validator: ETHValidator, 595 | }, { 596 | name: 'Dent', 597 | symbol: 'dent', 598 | validator: ETHValidator, 599 | }, { 600 | name: 'DigixDAO', 601 | symbol: 'dgd', 602 | validator: ETHValidator, 603 | }, { 604 | name: 'Digitex Futures', 605 | symbol: 'dgtx', 606 | validator: ETHValidator, 607 | }, { 608 | name: 'Agrello', 609 | symbol: 'dlt', 610 | validator: ETHValidator, 611 | }, { 612 | name: 'Dock', 613 | symbol: 'dock', 614 | validator: ETHValidator, 615 | }, { 616 | name: 'DomRaider', 617 | symbol: 'drt', 618 | validator: ETHValidator, 619 | }, { 620 | name: 'Dusk Network', 621 | symbol: 'dusk', 622 | validator: ETHValidator, 623 | }, { 624 | name: 'Edgeless', 625 | symbol: 'edg', 626 | validator: ETHValidator, 627 | }, { 628 | name: 'Eidoo', 629 | symbol: 'edo', 630 | validator: ETHValidator, 631 | }, { 632 | name: 'Electrify.Asia', 633 | symbol: 'elec', 634 | validator: ETHValidator, 635 | }, { 636 | name: 'aelf', 637 | symbol: 'elf', 638 | validator: ETHValidator, 639 | }, { 640 | name: 'Enigma', 641 | symbol: 'eng', 642 | validator: ETHValidator, 643 | }, { 644 | name: 'STASIS EURO', 645 | symbol: 'eurs', 646 | validator: ETHValidator, 647 | }, { 648 | name: 'Everex', 649 | symbol: 'evx', 650 | validator: ETHValidator, 651 | }, { 652 | name: 'FirmaChain', 653 | symbol: 'fct', 654 | validator: ETHValidator, 655 | }, { 656 | name: 'Fetch.ai', 657 | symbol: 'fet', 658 | validator: ETHValidator, 659 | }, { 660 | name: 'Fortuna', 661 | symbol: 'fota', 662 | validator: ETHValidator, 663 | }, { 664 | name: 'Fantom', 665 | symbol: 'ftm', 666 | validator: ETHValidator, 667 | }, { 668 | name: 'Etherparty', 669 | symbol: 'fuel', 670 | validator: ETHValidator, 671 | }, { 672 | name: 'Gifto', 673 | symbol: 'gto', 674 | validator: ETHValidator, 675 | }, { 676 | name: 'Gemini Dollar', 677 | symbol: 'gusd', 678 | validator: ETHValidator, 679 | }, { 680 | name: 'Genesis Vision', 681 | symbol: 'gvt', 682 | validator: ETHValidator, 683 | }, { 684 | name: 'Humaniq', 685 | symbol: 'hmq', 686 | validator: ETHValidator, 687 | }, { 688 | name: 'Holo', 689 | symbol: 'hot', 690 | validator: ETHValidator, 691 | }, { 692 | name: 'HOQU', 693 | symbol: 'hqx', 694 | validator: ETHValidator, 695 | }, { 696 | name: 'Huobi Token', 697 | symbol: 'ht', 698 | validator: ETHValidator, 699 | }, { 700 | name: 'ICON', 701 | symbol: 'icx', 702 | validator: ICXValidator, 703 | }, { 704 | name: 'Internet of Services', 705 | symbol: 'IOST', 706 | validator: IOSTValidator, 707 | // disable iota validation for now 708 | // }, { 709 | // name: 'Iota', 710 | // symbol: 'iota', 711 | // validator: IOTAValidator, 712 | }, { 713 | name: 'IHT Real Estate Protocol', 714 | symbol: 'iht', 715 | validator: ETHValidator, 716 | }, { 717 | name: 'Insolar', 718 | symbol: 'ins', 719 | validator: ETHValidator, 720 | }, { 721 | name: 'IoTeX', 722 | symbol: 'iotx', 723 | validator: ETHValidator, 724 | }, { 725 | name: 'BitKan', 726 | symbol: 'kan', 727 | validator: ETHValidator, 728 | }, { 729 | name: 'Kcash', 730 | symbol: 'kcash', 731 | validator: ETHValidator, 732 | }, { 733 | name: 'KEY', 734 | symbol: 'key', 735 | validator: ETHValidator, 736 | }, { 737 | name: 'KickToken', 738 | symbol: 'kick', 739 | validator: ETHValidator, 740 | }, { 741 | name: 'Kyber Network', 742 | symbol: 'knc', 743 | validator: ETHValidator, 744 | }, { 745 | name: 'Lambda', 746 | symbol: 'lamb', 747 | validator: ETHValidator, 748 | }, { 749 | name: 'Aave', 750 | symbol: 'lend', 751 | validator: ETHValidator, 752 | }, { 753 | name: 'LinkEye', 754 | symbol: 'let', 755 | validator: ETHValidator, 756 | }, { 757 | name: 'LIFE', 758 | symbol: 'life', 759 | validator: ETHValidator, 760 | }, { 761 | name: 'LockTrip', 762 | symbol: 'loc', 763 | validator: ETHValidator, 764 | }, { 765 | name: 'Loopring', 766 | symbol: 'lrc', 767 | validator: ETHValidator, 768 | }, { 769 | name: 'Lunyr', 770 | symbol: 'lun', 771 | validator: ETHValidator, 772 | }, { 773 | name: 'Decentraland', 774 | symbol: 'mana', 775 | validator: ETHValidator, 776 | }, { 777 | name: 'Matic Network', 778 | symbol: 'matic', 779 | validator: ETHValidator, 780 | }, { 781 | name: 'MCO', 782 | symbol: 'mco', 783 | validator: ETHValidator, 784 | }, { 785 | name: 'Moeda Loyalty Points', 786 | symbol: 'mda', 787 | validator: ETHValidator, 788 | }, { 789 | name: 'Measurable Data Token', 790 | symbol: 'mdt', 791 | validator: ETHValidator, 792 | }, { 793 | name: 'Mainframe', 794 | symbol: 'mft', 795 | validator: ETHValidator, 796 | }, { 797 | name: 'Mithril', 798 | symbol: 'mith', 799 | validator: ETHValidator, 800 | }, { 801 | name: 'Molecular Future', 802 | symbol: 'mof', 803 | validator: ETHValidator, 804 | }, { 805 | name: 'Monetha', 806 | symbol: 'mth', 807 | validator: ETHValidator, 808 | }, { 809 | name: 'Mysterium', 810 | symbol: 'myst', 811 | validator: ETHValidator, 812 | }, { 813 | name: 'Nucleus Vision', 814 | symbol: 'ncash', 815 | validator: ETHValidator, 816 | }, { 817 | name: 'Nexo', 818 | symbol: 'nexo', 819 | validator: ETHValidator, 820 | }, { 821 | name: 'NAGA', 822 | symbol: 'ngc', 823 | validator: ETHValidator, 824 | }, { 825 | name: 'Noah Coin', 826 | symbol: 'noah', 827 | validator: ETHValidator, 828 | }, { 829 | name: 'Pundi X', 830 | symbol: 'npxs', 831 | validator: ETHValidator, 832 | }, { 833 | name: 'NetKoin', 834 | symbol: 'ntk', 835 | validator: ETHValidator, 836 | }, { 837 | name: 'OAX', 838 | symbol: 'oax', 839 | validator: ETHValidator, 840 | }, { 841 | name: 'Menlo One', 842 | symbol: 'one', 843 | validator: ETHValidator, 844 | }, { 845 | name: 'SoMee.Social', 846 | symbol: 'ong', 847 | validator: ETHValidator, 848 | }, { 849 | name: 'ORS Group', 850 | symbol: 'ors', 851 | validator: ETHValidator, 852 | }, { 853 | name: 'OST', 854 | symbol: 'ost', 855 | validator: ETHValidator, 856 | }, { 857 | name: 'Patron', 858 | symbol: 'pat', 859 | validator: ETHValidator, 860 | }, { 861 | name: 'Paxos Standard', 862 | symbol: 'pax', 863 | validator: ETHValidator, 864 | }, { 865 | name: 'Peculium', 866 | symbol: 'pcl', 867 | validator: ETHValidator, 868 | }, { 869 | name: 'Perlin', 870 | symbol: 'perl', 871 | validator: ETHValidator, 872 | }, { 873 | name: 'Pillar', 874 | symbol: 'plr', 875 | validator: ETHValidator, 876 | }, { 877 | name: 'PumaPay', 878 | symbol: 'pma', 879 | validator: ETHValidator, 880 | }, { 881 | name: 'Po.et', 882 | symbol: 'poe', 883 | validator: ETHValidator, 884 | }, { 885 | name: 'Power Ledger', 886 | symbol: 'powr', 887 | validator: ETHValidator, 888 | }, { 889 | name: 'Populous', 890 | symbol: 'ppt', 891 | validator: ETHValidator, 892 | }, { 893 | name: 'Presearch', 894 | symbol: 'pre', 895 | validator: ETHValidator, 896 | }, { 897 | name: 'Patientory', 898 | symbol: 'ptoy', 899 | validator: ETHValidator, 900 | }, { 901 | name: 'QuarkChain', 902 | symbol: 'qkc', 903 | validator: ETHValidator, 904 | }, { 905 | name: 'Quantstamp', 906 | symbol: 'qsp', 907 | validator: ETHValidator, 908 | }, { 909 | name: 'Revain', 910 | symbol: 'r', 911 | validator: ETHValidator, 912 | }, { 913 | name: 'Raiden Network Token', 914 | symbol: 'rdn', 915 | validator: ETHValidator, 916 | }, { 917 | name: 'Ren', 918 | symbol: 'ren', 919 | validator: ETHValidator, 920 | }, { 921 | name: 'Request', 922 | symbol: 'req', 923 | validator: ETHValidator, 924 | }, { 925 | name: 'Refereum', 926 | symbol: 'rfr', 927 | validator: ETHValidator, 928 | }, { 929 | name: 'SiaCashCoin', 930 | symbol: 'scc', 931 | validator: ETHValidator, 932 | }, { 933 | name: 'Sentinel', 934 | symbol: 'sent', 935 | validator: ETHValidator, 936 | }, { 937 | name: 'SkinCoin', 938 | symbol: 'skin', 939 | validator: ETHValidator, 940 | }, { 941 | name: 'SunContract', 942 | symbol: 'snc', 943 | validator: ETHValidator, 944 | }, { 945 | name: 'SingularDTV', 946 | symbol: 'sngls', 947 | validator: ETHValidator, 948 | }, { 949 | name: 'SONM', 950 | symbol: 'snm', 951 | validator: ETHValidator, 952 | }, { 953 | name: 'All Sports', 954 | symbol: 'soc', 955 | validator: ETHValidator, 956 | }, { 957 | name: 'SIRIN LABS Token', 958 | symbol: 'srn', 959 | validator: ETHValidator, 960 | }, { 961 | name: 'Stox', 962 | symbol: 'stx', 963 | validator: ETHValidator, 964 | }, { 965 | name: 'Substratum', 966 | symbol: 'sub', 967 | validator: ETHValidator, 968 | }, { 969 | name: 'SwftCoin', 970 | symbol: 'swftc', 971 | validator: ETHValidator, 972 | }, { 973 | name: 'Lamden', 974 | symbol: 'tau', 975 | validator: ETHValidator, 976 | }, { 977 | name: 'Telcoin', 978 | symbol: 'tel', 979 | validator: ETHValidator, 980 | }, { 981 | name: 'Chronobank', 982 | symbol: 'time', 983 | validator: ETHValidator, 984 | }, { 985 | name: 'Monolith', 986 | symbol: 'tkn', 987 | validator: ETHValidator, 988 | }, { 989 | name: 'Time New Bank', 990 | symbol: 'tnb', 991 | validator: ETHValidator, 992 | }, { 993 | name: 'Tierion', 994 | symbol: 'tnt', 995 | validator: ETHValidator, 996 | }, { 997 | name: 'Tripio', 998 | symbol: 'trio', 999 | validator: ETHValidator, 1000 | }, { 1001 | name: 'WeTrust', 1002 | symbol: 'trst', 1003 | validator: ETHValidator, 1004 | }, { 1005 | name: 'USD Coin', 1006 | symbol: 'usdc', 1007 | validator: ETHValidator, 1008 | }, { 1009 | name: 'USDT ERC-20', 1010 | symbol: 'usdt20', 1011 | validator: ETHValidator, 1012 | }, { 1013 | name: 'Utrust', 1014 | symbol: 'utk', 1015 | validator: ETHValidator, 1016 | }, { 1017 | name: 'BLOCKv', 1018 | symbol: 'vee', 1019 | validator: ETHValidator, 1020 | }, { 1021 | name: 'VIBE', 1022 | symbol: 'vibe', 1023 | validator: ETHValidator, 1024 | }, { 1025 | name: 'Tael', 1026 | symbol: 'wabi', 1027 | validator: ETHValidator, 1028 | }, { 1029 | name: 'WePower', 1030 | symbol: 'wpr', 1031 | validator: ETHValidator, 1032 | }, { 1033 | name: 'Waltonchain', 1034 | symbol: 'wtc', 1035 | validator: ETHValidator, 1036 | }, { 1037 | name: 'BlitzPredict', 1038 | symbol: 'xbp', 1039 | validator: ETHValidator, 1040 | }, { 1041 | name: 'CryptoFranc', 1042 | symbol: 'xchf', 1043 | validator: ETHValidator, 1044 | }, { 1045 | name: 'Exchange Union', 1046 | symbol: 'xuc', 1047 | validator: ETHValidator, 1048 | }, { 1049 | name: 'YOU COIN', 1050 | symbol: 'you', 1051 | validator: ETHValidator, 1052 | }, { 1053 | name: 'Zap', 1054 | symbol: 'zap', 1055 | validator: ETHValidator, 1056 | }, { 1057 | name: 'Nano', 1058 | symbol: 'nano', 1059 | validator: NANOValidator, 1060 | }, { 1061 | name: 'RaiBlocks', 1062 | symbol: 'xrb', 1063 | validator: NANOValidator, 1064 | }, { 1065 | name: 'Siacoin', 1066 | symbol: 'sc', 1067 | validator: SCValidator, 1068 | }, { 1069 | name: 'HyperSpace', 1070 | symbol: 'xsc', 1071 | validator: SCValidator, 1072 | }, { 1073 | name: 'Loki', 1074 | symbol: 'loki', 1075 | addressTypes: { prod: ['114', '116'], testnet: ['156'] }, 1076 | subAddressTypes: { prod: ['114', '116'], testnet: ['158'] }, 1077 | iAddressTypes: { prod: ['115'], testnet: ['157'] }, 1078 | validator: LokiValidator, 1079 | }, { 1080 | name: 'LBRY Credits', 1081 | symbol: 'lbc', 1082 | addressTypes: { prod: ['55'], testnet: [] }, 1083 | validator: BTCValidator, 1084 | }, { 1085 | name: 'Tron', 1086 | symbol: 'trx', 1087 | addressTypes: { prod: [0x41], testnet: [0xa0] }, 1088 | validator: TRXValidator, 1089 | }, { 1090 | name: 'Nem', 1091 | symbol: 'xem', 1092 | validator: NEMValidator, 1093 | }, { 1094 | name: 'Lisk', 1095 | symbol: 'lsk', 1096 | validator: LSKValidator, 1097 | }, { 1098 | name: 'Stellar', 1099 | symbol: 'xlm', 1100 | validator: XLMValidator, 1101 | }, { 1102 | name: 'Scopuly', 1103 | symbol: 'sky', 1104 | validator: XLMValidator, 1105 | }, { 1106 | name: 'BTU Protocol', 1107 | symbol: 'btu', 1108 | validator: ETHValidator, 1109 | }, { 1110 | name: 'Crypto.com Coin', 1111 | symbol: 'cro', 1112 | validator: ETHValidator, 1113 | }, { 1114 | name: 'Multi-collateral DAI', 1115 | symbol: 'dai', 1116 | validator: ETHValidator, 1117 | }, { 1118 | name: 'Enjin Coin', 1119 | symbol: 'enj', 1120 | validator: ETHValidator, 1121 | }, { 1122 | name: 'HedgeTrade', 1123 | symbol: 'hedg', 1124 | validator: ETHValidator, 1125 | }, { 1126 | name: 'Cred', 1127 | symbol: 'lba', 1128 | validator: ETHValidator, 1129 | }, { 1130 | name: 'Chainlink', 1131 | symbol: 'link', 1132 | validator: ETHValidator, 1133 | }, { 1134 | name: 'Loom Network', 1135 | symbol: 'loom', 1136 | validator: ETHValidator, 1137 | }, { 1138 | name: 'Maker', 1139 | symbol: 'mkr', 1140 | validator: ETHValidator, 1141 | }, { 1142 | name: 'Metal', 1143 | symbol: 'mtl', 1144 | validator: ETHValidator, 1145 | }, { 1146 | name: 'Ocean Protocol', 1147 | symbol: 'ocean', 1148 | validator: ETHValidator, 1149 | //}, { 1150 | // name: 'PitisCoin', 1151 | // symbol: 'pts', # FIXME: symbol collides with ProtoShares 1152 | // validator: BTCValidator, 1153 | }, { 1154 | name: 'Quant', 1155 | symbol: 'qnt', 1156 | validator: ETHValidator, 1157 | }, { 1158 | name: 'Synthetix Network', 1159 | symbol: 'snx', 1160 | validator: ETHValidator, 1161 | }, { 1162 | name: 'SOLVE', 1163 | symbol: 'solve', 1164 | validator: ETHValidator, 1165 | }, { 1166 | name: 'Solana', 1167 | symbol: 'sol', 1168 | validator: SOLValidator, 1169 | }, { 1170 | name: 'Spendcoin', 1171 | symbol: 'spnd', 1172 | validator: ETHValidator, 1173 | }, { 1174 | name: 'TEMCO', 1175 | symbol: 'temco', 1176 | validator: ETHValidator, 1177 | }, { 1178 | name: 'Luniverse', 1179 | symbol: 'luniverse', 1180 | validator: ETHValidator, 1181 | }, { 1182 | name: 'Binance Smart Chain', 1183 | symbol: 'bsc', 1184 | validator: ETHValidator, 1185 | }, { 1186 | name: 'Binance', 1187 | symbol: 'bnb', 1188 | validator: BinanceValidator, 1189 | }, { 1190 | name: 'EOS', 1191 | symbol: 'eos', 1192 | validator: EOSValidator, 1193 | }, { 1194 | name: 'Tezos', 1195 | symbol: 'xtz', 1196 | validator: XTZValidator, 1197 | }, { 1198 | name: 'Hedera Hashgraph', 1199 | symbol: 'hbar', 1200 | validator: HBARValidator, 1201 | }, { 1202 | name: 'Verge', 1203 | symbol: 'xvg', 1204 | addressTypes: { prod: ['1e'], testnet: ['6F'] }, 1205 | validator: BTCValidator, 1206 | }, { 1207 | name: 'Zilliqa', 1208 | symbol: 'zil', 1209 | validator: ZILValidator 1210 | } 1211 | ]; 1212 | 1213 | 1214 | module.exports = { 1215 | getByNameOrSymbol: function (currencyNameOrSymbol) { 1216 | var nameOrSymbol = currencyNameOrSymbol.toLowerCase(); 1217 | return CURRENCIES.find(function (currency) { 1218 | return currency.name.toLowerCase() === nameOrSymbol || currency.symbol.toLowerCase() === nameOrSymbol 1219 | }); 1220 | }, 1221 | getAll: function () { 1222 | return CURRENCIES; 1223 | } 1224 | }; 1225 | 1226 | // spit out details for readme.md 1227 | // CURRENCIES 1228 | // .sort((a, b) => a.name.toUpperCase() > b.name.toUpperCase() ? 1 : -1) 1229 | // .forEach(c => console.log(`* ${c.name}/${c.symbol} \`'${c.name}'\` or \`'${c.symbol}'\` `)); 1230 | 1231 | //spit out keywords for package.json 1232 | // CURRENCIES 1233 | // .sort((a, b) => a.name.toUpperCase() > b.name.toUpperCase() ? 1 : -1) 1234 | // .forEach(c => console.log(`"${c.name}","${c.symbol}",`)); 1235 | 1236 | 1237 | -------------------------------------------------------------------------------- /src/eos_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | function isValidEOSAddress (address, currency, networkType) { 3 | var regex = /^[a-z0-9]+$/g // Must be numbers and lowercase letters only 4 | if (address.search(regex) !== -1 && address.length === 12) { 5 | return true 6 | } else { 7 | return false 8 | } 9 | } 10 | 11 | module.exports = { 12 | isValidAddress: function (address, currency, networkType) { 13 | return isValidEOSAddress(address, currency, networkType) 14 | }, 15 | 16 | getAddressType: function(address, currency, networkType) { 17 | if (this.isValidAddress(address, currency, networkType)) { 18 | return addressType.ADDRESS; 19 | } 20 | return undefined; 21 | }, 22 | } 23 | -------------------------------------------------------------------------------- /src/ethereum_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | var cryptoUtils = require('./crypto/utils'); 3 | 4 | module.exports = { 5 | isValidAddress: function (address) { 6 | if (!/^0x[0-9a-fA-F]{40}$/.test(address)) { 7 | // Check if it has the basic requirements of an address 8 | return false; 9 | } 10 | 11 | if (/^0x[0-9a-f]{40}$/.test(address) || /^0x?[0-9A-F]{40}$/.test(address)) { 12 | // If it's all small caps or all all caps, return true 13 | return true; 14 | } 15 | 16 | // Otherwise check each case 17 | return this.verifyChecksum(address); 18 | }, 19 | verifyChecksum: function (address) { 20 | // Check each case 21 | address = address.replace('0x',''); 22 | 23 | var addressHash = cryptoUtils.keccak256(address.toLowerCase()); 24 | 25 | for (var i = 0; i < 40; i++ ) { 26 | // The nth letter should be uppercase if the nth digit of casemap is 1 27 | if ((parseInt(addressHash[i], 16) > 7 && address[i].toUpperCase() !== address[i]) || 28 | (parseInt(addressHash[i], 16) <= 7 && address[i].toLowerCase() !== address[i])) { 29 | return false; 30 | } 31 | } 32 | 33 | return true; 34 | }, 35 | 36 | getAddressType: function(address, currency, networkType) { 37 | if (this.isValidAddress(address, currency, networkType)) { 38 | return addressType.ADDRESS; 39 | } 40 | return undefined; 41 | }, 42 | }; 43 | -------------------------------------------------------------------------------- /src/hbar_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | function isValidHBarAddress (address) { 3 | const split = address.split('.') 4 | if (split[0] !== '0' || split[1] !== '0') { 5 | return false 6 | } 7 | if (split[2].length <= 6 && /^\d+$/g.test(split[2])) { 8 | return true 9 | } 10 | } 11 | 12 | module.exports = { 13 | isValidAddress: function (address, currency, networkType) { 14 | return isValidHBarAddress(address) 15 | }, 16 | 17 | getAddressType: function(address, currency, networkType) { 18 | if (this.isValidAddress(address, currency, networkType)) { 19 | return addressType.ADDRESS; 20 | } 21 | return undefined; 22 | }, 23 | } 24 | 25 | -------------------------------------------------------------------------------- /src/icx_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | function isValidICXAddress (address, currency, networkType) { 3 | var regex = /^hx[0-9a-f]{40}$/g // Begins with hx followed by 40 hex chars 4 | if (address.search(regex) !== -1) { 5 | return true 6 | } else { 7 | return false 8 | } 9 | } 10 | 11 | module.exports = { 12 | isValidAddress: function (address, currency, networkType) { 13 | return isValidICXAddress(address, currency, networkType) 14 | }, 15 | 16 | getAddressType: function(address, currency, networkType) { 17 | if (this.isValidAddress(address, currency, networkType)) { 18 | return addressType.ADDRESS; 19 | } 20 | return undefined; 21 | }, 22 | } 23 | 24 | -------------------------------------------------------------------------------- /src/iost_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | const iostRegex = new RegExp('^[a-z0-9_]{5,11}$') 3 | 4 | module.exports = { 5 | isValidAddress: function (address, currency, networkType) { 6 | return iostRegex.test(address) 7 | }, 8 | 9 | getAddressType: function(address, currency, networkType) { 10 | if (this.isValidAddress(address, currency, networkType)) { 11 | return addressType.ADDRESS; 12 | } 13 | return undefined; 14 | }, 15 | } 16 | 17 | -------------------------------------------------------------------------------- /src/iota_validator.js: -------------------------------------------------------------------------------- 1 | // iota validation is disabled 2 | 3 | // var IOTA = require('@iota/validators') 4 | 5 | // function isValidIotaAddress (address, currency, networkType) { 6 | // var isValid = IOTA.isAddress(address) 7 | // return isValid 8 | // } 9 | 10 | // module.exports = { 11 | // isValidAddress: function (address, currency, networkType) { 12 | // return isValidIotaAddress(address, currency, networkType) 13 | // } 14 | // } 15 | 16 | -------------------------------------------------------------------------------- /src/lisk_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | var cryptoUtils = require('./crypto/utils'); 3 | 4 | var regexp = new RegExp('^[0-9]{1,20}L$'); 5 | 6 | module.exports = { 7 | isValidAddress: function(address) { 8 | return this.getAddressType(address) === addressType.ADDRESS; 9 | }, 10 | 11 | getAddressType: function(address) { 12 | if (!regexp.test(address)) { 13 | return undefined; 14 | } 15 | if(this.verifyAddress(address)) { 16 | return addressType.ADDRESS; 17 | } 18 | }, 19 | 20 | verifyAddress: function(address) { 21 | var BUFFER_SIZE = 8; 22 | var bigNumber = address.substring(0, address.length - 1); 23 | var addressBuffer = cryptoUtils.bigNumberToBuffer(bigNumber); 24 | return Buffer.from(addressBuffer).slice(0, BUFFER_SIZE).equals(addressBuffer); 25 | } 26 | }; -------------------------------------------------------------------------------- /src/loki_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('./crypto/utils'); 2 | var cryptoUtils = require('./crypto/utils') 3 | var cnBase58 = require('./crypto/cnBase58') 4 | 5 | var DEFAULT_NETWORK_TYPE = 'prod' 6 | 7 | var addressRegTest = new RegExp( 8 | '^L[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{94}$' 9 | ) 10 | var integratedAddressRegTest = new RegExp( 11 | '^L[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{105}$' 12 | ) 13 | 14 | function validateNetwork(decoded, currency, networkType, addressType) { 15 | var network = currency.addressTypes 16 | if (addressType == 'integrated') { 17 | network = currency.iAddressTypes 18 | } else if (addressType == 'subaddress') { 19 | network = currency.subAddressTypes 20 | } 21 | var at = parseInt(decoded.substr(0, 2), 16).toString() 22 | 23 | switch (networkType) { 24 | case 'prod': 25 | return network.prod.indexOf(at) >= 0 26 | case 'testnet': 27 | return network.testnet.indexOf(at) >= 0 28 | case 'both': 29 | return network.prod.indexOf(at) >= 0 || network.testnet.indexOf(at) >= 0 30 | default: 31 | return false 32 | } 33 | } 34 | 35 | function hextobin(hex) { 36 | if (hex.length % 2 !== 0) return null 37 | var res = new Uint8Array(hex.length / 2) 38 | for (var i = 0; i < hex.length / 2; ++i) { 39 | res[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16) 40 | } 41 | return res 42 | } 43 | 44 | module.exports = { 45 | isValidAddress: function(address, currency, networkType) { 46 | networkType = networkType || DEFAULT_NETWORK_TYPE 47 | var addressType = 'standard' 48 | if (!addressRegTest.test(address)) { // same regex for mainnet and testnet 49 | if (integratedAddressRegTest.test(address)) { 50 | addressType = 'integrated' 51 | } else { 52 | return false 53 | } 54 | } 55 | 56 | var decodedAddrStr = cnBase58.decode(address) 57 | if (!decodedAddrStr) return false 58 | 59 | if (!validateNetwork(decodedAddrStr, currency, networkType, addressType)) return false 60 | 61 | var addrChecksum = decodedAddrStr.slice(-8) 62 | var hashChecksum = cryptoUtils.keccak256Checksum(hextobin(decodedAddrStr.slice(0, -8))) 63 | 64 | return addrChecksum === hashChecksum 65 | }, 66 | 67 | getAddressType: function(address, currency, networkType) { 68 | if (this.isValidAddress(address, currency, networkType)) { 69 | return addressType.ADDRESS; 70 | } 71 | return undefined; 72 | }, 73 | } 74 | -------------------------------------------------------------------------------- /src/monero_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | var cryptoUtils = require('./crypto/utils') 3 | var cnBase58 = require('./crypto/cnBase58') 4 | 5 | var DEFAULT_NETWORK_TYPE = 'prod' 6 | var testnetRegTest = new RegExp( 7 | `^[A9][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{94}$` 8 | ) 9 | var addressRegTest = new RegExp( 10 | '^4[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{94}$' 11 | ) 12 | var subAddressRegTest = new RegExp( 13 | '^8[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{94}$' 14 | ) 15 | var integratedAddressRegTest = new RegExp( 16 | '^4[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{105}$' 17 | ) 18 | 19 | function validateNetwork(decoded, currency, networkType, addressType) { 20 | var network = currency.addressTypes 21 | if (addressType == 'integrated') { 22 | network = currency.iAddressTypes 23 | } else if (addressType == 'subaddress') { 24 | network = currency.subAddressTypes 25 | } 26 | var at = parseInt(decoded.substr(0, 2), 16).toString() 27 | 28 | switch (networkType) { 29 | case 'prod': 30 | return network.prod.indexOf(at) >= 0 31 | case 'testnet': 32 | return network.testnet.indexOf(at) >= 0 33 | case 'both': 34 | return network.prod.indexOf(at) >= 0 || network.testnet.indexOf(at) >= 0 35 | default: 36 | return false 37 | } 38 | } 39 | 40 | function hextobin(hex) { 41 | if (hex.length % 2 !== 0) return null 42 | var res = new Uint8Array(hex.length / 2) 43 | for (var i = 0; i < hex.length / 2; ++i) { 44 | res[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16) 45 | } 46 | return res 47 | } 48 | 49 | module.exports = { 50 | isValidAddress: function(address, currency, networkType) { 51 | networkType = networkType || DEFAULT_NETWORK_TYPE 52 | var addressType = 'standard' 53 | if (networkType === 'testnet') { 54 | if (!testnetRegTest.test(address)) { 55 | return false; 56 | } 57 | } else if (!addressRegTest.test(address)) { 58 | if (subAddressRegTest.test(address)) { 59 | addressType = 'subaddress' 60 | } else if (integratedAddressRegTest.test(address)) { 61 | addressType = 'integrated' 62 | } else { 63 | return false 64 | } 65 | } 66 | 67 | var decodedAddrStr = cnBase58.decode(address) 68 | if (!decodedAddrStr) return false 69 | 70 | if (!validateNetwork(decodedAddrStr, currency, networkType, addressType)) return false 71 | 72 | var addrChecksum = decodedAddrStr.slice(-8) 73 | var hashChecksum = cryptoUtils.keccak256Checksum(hextobin(decodedAddrStr.slice(0, -8))) 74 | 75 | return addrChecksum === hashChecksum 76 | }, 77 | 78 | getAddressType: function(address, currency, networkType) { 79 | if (this.isValidAddress(address, currency, networkType)) { 80 | return addressType.ADDRESS; 81 | } 82 | return undefined; 83 | }, 84 | } 85 | -------------------------------------------------------------------------------- /src/nano_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | var cryptoUtils = require('./crypto/utils'); 3 | var baseX = require('base-x'); 4 | 5 | var ALLOWED_CHARS = '13456789abcdefghijkmnopqrstuwxyz'; 6 | 7 | var codec = baseX(ALLOWED_CHARS); 8 | // https://github.com/nanocurrency/raiblocks/wiki/Accounts,-Keys,-Seeds,-and-Wallet-Identifiers 9 | var regexp = new RegExp('^(xrb|nano)_([' + ALLOWED_CHARS + ']{60})$'); 10 | 11 | module.exports = { 12 | isValidAddress: function (address) { 13 | if (regexp.test(address)) { 14 | return this.verifyChecksum(address); 15 | } 16 | 17 | return false; 18 | }, 19 | 20 | verifyChecksum: function (address) { 21 | var bytes = codec.decode(regexp.exec(address)[2]).slice(-37); 22 | // https://github.com/nanocurrency/raiblocks/blob/master/rai/lib/numbers.cpp#L73 23 | var computedChecksum = cryptoUtils.blake2b(cryptoUtils.toHex(bytes.slice(0, -5)), 5); 24 | var checksum = cryptoUtils.toHex(bytes.slice(-5).reverse()); 25 | 26 | return computedChecksum === checksum 27 | }, 28 | 29 | getAddressType: function(address, currency, networkType) { 30 | if (this.isValidAddress(address, currency, networkType)) { 31 | return addressType.ADDRESS; 32 | } 33 | return undefined; 34 | }, 35 | }; 36 | -------------------------------------------------------------------------------- /src/nem_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | var cryptoUtils = require('./crypto/utils'); 3 | 4 | /** 5 | * Check if an address is valid 6 | * 7 | * @param {string} _address - An address 8 | * 9 | * @return {boolean} - True if address is valid, false otherwise 10 | */ 11 | var isValidAddress = function(_address) { 12 | var address = _address.toString().toUpperCase().replace(/-/g, ''); 13 | if (!address || address.length !== 40) { 14 | return false; 15 | } 16 | var decoded = cryptoUtils.toHex(cryptoUtils.base32.b32decode(address)); 17 | var stepThreeChecksum = cryptoUtils.keccak256Checksum(Buffer.from(decoded.slice(0, 42), 'hex')); 18 | 19 | return stepThreeChecksum === decoded.slice(42); 20 | }; 21 | 22 | module.exports = { 23 | isValidAddress: isValidAddress, 24 | 25 | getAddressType: function(address, currency, networkType) { 26 | if (this.isValidAddress(address, currency, networkType)) { 27 | return addressType.ADDRESS; 28 | } 29 | return undefined; 30 | }, 31 | } -------------------------------------------------------------------------------- /src/nxt_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | const nxtRegex = new RegExp("^NXT(-[A-Z0-9]{4}){3}-[A-Z0-9]{5}$"); 3 | 4 | module.exports = { 5 | isValidAddress: function (address, currency, networkType) { 6 | if (!nxtRegex.test(address)) { 7 | return false; 8 | } 9 | return true; 10 | }, 11 | 12 | getAddressType: function (address, currency, networkType) { 13 | if (this.isValidAddress(address, currency, networkType)) { 14 | return addressType.ADDRESS; 15 | } 16 | return undefined; 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /src/ripple_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | var cryptoUtils = require('./crypto/utils'); 3 | var baseX = require('base-x'); 4 | 5 | var ALLOWED_CHARS = 'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz'; 6 | 7 | var codec = baseX(ALLOWED_CHARS); 8 | var regexp = new RegExp('^r[' + ALLOWED_CHARS + ']{27,35}$'); 9 | 10 | module.exports = { 11 | /** 12 | * ripple address validation 13 | */ 14 | isValidAddress: function (address) { 15 | if (regexp.test(address)) { 16 | return this.verifyChecksum(address); 17 | } 18 | 19 | return false; 20 | }, 21 | 22 | verifyChecksum: function (address) { 23 | var bytes = codec.decode(address); 24 | var computedChecksum = cryptoUtils.sha256Checksum(cryptoUtils.toHex(bytes.slice(0, -4))); 25 | var checksum = cryptoUtils.toHex(bytes.slice(-4)); 26 | 27 | return computedChecksum === checksum 28 | }, 29 | 30 | getAddressType: function (address, currency, networkType) { 31 | if (this.isValidAddress(address, currency, networkType)) { 32 | return addressType.ADDRESS; 33 | } 34 | return undefined; 35 | }, 36 | }; 37 | -------------------------------------------------------------------------------- /src/siacoin_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | var cryptoUtils = require('./crypto/utils') 3 | var isEqual = require('lodash/isEqual') 4 | 5 | module.exports = { 6 | isValidAddress: function(address) { 7 | if (address.length !== 76) { 8 | // Check if it has the basic requirements of an address 9 | return false; 10 | } 11 | 12 | // Otherwise check each case 13 | return this.verifyChecksum(address); 14 | }, 15 | verifyChecksum: function(address) { 16 | var checksumBytes = address.slice(0, 32*2) 17 | var check = address.slice(32*2, 38*2) 18 | var blakeHash = cryptoUtils.blake2b(checksumBytes, 32).slice(0, 6*2) 19 | return isEqual(blakeHash, check); 20 | }, 21 | 22 | getAddressType: function (address, currency, networkType) { 23 | if (this.isValidAddress(address)) { 24 | return addressType.ADDRESS; 25 | } 26 | return undefined; 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /src/solana_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | var base58 = require('./crypto/base58') 3 | 4 | module.exports = { 5 | isValidAddress: function (address) { 6 | try { 7 | const decoded = base58.decode(address); 8 | return decoded.length === 32; 9 | } catch (err) { 10 | return false; 11 | } 12 | }, 13 | getAddressType: function(address, currency, networkType) { 14 | if (this.isValidAddress(address, currency, networkType)) { 15 | return addressType.ADDRESS; 16 | } 17 | return undefined; 18 | }, 19 | } 20 | -------------------------------------------------------------------------------- /src/steem_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | const accountRegex = new RegExp('^[a-z0-9-.]{3,}$') 3 | const segmentRegex = new RegExp('^[a-z][a-z0-9-]+[a-z0-9]$') 4 | const doubleDashRegex = new RegExp('--') 5 | 6 | module.exports = { 7 | isValidAddress: function (address, currency, networkType) { 8 | if (!accountRegex.test(address)) { 9 | return false; 10 | } 11 | let segments = address.split('.') 12 | for (let i = 0; i < segments.length; i++) { 13 | let segment = segments[i] 14 | if (segment.length < 3) { 15 | return false; 16 | } 17 | if (!segmentRegex.test(segment)) { 18 | return false; 19 | } 20 | if (doubleDashRegex.test(segment)) { 21 | return false; 22 | } 23 | } 24 | return true; 25 | }, 26 | 27 | getAddressType: function (address, currency, networkType) { 28 | if (this.isValidAddress(address, currency, networkType)) { 29 | return addressType.ADDRESS; 30 | } 31 | return undefined; 32 | }, 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/stellar_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | const baseX = require('base-x'); 3 | const crc = require('crc'); 4 | const cryptoUtils = require('./crypto/utils'); 5 | 6 | const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; 7 | 8 | const base32 = baseX(ALPHABET); 9 | const regexp = new RegExp('^[' + ALPHABET + ']{56}$'); 10 | const ed25519PublicKeyVersionByte = (6 << 3); 11 | 12 | function swap16(number) { 13 | const lower = number & 0xFF; 14 | const upper = (number >> 8) & 0xFF; 15 | return (lower << 8) | upper; 16 | } 17 | 18 | module.exports = { 19 | isValidAddress: function (address) { 20 | if (regexp.test(address)) { 21 | return this.verifyChecksum(address); 22 | } 23 | 24 | return false; 25 | }, 26 | 27 | verifyChecksum: function (address) { 28 | // based on https://github.com/stellar/js-stellar-base/blob/master/src/strkey.js 29 | const bytes = base32.decode(address); 30 | if (bytes[0] !== ed25519PublicKeyVersionByte) { 31 | return false; 32 | } 33 | 34 | const payload = bytes.slice(0, -2); 35 | const checksum = cryptoUtils.toHex(bytes.slice(-2)); 36 | const computedChecksum = cryptoUtils.numberToHex(swap16(crc.crc16xmodem(payload)), 2); 37 | return computedChecksum === checksum; 38 | }, 39 | 40 | getAddressType: function (address, currency, networkType) { 41 | if (this.isValidAddress(address, currency, networkType)) { 42 | return addressType.ADDRESS; 43 | } 44 | return undefined; 45 | }, 46 | }; -------------------------------------------------------------------------------- /src/sys_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | const BTCValidator = require('./bitcoin_validator'); 3 | var regexp = new RegExp('^sys1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{39}$') 4 | 5 | module.exports = { 6 | isValidAddress: function (address, currency, networkType) { 7 | return regexp.test(address) || BTCValidator.isValidAddress(address, currency, networkType) 8 | }, 9 | 10 | getAddressType: function (address, currency, networkType) { 11 | if (this.isValidAddress(address, currency, networkType)) { 12 | return addressType.ADDRESS; 13 | } 14 | return undefined; 15 | }, 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/tezos_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | const base58 = require('./crypto/base58'); 3 | const cryptoUtils = require('./crypto/utils'); 4 | 5 | const prefix = new Uint8Array([6, 161, 159]); 6 | 7 | function decodeRaw(buffer) { 8 | let payload = buffer.slice(0, -4); 9 | let checksum = buffer.slice(-4); 10 | let newChecksum = cryptoUtils.hexStr2byteArray( 11 | cryptoUtils.sha256x2(cryptoUtils.byteArray2hexStr(payload)) 12 | ); 13 | 14 | if (checksum[0] ^ newChecksum[0] | 15 | checksum[1] ^ newChecksum[1] | 16 | checksum[2] ^ newChecksum[2] | 17 | checksum[3] ^ newChecksum[3]) 18 | return; 19 | return payload; 20 | } 21 | 22 | const isValidAddress = function(address) { 23 | try { 24 | let buffer = base58.decode(address); 25 | let payload = decodeRaw(buffer); 26 | if (!payload) 27 | return false; 28 | payload.slice(prefix.length); 29 | return true; 30 | } catch (e) { 31 | return false; 32 | } 33 | }; 34 | 35 | module.exports = { 36 | isValidAddress, 37 | 38 | getAddressType: function (address, currency, networkType) { 39 | if (this.isValidAddress(address, currency, networkType)) { 40 | return addressType.ADDRESS; 41 | } 42 | return undefined; 43 | }, 44 | }; 45 | -------------------------------------------------------------------------------- /src/tron_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | var cryptoUtils = require('./crypto/utils'); 3 | 4 | function decodeBase58Address(base58Sting) { 5 | if (typeof (base58Sting) !== 'string') { 6 | return false; 7 | } 8 | if (base58Sting.length <= 4) { 9 | return false; 10 | } 11 | 12 | try { 13 | var address = cryptoUtils.base58(base58Sting); 14 | } catch (e) { 15 | return false 16 | } 17 | 18 | /*if (base58Sting.length <= 4) { 19 | return false; 20 | }*/ 21 | var len = address.length; 22 | var offset = len - 4; 23 | var checkSum = address.slice(offset); 24 | address = address.slice(0, offset); 25 | var hash0 = cryptoUtils.sha256(cryptoUtils.byteArray2hexStr(address)); 26 | var hash1 = cryptoUtils.hexStr2byteArray(cryptoUtils.sha256(hash0)); 27 | var checkSum1 = hash1.slice(0, 4); 28 | if (checkSum[0] === checkSum1[0] && checkSum[1] === checkSum1[1] && checkSum[2] 29 | === checkSum1[2] && checkSum[3] === checkSum1[3] 30 | ) { 31 | return address; 32 | } 33 | 34 | return false; 35 | } 36 | 37 | function getEnv(currency, networkType) { 38 | var evn = networkType || 'prod'; 39 | 40 | if (evn !== 'prod' && evn !== 'testnet') evn = 'prod'; 41 | 42 | return currency.addressTypes[evn][0] 43 | } 44 | 45 | module.exports = { 46 | /** 47 | * tron address validation 48 | */ 49 | isValidAddress: function (mainAddress, currency, networkType) { 50 | var address = decodeBase58Address(mainAddress); 51 | 52 | if (!address) { 53 | return false; 54 | } 55 | 56 | if (address.length !== 21) { 57 | return false; 58 | } 59 | 60 | return getEnv(currency, networkType) === address[0]; 61 | }, 62 | 63 | getAddressType: function (address, currency, networkType) { 64 | if (this.isValidAddress(address, currency, networkType)) { 65 | return addressType.ADDRESS; 66 | } 67 | return undefined; 68 | }, 69 | }; -------------------------------------------------------------------------------- /src/wallet_address_validator.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'trezor-address-validator' { 2 | export interface Currency { 3 | name: string, 4 | symbol: string, 5 | } 6 | export type AddressType = 'address' | 'p2pkh' | 'p2wpkh' | 'p2wsh' | 'p2sh' | 'p2tr' | 'pw-unknown'; 7 | export function validate(address: string, currencyNameOrSymbol?: string, networkType?: string): boolean; 8 | export function getAddressType(address: string, currencyNameOrSymbol?: string, networkType?: string): AddressType | undefined; 9 | export function getCurrencies(): Currency[]; 10 | export function findCurrency(symbol: string): Currency 11 | } 12 | 13 | -------------------------------------------------------------------------------- /src/wallet_address_validator.js: -------------------------------------------------------------------------------- 1 | var currencies = require('./currencies'); 2 | const { addressType } = require('../src/crypto/utils'); 3 | 4 | var DEFAULT_CURRENCY_NAME = 'bitcoin'; 5 | 6 | module.exports = { 7 | validate: function (address, currencyNameOrSymbol, networkType) { 8 | var currency = currencies.getByNameOrSymbol(currencyNameOrSymbol || DEFAULT_CURRENCY_NAME); 9 | 10 | if (currency && currency.validator) { 11 | return currency.validator.isValidAddress(address, currency, networkType); 12 | } 13 | 14 | throw new Error('Missing validator for currency: ' + currencyNameOrSymbol); 15 | }, 16 | getAddressType: function(address, currencyNameOrSymbol, networkType) { 17 | var currency = currencies.getByNameOrSymbol(currencyNameOrSymbol || DEFAULT_CURRENCY_NAME); 18 | if (!currency || !currency.validator) { 19 | throw new Error('getAddressType: No validator for currency' + currencyNameOrSymbol); 20 | } 21 | if (currency && currency.validator && currency.validator.getAddressType) { 22 | return currency.validator.getAddressType(address, currency, networkType); 23 | } 24 | throw new Error('getAddressType not defined for currency: ' + currencyNameOrSymbol); 25 | }, 26 | getCurrencies: function () { 27 | return currencies.getAll(); 28 | }, 29 | findCurrency: function(symbol) { 30 | return currencies.getByNameOrSymbol(symbol) || null ; 31 | }, 32 | addressType, 33 | }; 34 | -------------------------------------------------------------------------------- /src/zil_validator.js: -------------------------------------------------------------------------------- 1 | const { addressType } = require('../src/crypto/utils'); 2 | const { bech32 } = require('bech32'); 3 | 4 | const ALLOWED_CHARS = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l' 5 | 6 | var regexp = new RegExp('^(zil)1([' + ALLOWED_CHARS + ']+)$') // zil + bech32 separated by '1' 7 | 8 | module.exports = { 9 | isValidAddress: function (address, currency, networkType) { 10 | let match = regexp.exec(address) 11 | if (!match) { 12 | return false; 13 | } 14 | const decoded = bech32.decode(address); 15 | return decoded && decoded.words.length === 32; 16 | }, 17 | 18 | getAddressType: function (address, currency, networkType) { 19 | if (this.isValidAddress(address, currency, networkType)) { 20 | return addressType.ADDRESS; 21 | } 22 | return undefined; 23 | }, 24 | } 25 | 26 | -------------------------------------------------------------------------------- /test/wallet_address_get_currencies.js: -------------------------------------------------------------------------------- 1 | var isNode = typeof module !== 'undefined' && typeof module.exports !== 'undefined' 2 | 3 | var chai = isNode ? require('chai') : window.chai, 4 | expect = chai.expect 5 | 6 | var WAValidator = isNode ? require('../src/wallet_address_validator') : window.WAValidator 7 | 8 | describe('WAValidator.getCurrencies()', function () { 9 | it('Should get all currencies', function () { 10 | var currencies = WAValidator.getCurrencies(); 11 | expect(currencies).to.be.ok; 12 | expect(currencies.length).to.be.greaterThan(0); 13 | }); 14 | 15 | it('Should find a specific currency by symbol', function() { 16 | var currency = WAValidator.findCurrency('xrp'); 17 | expect(currency).to.be.ok; 18 | expect(currency.name).to.equal('Ripple'); 19 | expect(currency.symbol).to.equal('xrp'); 20 | }); 21 | 22 | it('Should find a specific currency by name', function() { 23 | var currency = WAValidator.findCurrency('Ripple'); 24 | expect(currency).to.be.ok; 25 | expect(currency.name).to.equal('Ripple'); 26 | expect(currency.symbol).to.equal('xrp'); 27 | }); 28 | 29 | it('Should return null if currency is not found', function() { 30 | var currency = WAValidator.findCurrency('random'); 31 | expect(currency).to.be.null; 32 | }); 33 | }); 34 | --------------------------------------------------------------------------------