@chainflip/bitcoin 1.0.2 → 1.1.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.
package/dist/index.cjs CHANGED
@@ -1,8 +1,7 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } }// src/index.ts
2
2
  var _assertion = require('@chainflip/utils/assertion');
3
- var _base58 = require('@chainflip/utils/base58'); var base58 = _interopRequireWildcard(_base58);
4
3
  var _bytes = require('@chainflip/utils/bytes');
5
- var _sha256 = require('@noble/hashes/sha256');
4
+ var _bitcoinjslib = require('bitcoinjs-lib'); var bitcoin = _interopRequireWildcard(_bitcoinjslib);
6
5
  var p2pkhAddressVersion = {
7
6
  mainnet: 0,
8
7
  testnet: 111,
@@ -18,170 +17,11 @@ var networkHrp = {
18
17
  testnet: "tb",
19
18
  regtest: "bcrt"
20
19
  };
21
- function parseBase58Address(address, network) {
22
- const checksumLength = 4;
23
- const payloadLength = 21;
24
- const data = base58.decode(address);
25
- if (data.length !== payloadLength + checksumLength)
26
- return null;
27
- const payload = data.slice(0, payloadLength);
28
- const checksum = data.slice(-checksumLength);
29
- const computedChecksum = _sha256.sha256.call(void 0, _sha256.sha256.call(void 0, payload)).slice(0, checksumLength);
30
- if (!computedChecksum.every((byte, i) => byte === checksum[i]))
31
- return null;
32
- const [version, ...hash] = payload;
33
- if (version === p2pkhAddressVersion[network]) {
34
- return { type: "p2pkh", hash };
35
- }
36
- if (version === p2shAddressVersion[network]) {
37
- return { type: "p2sh", hash };
38
- }
39
- return null;
40
- }
41
- function encodeBase58Address(data, network, type) {
42
- const version = (type === "P2SH" ? p2shAddressVersion : p2pkhAddressVersion)[network];
43
- const payload = new Uint8Array([
44
- version,
45
- ...typeof data === "string" ? _bytes.hexToBytes.call(void 0, data) : data
46
- ]);
47
- const checksum = _sha256.sha256.call(void 0, _sha256.sha256.call(void 0, payload)).slice(0, 4);
48
- const address = base58.encode(Buffer.concat([payload, checksum]));
49
- return address;
50
- }
51
- var BECH32_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
52
- function decodeBech32(address) {
53
- const pos = address.lastIndexOf("1");
54
- if (pos === -1 || pos === 0 || pos + 7 > address.length) {
55
- return null;
56
- }
57
- const hrp = address.substring(0, pos);
58
- const data = [];
59
- for (let i = pos + 1; i < address.length; i++) {
60
- const charIndex = BECH32_CHARSET.indexOf(address[i]);
61
- if (charIndex === -1)
62
- return null;
63
- data.push(charIndex);
64
- }
65
- return { hrp, data };
66
- }
67
- function polymod(values) {
68
- const generators = [996825010, 642813549, 513874426, 1027748829, 705979059];
69
- let chk = 1;
70
- for (const value of values) {
71
- const top = chk >> 25;
72
- chk = (chk & 33554431) << 5 ^ value;
73
- for (let i = 0; i < 5; i++) {
74
- if (top >> i & 1) {
75
- chk ^= generators[i];
76
- }
77
- }
78
- }
79
- return chk;
80
- }
81
- function hrpExpand(hrp) {
82
- const ret = [];
83
- for (let i = 0; i < hrp.length; i++) {
84
- ret.push(hrp.charCodeAt(i) >> 5);
85
- }
86
- ret.push(0);
87
- for (let i = 0; i < hrp.length; i++) {
88
- ret.push(hrp.charCodeAt(i) & 31);
89
- }
90
- return ret;
91
- }
92
- function computeChecksum(hrp, data) {
93
- return polymod(hrpExpand(hrp).concat(data));
94
- }
95
- var checksums = {
96
- bech32: 1,
97
- bech32m: 734539939
98
- };
99
- function convert5BitGroupsToBytes(data) {
100
- let acc = 0;
101
- let bits = 0;
102
- const result = [];
103
- for (let i = 0; i < data.length; i++) {
104
- acc = acc << 5 | data[i];
105
- bits += 5;
106
- if (bits >= 8) {
107
- result.push(acc >> bits - 8 & 255);
108
- bits -= 8;
109
- }
110
- }
111
- if (bits > 0) {
112
- const remainingByte = acc << 8 - bits & 255;
113
- if (remainingByte !== 0 || bits > 5) {
114
- result.push(remainingByte);
115
- }
116
- }
117
- return new Uint8Array(result);
118
- }
119
- function decodeSegwitAddress(address) {
120
- const decoded = decodeBech32(address.toLowerCase());
121
- if (!decoded) {
122
- return null;
123
- }
124
- const { hrp, data: dataWithChecksum } = decoded;
125
- const checksum = computeChecksum(hrp, dataWithChecksum);
126
- let type;
127
- if (checksum === 1) {
128
- type = "bech32";
129
- } else if (checksum === 734539939) {
130
- type = "bech32m";
131
- } else {
132
- return null;
133
- }
134
- const data = convert5BitGroupsToBytes(dataWithChecksum.slice(1, -6));
135
- const [version] = dataWithChecksum;
136
- _assertion.assert.call(void 0, data.length >= 2 && data.length <= 40, "Invalid address");
137
- _assertion.assert.call(void 0, version !== 0 || data.length === 20 || data.length === 32, "Invalid address");
138
- return { hrp, data, type, version };
139
- }
140
- function createChecksum(hrp, data, variant) {
141
- const values = hrpExpand(hrp).concat(data).concat([0, 0, 0, 0, 0, 0]);
142
- const polymodValue = polymod(values) ^ checksums[variant];
143
- const checksum = [];
144
- for (let i = 0; i < 6; i++) {
145
- checksum.push(polymodValue >> 5 * (5 - i) & 31);
146
- }
147
- return checksum;
148
- }
149
- function encodeBech32(hrp, data) {
150
- return `${hrp}1${data.map((i) => BECH32_CHARSET[i]).join("")}`;
151
- }
152
- function convertBytesTo5BitGroups(data) {
153
- let acc = 0;
154
- let bits = 0;
155
- const result = [];
156
- for (let i = 0; i < data.length; i++) {
157
- acc = acc << 8 | data[i];
158
- bits += 8;
159
- while (bits >= 5) {
160
- result.push(acc >> bits - 5 & 31);
161
- bits -= 5;
162
- }
163
- }
164
- if (bits > 0) {
165
- result.push(acc << 5 - bits & 31);
166
- }
167
- return result;
168
- }
169
20
  var segwitVersions = {
170
21
  P2WPKH: 0,
171
22
  P2WSH: 0,
172
23
  Taproot: 1
173
24
  };
174
- function encodeSegwitAddress(byteData, kind, network) {
175
- const variant = kind === "Taproot" ? "bech32m" : "bech32";
176
- const bytes = typeof byteData === "string" ? _bytes.hexToBytes.call(void 0, byteData) : new Uint8Array(byteData);
177
- const version = segwitVersions[kind];
178
- _assertion.assert.call(void 0, bytes.length >= 2 && bytes.length <= 40, "Invalid address");
179
- _assertion.assert.call(void 0, version !== 0 || bytes.length === 20 || bytes.length === 32, "Invalid address");
180
- const data = [segwitVersions[kind]].concat(convertBytesTo5BitGroups(bytes));
181
- const hrp = networkHrp[network];
182
- const checksum = createChecksum(hrp, data, variant);
183
- return encodeBech32(hrp, data.concat(checksum));
184
- }
185
25
  var networkMap = {
186
26
  mainnet: "mainnet",
187
27
  perseverance: "testnet",
@@ -190,6 +30,7 @@ var networkMap = {
190
30
  backspin: "regtest",
191
31
  regtest: "regtest"
192
32
  };
33
+ var byteLikeToUint8Array = (data) => typeof data === "string" ? _bytes.hexToBytes.call(void 0, data) : new Uint8Array(data);
193
34
  var encodeAddress = (data, kind, cfOrBtcnetwork) => {
194
35
  const btcNetwork = networkMap[cfOrBtcnetwork];
195
36
  _assertion.assert.call(void 0, btcNetwork, `Invalid network: ${cfOrBtcnetwork}`);
@@ -198,40 +39,60 @@ var encodeAddress = (data, kind, cfOrBtcnetwork) => {
198
39
  typeof data !== "string" || /^(0x)?[0-9a-f]*$/.test(data),
199
40
  "bytes are not a valid hex string"
200
41
  );
42
+ const bytes = byteLikeToUint8Array(data);
201
43
  switch (kind) {
202
44
  case "P2PKH":
203
- case "P2SH":
204
- return encodeBase58Address(data, btcNetwork, kind);
45
+ case "P2SH": {
46
+ const version = (kind === "P2SH" ? p2shAddressVersion : p2pkhAddressVersion)[btcNetwork];
47
+ return bitcoin.address.toBase58Check(bytes, version);
48
+ }
205
49
  case "P2WPKH":
206
50
  case "P2WSH":
207
51
  case "Taproot":
208
- return encodeSegwitAddress(data, kind, btcNetwork);
52
+ return bitcoin.address.toBech32(bytes, segwitVersions[kind], networkHrp[btcNetwork]);
209
53
  default:
210
54
  throw new Error(`Invalid address type: ${kind}`);
211
55
  }
212
56
  };
213
- var isValidAddressForNetwork = (address, network) => {
214
- if (network === "mainnet") {
215
- if (/^(1|3)/.test(address)) {
216
- return parseBase58Address(address, network) !== null;
217
- }
218
- if (/^bc1/.test(address)) {
219
- return decodeSegwitAddress(address) !== null;
220
- }
221
- } else {
222
- if (/^(m|n|2)/.test(address)) {
223
- return parseBase58Address(address, network) !== null;
57
+ var decodeAddress = (address2, cfOrBtcNetwork) => {
58
+ const network = networkMap[cfOrBtcNetwork];
59
+ if (/^[13mn2]/.test(address2)) {
60
+ const { hash, version } = bitcoin.address.fromBase58Check(address2);
61
+ if (version === p2pkhAddressVersion[network]) {
62
+ return { type: "P2PKH", data: hash, version };
224
63
  }
225
- if (network === "regtest" && /^bcrt1/.test(address)) {
226
- return decodeSegwitAddress(address) !== null;
64
+ if (version === p2shAddressVersion[network]) {
65
+ return { type: "P2SH", data: hash, version };
227
66
  }
228
- if (network === "testnet" && /^tb1/.test(address)) {
229
- return decodeSegwitAddress(address) !== null;
67
+ throw new TypeError(`Invalid version: ${version}`);
68
+ }
69
+ if (/^(bc|tb|bcrt)1/.test(address2)) {
70
+ const { data, prefix, version } = bitcoin.address.fromBech32(address2);
71
+ _assertion.assert.call(void 0, prefix === networkHrp[network], `Invalid prefix: ${prefix}`);
72
+ let type;
73
+ if (version === 0 && data.length === 20) {
74
+ type = "P2WPKH";
75
+ } else if (version === 0) {
76
+ type = "P2WSH";
77
+ } else if (version === 1) {
78
+ type = "Taproot";
79
+ } else {
80
+ throw new TypeError(`Invalid version: ${version}`);
230
81
  }
82
+ return { hrp: prefix, data, type, version };
231
83
  }
232
- return false;
84
+ throw new TypeError(`Invalid address "${address2}" for network "${network}"`);
233
85
  };
86
+ var isValidAddressForNetwork = (address2, cfOrBtcNetwork) => {
87
+ try {
88
+ decodeAddress(address2, cfOrBtcNetwork);
89
+ return true;
90
+ } catch (e) {
91
+ return false;
92
+ }
93
+ };
94
+
234
95
 
235
96
 
236
97
 
237
- exports.encodeAddress = encodeAddress; exports.isValidAddressForNetwork = isValidAddressForNetwork;
98
+ exports.decodeAddress = decodeAddress; exports.encodeAddress = encodeAddress; exports.isValidAddressForNetwork = isValidAddressForNetwork;
package/dist/index.d.cts CHANGED
@@ -1,8 +1,27 @@
1
1
  type ChainflipNetwork = 'mainnet' | 'perseverance' | 'sisyphos' | 'backspin';
2
2
  type BitcoinNetwork = 'mainnet' | 'testnet' | 'regtest';
3
3
  type Bytelike = Uint8Array | number[] | `0x${string}`;
4
- type AddressType = 'P2WPKH' | 'P2SH' | 'P2PKH' | 'P2WSH' | 'Taproot';
5
- declare const encodeAddress: (data: Bytelike, kind: AddressType, cfOrBtcnetwork: BitcoinNetwork | ChainflipNetwork) => string;
6
- declare const isValidAddressForNetwork: (address: string, network: BitcoinNetwork) => boolean;
4
+ declare const networkHrp: {
5
+ readonly mainnet: "bc";
6
+ readonly testnet: "tb";
7
+ readonly regtest: "bcrt";
8
+ };
9
+ type HRP = (typeof networkHrp)[keyof typeof networkHrp];
10
+ type Base58AddressType = 'P2SH' | 'P2PKH';
11
+ type DecodedBase58Address = {
12
+ type: Base58AddressType;
13
+ data: Uint8Array;
14
+ version: number;
15
+ };
16
+ type DecodedSegwitAddress = {
17
+ hrp: HRP;
18
+ data: Uint8Array;
19
+ type: SegwitAddressType;
20
+ version: number;
21
+ };
22
+ type SegwitAddressType = 'P2WPKH' | 'P2WSH' | 'Taproot';
23
+ declare const encodeAddress: (data: Bytelike, kind: Base58AddressType | SegwitAddressType, cfOrBtcnetwork: BitcoinNetwork | ChainflipNetwork) => string;
24
+ declare const decodeAddress: (address: string, cfOrBtcNetwork: BitcoinNetwork | ChainflipNetwork) => DecodedBase58Address | DecodedSegwitAddress;
25
+ declare const isValidAddressForNetwork: (address: string, cfOrBtcNetwork: BitcoinNetwork | ChainflipNetwork) => boolean;
7
26
 
8
- export { encodeAddress, isValidAddressForNetwork };
27
+ export { type Base58AddressType, type BitcoinNetwork, type Bytelike, type ChainflipNetwork, type DecodedBase58Address, type DecodedSegwitAddress, type HRP, type SegwitAddressType, decodeAddress, encodeAddress, isValidAddressForNetwork };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,27 @@
1
1
  type ChainflipNetwork = 'mainnet' | 'perseverance' | 'sisyphos' | 'backspin';
2
2
  type BitcoinNetwork = 'mainnet' | 'testnet' | 'regtest';
3
3
  type Bytelike = Uint8Array | number[] | `0x${string}`;
4
- type AddressType = 'P2WPKH' | 'P2SH' | 'P2PKH' | 'P2WSH' | 'Taproot';
5
- declare const encodeAddress: (data: Bytelike, kind: AddressType, cfOrBtcnetwork: BitcoinNetwork | ChainflipNetwork) => string;
6
- declare const isValidAddressForNetwork: (address: string, network: BitcoinNetwork) => boolean;
4
+ declare const networkHrp: {
5
+ readonly mainnet: "bc";
6
+ readonly testnet: "tb";
7
+ readonly regtest: "bcrt";
8
+ };
9
+ type HRP = (typeof networkHrp)[keyof typeof networkHrp];
10
+ type Base58AddressType = 'P2SH' | 'P2PKH';
11
+ type DecodedBase58Address = {
12
+ type: Base58AddressType;
13
+ data: Uint8Array;
14
+ version: number;
15
+ };
16
+ type DecodedSegwitAddress = {
17
+ hrp: HRP;
18
+ data: Uint8Array;
19
+ type: SegwitAddressType;
20
+ version: number;
21
+ };
22
+ type SegwitAddressType = 'P2WPKH' | 'P2WSH' | 'Taproot';
23
+ declare const encodeAddress: (data: Bytelike, kind: Base58AddressType | SegwitAddressType, cfOrBtcnetwork: BitcoinNetwork | ChainflipNetwork) => string;
24
+ declare const decodeAddress: (address: string, cfOrBtcNetwork: BitcoinNetwork | ChainflipNetwork) => DecodedBase58Address | DecodedSegwitAddress;
25
+ declare const isValidAddressForNetwork: (address: string, cfOrBtcNetwork: BitcoinNetwork | ChainflipNetwork) => boolean;
7
26
 
8
- export { encodeAddress, isValidAddressForNetwork };
27
+ export { type Base58AddressType, type BitcoinNetwork, type Bytelike, type ChainflipNetwork, type DecodedBase58Address, type DecodedSegwitAddress, type HRP, type SegwitAddressType, decodeAddress, encodeAddress, isValidAddressForNetwork };
package/dist/index.mjs CHANGED
@@ -1,8 +1,7 @@
1
1
  // src/index.ts
2
2
  import { assert } from "@chainflip/utils/assertion";
3
- import * as base58 from "@chainflip/utils/base58";
4
3
  import { hexToBytes } from "@chainflip/utils/bytes";
5
- import { sha256 } from "@noble/hashes/sha256";
4
+ import * as bitcoin from "bitcoinjs-lib";
6
5
  var p2pkhAddressVersion = {
7
6
  mainnet: 0,
8
7
  testnet: 111,
@@ -18,170 +17,11 @@ var networkHrp = {
18
17
  testnet: "tb",
19
18
  regtest: "bcrt"
20
19
  };
21
- function parseBase58Address(address, network) {
22
- const checksumLength = 4;
23
- const payloadLength = 21;
24
- const data = base58.decode(address);
25
- if (data.length !== payloadLength + checksumLength)
26
- return null;
27
- const payload = data.slice(0, payloadLength);
28
- const checksum = data.slice(-checksumLength);
29
- const computedChecksum = sha256(sha256(payload)).slice(0, checksumLength);
30
- if (!computedChecksum.every((byte, i) => byte === checksum[i]))
31
- return null;
32
- const [version, ...hash] = payload;
33
- if (version === p2pkhAddressVersion[network]) {
34
- return { type: "p2pkh", hash };
35
- }
36
- if (version === p2shAddressVersion[network]) {
37
- return { type: "p2sh", hash };
38
- }
39
- return null;
40
- }
41
- function encodeBase58Address(data, network, type) {
42
- const version = (type === "P2SH" ? p2shAddressVersion : p2pkhAddressVersion)[network];
43
- const payload = new Uint8Array([
44
- version,
45
- ...typeof data === "string" ? hexToBytes(data) : data
46
- ]);
47
- const checksum = sha256(sha256(payload)).slice(0, 4);
48
- const address = base58.encode(Buffer.concat([payload, checksum]));
49
- return address;
50
- }
51
- var BECH32_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
52
- function decodeBech32(address) {
53
- const pos = address.lastIndexOf("1");
54
- if (pos === -1 || pos === 0 || pos + 7 > address.length) {
55
- return null;
56
- }
57
- const hrp = address.substring(0, pos);
58
- const data = [];
59
- for (let i = pos + 1; i < address.length; i++) {
60
- const charIndex = BECH32_CHARSET.indexOf(address[i]);
61
- if (charIndex === -1)
62
- return null;
63
- data.push(charIndex);
64
- }
65
- return { hrp, data };
66
- }
67
- function polymod(values) {
68
- const generators = [996825010, 642813549, 513874426, 1027748829, 705979059];
69
- let chk = 1;
70
- for (const value of values) {
71
- const top = chk >> 25;
72
- chk = (chk & 33554431) << 5 ^ value;
73
- for (let i = 0; i < 5; i++) {
74
- if (top >> i & 1) {
75
- chk ^= generators[i];
76
- }
77
- }
78
- }
79
- return chk;
80
- }
81
- function hrpExpand(hrp) {
82
- const ret = [];
83
- for (let i = 0; i < hrp.length; i++) {
84
- ret.push(hrp.charCodeAt(i) >> 5);
85
- }
86
- ret.push(0);
87
- for (let i = 0; i < hrp.length; i++) {
88
- ret.push(hrp.charCodeAt(i) & 31);
89
- }
90
- return ret;
91
- }
92
- function computeChecksum(hrp, data) {
93
- return polymod(hrpExpand(hrp).concat(data));
94
- }
95
- var checksums = {
96
- bech32: 1,
97
- bech32m: 734539939
98
- };
99
- function convert5BitGroupsToBytes(data) {
100
- let acc = 0;
101
- let bits = 0;
102
- const result = [];
103
- for (let i = 0; i < data.length; i++) {
104
- acc = acc << 5 | data[i];
105
- bits += 5;
106
- if (bits >= 8) {
107
- result.push(acc >> bits - 8 & 255);
108
- bits -= 8;
109
- }
110
- }
111
- if (bits > 0) {
112
- const remainingByte = acc << 8 - bits & 255;
113
- if (remainingByte !== 0 || bits > 5) {
114
- result.push(remainingByte);
115
- }
116
- }
117
- return new Uint8Array(result);
118
- }
119
- function decodeSegwitAddress(address) {
120
- const decoded = decodeBech32(address.toLowerCase());
121
- if (!decoded) {
122
- return null;
123
- }
124
- const { hrp, data: dataWithChecksum } = decoded;
125
- const checksum = computeChecksum(hrp, dataWithChecksum);
126
- let type;
127
- if (checksum === 1) {
128
- type = "bech32";
129
- } else if (checksum === 734539939) {
130
- type = "bech32m";
131
- } else {
132
- return null;
133
- }
134
- const data = convert5BitGroupsToBytes(dataWithChecksum.slice(1, -6));
135
- const [version] = dataWithChecksum;
136
- assert(data.length >= 2 && data.length <= 40, "Invalid address");
137
- assert(version !== 0 || data.length === 20 || data.length === 32, "Invalid address");
138
- return { hrp, data, type, version };
139
- }
140
- function createChecksum(hrp, data, variant) {
141
- const values = hrpExpand(hrp).concat(data).concat([0, 0, 0, 0, 0, 0]);
142
- const polymodValue = polymod(values) ^ checksums[variant];
143
- const checksum = [];
144
- for (let i = 0; i < 6; i++) {
145
- checksum.push(polymodValue >> 5 * (5 - i) & 31);
146
- }
147
- return checksum;
148
- }
149
- function encodeBech32(hrp, data) {
150
- return `${hrp}1${data.map((i) => BECH32_CHARSET[i]).join("")}`;
151
- }
152
- function convertBytesTo5BitGroups(data) {
153
- let acc = 0;
154
- let bits = 0;
155
- const result = [];
156
- for (let i = 0; i < data.length; i++) {
157
- acc = acc << 8 | data[i];
158
- bits += 8;
159
- while (bits >= 5) {
160
- result.push(acc >> bits - 5 & 31);
161
- bits -= 5;
162
- }
163
- }
164
- if (bits > 0) {
165
- result.push(acc << 5 - bits & 31);
166
- }
167
- return result;
168
- }
169
20
  var segwitVersions = {
170
21
  P2WPKH: 0,
171
22
  P2WSH: 0,
172
23
  Taproot: 1
173
24
  };
174
- function encodeSegwitAddress(byteData, kind, network) {
175
- const variant = kind === "Taproot" ? "bech32m" : "bech32";
176
- const bytes = typeof byteData === "string" ? hexToBytes(byteData) : new Uint8Array(byteData);
177
- const version = segwitVersions[kind];
178
- assert(bytes.length >= 2 && bytes.length <= 40, "Invalid address");
179
- assert(version !== 0 || bytes.length === 20 || bytes.length === 32, "Invalid address");
180
- const data = [segwitVersions[kind]].concat(convertBytesTo5BitGroups(bytes));
181
- const hrp = networkHrp[network];
182
- const checksum = createChecksum(hrp, data, variant);
183
- return encodeBech32(hrp, data.concat(checksum));
184
- }
185
25
  var networkMap = {
186
26
  mainnet: "mainnet",
187
27
  perseverance: "testnet",
@@ -190,6 +30,7 @@ var networkMap = {
190
30
  backspin: "regtest",
191
31
  regtest: "regtest"
192
32
  };
33
+ var byteLikeToUint8Array = (data) => typeof data === "string" ? hexToBytes(data) : new Uint8Array(data);
193
34
  var encodeAddress = (data, kind, cfOrBtcnetwork) => {
194
35
  const btcNetwork = networkMap[cfOrBtcnetwork];
195
36
  assert(btcNetwork, `Invalid network: ${cfOrBtcnetwork}`);
@@ -198,40 +39,60 @@ var encodeAddress = (data, kind, cfOrBtcnetwork) => {
198
39
  typeof data !== "string" || /^(0x)?[0-9a-f]*$/.test(data),
199
40
  "bytes are not a valid hex string"
200
41
  );
42
+ const bytes = byteLikeToUint8Array(data);
201
43
  switch (kind) {
202
44
  case "P2PKH":
203
- case "P2SH":
204
- return encodeBase58Address(data, btcNetwork, kind);
45
+ case "P2SH": {
46
+ const version = (kind === "P2SH" ? p2shAddressVersion : p2pkhAddressVersion)[btcNetwork];
47
+ return bitcoin.address.toBase58Check(bytes, version);
48
+ }
205
49
  case "P2WPKH":
206
50
  case "P2WSH":
207
51
  case "Taproot":
208
- return encodeSegwitAddress(data, kind, btcNetwork);
52
+ return bitcoin.address.toBech32(bytes, segwitVersions[kind], networkHrp[btcNetwork]);
209
53
  default:
210
54
  throw new Error(`Invalid address type: ${kind}`);
211
55
  }
212
56
  };
213
- var isValidAddressForNetwork = (address, network) => {
214
- if (network === "mainnet") {
215
- if (/^(1|3)/.test(address)) {
216
- return parseBase58Address(address, network) !== null;
217
- }
218
- if (/^bc1/.test(address)) {
219
- return decodeSegwitAddress(address) !== null;
57
+ var decodeAddress = (address2, cfOrBtcNetwork) => {
58
+ const network = networkMap[cfOrBtcNetwork];
59
+ if (/^[13mn2]/.test(address2)) {
60
+ const { hash, version } = bitcoin.address.fromBase58Check(address2);
61
+ if (version === p2pkhAddressVersion[network]) {
62
+ return { type: "P2PKH", data: hash, version };
220
63
  }
221
- } else {
222
- if (/^(m|n|2)/.test(address)) {
223
- return parseBase58Address(address, network) !== null;
64
+ if (version === p2shAddressVersion[network]) {
65
+ return { type: "P2SH", data: hash, version };
224
66
  }
225
- if (network === "regtest" && /^bcrt1/.test(address)) {
226
- return decodeSegwitAddress(address) !== null;
227
- }
228
- if (network === "testnet" && /^tb1/.test(address)) {
229
- return decodeSegwitAddress(address) !== null;
67
+ throw new TypeError(`Invalid version: ${version}`);
68
+ }
69
+ if (/^(bc|tb|bcrt)1/.test(address2)) {
70
+ const { data, prefix, version } = bitcoin.address.fromBech32(address2);
71
+ assert(prefix === networkHrp[network], `Invalid prefix: ${prefix}`);
72
+ let type;
73
+ if (version === 0 && data.length === 20) {
74
+ type = "P2WPKH";
75
+ } else if (version === 0) {
76
+ type = "P2WSH";
77
+ } else if (version === 1) {
78
+ type = "Taproot";
79
+ } else {
80
+ throw new TypeError(`Invalid version: ${version}`);
230
81
  }
82
+ return { hrp: prefix, data, type, version };
83
+ }
84
+ throw new TypeError(`Invalid address "${address2}" for network "${network}"`);
85
+ };
86
+ var isValidAddressForNetwork = (address2, cfOrBtcNetwork) => {
87
+ try {
88
+ decodeAddress(address2, cfOrBtcNetwork);
89
+ return true;
90
+ } catch {
91
+ return false;
231
92
  }
232
- return false;
233
93
  };
234
94
  export {
95
+ decodeAddress,
235
96
  encodeAddress,
236
97
  isValidAddressForNetwork
237
98
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chainflip/bitcoin",
3
- "version": "1.0.2",
3
+ "version": "1.1.1",
4
4
  "type": "module",
5
5
  "repository": "https://github.com/chainflip-io/chainflip-product-toolkit.git",
6
6
  "publishConfig": {
@@ -15,7 +15,7 @@
15
15
  "module": "dist/index.mjs",
16
16
  "dependencies": {
17
17
  "@chainflip/utils": "^0.4.0",
18
- "@noble/hashes": "^1.4.0"
18
+ "bitcoinjs-lib": "^7.0.0-rc.0"
19
19
  },
20
20
  "scripts": {
21
21
  "prepublish": "pnpm build && pnpm test run",