multichain-address-validator 0.7.8 → 0.8.0

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 (50) hide show
  1. package/dist/cjs/chain-validators.js +21 -1
  2. package/dist/cjs/crypto/segwit_addr.js +8 -3
  3. package/dist/cjs/index.d.ts +1 -0
  4. package/dist/cjs/index.js +2 -1
  5. package/dist/cjs/validators/bitcoin_validator.d.ts +5 -0
  6. package/dist/cjs/validators/bitcoin_validator.js +6 -5
  7. package/dist/cjs/validators/bittensor_validator.d.ts +2 -0
  8. package/dist/cjs/validators/bittensor_validator.js +11 -0
  9. package/dist/cjs/validators/index.d.ts +2 -0
  10. package/dist/cjs/validators/index.js +5 -1
  11. package/dist/cjs/validators/polkadot_validator.d.ts +1 -4
  12. package/dist/cjs/validators/polkadot_validator.js +5 -49
  13. package/dist/cjs/validators/ss58_validator.d.ts +11 -0
  14. package/dist/cjs/validators/ss58_validator.js +70 -0
  15. package/dist/cjs/validators/zcash_validator.d.ts +5 -0
  16. package/dist/cjs/validators/zcash_validator.js +52 -0
  17. package/dist/esm/chain-validators.js +22 -2
  18. package/dist/esm/crypto/segwit_addr.js +8 -3
  19. package/dist/esm/index.d.ts +1 -0
  20. package/dist/esm/index.js +2 -1
  21. package/dist/esm/validators/bitcoin_validator.d.ts +5 -0
  22. package/dist/esm/validators/bitcoin_validator.js +5 -5
  23. package/dist/esm/validators/bittensor_validator.d.ts +2 -0
  24. package/dist/esm/validators/bittensor_validator.js +6 -0
  25. package/dist/esm/validators/index.d.ts +2 -0
  26. package/dist/esm/validators/index.js +2 -0
  27. package/dist/esm/validators/polkadot_validator.d.ts +1 -4
  28. package/dist/esm/validators/polkadot_validator.js +5 -49
  29. package/dist/esm/validators/ss58_validator.d.ts +11 -0
  30. package/dist/esm/validators/ss58_validator.js +64 -0
  31. package/dist/esm/validators/zcash_validator.d.ts +5 -0
  32. package/dist/esm/validators/zcash_validator.js +47 -0
  33. package/package-lock.json +1705 -0
  34. package/package.json +1 -1
  35. package/src/chain-validators.ts +23 -1
  36. package/src/crypto/segwit_addr.js +9 -3
  37. package/src/index.ts +2 -1
  38. package/src/validators/bitcoin_validator.ts +5 -6
  39. package/src/validators/bittensor_validator.ts +8 -0
  40. package/src/validators/index.ts +2 -0
  41. package/src/validators/polkadot_validator.ts +5 -55
  42. package/src/validators/ss58_validator.ts +80 -0
  43. package/src/validators/zcash_validator.ts +57 -0
  44. package/test/addresses/addresses.ts +4 -0
  45. package/test/addresses/bittensor.json +27 -0
  46. package/test/addresses/btc-testnet.json +1 -0
  47. package/test/addresses/btc.json +5 -1
  48. package/test/addresses/ltc.json +1 -0
  49. package/test/addresses/zcash.json +8 -0
  50. package/test/multichain-address-validator.test.ts +18 -1
