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.
- package/dist/cjs/chain-validators.js +21 -1
- package/dist/cjs/crypto/segwit_addr.js +8 -3
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +2 -1
- package/dist/cjs/validators/bitcoin_validator.d.ts +5 -0
- package/dist/cjs/validators/bitcoin_validator.js +6 -5
- package/dist/cjs/validators/bittensor_validator.d.ts +2 -0
- package/dist/cjs/validators/bittensor_validator.js +11 -0
- package/dist/cjs/validators/index.d.ts +2 -0
- package/dist/cjs/validators/index.js +5 -1
- package/dist/cjs/validators/polkadot_validator.d.ts +1 -4
- package/dist/cjs/validators/polkadot_validator.js +5 -49
- package/dist/cjs/validators/ss58_validator.d.ts +11 -0
- package/dist/cjs/validators/ss58_validator.js +70 -0
- package/dist/cjs/validators/zcash_validator.d.ts +5 -0
- package/dist/cjs/validators/zcash_validator.js +52 -0
- package/dist/esm/chain-validators.js +22 -2
- package/dist/esm/crypto/segwit_addr.js +8 -3
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +2 -1
- package/dist/esm/validators/bitcoin_validator.d.ts +5 -0
- package/dist/esm/validators/bitcoin_validator.js +5 -5
- package/dist/esm/validators/bittensor_validator.d.ts +2 -0
- package/dist/esm/validators/bittensor_validator.js +6 -0
- package/dist/esm/validators/index.d.ts +2 -0
- package/dist/esm/validators/index.js +2 -0
- package/dist/esm/validators/polkadot_validator.d.ts +1 -4
- package/dist/esm/validators/polkadot_validator.js +5 -49
- package/dist/esm/validators/ss58_validator.d.ts +11 -0
- package/dist/esm/validators/ss58_validator.js +64 -0
- package/dist/esm/validators/zcash_validator.d.ts +5 -0
- package/dist/esm/validators/zcash_validator.js +47 -0
- package/package-lock.json +1705 -0
- package/package.json +1 -1
- package/src/chain-validators.ts +23 -1
- package/src/crypto/segwit_addr.js +9 -3
- package/src/index.ts +2 -1
- package/src/validators/bitcoin_validator.ts +5 -6
- package/src/validators/bittensor_validator.ts +8 -0
- package/src/validators/index.ts +2 -0
- package/src/validators/polkadot_validator.ts +5 -55
- package/src/validators/ss58_validator.ts +80 -0
- package/src/validators/zcash_validator.ts +57 -0
- package/test/addresses/addresses.ts +4 -0
- package/test/addresses/bittensor.json +27 -0
- package/test/addresses/btc-testnet.json +1 -0
- package/test/addresses/btc.json +5 -1
- package/test/addresses/ltc.json +1 -0
- package/test/addresses/zcash.json +8 -0
- package/test/multichain-address-validator.test.ts +18 -1
|
@@ -1,49 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
|
|
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,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
|
+
});
|