├── .gitignore ├── .gitattributes ├── .travis.yml ├── license ├── package.json ├── index.js ├── readme.md └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.js text eol=lf -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '9' 4 | - '10' 5 | - '12' -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Nikolaos Kamarinakis (nikolaskama.me) 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 13 | all 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 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cryptocurrency-address-detector", 3 | "version": "1.1.1", 4 | "description": "Detect which cryptocurrency an address corresponds to.", 5 | "license": "MIT", 6 | "repository": "k4m4/cryptocurrency-address-detector", 7 | "author": { 8 | "name": "Nikolaos Kamarinakis", 9 | "url": "nikolaskama.me", 10 | "email": "nikolaskam@gmail.com" 11 | }, 12 | "ava": { 13 | "babel": true 14 | }, 15 | "engines": { 16 | "node": ">=6" 17 | }, 18 | "main": "index.js", 19 | "scripts": { 20 | "test": "ava" 21 | }, 22 | "keywords": [ 23 | "cryptocurrency", 24 | "address", 25 | "detector", 26 | "regex" 27 | ], 28 | "files": [ 29 | "index.js" 30 | ], 31 | "devDependencies": { 32 | "@ava/babel": "^1.0.1", 33 | "ava": "^3.5.2" 34 | }, 35 | "dependencies": { 36 | "arrify": "^1.0.1", 37 | "bitcoin-regex": "^2.0.0", 38 | "bitcoincash-regex": "^1.1.8", 39 | "dash-regex": "^1.0.10", 40 | "dogecoin-regex": "^1.0.9", 41 | "ethereum-regex": "^1.1.12", 42 | "litecoin-regex": "^1.0.8", 43 | "monero-regex": "^1.0.8", 44 | "neo-regex": "^1.0.7", 45 | "p-any": "^1.1.0", 46 | "p-timeout": "^2.0.1", 47 | "pify": "^3.0.0", 48 | "ripple-regex": "^1.1.8" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const arrify = require('arrify'); 3 | const pAny = require('p-any'); 4 | const pify = require('pify'); 5 | const pTimeout = require('p-timeout'); 6 | const bitcoinRegex = require('bitcoin-regex'); 7 | const ethereumRegex = require('ethereum-regex'); 8 | const litecoinRegex = require('litecoin-regex'); 9 | const dogecoinRegex = require('dogecoin-regex'); 10 | const bitcoincashRegex = require('bitcoincash-regex'); 11 | const dashRegex = require('dash-regex'); 12 | const moneroRegex = require('monero-regex'); 13 | const rippleRegex = require('ripple-regex'); 14 | const neoRegex = require('neo-regex'); 15 | 16 | function detectCrypto(address) { 17 | if (bitcoinRegex({exact: true}).test(address)) return 'BTC/BCH'; 18 | else if (ethereumRegex({exact: true}).test(address)) return 'ETH'; 19 | else if (litecoinRegex({exact: true}).test(address)) return 'LTC'; 20 | else if (dogecoinRegex({exact: true}).test(address)) return 'DOGE'; 21 | else if (dashRegex({exact: true}).test(address)) return 'DASH'; 22 | else if (moneroRegex({exact: true}).test(address)) return 'XMR'; 23 | else if (rippleRegex({exact: true}).test(address)) return 'XRP'; 24 | else if (bitcoincashRegex.format('cashaddr', {exact: true}).test(address)) return 'BCH'; 25 | else if (neoRegex({exact: true}).test(address)) return 'NEO'; 26 | else return 'Cryptocurrency could not be detected' 27 | } 28 | 29 | module.exports = (dests, opts) => { 30 | opts = opts || {}; 31 | opts.timeout = typeof opts.timeout === 'number' ? opts.timeout : 5000; 32 | 33 | const p = pAny(arrify(dests).map(detectCrypto)); 34 | return pTimeout(p, opts.timeout).catch(() => 'Cryptocurrency could not be detected'); 35 | }; -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # cryptocurrency-address-detector [![Build Status](https://travis-ci.org/k4m4/cryptocurrency-address-detector.svg?branch=master)](https://travis-ci.org/k4m4/cryptocurrency-address-detector) 2 | 3 | > Detect which cryptocurrency an address corresponds to. 4 | 5 | 6 | ## Install 7 | 8 | ``` 9 | ~ ❯❯❯ npm install cryptocurrency-address-detector 10 | ``` 11 | 12 | 13 | ## Usage 14 | 15 | ```js 16 | const addressDetect = require('cryptocurrency-address-detector'); 17 | 18 | addressDetect('0x281055afc982d96fab65b3a49cac8b878184cb16').then(cryptocurrency => { 19 | console.log(cryptocurrency); 20 | //=> 'ETH' 21 | }); 22 | 23 | addressDetect('1dice8EMZmqKvrGE4Qc9bUFf9PX3xaYDp').then(cryptocurrency => { 24 | console.log(cryptocurrency); 25 | //=> 'BTC/BCH' 26 | }); 27 | 28 | addressDetect('LQL9pVH1LsMfKwt82Y2wGhNGkrjF8vwUst').then(cryptocurrency => { 29 | console.log(cryptocurrency); 30 | //=> 'LTC' 31 | }); 32 | 33 | addressDetect('0xsfdlffsjksldfj[IPv6:2001:db8::2]').then(cryptocurrency => { 34 | console.log(cryptocurrency); 35 | //=> 'Cryptocurrency could not be detected' 36 | }); 37 | ``` 38 | 39 | 40 | ## API 41 | 42 | ### addressDetect(address, [options]) 43 | 44 | Returns the cryptocurrency that an address corresponds to. 45 | 46 | #### address 47 | 48 | Type: `string` 49 | 50 | Address to check for popular cryptocurrencies. 51 | 52 | #### options 53 | 54 | ##### timeout 55 | 56 | Type: `number` 57 | 58 | Timeout in milliseconds after which a request is considered failed. Default: `5000`. 59 | 60 | 61 | ## Supported Cryptocurrencies 62 | 63 | - [`Bitcoin/BTC`](https://github.com/kevva/bitcoin-regex) 64 | - [`Bitcoin Cash/BCH`](https://github.com/k4m4/bitcoincash-regex) 65 | - [`Ethereum/ETH`](https://github.com/k4m4/ethereum-regex) 66 | - [`Litecoin/LTC`](https://github.com/k4m4/litecoin-regex) 67 | - [`Monero/XMR`](https://github.com/k4m4/monero-regex) 68 | - [`Dash/DASH`](https://github.com/k4m4/dash-regex) 69 | - [`Ripple/XRP`](https://github.com/k4m4/ripple-regex) 70 | - [`NEO/NEO`](https://github.com/k4m4/neo-regex) 71 | - [`Dogecoin/DOGE`](https://github.com/k4m4/dogecoin-regex) 72 | 73 | 74 | ## Related 75 | 76 | - [cryptaddress.now](https://github.com/k4m4/cryptaddress.now) - Minimal service to detect what cryptocurrency an address corresponds to. 77 | 78 | 79 | ## License 80 | 81 | MIT © [Nikolaos Kamarinakis](https://nikolaskama.me) -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import m from './'; 3 | 4 | const fixturesBTC = [ 5 | '1dice8EMZmqKvrGE4Qc9bUFf9PX3xaYDp', 6 | '1JeTiYgfVtpA3ygQTYFswkaoiH2VnFZJf9', 7 | '1Ak6rNZYm5tNtDVJRt93Cax17TBih6pM7Y', 8 | '1dice6YgEVBf88erBFra9BHf6ZMoyvG88', 9 | '1FFirnLctcZxVx5otnLNZ4dDGUkMBM4vNr' 10 | ]; 11 | const fixturesBCH = [ 12 | '19hZx234vNtLazfx5J2bxHsiWEmeYE8a7k', 13 | '1F4MH7XeQypXZTjFgCj8ZSd63NX8ywTEbG', 14 | '1JCe8z4jJVNXSjohjM4i9Hh813dLCNx2Sy', 15 | '3B8vnfVt8UhHtYW7ib5BA7ZiVKDXY9UkRS', 16 | '1EeBbBiJGvVzemoLodsrZxv9sEKq1dz1KT' 17 | ]; 18 | test('Bitcoin/Bitcoin Cash', async t => { 19 | for (const x of fixturesBTC) { 20 | t.is((await m(x)), 'BTC/BCH'); 21 | } 22 | for (const x of fixturesBCH) { 23 | t.is((await m(x)), 'BTC/BCH'); 24 | } 25 | }); 26 | test('Bitcoin/Bitcoin Cash with timeout', async t => { 27 | for (const x of fixturesBTC) { 28 | t.is((await m(x, {timeout: 3000})), 'BTC/BCH'); 29 | } 30 | for (const x of fixturesBCH) { 31 | t.is((await m(x, {timeout: 3000})), 'BTC/BCH'); 32 | } 33 | }); 34 | 35 | const fixturesBCHCashAddr = [ 36 | 'bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a', 37 | 'bitcoincash:qr95sy3j9xwd2ap32xkykttr4cvcu7as4y0qverfuy', 38 | 'bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq', 39 | 'bitcoincash:pr95sy3j9xwd2ap32xkykttr4cvcu7as4yc93ky28e', 40 | 'bitcoincash:pqq3728yw0y47sqn6l2na30mcw6zm78dzq5ucqzc37' 41 | ]; 42 | test('Bitcoin Cash (CashAddr)', async t => { 43 | for (const x of fixturesBCHCashAddr) { 44 | t.is((await m(x)), 'BCH'); 45 | } 46 | }); 47 | test('Bitcoin Cash (CashAddr) with timeout', async t => { 48 | for (const x of fixturesBCHCashAddr) { 49 | t.is((await m(x, {timeout: 3000})), 'BCH'); 50 | } 51 | }); 52 | 53 | const fixturesETH = [ 54 | '0x281055afc982d96fab65b3a49cac8b878184cb16', 55 | '0x6f46cf5569aefa1acc1009290c8e043747172d89', 56 | '0x90e63c3d53e0ea496845b7a03ec7548b70014a91', 57 | '0xab7c74abc0c4d48d1bdad5dcb26153fc8780f83e', 58 | '0x53d284357ec70ce289d6d64134dfac8e511c8a3d' 59 | ]; 60 | test('Ethereum', async t => { 61 | for (const x of fixturesETH) { 62 | t.is((await m(x)), 'ETH'); 63 | } 64 | }); 65 | test('Ethereum with timeout', async t => { 66 | for (const x of fixturesETH) { 67 | t.is((await m(x, {timeout: 3000})), 'ETH'); 68 | } 69 | }); 70 | 71 | const fixturesLTC = [ 72 | 'LQL9pVH1LsMfKwt82Y2wGhNGkrjF8vwUst', 73 | 'LPpHectVSbk7YHa5X89Cm3FoFBfzkJBJc9', 74 | 'LRcYfbDMhwvXaGPFccaKuc3fZD1Nb55aGn', 75 | 'LY5fxZS74Ewuj1TTHwat23eUmZwimsksrU', 76 | 'Laub752qu81oWwkNKEyawyKruUC6cEyD2x' 77 | ]; 78 | test('Litecoin', async t => { 79 | for (const x of fixturesLTC) { 80 | t.is((await m(x)), 'LTC'); 81 | } 82 | }); 83 | test('Litecoin with timeout', async t => { 84 | for (const x of fixturesLTC) { 85 | t.is((await m(x, {timeout: 3000})), 'LTC'); 86 | } 87 | }); 88 | 89 | const fixturesDOGE = [ 90 | 'DANHz6EQVoWyZ9rER56DwTXHWUxfkv9k2o', 91 | 'DDTtqnuZ5kfRT5qh2c7sNtqrJmV3iXYdGG', 92 | 'DP5mjk9SEYtzhnhkkC24PEjxNtDN7JGRx3', 93 | 'D8EyEfuNsfQ3root9R3ac54mMcLmoNBW6q', 94 | 'DFN5b3Usara4aZAvhT6muXd3hR49d5zxio' 95 | ]; 96 | test('Dogecoin', async t => { 97 | for (const x of fixturesDOGE) { 98 | t.is((await m(x)), 'DOGE'); 99 | } 100 | }); 101 | test('Dogecoin with timeout', async t => { 102 | for (const x of fixturesDOGE) { 103 | t.is((await m(x, {timeout: 3000})), 'DOGE'); 104 | } 105 | }); 106 | 107 | const fixturesDASH = [ 108 | 'XbtvGzi2JgjYTbTqabUjSREWeovDxznoyh', 109 | 'Xm9TJiJ7nWjme8K7iEPUGsC5JjYGzPk2QU', 110 | 'Xe4q4hA2bXWuZHHDRPb3R72cpauDYEk8CP', 111 | 'XvwKzdsn46psqy6WhZ2wfhRPyRkD6GL2BG', 112 | 'XcKvX5SeAwPSfyiKBw6QKt6EnA9FtWvk1r' 113 | ]; 114 | test('Dash', async t => { 115 | for (const x of fixturesDASH) { 116 | t.is((await m(x)), 'DASH'); 117 | } 118 | }); 119 | test('Dash with timeout', async t => { 120 | for (const x of fixturesDASH) { 121 | t.is((await m(x, {timeout: 3000})), 'DASH'); 122 | } 123 | }); 124 | 125 | const fixturesXMR = [ 126 | '47BnvD18P456f4KJUBKPS3Rqa97LrTaeqJ5NFYmjQM6nVoz6TBv4rJ24GZk883BNo22fAKbr8BSuTjhQC6K7DsSJFa8SHDs', 127 | '42oAxV3DVXXG3HhyCyi2xaPukKXbip9Sx1YuJtoCqjZRSze4tYCq7n3VUswDBFV59Zev8yfHSZro4TUwXumtRWnQ8xQipkC', 128 | '44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A', 129 | '47gRtvuDS9dNjkNs2nFqiSVHk3tqdT239j9Tj1KxAWNPRogHnGUdMdvQBwevobeAxQHqjBu8WcZzfNrdbReYNAU1KBidTzc', 130 | '46qB9tcR1feVZ7xq42tx8V8sLbYdnFdGf6EndL1fCPRuUXroufYGzzCFtZwrjkthAc8C65xBpmWCYAR1KKBXykF76GADvYE' 131 | ]; 132 | test('Monero', async t => { 133 | for (const x of fixturesXMR) { 134 | t.is((await m(x)), 'XMR'); 135 | } 136 | }); 137 | test('Monero with timeout', async t => { 138 | for (const x of fixturesXMR) { 139 | t.is((await m(x, {timeout: 3000})), 'XMR'); 140 | } 141 | }); 142 | 143 | const fixturesXRP = [ 144 | 'rG2ZJRab3EGBmpoxUyiF2guB3GoQTwMGEC', 145 | 'rfBKzgkPt9EvSJmk1uhoWTauaFCaRh4jMp', 146 | 'rPDXxSZcuVL3ZWoyU82bcde3zwvmShkRyF', 147 | 'r9Gps6fB9YLuZ87rWx7M9TgLAGK2zsz5s6', 148 | 'rJHygWcTLVpSXkowott6kzgZU6viQSVYM1' 149 | ]; 150 | test('Ripple', async t => { 151 | for (const x of fixturesXRP) { 152 | t.is((await m(x)), 'XRP'); 153 | } 154 | }); 155 | test('Ripple with timeout', async t => { 156 | for (const x of fixturesXRP) { 157 | t.is((await m(x, {timeout: 3000})), 'XRP'); 158 | } 159 | }); 160 | 161 | const fixturesNEO = [ 162 | 'AQVh2pG732YvtNaxEGkQUei3YA4cvo7d2i', 163 | 'AR4QmqYENiZAD6oXe7ftm6eDcwtHk7rVTT', 164 | 'AddZkjqPoPyhDhWoA8f9CXQeHQRDr8HbPo', 165 | 'APMyYHutJZsZVWAQRe9h4eVrzzD3HLroQW', 166 | 'ANpB7FBPoPpqjxKFWiiAD3arFgsQtwYUPb' 167 | ]; 168 | test('NEO', async t => { 169 | for (const x of fixturesNEO) { 170 | t.is((await m(x)), 'NEO'); 171 | } 172 | }); 173 | test('NEO with timeout', async t => { 174 | for (const x of fixturesNEO) { 175 | t.is((await m(x, {timeout: 3000})), 'NEO'); 176 | } 177 | }); 178 | 179 | const fixturesNot = [ 180 | '192.168.1.1,192.168.1.2,192.168.1.3', 181 | 'k4m4/ethereum-regex', 182 | '0xsfdlffsjksldfj[IPv6:2001:db8::2]', 183 | 'nikolaskam{at}gmail{dot}com' 184 | ]; 185 | test('Non-crypto', async t => { 186 | for (const x of fixturesNot) { 187 | t.is((await m(x)), 'Cryptocurrency could not be detected'); 188 | } 189 | }); --------------------------------------------------------------------------------