multichain-address-validator 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/.editorconfig +10 -0
  2. package/.travis.yml +11 -0
  3. package/.vscode/launch.json +23 -0
  4. package/LICENSE +21 -0
  5. package/README.md +87 -0
  6. package/config/esbuild.inject.js +1 -0
  7. package/config/esbuild.ts +14 -0
  8. package/dist/chain-validators.d.ts +2 -0
  9. package/dist/chain-validators.js +98 -0
  10. package/dist/crypto/base32.d.ts +5 -0
  11. package/dist/crypto/base32.js +64 -0
  12. package/dist/crypto/base58.d.ts +4 -0
  13. package/dist/crypto/base58.js +42 -0
  14. package/dist/crypto/bech32.d.ts +17 -0
  15. package/dist/crypto/bech32.js +124 -0
  16. package/dist/crypto/biginteger.d.ts +57 -0
  17. package/dist/crypto/biginteger.js +1311 -0
  18. package/dist/crypto/blake256.d.ts +22 -0
  19. package/dist/crypto/blake256.js +169 -0
  20. package/dist/crypto/blake2b.d.ts +13 -0
  21. package/dist/crypto/blake2b.js +242 -0
  22. package/dist/crypto/cnBase58.d.ts +7 -0
  23. package/dist/crypto/cnBase58.js +209 -0
  24. package/dist/crypto/segwit_addr.d.ts +12 -0
  25. package/dist/crypto/segwit_addr.js +102 -0
  26. package/dist/crypto/utils.d.ts +26 -0
  27. package/dist/crypto/utils.js +123 -0
  28. package/dist/helpers.d.ts +2 -0
  29. package/dist/helpers.js +5 -0
  30. package/dist/multichain-address-validator.bundle.min.js +17 -0
  31. package/dist/multichain-address-validator.d.ts +2 -0
  32. package/dist/multichain-address-validator.js +8 -0
  33. package/dist/types.d.ts +15 -0
  34. package/dist/types.js +5 -0
  35. package/dist/validators/algorand_validator.d.ts +5 -0
  36. package/dist/validators/algorand_validator.js +23 -0
  37. package/dist/validators/base58_validator.d.ts +4 -0
  38. package/dist/validators/base58_validator.js +31 -0
  39. package/dist/validators/bch_validator.d.ts +13 -0
  40. package/dist/validators/bch_validator.js +50 -0
  41. package/dist/validators/bip173_validator.d.ts +7 -0
  42. package/dist/validators/bip173_validator.js +12 -0
  43. package/dist/validators/bitcoin_validator.d.ts +12 -0
  44. package/dist/validators/bitcoin_validator.js +68 -0
  45. package/dist/validators/cardano_validator.d.ts +5 -0
  46. package/dist/validators/cardano_validator.js +41 -0
  47. package/dist/validators/eos_validator.d.ts +5 -0
  48. package/dist/validators/eos_validator.js +10 -0
  49. package/dist/validators/ethereum_validator.d.ts +6 -0
  50. package/dist/validators/ethereum_validator.js +30 -0
  51. package/dist/validators/index.d.ts +16 -0
  52. package/dist/validators/index.js +16 -0
  53. package/dist/validators/monero_validator.d.ts +5 -0
  54. package/dist/validators/monero_validator.js +58 -0
  55. package/dist/validators/nano_validator.d.ts +6 -0
  56. package/dist/validators/nano_validator.js +23 -0
  57. package/dist/validators/nem_validator.d.ts +5 -0
  58. package/dist/validators/nem_validator.js +14 -0
  59. package/dist/validators/polkadot_validator.d.ts +5 -0
  60. package/dist/validators/polkadot_validator.js +49 -0
  61. package/dist/validators/ripple_validator.d.ts +10 -0
  62. package/dist/validators/ripple_validator.js +26 -0
  63. package/dist/validators/sia_validator.d.ts +5 -0
  64. package/dist/validators/sia_validator.js +27 -0
  65. package/dist/validators/solana_validator.d.ts +5 -0
  66. package/dist/validators/solana_validator.js +10 -0
  67. package/dist/validators/tezos_validator.d.ts +5 -0
  68. package/dist/validators/tezos_validator.js +30 -0
  69. package/dist/validators/tron_validator.d.ts +8 -0
  70. package/dist/validators/tron_validator.js +45 -0
  71. package/dist/validators/xlm_validator.d.ts +6 -0
  72. package/dist/validators/xlm_validator.js +32 -0
  73. package/index.html +12 -0
  74. package/package.json +353 -0
  75. package/src/chain-validators.ts +131 -0
  76. package/src/crypto/base32.ts +66 -0
  77. package/src/crypto/base58.ts +46 -0
  78. package/src/crypto/bech32.js +132 -0
  79. package/src/crypto/biginteger.js +1426 -0
  80. package/src/crypto/blake256.js +186 -0
  81. package/src/crypto/blake2b.js +276 -0
  82. package/src/crypto/cnBase58.js +226 -0
  83. package/src/crypto/segwit_addr.js +112 -0
  84. package/src/crypto/utils.ts +133 -0
  85. package/src/helpers.ts +7 -0
  86. package/src/multichain-address-validator.ts +11 -0
  87. package/src/types.ts +18 -0
  88. package/src/validators/algorand_validator.ts +28 -0
  89. package/src/validators/base58_validator.ts +32 -0
  90. package/src/validators/bch_validator.ts +66 -0
  91. package/src/validators/bip173_validator.ts +19 -0
  92. package/src/validators/bitcoin_validator.ts +94 -0
  93. package/src/validators/cardano_validator.ts +50 -0
  94. package/src/validators/eos_validator.ts +13 -0
  95. package/src/validators/ethereum_validator.ts +37 -0
  96. package/src/validators/index.ts +16 -0
  97. package/src/validators/monero_validator.ts +72 -0
  98. package/src/validators/nano_validator.ts +32 -0
  99. package/src/validators/nem_validator.ts +18 -0
  100. package/src/validators/polkadot_validator.ts +57 -0
  101. package/src/validators/ripple_validator.ts +36 -0
  102. package/src/validators/sia_validator.ts +33 -0
  103. package/src/validators/solana_validator.ts +12 -0
  104. package/src/validators/tezos_validator.ts +36 -0
  105. package/src/validators/tron_validator.ts +59 -0
  106. package/src/validators/xlm_validator.ts +42 -0
  107. package/test/addresses/addresses.ts +45 -0
  108. package/test/addresses/algorand.json +6 -0
  109. package/test/addresses/bch-testnet.json +4 -0
  110. package/test/addresses/bch.json +12 -0
  111. package/test/addresses/btc-testnet.json +6 -0
  112. package/test/addresses/btc.json +14 -0
  113. package/test/addresses/cardano.json +8 -0
  114. package/test/addresses/doge.json +7 -0
  115. package/test/addresses/eos.json +6 -0
  116. package/test/addresses/evm.json +21 -0
  117. package/test/addresses/invalid.json +15 -0
  118. package/test/addresses/ltc-testnet.json +7 -0
  119. package/test/addresses/ltc.json +9 -0
  120. package/test/addresses/monero.json +7 -0
  121. package/test/addresses/nano.json +12 -0
  122. package/test/addresses/nem.json +4 -0
  123. package/test/addresses/polkadot.json +8 -0
  124. package/test/addresses/ripple.json +11 -0
  125. package/test/addresses/sia.json +6 -0
  126. package/test/addresses/solana.json +8 -0
  127. package/test/addresses/tezos.json +9 -0
  128. package/test/addresses/tron.json +6 -0
  129. package/test/addresses/xlm.json +12 -0
  130. package/test/multichain-address-validator.test.ts +1589 -0
  131. package/tsconfig.json +23 -0
