multichain-address-validator 0.8.2 → 0.8.4
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/README.md +1 -0
- package/dist/cjs/chain-validators.js +4 -0
- package/dist/cjs/crypto/base32.d.ts +1 -1
- package/dist/cjs/crypto/utils.d.ts +5 -5
- package/dist/cjs/crypto/utils.js +13 -13
- package/dist/cjs/validators/bch_validator.js +49 -15
- package/dist/cjs/validators/cardano_validator.js +3 -3
- package/dist/cjs/validators/cosmos_validator.d.ts +5 -0
- package/dist/cjs/validators/cosmos_validator.js +17 -0
- package/dist/cjs/validators/index.d.ts +1 -0
- package/dist/cjs/validators/index.js +3 -1
- package/dist/cjs/validators/sia_validator.js +1 -9
- package/dist/cjs/validators/tezos_validator.js +16 -9
- package/dist/cjs/validators/xlm_validator.js +2 -1
- package/dist/esm/chain-validators.js +5 -1
- package/dist/esm/crypto/base32.d.ts +1 -1
- package/dist/esm/crypto/utils.d.ts +5 -5
- package/dist/esm/crypto/utils.js +11 -11
- package/dist/esm/validators/bch_validator.js +49 -15
- package/dist/esm/validators/cardano_validator.js +3 -3
- package/dist/esm/validators/cosmos_validator.d.ts +5 -0
- package/dist/esm/validators/cosmos_validator.js +12 -0
- package/dist/esm/validators/index.d.ts +1 -0
- package/dist/esm/validators/index.js +1 -0
- package/dist/esm/validators/sia_validator.js +1 -9
- package/dist/esm/validators/tezos_validator.js +16 -9
- package/dist/esm/validators/xlm_validator.js +2 -1
- package/package.json +8 -9
- package/dist/cjs/crypto/blake2b.d.ts +0 -13
- package/dist/cjs/crypto/blake2b.js +0 -243
- package/dist/esm/crypto/blake2b.d.ts +0 -13
- package/dist/esm/crypto/blake2b.js +0 -242
package/README.md
CHANGED
|
@@ -30,6 +30,7 @@ npm install multichain-address-validator
|
|
|
30
30
|
* Bitcoin: `bitcoin`, `btc`, `omni`
|
|
31
31
|
* Bitcoin Cash: `bitcoin-cash`, `bitcoincash`, `bitcoin cash`, `bch`
|
|
32
32
|
* Cardano: `cardano`, `ada`
|
|
33
|
+
* Cosmos: `cosmos`, `atom`
|
|
33
34
|
* Dogecoin: `dogecoin`, `doge`
|
|
34
35
|
* EOS: `eos`
|
|
35
36
|
* Etherum: `ethereum`, `eth`, `erc20`, `flare`, `avalanche`, `avalanche-c`, `bsc`, `bnb`, `binance`, `sonic`, `berachain`, `story`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
declare function numberToHex(number: number, length: number): string;
|
|
2
2
|
declare function byteArray2hexStr(byteArray: number[]): string;
|
|
3
|
-
declare function hexStr2byteArray(str: string): Uint8Array
|
|
3
|
+
declare function hexStr2byteArray(str: string): Uint8Array<ArrayBuffer>;
|
|
4
4
|
declare const _default: {
|
|
5
5
|
numberToHex: typeof numberToHex;
|
|
6
6
|
toHex: (arrayOfBytes: any) => string;
|
|
@@ -11,15 +11,15 @@ declare const _default: {
|
|
|
11
11
|
sha512_256: (payload: any, format?: string) => string;
|
|
12
12
|
blake256: (hexString: string) => string;
|
|
13
13
|
blake256Checksum: (payload: any) => any;
|
|
14
|
-
blake2b: (hexString: string, outlen: number) =>
|
|
15
|
-
keccak256: (
|
|
14
|
+
blake2b: (hexString: string, outlen: number) => string;
|
|
15
|
+
keccak256: (input: string | Uint8Array) => string;
|
|
16
16
|
keccak256Checksum: (payload: any) => any;
|
|
17
|
-
blake2b256: (hexString: string) =>
|
|
17
|
+
blake2b256: (hexString: string) => string;
|
|
18
18
|
base58: (string: string) => number[];
|
|
19
19
|
byteArray2hexStr: typeof byteArray2hexStr;
|
|
20
20
|
hexStr2byteArray: typeof hexStr2byteArray;
|
|
21
21
|
base32: {
|
|
22
|
-
b32decode: (s: string) => Uint8Array
|
|
22
|
+
b32decode: (s: string) => Uint8Array<ArrayBuffer>;
|
|
23
23
|
b32encode: (s: string) => string;
|
|
24
24
|
};
|
|
25
25
|
};
|
package/dist/cjs/crypto/utils.js
CHANGED
|
@@ -3,15 +3,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
6
|
+
const sha2_js_1 = require("@noble/hashes/sha2.js");
|
|
7
|
+
const sha2_js_2 = require("@noble/hashes/sha2.js");
|
|
8
|
+
const utils_js_1 = require("@noble/hashes/utils.js");
|
|
9
|
+
const sha3_js_1 = require("@noble/hashes/sha3.js");
|
|
10
|
+
const blake2_js_1 = require("@noble/hashes/blake2.js");
|
|
11
11
|
const base32_js_1 = __importDefault(require("./base32.js"));
|
|
12
12
|
const base58_js_1 = __importDefault(require("./base58.js"));
|
|
13
13
|
const blake256_js_1 = __importDefault(require("./blake256.js"));
|
|
14
|
-
const blake2b_js_1 = __importDefault(require("./blake2b.js"));
|
|
15
14
|
function numberToHex(number, length) {
|
|
16
15
|
let hex = number.toString(16);
|
|
17
16
|
if (hex.length % 2 === 1) {
|
|
@@ -89,7 +88,7 @@ exports.default = {
|
|
|
89
88
|
return hex;
|
|
90
89
|
},
|
|
91
90
|
sha256: function (payload, format = 'HEX') {
|
|
92
|
-
return (0,
|
|
91
|
+
return (0, utils_js_1.bytesToHex)((0, sha2_js_1.sha256)(hexStr2byteArray(payload)));
|
|
93
92
|
},
|
|
94
93
|
sha256x2: function (buffer, format = 'HEX') {
|
|
95
94
|
return this.sha256(this.sha256(buffer, format), format);
|
|
@@ -98,10 +97,10 @@ exports.default = {
|
|
|
98
97
|
return this.sha256(this.sha256(payload)).slice(0, 8);
|
|
99
98
|
},
|
|
100
99
|
sha512: function (payload, format = 'HEX') {
|
|
101
|
-
return (0,
|
|
100
|
+
return (0, utils_js_1.bytesToHex)((0, sha2_js_2.sha512)(payload instanceof Uint8Array ? payload : hexStr2byteArray(payload)));
|
|
102
101
|
},
|
|
103
102
|
sha512_256: function (payload, format = 'HEX') {
|
|
104
|
-
return (0,
|
|
103
|
+
return (0, utils_js_1.bytesToHex)((0, sha2_js_2.sha512_256)(hexStr2byteArray(payload)));
|
|
105
104
|
},
|
|
106
105
|
blake256: function (hexString) {
|
|
107
106
|
return new blake256_js_1.default().update(hexString, 'hex').digest('hex');
|
|
@@ -110,16 +109,17 @@ exports.default = {
|
|
|
110
109
|
return this.blake256(this.blake256(payload)).substr(0, 8);
|
|
111
110
|
},
|
|
112
111
|
blake2b: function (hexString, outlen) {
|
|
113
|
-
return
|
|
112
|
+
return (0, utils_js_1.bytesToHex)((0, blake2_js_1.blake2b)((0, utils_js_1.hexToBytes)(hexString), { dkLen: outlen }));
|
|
114
113
|
},
|
|
115
|
-
keccak256: function (
|
|
116
|
-
|
|
114
|
+
keccak256: function (input) {
|
|
115
|
+
const data = typeof input === 'string' ? new TextEncoder().encode(input) : input;
|
|
116
|
+
return (0, utils_js_1.bytesToHex)((0, sha3_js_1.keccak_256)(data));
|
|
117
117
|
},
|
|
118
118
|
keccak256Checksum: function (payload) {
|
|
119
119
|
return this.keccak256(payload).toString().substr(0, 8);
|
|
120
120
|
},
|
|
121
121
|
blake2b256: function (hexString) {
|
|
122
|
-
return
|
|
122
|
+
return (0, utils_js_1.bytesToHex)((0, blake2_js_1.blake2b)((0, utils_js_1.hexToBytes)(hexString), { dkLen: 32 }));
|
|
123
123
|
},
|
|
124
124
|
base58: base58_js_1.default.decode,
|
|
125
125
|
byteArray2hexStr: byteArray2hexStr,
|
|
@@ -3,53 +3,87 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const utils_js_1 = __importDefault(require("../crypto/utils.js"));
|
|
7
|
-
const bech32_js_1 = __importDefault(require("../crypto/bech32.js"));
|
|
8
6
|
const types_js_1 = require("../types.js");
|
|
9
7
|
const bitcoin_validator_js_1 = __importDefault(require("./bitcoin_validator.js"));
|
|
10
8
|
const helpers_js_1 = require("../helpers.js");
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
|
|
10
|
+
const GENERATOR = [
|
|
11
|
+
0x98f2bc8e61n, 0x79b76d99e2n, 0xf33e5fb3c4n, 0xae2eabe2a8n, 0x1e4f43e470n
|
|
12
|
+
];
|
|
13
|
+
function cashAddrPolymod(values) {
|
|
14
|
+
let chk = 1n;
|
|
15
|
+
for (let i = 0; i < values.length; i++) {
|
|
16
|
+
const top = chk >> 35n;
|
|
17
|
+
chk = ((chk & 0x07ffffffffn) << 5n) ^ BigInt(values[i]);
|
|
18
|
+
for (let j = 0n; j < 5n; j++) {
|
|
19
|
+
if ((top >> j) & 1n) {
|
|
20
|
+
chk ^= GENERATOR[Number(j)];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return chk ^ 1n;
|
|
25
|
+
}
|
|
26
|
+
function prefixExpand(prefix) {
|
|
27
|
+
const ret = [];
|
|
28
|
+
for (let i = 0; i < prefix.length; i++) {
|
|
29
|
+
ret.push(prefix.charCodeAt(i) & 31);
|
|
30
|
+
}
|
|
31
|
+
ret.push(0);
|
|
32
|
+
return ret;
|
|
33
|
+
}
|
|
34
|
+
function verifyCashAddrChecksum(prefix, payload) {
|
|
35
|
+
const expanded = prefixExpand(prefix).concat(payload);
|
|
36
|
+
return cashAddrPolymod(expanded) === 0n;
|
|
37
|
+
}
|
|
38
|
+
function validateCashAddr(address, opts) {
|
|
13
39
|
let raw_address;
|
|
40
|
+
const prefix = opts.networkType === types_js_1.NetworkType.MainNet
|
|
41
|
+
? 'bitcoincash'
|
|
42
|
+
: 'bchtest';
|
|
14
43
|
const res = address.split(':');
|
|
15
44
|
if (res.length === 1) {
|
|
16
45
|
raw_address = address;
|
|
17
46
|
}
|
|
18
47
|
else {
|
|
19
|
-
if (res[0] !==
|
|
48
|
+
if (res[0] !== prefix) {
|
|
20
49
|
return false;
|
|
21
50
|
}
|
|
22
51
|
raw_address = res[1];
|
|
23
52
|
}
|
|
53
|
+
const regexp = new RegExp(opts.regexp);
|
|
24
54
|
if (!regexp.test(raw_address)) {
|
|
25
55
|
return false;
|
|
26
56
|
}
|
|
27
|
-
if (raw_address.toLowerCase()
|
|
57
|
+
if (raw_address.toLowerCase() !== raw_address && raw_address.toUpperCase() !== raw_address) {
|
|
28
58
|
return false;
|
|
29
59
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
60
|
+
raw_address = raw_address.toLowerCase();
|
|
61
|
+
// Decode characters using the bech32/CashAddr charset
|
|
62
|
+
const data = [];
|
|
63
|
+
for (const c of raw_address) {
|
|
64
|
+
const d = CHARSET.indexOf(c);
|
|
65
|
+
if (d === -1) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
data.push(d);
|
|
69
|
+
}
|
|
34
70
|
try {
|
|
35
|
-
if (
|
|
71
|
+
if (!verifyCashAddrChecksum(prefix, data)) {
|
|
36
72
|
return false;
|
|
37
73
|
}
|
|
38
74
|
}
|
|
39
|
-
catch
|
|
75
|
+
catch {
|
|
40
76
|
return false;
|
|
41
77
|
}
|
|
42
78
|
return true;
|
|
43
79
|
}
|
|
44
80
|
const DefaultBCHValidatorOpts = {
|
|
45
|
-
// addressTypes: {mainnet: ['00', '05'], testnet: ['6f', 'c4', '3c', '26']},
|
|
46
|
-
// bech32Hrp: {mainnet: ['bc'], testnet: ['tb']},
|
|
47
81
|
regexp: /^[qQpP][0-9a-zA-Z]{41}$/,
|
|
48
82
|
};
|
|
49
83
|
exports.default = (opts) => ({
|
|
50
84
|
isValidAddress: function (address) {
|
|
51
85
|
const addr = (0, helpers_js_1.getAddress)(address);
|
|
52
86
|
const _opts = { ...DefaultBCHValidatorOpts, ...opts };
|
|
53
|
-
return
|
|
87
|
+
return validateCashAddr(addr, _opts) || (0, bitcoin_validator_js_1.default)(opts).isValidAddress(address);
|
|
54
88
|
}
|
|
55
89
|
});
|
|
@@ -20,7 +20,7 @@ function getDecoded(address) {
|
|
|
20
20
|
}
|
|
21
21
|
function isValidAddressV1(address) {
|
|
22
22
|
const decoded = getDecoded(address);
|
|
23
|
-
if (!decoded ||
|
|
23
|
+
if (!decoded || !Array.isArray(decoded) || decoded.length !== 2) {
|
|
24
24
|
return false;
|
|
25
25
|
}
|
|
26
26
|
const tagged = decoded[0];
|
|
@@ -30,7 +30,7 @@ function isValidAddressV1(address) {
|
|
|
30
30
|
}
|
|
31
31
|
// get crc of the payload
|
|
32
32
|
const crc = crc_1.default.crc32(tagged);
|
|
33
|
-
return crc
|
|
33
|
+
return crc === validCrc;
|
|
34
34
|
}
|
|
35
35
|
function isValidAddressShelley(address, opts) {
|
|
36
36
|
// shelley address are just bip 173 - bech32 addresses (https://cips.cardano.org/cips/cip4/)
|
|
@@ -39,7 +39,7 @@ function isValidAddressShelley(address, opts) {
|
|
|
39
39
|
exports.default = {
|
|
40
40
|
isValidAddress(address) {
|
|
41
41
|
const addr = (0, helpers_js_1.getAddress)(address);
|
|
42
|
-
return isValidAddressV1(
|
|
42
|
+
return isValidAddressV1(addr) || isValidAddressShelley(addr, {
|
|
43
43
|
bech32Hrp: ['addr']
|
|
44
44
|
});
|
|
45
45
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const bip173_validator_js_1 = __importDefault(require("./bip173_validator.js"));
|
|
7
|
+
const helpers_js_1 = require("../helpers.js");
|
|
8
|
+
// Cosmos uses Bech32 encoding with 'cosmos' as the HRP (Human Readable Part)
|
|
9
|
+
// Mainnet addresses start with 'cosmos1'
|
|
10
|
+
exports.default = {
|
|
11
|
+
isValidAddress(address) {
|
|
12
|
+
const addr = (0, helpers_js_1.getAddress)(address);
|
|
13
|
+
return bip173_validator_js_1.default.isValidAddress(addr, {
|
|
14
|
+
bech32Hrp: ['cosmos']
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
};
|
|
@@ -3,6 +3,7 @@ export { default as BCHValidator } from "./bch_validator.js";
|
|
|
3
3
|
export { default as BittensorValidator } from "./bittensor_validator.js";
|
|
4
4
|
export { default as BTCValidator } from "./bitcoin_validator.js";
|
|
5
5
|
export { default as CardanoValidator } from "./cardano_validator.js";
|
|
6
|
+
export { default as CosmosValidator } from "./cosmos_validator.js";
|
|
6
7
|
export { default as EOSValidator } from "./eos_validator.js";
|
|
7
8
|
export { default as ETHValidator } from "./ethereum_validator.js";
|
|
8
9
|
export { default as HederaValidator } from "./hedera_validator.js";
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.ZcashValidator = exports.XLMValidator = exports.TronValidator = exports.TezosValidator = exports.SolanaValidator = exports.SiaValidator = exports.RippleValidator = exports.PolkadotValidator = exports.NanoValidator = exports.NemValidator = exports.MoveValidator = exports.MoneroValidator = exports.HederaValidator = exports.ETHValidator = exports.EOSValidator = exports.CardanoValidator = exports.BTCValidator = exports.BittensorValidator = exports.BCHValidator = exports.AlgorandValidator = void 0;
|
|
6
|
+
exports.ZcashValidator = exports.XLMValidator = exports.TronValidator = exports.TezosValidator = exports.SolanaValidator = exports.SiaValidator = exports.RippleValidator = exports.PolkadotValidator = exports.NanoValidator = exports.NemValidator = exports.MoveValidator = exports.MoneroValidator = exports.HederaValidator = exports.ETHValidator = exports.EOSValidator = exports.CosmosValidator = exports.CardanoValidator = exports.BTCValidator = exports.BittensorValidator = exports.BCHValidator = exports.AlgorandValidator = void 0;
|
|
7
7
|
var algorand_validator_js_1 = require("./algorand_validator.js");
|
|
8
8
|
Object.defineProperty(exports, "AlgorandValidator", { enumerable: true, get: function () { return __importDefault(algorand_validator_js_1).default; } });
|
|
9
9
|
var bch_validator_js_1 = require("./bch_validator.js");
|
|
@@ -14,6 +14,8 @@ var bitcoin_validator_js_1 = require("./bitcoin_validator.js");
|
|
|
14
14
|
Object.defineProperty(exports, "BTCValidator", { enumerable: true, get: function () { return __importDefault(bitcoin_validator_js_1).default; } });
|
|
15
15
|
var cardano_validator_js_1 = require("./cardano_validator.js");
|
|
16
16
|
Object.defineProperty(exports, "CardanoValidator", { enumerable: true, get: function () { return __importDefault(cardano_validator_js_1).default; } });
|
|
17
|
+
var cosmos_validator_js_1 = require("./cosmos_validator.js");
|
|
18
|
+
Object.defineProperty(exports, "CosmosValidator", { enumerable: true, get: function () { return __importDefault(cosmos_validator_js_1).default; } });
|
|
17
19
|
var eos_validator_js_1 = require("./eos_validator.js");
|
|
18
20
|
Object.defineProperty(exports, "EOSValidator", { enumerable: true, get: function () { return __importDefault(eos_validator_js_1).default; } });
|
|
19
21
|
var ethereum_validator_js_1 = require("./ethereum_validator.js");
|
|
@@ -3,21 +3,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const lodash_isequal_1 = __importDefault(require("lodash.isequal"));
|
|
7
6
|
const utils_js_1 = __importDefault(require("../crypto/utils.js"));
|
|
8
7
|
const helpers_js_1 = require("../helpers.js");
|
|
9
|
-
function hexToBytes(hex) {
|
|
10
|
-
const bytes = [];
|
|
11
|
-
for (let c = 0; c < hex.length; c += 2) {
|
|
12
|
-
bytes.push(parseInt(hex.substr(c, 2), 16));
|
|
13
|
-
}
|
|
14
|
-
return bytes;
|
|
15
|
-
}
|
|
16
8
|
function verifyChecksum(address) {
|
|
17
9
|
const checksumBytes = address.slice(0, 32 * 2);
|
|
18
10
|
const check = address.slice(32 * 2, 38 * 2);
|
|
19
11
|
const blakeHash = utils_js_1.default.blake2b(checksumBytes, 32).slice(0, 6 * 2);
|
|
20
|
-
return
|
|
12
|
+
return blakeHash === check;
|
|
21
13
|
}
|
|
22
14
|
exports.default = {
|
|
23
15
|
isValidAddress: function (address) {
|
|
@@ -6,11 +6,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const base58_js_1 = __importDefault(require("../crypto/base58.js"));
|
|
7
7
|
const utils_js_1 = __importDefault(require("../crypto/utils.js"));
|
|
8
8
|
const helpers_js_1 = require("../helpers.js");
|
|
9
|
-
const
|
|
9
|
+
const VALID_PREFIXES = [
|
|
10
|
+
[6, 161, 159], // tz1 (ed25519)
|
|
11
|
+
[6, 161, 161], // tz2 (secp256k1)
|
|
12
|
+
[6, 161, 164], // tz3 (p256)
|
|
13
|
+
[2, 90, 121], // KT1 (originated)
|
|
14
|
+
];
|
|
10
15
|
function decodeRaw(buffer) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
const payload = buffer.slice(0, -4);
|
|
17
|
+
const checksum = buffer.slice(-4);
|
|
18
|
+
const newChecksum = utils_js_1.default.hexStr2byteArray(utils_js_1.default.sha256x2(utils_js_1.default.byteArray2hexStr(payload)));
|
|
14
19
|
if (checksum[0] ^ newChecksum[0] |
|
|
15
20
|
checksum[1] ^ newChecksum[1] |
|
|
16
21
|
checksum[2] ^ newChecksum[2] |
|
|
@@ -18,17 +23,19 @@ function decodeRaw(buffer) {
|
|
|
18
23
|
return;
|
|
19
24
|
return payload;
|
|
20
25
|
}
|
|
26
|
+
function hasValidPrefix(payload) {
|
|
27
|
+
return VALID_PREFIXES.some(prefix => prefix.every((byte, i) => payload[i] === byte));
|
|
28
|
+
}
|
|
21
29
|
exports.default = {
|
|
22
30
|
isValidAddress(address) {
|
|
23
31
|
try {
|
|
24
|
-
|
|
25
|
-
|
|
32
|
+
const buffer = base58_js_1.default.decode((0, helpers_js_1.getAddress)(address));
|
|
33
|
+
const payload = decodeRaw(buffer);
|
|
26
34
|
if (!payload)
|
|
27
35
|
return false;
|
|
28
|
-
payload
|
|
29
|
-
return true;
|
|
36
|
+
return hasValidPrefix(payload);
|
|
30
37
|
}
|
|
31
|
-
catch
|
|
38
|
+
catch {
|
|
32
39
|
return false;
|
|
33
40
|
}
|
|
34
41
|
}
|
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const base_x_1 = __importDefault(require("base-x"));
|
|
7
|
+
const buffer_1 = require("buffer");
|
|
7
8
|
const crc_1 = __importDefault(require("crc"));
|
|
8
9
|
const utils_js_1 = __importDefault(require("../crypto/utils.js"));
|
|
9
10
|
const helpers_js_1 = require("../helpers.js");
|
|
@@ -39,7 +40,7 @@ exports.default = {
|
|
|
39
40
|
if (bytes[0] !== ed25519PublicKeyVersionByte) {
|
|
40
41
|
return false;
|
|
41
42
|
}
|
|
42
|
-
const computedChecksum = utils_js_1.default.numberToHex(swap16(crc_1.default.crc16xmodem(bytes.slice(0, -2))), 4);
|
|
43
|
+
const computedChecksum = utils_js_1.default.numberToHex(swap16(crc_1.default.crc16xmodem(buffer_1.Buffer.from(bytes.slice(0, -2)))), 4);
|
|
43
44
|
const checksum = utils_js_1.default.toHex(bytes.slice(-2));
|
|
44
45
|
return computedChecksum === checksum;
|
|
45
46
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NetworkType } from './types.js';
|
|
2
|
-
import { AlgorandValidator, BCHValidator, BittensorValidator, BTCValidator, CardanoValidator, EOSValidator, ETHValidator, HederaValidator, MoneroValidator, MoveValidator, NanoValidator, NemValidator, PolkadotValidator, RippleValidator, SiaValidator, SolanaValidator, TezosValidator, TronValidator, XLMValidator, ZcashValidator, } from './validators/index.js';
|
|
2
|
+
import { AlgorandValidator, BCHValidator, BittensorValidator, BTCValidator, CardanoValidator, CosmosValidator, EOSValidator, ETHValidator, HederaValidator, MoneroValidator, MoveValidator, NanoValidator, NemValidator, PolkadotValidator, RippleValidator, SiaValidator, SolanaValidator, TezosValidator, TronValidator, XLMValidator, ZcashValidator, } from './validators/index.js';
|
|
3
3
|
import { SegwitVersion } from './validators/bitcoin_validator';
|
|
4
4
|
const chainValidators = {
|
|
5
5
|
algorand: { validator: AlgorandValidator },
|
|
@@ -42,6 +42,10 @@ const chainValidators = {
|
|
|
42
42
|
alternatives: ['ada'],
|
|
43
43
|
validator: CardanoValidator,
|
|
44
44
|
},
|
|
45
|
+
cosmos: {
|
|
46
|
+
alternatives: ['atom'],
|
|
47
|
+
validator: CosmosValidator,
|
|
48
|
+
},
|
|
45
49
|
doge: {
|
|
46
50
|
alternatives: ['dogecoin'],
|
|
47
51
|
validator: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
declare function numberToHex(number: number, length: number): string;
|
|
2
2
|
declare function byteArray2hexStr(byteArray: number[]): string;
|
|
3
|
-
declare function hexStr2byteArray(str: string): Uint8Array
|
|
3
|
+
declare function hexStr2byteArray(str: string): Uint8Array<ArrayBuffer>;
|
|
4
4
|
declare const _default: {
|
|
5
5
|
numberToHex: typeof numberToHex;
|
|
6
6
|
toHex: (arrayOfBytes: any) => string;
|
|
@@ -11,15 +11,15 @@ declare const _default: {
|
|
|
11
11
|
sha512_256: (payload: any, format?: string) => string;
|
|
12
12
|
blake256: (hexString: string) => string;
|
|
13
13
|
blake256Checksum: (payload: any) => any;
|
|
14
|
-
blake2b: (hexString: string, outlen: number) =>
|
|
15
|
-
keccak256: (
|
|
14
|
+
blake2b: (hexString: string, outlen: number) => string;
|
|
15
|
+
keccak256: (input: string | Uint8Array) => string;
|
|
16
16
|
keccak256Checksum: (payload: any) => any;
|
|
17
|
-
blake2b256: (hexString: string) =>
|
|
17
|
+
blake2b256: (hexString: string) => string;
|
|
18
18
|
base58: (string: string) => number[];
|
|
19
19
|
byteArray2hexStr: typeof byteArray2hexStr;
|
|
20
20
|
hexStr2byteArray: typeof hexStr2byteArray;
|
|
21
21
|
base32: {
|
|
22
|
-
b32decode: (s: string) => Uint8Array
|
|
22
|
+
b32decode: (s: string) => Uint8Array<ArrayBuffer>;
|
|
23
23
|
b32encode: (s: string) => string;
|
|
24
24
|
};
|
|
25
25
|
};
|
package/dist/esm/crypto/utils.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
2
|
+
import { sha512, sha512_256 } from '@noble/hashes/sha2.js';
|
|
3
|
+
import { bytesToHex, hexToBytes } from '@noble/hashes/utils.js';
|
|
4
|
+
import { keccak_256 } from '@noble/hashes/sha3.js';
|
|
5
|
+
import { blake2b as nobleBlake2b } from '@noble/hashes/blake2.js';
|
|
6
6
|
import base32 from './base32.js';
|
|
7
7
|
import base58 from './base58.js';
|
|
8
8
|
import Blake256 from './blake256.js';
|
|
9
|
-
import Blake2B from './blake2b.js';
|
|
10
9
|
function numberToHex(number, length) {
|
|
11
10
|
let hex = number.toString(16);
|
|
12
11
|
if (hex.length % 2 === 1) {
|
|
@@ -93,7 +92,7 @@ export default {
|
|
|
93
92
|
return this.sha256(this.sha256(payload)).slice(0, 8);
|
|
94
93
|
},
|
|
95
94
|
sha512: function (payload, format = 'HEX') {
|
|
96
|
-
return bytesToHex(sha512(payload));
|
|
95
|
+
return bytesToHex(sha512(payload instanceof Uint8Array ? payload : hexStr2byteArray(payload)));
|
|
97
96
|
},
|
|
98
97
|
sha512_256: function (payload, format = 'HEX') {
|
|
99
98
|
return bytesToHex(sha512_256(hexStr2byteArray(payload)));
|
|
@@ -105,16 +104,17 @@ export default {
|
|
|
105
104
|
return this.blake256(this.blake256(payload)).substr(0, 8);
|
|
106
105
|
},
|
|
107
106
|
blake2b: function (hexString, outlen) {
|
|
108
|
-
return
|
|
107
|
+
return bytesToHex(nobleBlake2b(hexToBytes(hexString), { dkLen: outlen }));
|
|
109
108
|
},
|
|
110
|
-
keccak256: function (
|
|
111
|
-
|
|
109
|
+
keccak256: function (input) {
|
|
110
|
+
const data = typeof input === 'string' ? new TextEncoder().encode(input) : input;
|
|
111
|
+
return bytesToHex(keccak_256(data));
|
|
112
112
|
},
|
|
113
113
|
keccak256Checksum: function (payload) {
|
|
114
114
|
return this.keccak256(payload).toString().substr(0, 8);
|
|
115
115
|
},
|
|
116
116
|
blake2b256: function (hexString) {
|
|
117
|
-
return
|
|
117
|
+
return bytesToHex(nobleBlake2b(hexToBytes(hexString), { dkLen: 32 }));
|
|
118
118
|
},
|
|
119
119
|
base58: base58.decode,
|
|
120
120
|
byteArray2hexStr: byteArray2hexStr,
|
|
@@ -1,50 +1,84 @@
|
|
|
1
|
-
import cryptoUtils from '../crypto/utils.js';
|
|
2
|
-
import bech32 from '../crypto/bech32.js';
|
|
3
1
|
import { NetworkType } from '../types.js';
|
|
4
2
|
import BTCValidator from './bitcoin_validator.js';
|
|
5
3
|
import { getAddress } from '../helpers.js';
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
const CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
|
|
5
|
+
const GENERATOR = [
|
|
6
|
+
0x98f2bc8e61n, 0x79b76d99e2n, 0xf33e5fb3c4n, 0xae2eabe2a8n, 0x1e4f43e470n
|
|
7
|
+
];
|
|
8
|
+
function cashAddrPolymod(values) {
|
|
9
|
+
let chk = 1n;
|
|
10
|
+
for (let i = 0; i < values.length; i++) {
|
|
11
|
+
const top = chk >> 35n;
|
|
12
|
+
chk = ((chk & 0x07ffffffffn) << 5n) ^ BigInt(values[i]);
|
|
13
|
+
for (let j = 0n; j < 5n; j++) {
|
|
14
|
+
if ((top >> j) & 1n) {
|
|
15
|
+
chk ^= GENERATOR[Number(j)];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return chk ^ 1n;
|
|
20
|
+
}
|
|
21
|
+
function prefixExpand(prefix) {
|
|
22
|
+
const ret = [];
|
|
23
|
+
for (let i = 0; i < prefix.length; i++) {
|
|
24
|
+
ret.push(prefix.charCodeAt(i) & 31);
|
|
25
|
+
}
|
|
26
|
+
ret.push(0);
|
|
27
|
+
return ret;
|
|
28
|
+
}
|
|
29
|
+
function verifyCashAddrChecksum(prefix, payload) {
|
|
30
|
+
const expanded = prefixExpand(prefix).concat(payload);
|
|
31
|
+
return cashAddrPolymod(expanded) === 0n;
|
|
32
|
+
}
|
|
33
|
+
function validateCashAddr(address, opts) {
|
|
8
34
|
let raw_address;
|
|
35
|
+
const prefix = opts.networkType === NetworkType.MainNet
|
|
36
|
+
? 'bitcoincash'
|
|
37
|
+
: 'bchtest';
|
|
9
38
|
const res = address.split(':');
|
|
10
39
|
if (res.length === 1) {
|
|
11
40
|
raw_address = address;
|
|
12
41
|
}
|
|
13
42
|
else {
|
|
14
|
-
if (res[0] !==
|
|
43
|
+
if (res[0] !== prefix) {
|
|
15
44
|
return false;
|
|
16
45
|
}
|
|
17
46
|
raw_address = res[1];
|
|
18
47
|
}
|
|
48
|
+
const regexp = new RegExp(opts.regexp);
|
|
19
49
|
if (!regexp.test(raw_address)) {
|
|
20
50
|
return false;
|
|
21
51
|
}
|
|
22
|
-
if (raw_address.toLowerCase()
|
|
52
|
+
if (raw_address.toLowerCase() !== raw_address && raw_address.toUpperCase() !== raw_address) {
|
|
23
53
|
return false;
|
|
24
54
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
55
|
+
raw_address = raw_address.toLowerCase();
|
|
56
|
+
// Decode characters using the bech32/CashAddr charset
|
|
57
|
+
const data = [];
|
|
58
|
+
for (const c of raw_address) {
|
|
59
|
+
const d = CHARSET.indexOf(c);
|
|
60
|
+
if (d === -1) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
data.push(d);
|
|
64
|
+
}
|
|
29
65
|
try {
|
|
30
|
-
if (
|
|
66
|
+
if (!verifyCashAddrChecksum(prefix, data)) {
|
|
31
67
|
return false;
|
|
32
68
|
}
|
|
33
69
|
}
|
|
34
|
-
catch
|
|
70
|
+
catch {
|
|
35
71
|
return false;
|
|
36
72
|
}
|
|
37
73
|
return true;
|
|
38
74
|
}
|
|
39
75
|
const DefaultBCHValidatorOpts = {
|
|
40
|
-
// addressTypes: {mainnet: ['00', '05'], testnet: ['6f', 'c4', '3c', '26']},
|
|
41
|
-
// bech32Hrp: {mainnet: ['bc'], testnet: ['tb']},
|
|
42
76
|
regexp: /^[qQpP][0-9a-zA-Z]{41}$/,
|
|
43
77
|
};
|
|
44
78
|
export default (opts) => ({
|
|
45
79
|
isValidAddress: function (address) {
|
|
46
80
|
const addr = getAddress(address);
|
|
47
81
|
const _opts = { ...DefaultBCHValidatorOpts, ...opts };
|
|
48
|
-
return
|
|
82
|
+
return validateCashAddr(addr, _opts) || BTCValidator(opts).isValidAddress(address);
|
|
49
83
|
}
|
|
50
84
|
});
|
|
@@ -15,7 +15,7 @@ function getDecoded(address) {
|
|
|
15
15
|
}
|
|
16
16
|
function isValidAddressV1(address) {
|
|
17
17
|
const decoded = getDecoded(address);
|
|
18
|
-
if (!decoded ||
|
|
18
|
+
if (!decoded || !Array.isArray(decoded) || decoded.length !== 2) {
|
|
19
19
|
return false;
|
|
20
20
|
}
|
|
21
21
|
const tagged = decoded[0];
|
|
@@ -25,7 +25,7 @@ function isValidAddressV1(address) {
|
|
|
25
25
|
}
|
|
26
26
|
// get crc of the payload
|
|
27
27
|
const crc = CRC.crc32(tagged);
|
|
28
|
-
return crc
|
|
28
|
+
return crc === validCrc;
|
|
29
29
|
}
|
|
30
30
|
function isValidAddressShelley(address, opts) {
|
|
31
31
|
// shelley address are just bip 173 - bech32 addresses (https://cips.cardano.org/cips/cip4/)
|
|
@@ -34,7 +34,7 @@ function isValidAddressShelley(address, opts) {
|
|
|
34
34
|
export default {
|
|
35
35
|
isValidAddress(address) {
|
|
36
36
|
const addr = getAddress(address);
|
|
37
|
-
return isValidAddressV1(
|
|
37
|
+
return isValidAddressV1(addr) || isValidAddressShelley(addr, {
|
|
38
38
|
bech32Hrp: ['addr']
|
|
39
39
|
});
|
|
40
40
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import BIP173Validator from './bip173_validator.js';
|
|
2
|
+
import { getAddress } from '../helpers.js';
|
|
3
|
+
// Cosmos uses Bech32 encoding with 'cosmos' as the HRP (Human Readable Part)
|
|
4
|
+
// Mainnet addresses start with 'cosmos1'
|
|
5
|
+
export default {
|
|
6
|
+
isValidAddress(address) {
|
|
7
|
+
const addr = getAddress(address);
|
|
8
|
+
return BIP173Validator.isValidAddress(addr, {
|
|
9
|
+
bech32Hrp: ['cosmos']
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
};
|