@@ -1,49 +1,5 @@
1
- import cryptoUtils from '../crypto/utils.js';
2
- import { getAddress } from '../helpers.js';
3
- // from https://github.com/paritytech/substrate/wiki/External-Address-Format-(SS58)
4
- const addressFormats = [
5
- { addressLength: 3, accountIndexLength: 1, checkSumLength: 1 },
6
- { addressLength: 4, accountIndexLength: 2, checkSumLength: 1 },
7
- { addressLength: 5, accountIndexLength: 2, checkSumLength: 2 },
8
- { addressLength: 6, accountIndexLength: 4, checkSumLength: 1 },
9
- { addressLength: 7, accountIndexLength: 4, checkSumLength: 2 },
10
- { addressLength: 8, accountIndexLength: 4, checkSumLength: 3 },
11
- { addressLength: 9, accountIndexLength: 4, checkSumLength: 4 },
12
- { addressLength: 10, accountIndexLength: 8, checkSumLength: 1 },
13
- { addressLength: 11, accountIndexLength: 8, checkSumLength: 2 },
14
- { addressLength: 12, accountIndexLength: 8, checkSumLength: 3 },
15
- { addressLength: 13, accountIndexLength: 8, checkSumLength: 4 },
16
- { addressLength: 14, accountIndexLength: 8, checkSumLength: 5 },
17
- { addressLength: 15, accountIndexLength: 8, checkSumLength: 6 },
18
- { addressLength: 16, accountIndexLength: 8, checkSumLength: 7 },
19
- { addressLength: 17, accountIndexLength: 8, checkSumLength: 8 },
20
- { addressLength: 34, accountIndexLength: 32, checkSumLength: 2 },
21
- ];
22
- function verifyChecksum(address) {
23
- try {
24
- const preImage = '53533538505245';
25
- const decoded = cryptoUtils.base58(address);
26
- const addressType = cryptoUtils.byteArray2hexStr(decoded.slice(0, 1));
27
- const addressAndChecksum = decoded.slice(1);
28
- // get the address format
29
- const addressFormat = addressFormats.find(af => af.addressLength === addressAndChecksum.length);
30
- if (!addressFormat) {
31
- throw new Error('Invalid address length');
32
- }
33
- const decodedAddress = cryptoUtils.byteArray2hexStr(addressAndChecksum.slice(0, addressFormat.accountIndexLength));
34
- const checksum = cryptoUtils.byteArray2hexStr(addressAndChecksum.slice(-addressFormat.checkSumLength));
35
- const calculatedHash = cryptoUtils
36
- .blake2b(preImage + addressType + decodedAddress, 64)
37
- .substr(0, addressFormat.checkSumLength * 2)
38
- .toUpperCase();
39
- return calculatedHash == checksum;
40
- }
41
- catch (err) {
42
- return false;
43
- }
44
- }
45
- export default {
46
- isValidAddress(address) {
47
- return verifyChecksum(getAddress(address));
48
- },
49
- };
1
+ import createSS58Validator from './ss58_validator.js';
2
+ // Polkadot uses SS58 address format (Substrate-based)
3
+ // SS58 Registry: https://github.com/paritytech/ss58-registry
4
+ // Accepts any valid SS58 address (no network prefix restriction)
5
+ export default createSS58Validator();
@@ -0,0 +1,11 @@
1
+ import { Validator } from '../types.js';
2
+ interface SS58ValidatorOptions {
3
+ networkPrefix?: number;
4
+ }
5
+ /**
6
+ * Creates an SS58 validator with optional network prefix filtering
7
+ * @param options Configuration options including optional network prefix
8
+ * @returns Validator instance for SS58 addresses
9
+ */
10
+ export default function createSS58Validator(options?: SS58ValidatorOptions): Validator;
11
+ export {};
@@ -0,0 +1,64 @@
1
+ import cryptoUtils from '../crypto/utils.js';
2
+ import { getAddress } from '../helpers.js';
3
+ // SS58 address format (Substrate-based)
4
+ // SS58 Registry: https://github.com/paritytech/ss58-registry
5
+ const addressFormats = [
6
+ { addressLength: 3, accountIndexLength: 1, checkSumLength: 1 },
7
+ { addressLength: 4, accountIndexLength: 2, checkSumLength: 1 },
8
+ { addressLength: 5, accountIndexLength: 2, checkSumLength: 2 },
9
+ { addressLength: 6, accountIndexLength: 4, checkSumLength: 1 },
10
+ { addressLength: 7, accountIndexLength: 4, checkSumLength: 2 },
11
+ { addressLength: 8, accountIndexLength: 4, checkSumLength: 3 },
12
+ { addressLength: 9, accountIndexLength: 4, checkSumLength: 4 },
13
+ { addressLength: 10, accountIndexLength: 8, checkSumLength: 1 },
14
+ { addressLength: 11, accountIndexLength: 8, checkSumLength: 2 },
15
+ { addressLength: 12, accountIndexLength: 8, checkSumLength: 3 },
16
+ { addressLength: 13, accountIndexLength: 8, checkSumLength: 4 },
17
+ { addressLength: 14, accountIndexLength: 8, checkSumLength: 5 },
18
+ { addressLength: 15, accountIndexLength: 8, checkSumLength: 6 },
19
+ { addressLength: 16, accountIndexLength: 8, checkSumLength: 7 },
20
+ { addressLength: 17, accountIndexLength: 8, checkSumLength: 8 },
21
+ { addressLength: 34, accountIndexLength: 32, checkSumLength: 2 },
22
+ ];
23
+ /**
24
+ * Creates an SS58 validator with optional network prefix filtering
25
+ * @param options Configuration options including optional network prefix
26
+ * @returns Validator instance for SS58 addresses
27
+ */
28
+ export default function createSS58Validator(options = {}) {
29
+ function verifyChecksum(address) {
30
+ try {
31
+ const preImage = '53533538505245';
32
+ const decoded = cryptoUtils.base58(address);
33
+ const addressType = cryptoUtils.byteArray2hexStr(decoded.slice(0, 1));
34
+ // If a specific network prefix is required, validate it
35
+ if (options.networkPrefix !== undefined) {
36
+ const expectedPrefix = options.networkPrefix.toString(16).padStart(2, '0').toUpperCase();
37
+ if (addressType.toUpperCase() !== expectedPrefix) {
38
+ return false;
39
+ }
40
+ }
41
+ const addressAndChecksum = decoded.slice(1);
42
+ // get the address format
43
+ const addressFormat = addressFormats.find(af => af.addressLength === addressAndChecksum.length);
44
+ if (!addressFormat) {
45
+ throw new Error('Invalid address length');
46
+ }
47
+ const decodedAddress = cryptoUtils.byteArray2hexStr(addressAndChecksum.slice(0, addressFormat.accountIndexLength));
48
+ const checksum = cryptoUtils.byteArray2hexStr(addressAndChecksum.slice(-addressFormat.checkSumLength));
49
+ const calculatedHash = cryptoUtils
50
+ .blake2b(preImage + addressType + decodedAddress, 64)
51
+ .substr(0, addressFormat.checkSumLength * 2)
52
+ .toUpperCase();
53
+ return calculatedHash == checksum;
54
+ }
55
+ catch (err) {
56
+ return false;
57
+ }
58
+ }
59
+ return {
60
+ isValidAddress(address) {
61
+ return verifyChecksum(getAddress(address));
62
+ },
63
+ };
64
+ }
@@ -0,0 +1,5 @@
1
+ import { Address, NetworkType } from '../types.js';
2
+ declare const _default: (networkType: NetworkType) => {
3
+ isValidAddress(address: Address): boolean;
4
+ };
5
+ export default _default;
@@ -0,0 +1,47 @@
1
+ import base58 from '../crypto/base58.js';
2
+ import cryptoUtils from '../crypto/utils.js';
3
+ import { NetworkType } from '../types.js';
4
+ import { getAddress } from '../helpers.js';
5
+ function getDecoded(address) {
6
+ try {
7
+ return base58.decode(address);
8
+ }
9
+ catch (e) {
10
+ // if decoding fails, assume invalid address
11
+ return null;
12
+ }
13
+ }
14
+ function getChecksum(payload) {
15
+ return cryptoUtils.sha256Checksum(payload);
16
+ }
17
+ function isValidTransparentAddress(address, networkType) {
18
+ // Zcash transparent addresses use 2-byte version prefixes
19
+ // Expected length: 26 bytes (2 bytes version + 20 bytes payload + 4 bytes checksum)
20
+ const expectedLength = 26;
21
+ const decoded = getDecoded(address);
22
+ if (!decoded || decoded.length !== expectedLength) {
23
+ return false;
24
+ }
25
+ const checksum = cryptoUtils.toHex(decoded.slice(expectedLength - 4, expectedLength));
26
+ const body = cryptoUtils.toHex(decoded.slice(0, expectedLength - 4));
27
+ const goodChecksum = getChecksum(body);
28
+ if (checksum !== goodChecksum) {
29
+ return false;
30
+ }
31
+ // Get the 2-byte version prefix
32
+ const versionPrefix = cryptoUtils.toHex(decoded.slice(0, 2));
33
+ // Define valid version prefixes for each network
34
+ // Only supporting transparent addresses (t1/t3 for mainnet, tm/t2 for testnet)
35
+ const validPrefixes = networkType === NetworkType.MainNet
36
+ ? ['1cb8', '1cbd'] // t1 (P2PKH) and t3 (P2SH) for mainnet
37
+ : ['1d25', '1cba']; // tm (P2PKH) and t2 (P2SH) for testnet
38
+ return validPrefixes.includes(versionPrefix);
39
+ }
40
+ export default (networkType) => ({
41
+ isValidAddress(address) {
42
+ const addr = getAddress(address);
43
+ // Only validate transparent addresses (t1/t3 for mainnet, tm/t2 for testnet)
44
+ // Sapling (zs) and Unified (u) addresses are NOT supported
45
+ return isValidTransparentAddress(addr, networkType);
46
+ }
47
+ });