@@ -0,0 +1,112 @@
1
+ // Copyright (c) 2017, 2021 Pieter Wuille
2
+ //
3
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ // of this software and associated documentation files (the "Software"), to deal
5
+ // in the Software without restriction, including without limitation the rights
6
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ // copies of the Software, and to permit persons to whom the Software is
8
+ // furnished to do so, subject to the following conditions:
9
+ //
10
+ // The above copyright notice and this permission notice shall be included in
11
+ // all copies or substantial portions of the Software.
12
+ //
13
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ // THE SOFTWARE.
20
+
21
+ import bech32 from './bech32'
22
+
23
+ function convertbits (data, frombits, tobits, pad) {
24
+ var acc = 0;
25
+ var bits = 0;
26
+ var ret = [];
27
+ var maxv = (1 << tobits) - 1;
28
+ for (var p = 0; p < data.length; ++p) {
29
+ var value = data[p];
30
+ if (value < 0 || (value >> frombits) !== 0) {
31
+ return null;
32
+ }
33
+ acc = (acc << frombits) | value;
34
+ bits += frombits;
35
+ while (bits >= tobits) {
36
+ bits -= tobits;
37
+ ret.push((acc >> bits) & maxv);
38
+ }
39
+ }
40
+ if (pad) {
41
+ if (bits > 0) {
42
+ ret.push((acc << (tobits - bits)) & maxv);
43
+ }
44
+ } else if (bits >= frombits || ((acc << (tobits - bits)) & maxv)) {
45
+ return null;
46
+ }
47
+ return ret;
48
+ }
49
+
50
+ function decode (hrp, addr) {
51
+ var bech32m = false;
52
+ var dec = bech32.decode(addr, bech32.encodings.BECH32);
53
+ if (dec === null) {
54
+ dec = bech32.decode(addr, bech32.encodings.BECH32M);
55
+ bech32m = true;
56
+ }
57
+ if (dec === null || dec.hrp !== hrp || dec.data.length < 1 || dec.data[0] > 16) {
58
+ return null;
59
+ }
60
+ var res = convertbits(dec.data.slice(1), 5, 8, false);
61
+ if (res === null || res.length < 2 || res.length > 40) {
62
+ return null;
63
+ }
64
+ if (dec.data[0] === 0 && res.length !== 20 && res.length !== 32) {
65
+ return null;
66
+ }
67
+ if (dec.data[0] === 0 && bech32m) {
68
+ return null;
69
+ }
70
+ if (dec.data[0] !== 0 && !bech32m) {
71
+ return null;
72
+ }
73
+ return {version: dec.data[0], program: res};
74
+ }
75
+
76
+ function encode (hrp, version, program) {
77
+ var enc = bech32.encodings.BECH32;
78
+ if (version > 0) {
79
+ enc = bech32.encodings.BECH32M;
80
+ }
81
+ var ret = bech32.encode(hrp, [version].concat(convertbits(program, 8, 5, true)), enc);
82
+ if (decode(hrp, ret, enc) === null) {
83
+ return null;
84
+ }
85
+ return ret;
86
+ }
87
+
88
+ /////////////////////////////////////////////////////
89
+
90
+ function isValidAddress(address, opts = {}) {
91
+
92
+ if(!opts.bech32Hrp || opts.bech32Hrp.length === 0) {
93
+ return false;
94
+ }
95
+
96
+ const correctBech32Hrps = opts.bech32Hrp;
97
+
98
+ for(var chrp of correctBech32Hrps) {
99
+ var ret = decode(chrp, address);
100
+ if(ret) {
101
+ return encode(chrp, ret.version, ret.program) === address.toLowerCase();
102
+ }
103
+ }
104
+
105
+ return false;
106
+ }
107
+
108
+ export default {
109
+ encode: encode,
110
+ decode: decode,
111
+ isValidAddress: isValidAddress,
112
+ }
@@ -0,0 +1,133 @@
1
+ import {Buffer} from 'buffer'
2
+ import { sha256 } from '@noble/hashes/sha256'
3
+ import { sha512, sha512_256 } from '@noble/hashes/sha512'
4
+ import { bytesToHex } from '@noble/hashes/utils'
5
+ import { keccak_256 } from '@noble/hashes/sha3'
6
+
7
+ import base32 from './base32.js'
8
+ import base58 from './base58.js'
9
+
10
+ import Blake256 from './blake256.js'
11
+ import Blake2B from './blake2b.js'
12
+
13
+ function numberToHex(number: number, length: number) {
14
+ let hex = number.toString(16);
15
+ if (hex.length % 2 === 1) {
16
+ hex = '0' + hex;
17
+ }
18
+ return hex.padStart(length, '0');
19
+ }
20
+
21
+ function isHexChar(c: string) {
22
+ if ((c >= 'A' && c <= 'F') ||
23
+ (c >= 'a' && c <= 'f') ||
24
+ (c >= '0' && c <= '9')) {
25
+ return 1;
26
+ }
27
+ return 0;
28
+ }
29
+
30
+ /* Convert a hex char to value */
31
+ function hexChar2byte(c: string) {
32
+ let d = 0;
33
+ if (c >= 'A' && c <= 'F') {
34
+ d = c.charCodeAt(0) - 'A'.charCodeAt(0) + 10;
35
+ }
36
+ else if (c >= 'a' && c <= 'f') {
37
+ d = c.charCodeAt(0) - 'a'.charCodeAt(0) + 10;
38
+ }
39
+ else if (c >= '0' && c <= '9') {
40
+ d = c.charCodeAt(0) - '0'.charCodeAt(0);
41
+ }
42
+ return d;
43
+ }
44
+
45
+ /* Convert a byte to string */
46
+ function byte2hexStr(byte: number) {
47
+ const hexByteMap = "0123456789ABCDEF";
48
+ let str = "";
49
+ str += hexByteMap.charAt(byte >> 4);
50
+ str += hexByteMap.charAt(byte & 0x0f);
51
+ return str;
52
+ }
53
+
54
+ function byteArray2hexStr(byteArray: number[]) {
55
+ let str = "";
56
+ let i = 0
57
+ for (i = 0; i < (byteArray.length - 1); i++) {
58
+ str += byte2hexStr(byteArray[i]);
59
+ }
60
+ str += byte2hexStr(byteArray[i]);
61
+ return str;
62
+ }
63
+
64
+ function hexStr2byteArray(str: string) {
65
+ const byteArray = new Uint8Array(str.length/2);
66
+ let d = 0;
67
+ let i = 0;
68
+ let j = 0;
69
+ let k = 0;
70
+
71
+ for (i = 0; i < str.length; i++) {
72
+ const c = str.charAt(i);
73
+ if (isHexChar(c)) {
74
+ d <<= 4;
75
+ d += hexChar2byte(c);
76
+ j++;
77
+ if (0 === (j % 2)) {
78
+ byteArray[k++] = d;
79
+ d = 0;
80
+ }
81
+ }
82
+ }
83
+ return byteArray;
84
+ }
85
+
86
+ export default {
87
+ numberToHex: numberToHex,
88
+ toHex: function (arrayOfBytes: any) {
89
+ let hex = '';
90
+ for (let i = 0; i < arrayOfBytes.length; i++) {
91
+ // @ts-expect-error
92
+ hex += numberToHex(arrayOfBytes[i]);
93
+ }
94
+ return hex;
95
+ },
96
+ sha256: function (payload: any, format = 'HEX') {
97
+ return bytesToHex(sha256(hexStr2byteArray(payload) as any))
98
+ },
99
+ sha256x2: function (buffer: any, format = 'HEX') {
100
+ return this.sha256(this.sha256(buffer, format), format);
101
+ },
102
+ sha256Checksum: function (payload: any) {
103
+ return this.sha256(this.sha256(payload)).slice(0, 8);
104
+ },
105
+ sha512: function(payload: any, format = 'HEX') {
106
+ return bytesToHex(sha512(payload))
107
+ },
108
+ sha512_256: function (payload: any, format = 'HEX') {
109
+ return bytesToHex(sha512_256(hexStr2byteArray(payload)))
110
+ },
111
+ blake256: function (hexString: string) {
112
+ return new Blake256().update(hexString, 'hex').digest('hex');
113
+ },
114
+ blake256Checksum: function (payload: any) {
115
+ return this.blake256(this.blake256(payload)).substr(0, 8);
116
+ },
117
+ blake2b: function (hexString: string, outlen: number) {
118
+ return new Blake2B(outlen).update(Buffer.from(hexString, 'hex')).digest('hex');
119
+ },
120
+ keccak256: function (hexString: string) {
121
+ return bytesToHex(keccak_256(hexString));
122
+ },
123
+ keccak256Checksum: function (payload: any) {
124
+ return this.keccak256(payload).toString().substr(0, 8);
125
+ },
126
+ blake2b256: function (hexString: string) {
127
+ return new Blake2B(32).update(Buffer.from(hexString, 'hex')).digest('hex');
128
+ },
129
+ base58: base58.decode,
130
+ byteArray2hexStr: byteArray2hexStr,
131
+ hexStr2byteArray: hexStr2byteArray,
132
+ base32: base32
133
+ }
package/src/helpers.ts ADDED
@@ -0,0 +1,7 @@
1
+ import {Address} from './types.js'
2
+
3
+ export function getAddress(address: Address): string {
4
+ return typeof address === 'string'
5
+ ? address
6
+ : address.address
7
+ }
@@ -0,0 +1,11 @@
1
+ import {Address, Chain} from './types.js'
2
+ import {getValidatorForChain} from './chain-validators.js'
3
+
4
+ export function validate(address: Address, chain: Chain) {
5
+ const validator = getValidatorForChain(chain)
6
+ if (validator) {
7
+ return validator.isValidAddress(address);
8
+ }
9
+
10
+ throw new Error(`Missing validator for chain: ${chain}`);
11
+ }
package/src/types.ts ADDED
@@ -0,0 +1,18 @@
1
+ export type Address = string | {
2
+ address: string,
3
+ memo?: string,
4
+ }
5
+
6
+ export type Chain = string | {
7
+ chain: string,
8
+ networkType?: NetworkType
9
+ }
10
+
11
+ export interface Validator {
12
+ isValidAddress(address: Address): boolean
13
+ }
14
+
15
+ export enum NetworkType {
16
+ MainNet = 'mainnet',
17
+ TestNet = 'testnet',
18
+ }
@@ -0,0 +1,28 @@
1
+ import cryptoUtils from '../crypto/utils.js'
2
+ import {Address} from '../types.js'
3
+ import {getAddress} from '../helpers.js'
4
+
5
+ const ALGORAND_CHECKSUM_BYTE_LENGTH = 4;
6
+ const ALGORAND_ADDRESS_LENGTH = 58;
7
+
8
+ function verifyChecksum(address: string) {
9
+ if (address.length !== ALGORAND_ADDRESS_LENGTH) {
10
+ return false
11
+ } else {
12
+ // Decode base32 Address
13
+ const decoded = cryptoUtils.base32.b32decode(address);
14
+ const addr = decoded.slice(0, decoded.length - ALGORAND_CHECKSUM_BYTE_LENGTH)
15
+ const checksum = cryptoUtils.byteArray2hexStr(decoded.slice(-4) as any)
16
+
17
+ // Hash Address - Checksum
18
+ const code = cryptoUtils.sha512_256(cryptoUtils.byteArray2hexStr(addr as any)).substr(-ALGORAND_CHECKSUM_BYTE_LENGTH * 2);
19
+
20
+ return code.toUpperCase() === checksum
21
+ }
22
+ }
23
+
24
+ export default {
25
+ isValidAddress: function (address: Address) {
26
+ return verifyChecksum(getAddress(address))
27
+ }
28
+ }
@@ -0,0 +1,32 @@
1
+ import base58 from '../crypto/base58.js'
2
+
3
+ // simple base58 validator. Just checks if it can be decoded.
4
+ export default {
5
+ isValidAddress: function (address, opts: any) {
6
+ try {
7
+ if (!address || address.length == 0) {
8
+ return false;
9
+ }
10
+
11
+ if (opts.minLength && (address.length < opts.minLength)) {
12
+ return false;
13
+ }
14
+
15
+ if (opts.maxLength && (address.length > opts.maxLength)) {
16
+ return false;
17
+ }
18
+ try {
19
+ const decoded = base58.decode(address);
20
+ if (!decoded || !decoded.length) {
21
+ return false;
22
+ }
23
+ } catch (e) {
24
+ // if decoding fails, assume invalid address
25
+ return false;
26
+ }
27
+ return true;
28
+ } catch (e) {
29
+ return false;
30
+ }
31
+ }
32
+ };
@@ -0,0 +1,66 @@
1
+ import cryptoUtils from '../crypto/utils.js'
2
+ import bech32 from '../crypto/bech32.js'
3
+ import {Address, NetworkType} from '../types.js'
4
+ import BTCValidator from './bitcoin_validator.js'
5
+ import {getAddress} from '../helpers.js'
6
+
7
+ function validateAddress(address: string, opts: BCHValidatorOpts) {
8
+ const regexp = new RegExp(opts.regexp);
9
+ let raw_address: string;
10
+
11
+ const res = address.split(':');
12
+ if (res.length === 1) {
13
+ raw_address = address
14
+ } else {
15
+ if (res[0] !== 'bitcoincash') {
16
+ return false;
17
+ }
18
+ raw_address = res[1];
19
+ }
20
+
21
+ if (!regexp.test(raw_address)) {
22
+ return false;
23
+ }
24
+
25
+ if (raw_address.toLowerCase() != raw_address && raw_address.toUpperCase() != raw_address) {
26
+ return false;
27
+ }
28
+
29
+ const decoded = cryptoUtils.base32.b32decode(raw_address);
30
+
31
+ const prefix = opts.networkType === NetworkType.MainNet
32
+ ? 'bitcoincash'
33
+ : 'bchtest'
34
+
35
+ try {
36
+ if (bech32.verifyChecksum(prefix, decoded, bech32.encodings.BECH32)) {
37
+ return false;
38
+ }
39
+ } catch (e) {
40
+ return false;
41
+ }
42
+ return true;
43
+ }
44
+
45
+ interface BCHValidatorOpts {
46
+ addressTypes: string[]
47
+ expectedLength?: number
48
+ bech32Hrp?: [string],
49
+ hashFunction?: 'blake256' | 'blake256keccak256' | 'keccak256' | 'sha256',
50
+ regexp?: RegExp,
51
+ networkType: NetworkType,
52
+ }
53
+
54
+ const DefaultBCHValidatorOpts: Partial<BCHValidatorOpts> = {
55
+ // addressTypes: {mainnet: ['00', '05'], testnet: ['6f', 'c4', '3c', '26']},
56
+ // bech32Hrp: {mainnet: ['bc'], testnet: ['tb']},
57
+ regexp: /^[qQpP][0-9a-zA-Z]{41}$/,
58
+ }
59
+
60
+ export default (opts: BCHValidatorOpts) => ({
61
+ isValidAddress: function (address: Address) {
62
+ const addr = getAddress(address)
63
+ const _opts = {...DefaultBCHValidatorOpts, ...opts}
64
+ return validateAddress(addr, _opts) || BTCValidator(opts).isValidAddress(address);
65
+ }
66
+ })
@@ -0,0 +1,19 @@
1
+ import bech32 from '../crypto/bech32.js'
2
+
3
+ interface Bip173Options {
4
+ bech32Hrp: string[]
5
+ }
6
+
7
+ // bip 173 bech 32 addresses (https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki)
8
+ export default {
9
+ isValidAddress: function (address: string, opts: Bip173Options) {
10
+ const decoded = bech32.decode(address, bech32.encodings.BECH32);
11
+ if (!decoded) {
12
+ return false;
13
+ }
14
+
15
+ const bech32Hrp = decoded.hrp;
16
+
17
+ return opts.bech32Hrp.indexOf(bech32Hrp) !== -1;
18
+ }
19
+ };
@@ -0,0 +1,94 @@
1
+ import base58 from '../crypto/base58.js'
2
+ import segwit from '../crypto/segwit_addr.js'
3
+ import cryptoUtils from '../crypto/utils.js'
4
+
5
+ import {Address, NetworkType} from '../types.js'
6
+ import {getAddress} from '../helpers.js'
7
+ import {Buffer} from 'buffer'
8
+
9
+ function getDecoded(address: string) {
10
+ try {
11
+ return base58.decode(address);
12
+ } catch (e) {
13
+ // if decoding fails, assume invalid address
14
+ return null;
15
+ }
16
+ }
17
+
18
+ function getChecksum(hashFunction: BTCValidatorOpts['hashFunction'], payload: any) {
19
+ // Each currency may implement different hashing algorithm
20
+ switch (hashFunction) {
21
+ // blake then keccak hash chain
22
+ case 'blake256keccak256':
23
+ const blake = cryptoUtils.blake2b256(payload);
24
+ return cryptoUtils.keccak256Checksum(Buffer.from(blake, 'hex'));
25
+ case 'blake256':
26
+ return cryptoUtils.blake256Checksum(payload);
27
+ case 'keccak256':
28
+ return cryptoUtils.keccak256Checksum(payload);
29
+ case 'sha256':
30
+ default:
31
+ return cryptoUtils.sha256Checksum(payload);
32
+ }
33
+ }
34
+
35
+ function getAddressType(address: string, opts: BTCValidatorOpts) {
36
+ // should be 25 bytes per btc address spec and 26 decred
37
+ const expectedLength = opts.expectedLength || 25;
38
+ const hashFunction = opts.hashFunction || 'sha256';
39
+ const decoded = getDecoded(address);
40
+
41
+ if (decoded) {
42
+ const length = decoded.length;
43
+
44
+ if (length !== expectedLength) {
45
+ return null;
46
+ }
47
+
48
+ if (opts.regex) {
49
+ if (!opts.regex.test(address)) {
50
+ return false;
51
+ }
52
+ }
53
+
54
+ const checksum = cryptoUtils.toHex(decoded.slice(length - 4, length)),
55
+ body = cryptoUtils.toHex(decoded.slice(0, length - 4)),
56
+ goodChecksum = getChecksum(hashFunction, body);
57
+
58
+ return checksum === goodChecksum ? cryptoUtils.toHex(decoded.slice(0, expectedLength - 24)) : null;
59
+ }
60
+
61
+ return null;
62
+ }
63
+
64
+ function isValidP2PKHandP2SHAddress(address: string, opts: BTCValidatorOpts) {
65
+ const addressType = getAddressType(address, opts);
66
+
67
+ if (addressType) {
68
+ return opts.addressTypes.indexOf(addressType) >= 0;
69
+ }
70
+
71
+ return false;
72
+ }
73
+
74
+
75
+ interface BTCValidatorOpts {
76
+ addressTypes: string[],
77
+ expectedLength?: number,
78
+ bech32Hrp?: [string],
79
+ hashFunction?: 'blake256' | 'blake256keccak256' | 'keccak256' | 'sha256',
80
+ regex?: RegExp,
81
+ }
82
+
83
+ // const DefaultBTCValidatorOpts: BTCValidatorOpts = {
84
+ // addressTypes: {mainnet: ['00', '05'], testnet: ['6f', 'c4', '3c', '26']},
85
+ // bech32Hrp: {mainnet: ['bc'], testnet: ['tb']},
86
+ // }
87
+
88
+ export default (opts: BTCValidatorOpts) => ({
89
+ isValidAddress(address: Address): boolean {
90
+ const addr = getAddress(address)
91
+ // const _opts = {...DefaultBTCValidatorOpts, ...opts}
92
+ return isValidP2PKHandP2SHAddress(addr, opts) || segwit.isValidAddress(addr, opts);
93
+ }
94
+ })
@@ -0,0 +1,50 @@
1
+ import cbor from 'cbor-js'
2
+ import CRC from 'crc'
3
+
4
+ import base58 from '../crypto/base58.js'
5
+ import BIP173Validator from './bip173_validator.js'
6
+ import {Address} from '../types.js'
7
+ import {getAddress} from '../helpers.js'
8
+
9
+ function getDecoded(address: string) {
10
+ try {
11
+ const 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 isValidAddressV1(address: string) {
20
+ const decoded = getDecoded(address);
21
+
22
+ if (!decoded || (!Array.isArray(decoded) && decoded.length != 2)) {
23
+ return false;
24
+ }
25
+
26
+ const tagged = decoded[0];
27
+ const validCrc = decoded[1];
28
+ if (typeof (validCrc) != 'number') {
29
+ return false;
30
+ }
31
+
32
+ // get crc of the payload
33
+ const crc = CRC.crc32(tagged);
34
+
35
+ return crc == validCrc;
36
+ }
37
+
38
+ function isValidAddressShelley(address: string, opts: { bech32Hrp: string [] }) {
39
+ // shelley address are just bip 173 - bech32 addresses (https://cips.cardano.org/cips/cip4/)
40
+ return BIP173Validator.isValidAddress(address, opts);
41
+ }
42
+
43
+ export default {
44
+ isValidAddress(address: Address) {
45
+ const addr = getAddress(address)
46
+ return isValidAddressV1(getAddress(addr)) || isValidAddressShelley(addr, {
47
+ bech32Hrp: ['addr']
48
+ });
49
+ }
50
+ }
@@ -0,0 +1,13 @@
1
+ import {Address} from '../types.js'
2
+ import {getAddress} from '../helpers.js'
3
+
4
+ function isValidEOSAddress(address: string) {
5
+ const regex = /^[a-z0-9.]+$/g // Must be numbers, lowercase letters and decimal points only
6
+ return address.search(regex) !== -1 && address.length === 12;
7
+ }
8
+
9
+ export default {
10
+ isValidAddress: function (address: Address) {
11
+ return isValidEOSAddress(getAddress(address))
12
+ }
13
+ }
@@ -0,0 +1,37 @@
1
+ import cryptoUtils from '../crypto/utils.js'
2
+ import {Address} from '../types.js'
3
+ import {getAddress} from '../helpers.js'
4
+
5
+ export default {
6
+ isValidAddress: function (address: Address) {
7
+ const addr = getAddress(address)
8
+ if (!/^0x[0-9a-fA-F]{40}$/.test(addr)) {
9
+ // Check if it has the basic requirements of an address
10
+ return false;
11
+ }
12
+
13
+ if (/^0x[0-9a-f]{40}$/.test(addr) || /^0x?[0-9A-F]{40}$/.test(addr)) {
14
+ // If it's all small caps or all caps, return true
15
+ return true;
16
+ }
17
+
18
+ // Otherwise check each case
19
+ return this.verifyChecksum(addr);
20
+ },
21
+ verifyChecksum: function (address: string) {
22
+ // Check each case
23
+ address = address.replace('0x', '');
24
+
25
+ const addressHash = cryptoUtils.keccak256(address.toLowerCase());
26
+
27
+ for (let i = 0; i < 40; i++) {
28
+ // The nth letter should be uppercase if the nth digit of casemap is 1
29
+ if ((parseInt(addressHash[i], 16) > 7 && address[i].toUpperCase() !== address[i]) ||
30
+ (parseInt(addressHash[i], 16) <= 7 && address[i].toLowerCase() !== address[i])) {
31
+ return false;
32
+ }
33
+ }
34
+
35
+ return true;
36
+ }
37
+ };
@@ -0,0 +1,16 @@
1
+ export {default as AlgorandValidator} from "./algorand_validator.js"
2
+ export {default as BCHValidator} from "./bch_validator.js"
3
+ export {default as BTCValidator} from "./bitcoin_validator.js"
4
+ export {default as CardanoValidator} from "./cardano_validator.js"
5
+ export {default as EOSValidator} from "./eos_validator.js"
6
+ export {default as ETHValidator} from "./ethereum_validator.js"
7
+ export {default as MoneroValidator} from "./monero_validator.js"
8
+ export {default as NemValidator} from "./nem_validator.js"
9
+ export {default as NanoValidator} from "./nano_validator.js"
10
+ export {default as PolkadotValidator} from "./polkadot_validator.js"
11
+ export {default as RippleValidator} from "./ripple_validator.js"
12
+ export {default as SiaValidator} from "./sia_validator.js"
13
+ export {default as SolanaValidator} from "./solana_validator.js"
14
+ export {default as TezosValidator} from "./tezos_validator.js"
15
+ export {default as TronValidator} from "./tron_validator.js"
16
+ export {default as XLMValidator} from "./xlm_validator.js"