@btc-vision/bitcoin 7.0.0-beta.0 → 7.0.0-beta.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 (116) hide show
  1. package/README.md +112 -13
  2. package/benchmark-compare/BENCHMARK.md +74 -59
  3. package/benchmark-compare/compare.bench.ts +249 -96
  4. package/benchmark-compare/harness.ts +23 -25
  5. package/benchmark-compare/package.json +1 -0
  6. package/browser/address.d.ts +4 -4
  7. package/browser/address.d.ts.map +1 -1
  8. package/browser/chunks/{psbt-parallel-B-dfm5GZ.js → psbt-parallel-jZ6QcCnM.js} +3128 -2731
  9. package/browser/index.d.ts +1 -1
  10. package/browser/index.d.ts.map +1 -1
  11. package/browser/index.js +603 -585
  12. package/browser/io/base58check.d.ts +1 -25
  13. package/browser/io/base58check.d.ts.map +1 -1
  14. package/browser/io/base64.d.ts.map +1 -1
  15. package/browser/networks.d.ts +1 -0
  16. package/browser/networks.d.ts.map +1 -1
  17. package/browser/payments/bip341.d.ts +17 -0
  18. package/browser/payments/bip341.d.ts.map +1 -1
  19. package/browser/payments/index.d.ts +3 -2
  20. package/browser/payments/index.d.ts.map +1 -1
  21. package/browser/payments/p2mr.d.ts +169 -0
  22. package/browser/payments/p2mr.d.ts.map +1 -0
  23. package/browser/payments/types.d.ts +11 -1
  24. package/browser/payments/types.d.ts.map +1 -1
  25. package/browser/psbt/bip371.d.ts +30 -0
  26. package/browser/psbt/bip371.d.ts.map +1 -1
  27. package/browser/psbt/psbtutils.d.ts +1 -0
  28. package/browser/psbt/psbtutils.d.ts.map +1 -1
  29. package/browser/psbt.d.ts.map +1 -1
  30. package/browser/workers/index.js +9 -9
  31. package/build/address.d.ts +4 -4
  32. package/build/address.d.ts.map +1 -1
  33. package/build/address.js +11 -1
  34. package/build/address.js.map +1 -1
  35. package/build/index.d.ts +1 -1
  36. package/build/index.d.ts.map +1 -1
  37. package/build/index.js.map +1 -1
  38. package/build/io/base58check.d.ts +1 -25
  39. package/build/io/base58check.d.ts.map +1 -1
  40. package/build/io/base58check.js +1 -31
  41. package/build/io/base58check.js.map +1 -1
  42. package/build/io/base64.d.ts.map +1 -1
  43. package/build/io/base64.js +3 -0
  44. package/build/io/base64.js.map +1 -1
  45. package/build/networks.d.ts +1 -0
  46. package/build/networks.d.ts.map +1 -1
  47. package/build/networks.js +12 -0
  48. package/build/networks.js.map +1 -1
  49. package/build/payments/bip341.d.ts +17 -0
  50. package/build/payments/bip341.d.ts.map +1 -1
  51. package/build/payments/bip341.js +32 -1
  52. package/build/payments/bip341.js.map +1 -1
  53. package/build/payments/index.d.ts +3 -2
  54. package/build/payments/index.d.ts.map +1 -1
  55. package/build/payments/index.js +2 -1
  56. package/build/payments/index.js.map +1 -1
  57. package/build/payments/p2mr.d.ts +178 -0
  58. package/build/payments/p2mr.d.ts.map +1 -0
  59. package/build/payments/p2mr.js +555 -0
  60. package/build/payments/p2mr.js.map +1 -0
  61. package/build/payments/types.d.ts +11 -1
  62. package/build/payments/types.d.ts.map +1 -1
  63. package/build/payments/types.js +1 -0
  64. package/build/payments/types.js.map +1 -1
  65. package/build/psbt/bip371.d.ts +30 -0
  66. package/build/psbt/bip371.d.ts.map +1 -1
  67. package/build/psbt/bip371.js +80 -15
  68. package/build/psbt/bip371.js.map +1 -1
  69. package/build/psbt/psbtutils.d.ts +1 -0
  70. package/build/psbt/psbtutils.d.ts.map +1 -1
  71. package/build/psbt/psbtutils.js +2 -0
  72. package/build/psbt/psbtutils.js.map +1 -1
  73. package/build/psbt.d.ts.map +1 -1
  74. package/build/psbt.js +3 -2
  75. package/build/psbt.js.map +1 -1
  76. package/build/pubkey.js +1 -1
  77. package/build/pubkey.js.map +1 -1
  78. package/build/tsconfig.build.tsbuildinfo +1 -1
  79. package/documentation/README.md +122 -0
  80. package/documentation/address.md +820 -0
  81. package/documentation/block.md +679 -0
  82. package/documentation/crypto.md +461 -0
  83. package/documentation/ecc.md +584 -0
  84. package/documentation/errors.md +656 -0
  85. package/documentation/io.md +942 -0
  86. package/documentation/networks.md +625 -0
  87. package/documentation/p2mr.md +380 -0
  88. package/documentation/payments.md +1485 -0
  89. package/documentation/psbt.md +1400 -0
  90. package/documentation/script.md +730 -0
  91. package/documentation/taproot.md +670 -0
  92. package/documentation/transaction.md +943 -0
  93. package/documentation/types.md +587 -0
  94. package/documentation/workers.md +1007 -0
  95. package/eslint.config.js +3 -0
  96. package/package.json +17 -14
  97. package/src/address.ts +22 -10
  98. package/src/index.ts +1 -0
  99. package/src/io/base58check.ts +1 -35
  100. package/src/io/base64.ts +5 -0
  101. package/src/networks.ts +13 -0
  102. package/src/payments/bip341.ts +36 -1
  103. package/src/payments/index.ts +4 -0
  104. package/src/payments/p2mr.ts +660 -0
  105. package/src/payments/types.ts +12 -0
  106. package/src/psbt/bip371.ts +84 -13
  107. package/src/psbt/psbtutils.ts +2 -0
  108. package/src/psbt.ts +4 -2
  109. package/src/pubkey.ts +1 -1
  110. package/test/bitcoin.core.spec.ts +1 -1
  111. package/test/fixtures/p2mr.json +270 -0
  112. package/test/integration/taproot.spec.ts +7 -3
  113. package/test/opnetTestnet.spec.ts +302 -0
  114. package/test/payments.spec.ts +3 -1
  115. package/test/psbt.spec.ts +297 -2
  116. package/test/tsconfig.json +2 -2
@@ -0,0 +1,820 @@
1
+ # Address Module
2
+
3
+ The address module provides encoding and decoding tools for all Bitcoin address formats, including Base58Check (legacy), Bech32/Bech32m (SegWit), and conversion between addresses and output scripts. It supports P2PKH, P2SH, P2WPKH, P2WSH, P2TR, P2MR, P2OP, and future SegWit versions.
4
+
5
+ ## Overview
6
+
7
+ | Feature | Description |
8
+ |---------|-------------|
9
+ | Base58Check | Encode/decode legacy P2PKH and P2SH addresses |
10
+ | Bech32 | Encode/decode SegWit v0 addresses (P2WPKH, P2WSH) |
11
+ | Bech32m | Encode/decode SegWit v1+ addresses (P2TR, P2MR, P2OP, future) |
12
+ | Output scripts | Convert between addresses and their locking scripts |
13
+ | Networks | Bitcoin mainnet, testnet, regtest, Litecoin, Dogecoin, Dash, and more |
14
+
15
+ ---
16
+
17
+ ## Supported Address Types
18
+
19
+ | Type | SegWit Version | Encoding | Mainnet Prefix | Testnet Prefix | Regtest Prefix | Script Pattern |
20
+ |------|---------------|----------|----------------|----------------|----------------|----------------|
21
+ | P2PKH | N/A | Base58Check | `1...` | `m...` / `n...` | `m...` / `n...` | `OP_DUP OP_HASH160 <20B> OP_EQUALVERIFY OP_CHECKSIG` |
22
+ | P2SH | N/A | Base58Check | `3...` | `2...` | `2...` | `OP_HASH160 <20B> OP_EQUAL` |
23
+ | P2WPKH | 0 | Bech32 | `bc1q...` | `tb1q...` | `bcrt1q...` | `OP_0 <20B>` |
24
+ | P2WSH | 0 | Bech32 | `bc1q...` | `tb1q...` | `bcrt1q...` | `OP_0 <32B>` |
25
+ | P2TR | 1 | Bech32m | `bc1p...` | `tb1p...` | `bcrt1p...` | `OP_1 <32B>` |
26
+ | P2MR | 2 | Bech32m | `bc1z...` | `tb1z...` | `bcrt1z...` | `OP_2 <32B>` |
27
+ | P2OP | 16 | Bech32m | `op1...` | `opt1...` | `opr1...` | `OP_16 <program>` |
28
+ | Future SegWit | 2-15 | Bech32m | `bc1...` | `tb1...` | `bcrt1...` | `OP_n <2-40B>` |
29
+
30
+ ---
31
+
32
+ ## Network-Specific Prefixes
33
+
34
+ | Network | `bech32` | `bech32Opnet` | `pubKeyHash` | `scriptHash` |
35
+ |---------|----------|---------------|--------------|--------------|
36
+ | Bitcoin mainnet | `bc` | `op` | `0x00` | `0x05` |
37
+ | Bitcoin testnet | `tb` | `opt` | `0x6f` | `0xc4` |
38
+ | Bitcoin regtest | `bcrt` | `opr` | `0x6f` | `0xc4` |
39
+ | Litecoin mainnet | `ltc` | `opl` | `0x30` | `0x32` |
40
+ | Litecoin testnet | `tltc` | `oplt` | `0x6f` | `0x3a` |
41
+
42
+ ---
43
+
44
+ ## Installation
45
+
46
+ ```typescript
47
+ import {
48
+ address,
49
+ networks,
50
+ } from '@btc-vision/bitcoin';
51
+
52
+ // Or import specific functions directly (re-exported from address module)
53
+ import {
54
+ fromBase58Check,
55
+ toBase58Check,
56
+ fromBech32,
57
+ toBech32,
58
+ fromOutputScript,
59
+ toOutputScript,
60
+ toFutureOPNetAddress,
61
+ _toFutureSegwitAddress,
62
+ isUnknownSegwitVersion,
63
+ FUTURE_SEGWIT_MAX_SIZE,
64
+ FUTURE_SEGWIT_MIN_SIZE,
65
+ FUTURE_SEGWIT_MAX_VERSION,
66
+ FUTURE_MAX_VERSION,
67
+ FUTURE_OPNET_VERSION,
68
+ FUTURE_SEGWIT_MIN_VERSION,
69
+ FUTURE_SEGWIT_VERSION_DIFF,
70
+ } from '@btc-vision/bitcoin';
71
+
72
+ // Types
73
+ import type {
74
+ Base58CheckResult,
75
+ Bech32Result,
76
+ ToOutputScriptOptions,
77
+ } from '@btc-vision/bitcoin';
78
+ ```
79
+
80
+ ---
81
+
82
+ ## Interfaces
83
+
84
+ ### Base58CheckResult
85
+
86
+ Returned by `fromBase58Check()` when decoding a legacy Base58Check address.
87
+
88
+ ```typescript
89
+ interface Base58CheckResult {
90
+ /** The 20-byte address hash (HASH160 of public key or script) */
91
+ readonly hash: Bytes20;
92
+ /** The version byte: 0x00 for P2PKH, 0x05 for P2SH (mainnet) */
93
+ readonly version: number;
94
+ }
95
+ ```
96
+
97
+ | Field | Type | Description |
98
+ |-------|------|-------------|
99
+ | `hash` | `Bytes20` | 20-byte HASH160 payload |
100
+ | `version` | `number` | Version prefix byte identifying the address type and network |
101
+
102
+ ### Bech32Result
103
+
104
+ Returned by `fromBech32()` when decoding a Bech32 or Bech32m address.
105
+
106
+ ```typescript
107
+ interface Bech32Result {
108
+ /** Witness version: 0 for P2WPKH/P2WSH, 1 for P2TR, 2 for P2MR, 16 for P2OP */
109
+ version: number;
110
+ /** Human-readable prefix: "bc" for mainnet, "tb" for testnet, "bcrt" for regtest */
111
+ prefix: string;
112
+ /** Witness program: 20 bytes for P2WPKH, 32 bytes for P2WSH/P2TR/P2MR */
113
+ data: Uint8Array;
114
+ }
115
+ ```
116
+
117
+ | Field | Type | Description |
118
+ |-------|------|-------------|
119
+ | `version` | `number` | SegWit witness version (0-16) |
120
+ | `prefix` | `string` | Bech32 human-readable part (e.g., `"bc"`, `"tb"`, `"op"`) |
121
+ | `data` | `Uint8Array` | Decoded witness program bytes |
122
+
123
+ ### ToOutputScriptOptions
124
+
125
+ Options object for `toOutputScript()`.
126
+
127
+ ```typescript
128
+ interface ToOutputScriptOptions {
129
+ /** Network to use for encoding. Defaults to bitcoin mainnet. */
130
+ readonly network?: Network;
131
+ /**
132
+ * Optional callback for future segwit version warnings.
133
+ * Called with a warning string when encoding a future segwit version (v2-v15) address.
134
+ */
135
+ readonly onFutureSegwitWarning?: (warning: string) => void;
136
+ }
137
+ ```
138
+
139
+ ---
140
+
141
+ ## Constants
142
+
143
+ | Constant | Value | Description |
144
+ |----------|-------|-------------|
145
+ | `FUTURE_SEGWIT_MAX_SIZE` | `40` | Maximum witness program length for future SegWit versions |
146
+ | `FUTURE_SEGWIT_MIN_SIZE` | `2` | Minimum witness program length for future SegWit versions |
147
+ | `FUTURE_SEGWIT_MAX_VERSION` | `15` | Maximum SegWit version for standard future addresses |
148
+ | `FUTURE_MAX_VERSION` | `16` | Maximum SegWit version (including OPNet) |
149
+ | `FUTURE_OPNET_VERSION` | `16` | SegWit version reserved for OPNet (P2OP) |
150
+ | `FUTURE_SEGWIT_MIN_VERSION` | `2` | Minimum SegWit version treated as "future" |
151
+ | `FUTURE_SEGWIT_VERSION_DIFF` | `0x50` | Offset between SegWit version number and the corresponding opcode (`OP_1` = `0x51`, so version 1 = `0x51 - 0x50`) |
152
+
153
+ ---
154
+
155
+ ## API Reference
156
+
157
+ ### fromBase58Check()
158
+
159
+ Decodes a Base58Check-encoded address into its version byte and 20-byte hash.
160
+
161
+ ```typescript
162
+ function fromBase58Check(address: string): Base58CheckResult
163
+ ```
164
+
165
+ | Parameter | Type | Description |
166
+ |-----------|------|-------------|
167
+ | `address` | `string` | A Base58Check-encoded address string |
168
+
169
+ **Returns:** `Base58CheckResult` with `version` and `hash` fields.
170
+
171
+ **Throws:** `TypeError` if the decoded payload is not exactly 21 bytes.
172
+
173
+ #### Example
174
+
175
+ ```typescript
176
+ import { address } from '@btc-vision/bitcoin';
177
+
178
+ // Decode a P2PKH mainnet address
179
+ const result = address.fromBase58Check('1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH');
180
+ console.log(result.version); // 0 (P2PKH mainnet)
181
+ console.log(result.hash); // Uint8Array(20) - the HASH160
182
+
183
+ // Decode a P2SH mainnet address
184
+ const p2shResult = address.fromBase58Check('3LRW7jeCvQCRdPF8S3yUCfRAx4eqXFmdcr');
185
+ console.log(p2shResult.version); // 5 (P2SH mainnet)
186
+
187
+ // Decode a testnet P2PKH address
188
+ const testnetResult = address.fromBase58Check('mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r');
189
+ console.log(testnetResult.version); // 111 (0x6f, testnet P2PKH)
190
+ ```
191
+
192
+ ---
193
+
194
+ ### toBase58Check()
195
+
196
+ Encodes a 20-byte hash and version byte into a Base58Check address string.
197
+
198
+ ```typescript
199
+ function toBase58Check(hash: Bytes20, version: number): string
200
+ ```
201
+
202
+ | Parameter | Type | Description |
203
+ |-----------|------|-------------|
204
+ | `hash` | `Bytes20` | 20-byte hash (HASH160 of public key or script) |
205
+ | `version` | `number` | Version byte (must be a valid UInt8, 0-255) |
206
+
207
+ **Returns:** Base58Check-encoded address string.
208
+
209
+ **Throws:** `TypeError` if `hash` is not exactly 20 bytes or `version` is not a valid UInt8.
210
+
211
+ #### Example
212
+
213
+ ```typescript
214
+ import { address, networks } from '@btc-vision/bitcoin';
215
+ import { fromHex } from '@btc-vision/bitcoin';
216
+ import type { Bytes20 } from '@btc-vision/bitcoin';
217
+
218
+ const hash = fromHex('751e76e8199196d454941c45d1b3a323f1433bd6') as Bytes20;
219
+
220
+ // Encode as P2PKH mainnet (version 0x00)
221
+ const p2pkhAddress = address.toBase58Check(hash, networks.bitcoin.pubKeyHash);
222
+ console.log(p2pkhAddress); // '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH'
223
+
224
+ // Encode as P2SH mainnet (version 0x05)
225
+ const p2shHash = fromHex('cd7b44d0b03f2d026d1e586d7ae18903b0d385f6') as Bytes20;
226
+ const p2shAddress = address.toBase58Check(p2shHash, networks.bitcoin.scriptHash);
227
+ console.log(p2shAddress); // '3LRW7jeCvQCRdPF8S3yUCfRAx4eqXFmdcr'
228
+
229
+ // Encode as testnet P2PKH (version 0x6f)
230
+ const testnetAddress = address.toBase58Check(hash, networks.testnet.pubKeyHash);
231
+ console.log(testnetAddress); // 'mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r'
232
+ ```
233
+
234
+ ---
235
+
236
+ ### fromBech32()
237
+
238
+ Decodes a Bech32 or Bech32m address into its witness version, human-readable prefix, and witness program data. Automatically detects whether the address uses Bech32 (version 0) or Bech32m (version 1+).
239
+
240
+ ```typescript
241
+ function fromBech32(address: string): Bech32Result
242
+ ```
243
+
244
+ | Parameter | Type | Description |
245
+ |-----------|------|-------------|
246
+ | `address` | `string` | A Bech32 or Bech32m encoded address |
247
+
248
+ **Returns:** `Bech32Result` with `version`, `prefix`, and `data` fields.
249
+
250
+ **Throws:** `TypeError` if the encoding is mismatched (e.g., Bech32 with version != 0, or Bech32m with version 0).
251
+
252
+ #### Example
253
+
254
+ ```typescript
255
+ import { address } from '@btc-vision/bitcoin';
256
+
257
+ // Decode a P2WPKH address (SegWit v0, Bech32)
258
+ const wpkh = address.fromBech32('bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4');
259
+ console.log(wpkh.version); // 0
260
+ console.log(wpkh.prefix); // 'bc'
261
+ console.log(wpkh.data); // Uint8Array(20)
262
+
263
+ // Decode a P2WSH address (SegWit v0, Bech32)
264
+ const wsh = address.fromBech32(
265
+ 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7'
266
+ );
267
+ console.log(wsh.version); // 0
268
+ console.log(wsh.prefix); // 'tb'
269
+ console.log(wsh.data); // Uint8Array(32)
270
+
271
+ // Decode a P2TR address (SegWit v1, Bech32m)
272
+ const tr = address.fromBech32(
273
+ 'bc1p3efq8ujsj0qr5xvms7mv89p8cz0crqdtuxe9ms6grqgxc9sgsntslthf6w'
274
+ );
275
+ console.log(tr.version); // 1
276
+ console.log(tr.prefix); // 'bc'
277
+ console.log(tr.data); // Uint8Array(32) - x-only public key
278
+
279
+ // Decode a P2MR address (SegWit v2, Bech32m, 32-byte program)
280
+ const mr = address.fromBech32('bc1z3efq8ujsj0qr5xvms7mv89p8cz0crqdtuxe9ms6grqgxc9sgsntssjqzpz');
281
+ console.log(mr.version); // 2
282
+ console.log(mr.prefix); // 'bc'
283
+ console.log(mr.data.length); // 32
284
+ ```
285
+
286
+ ---
287
+
288
+ ### toBech32()
289
+
290
+ Encodes witness program data into a Bech32 (version 0) or Bech32m (version 1+) address string. When the version is `FUTURE_OPNET_VERSION` (16) and an OPNet prefix is provided, the address is encoded with the OPNet prefix.
291
+
292
+ ```typescript
293
+ function toBech32(
294
+ data: Uint8Array,
295
+ version: number,
296
+ prefix: string,
297
+ prefixOpnet?: string,
298
+ ): string
299
+ ```
300
+
301
+ | Parameter | Type | Description |
302
+ |-----------|------|-------------|
303
+ | `data` | `Uint8Array` | Witness program bytes |
304
+ | `version` | `number` | SegWit witness version (0-16) |
305
+ | `prefix` | `string` | Bech32 human-readable prefix (e.g., `"bc"`, `"tb"`) |
306
+ | `prefixOpnet` | `string` (optional) | OPNet-specific prefix, used when version is 16 |
307
+
308
+ **Returns:** Encoded Bech32 or Bech32m address string.
309
+
310
+ #### Example
311
+
312
+ ```typescript
313
+ import { address, networks } from '@btc-vision/bitcoin';
314
+ import { fromHex } from '@btc-vision/bitcoin';
315
+
316
+ // Encode a P2WPKH address (version 0 uses Bech32)
317
+ const wpkhData = fromHex('751e76e8199196d454941c45d1b3a323f1433bd6');
318
+ const wpkhAddr = address.toBech32(wpkhData, 0, networks.bitcoin.bech32);
319
+ console.log(wpkhAddr); // 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'
320
+
321
+ // Encode a P2TR address (version 1 uses Bech32m)
322
+ const trData = fromHex(
323
+ '8e5203f25093c03a199b87b6c39427c09f8181abe1b25dc34818106c160884d7'
324
+ );
325
+ const trAddr = address.toBech32(trData, 1, networks.bitcoin.bech32);
326
+ console.log(trAddr); // 'bc1p3efq8ujsj0qr5xvms7mv89p8cz0crqdtuxe9ms6grqgxc9sgsntslthf6w'
327
+
328
+ // Encode a P2MR address (version 2 uses Bech32m, 32-byte program required)
329
+ const mrData = fromHex(
330
+ '8e5203f25093c03a199b87b6c39427c09f8181abe1b25dc34818106c160884d7'
331
+ );
332
+ const mrAddr = address.toBech32(mrData, 2, networks.bitcoin.bech32);
333
+ console.log(mrAddr); // 'bc1z3efq8ujsj0qr5xvms7mv89p8cz0crqdtuxe9ms6grqgxc9sgsntssjqzpz'
334
+
335
+ // Encode a testnet address
336
+ const testnetAddr = address.toBech32(wpkhData, 0, networks.testnet.bech32);
337
+ console.log(testnetAddr); // 'tb1q...'
338
+
339
+ // Encode a P2OP (OPNet) address (version 16 uses bech32Opnet prefix)
340
+ const opData = fromHex('751e');
341
+ const opAddr = address.toBech32(opData, 16, networks.bitcoin.bech32, networks.bitcoin.bech32Opnet);
342
+ console.log(opAddr); // 'op1sw50qcspuvz'
343
+ ```
344
+
345
+ ---
346
+
347
+ ### fromOutputScript()
348
+
349
+ Converts an output script (`scriptPubKey`) into its corresponding address string. Uses fast byte-pattern matching for common script types (P2PKH, P2SH, P2WPKH, P2WSH, P2TR, P2MR) and falls back to payment constructors for exotic types like P2OP and future SegWit.
350
+
351
+ ```typescript
352
+ function fromOutputScript(output: Uint8Array, network?: Network): string
353
+ ```
354
+
355
+ | Parameter | Type | Description |
356
+ |-----------|------|-------------|
357
+ | `output` | `Uint8Array` | The output script (scriptPubKey) bytes |
358
+ | `network` | `Network` (optional) | Network configuration. Defaults to `networks.bitcoin`. |
359
+
360
+ **Returns:** The address string corresponding to the output script.
361
+
362
+ **Throws:** `Error` if the output script does not match any known address format.
363
+
364
+ #### Example
365
+
366
+ ```typescript
367
+ import { address, networks, script } from '@btc-vision/bitcoin';
368
+
369
+ // P2PKH output script to address
370
+ const p2pkhScript = script.fromASM(
371
+ 'OP_DUP OP_HASH160 751e76e8199196d454941c45d1b3a323f1433bd6 OP_EQUALVERIFY OP_CHECKSIG'
372
+ );
373
+ const p2pkhAddr = address.fromOutputScript(p2pkhScript);
374
+ console.log(p2pkhAddr); // '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH'
375
+
376
+ // P2SH output script to address
377
+ const p2shScript = script.fromASM(
378
+ 'OP_HASH160 cd7b44d0b03f2d026d1e586d7ae18903b0d385f6 OP_EQUAL'
379
+ );
380
+ const p2shAddr = address.fromOutputScript(p2shScript);
381
+ console.log(p2shAddr); // '3LRW7jeCvQCRdPF8S3yUCfRAx4eqXFmdcr'
382
+
383
+ // P2WPKH output script to address
384
+ const p2wpkhScript = script.fromASM(
385
+ 'OP_0 751e76e8199196d454941c45d1b3a323f1433bd6'
386
+ );
387
+ const p2wpkhAddr = address.fromOutputScript(p2wpkhScript);
388
+ console.log(p2wpkhAddr); // 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'
389
+
390
+ // P2TR output script to address
391
+ const p2trScript = script.fromASM(
392
+ 'OP_1 8e5203f25093c03a199b87b6c39427c09f8181abe1b25dc34818106c160884d7'
393
+ );
394
+ const p2trAddr = address.fromOutputScript(p2trScript);
395
+ console.log(p2trAddr); // 'bc1p3efq8ujsj0qr5xvms7mv89p8cz0crqdtuxe9ms6grqgxc9sgsntslthf6w'
396
+
397
+ // P2MR output script to address (must be 34 bytes: OP_2 + 32-byte push)
398
+ const p2mrScript = script.fromASM(
399
+ 'OP_2 8e5203f25093c03a199b87b6c39427c09f8181abe1b25dc34818106c160884d7'
400
+ );
401
+ const p2mrAddr = address.fromOutputScript(p2mrScript);
402
+ console.log(p2mrAddr); // 'bc1z3efq8ujsj0qr5xvms7mv89p8cz0crqdtuxe9ms6grqgxc9sgsntssjqzpz'
403
+
404
+ // Using a specific network
405
+ const testnetScript = script.fromASM(
406
+ 'OP_0 751e76e8199196d454941c45d1b3a323f1433bd6'
407
+ );
408
+ const testnetAddr = address.fromOutputScript(testnetScript, networks.testnet);
409
+ console.log(testnetAddr); // 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx'
410
+ ```
411
+
412
+ ---
413
+
414
+ ### toOutputScript()
415
+
416
+ Converts an address string into its corresponding output script (`scriptPubKey`). Accepts either a `Network` object or a `ToOutputScriptOptions` object as the second parameter.
417
+
418
+ ```typescript
419
+ function toOutputScript(
420
+ address: string,
421
+ networkOrOptions?: Network | ToOutputScriptOptions,
422
+ ): Uint8Array
423
+ ```
424
+
425
+ | Parameter | Type | Description |
426
+ |-----------|------|-------------|
427
+ | `address` | `string` | The address to convert |
428
+ | `networkOrOptions` | `Network \| ToOutputScriptOptions` (optional) | Network or options object. Defaults to `networks.bitcoin`. |
429
+
430
+ **Returns:** The output script as `Uint8Array`.
431
+
432
+ **Throws:** `TypeError` if the address does not match any known script pattern for the given network.
433
+
434
+ #### Example: Basic Usage
435
+
436
+ ```typescript
437
+ import { address, script, networks } from '@btc-vision/bitcoin';
438
+
439
+ // P2PKH address to output script
440
+ const p2pkhOutput = address.toOutputScript('1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH');
441
+ console.log(script.toASM(p2pkhOutput));
442
+ // 'OP_DUP OP_HASH160 751e76e8199196d454941c45d1b3a323f1433bd6 OP_EQUALVERIFY OP_CHECKSIG'
443
+
444
+ // P2SH address to output script
445
+ const p2shOutput = address.toOutputScript('3LRW7jeCvQCRdPF8S3yUCfRAx4eqXFmdcr');
446
+ console.log(script.toASM(p2shOutput));
447
+ // 'OP_HASH160 cd7b44d0b03f2d026d1e586d7ae18903b0d385f6 OP_EQUAL'
448
+
449
+ // P2WPKH address to output script
450
+ const wpkhOutput = address.toOutputScript(
451
+ 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'
452
+ );
453
+ console.log(script.toASM(wpkhOutput));
454
+ // 'OP_0 751e76e8199196d454941c45d1b3a323f1433bd6'
455
+
456
+ // P2TR address to output script
457
+ const trOutput = address.toOutputScript(
458
+ 'bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0'
459
+ );
460
+ console.log(script.toASM(trOutput));
461
+ // 'OP_1 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'
462
+ ```
463
+
464
+ #### Example: With Network
465
+
466
+ ```typescript
467
+ import { address, script, networks } from '@btc-vision/bitcoin';
468
+
469
+ // Testnet P2PKH
470
+ const testnetOutput = address.toOutputScript(
471
+ 'mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r',
472
+ networks.testnet,
473
+ );
474
+ console.log(script.toASM(testnetOutput));
475
+ // 'OP_DUP OP_HASH160 751e76e8199196d454941c45d1b3a323f1433bd6 OP_EQUALVERIFY OP_CHECKSIG'
476
+
477
+ // Testnet P2SH
478
+ const testnetP2sh = address.toOutputScript(
479
+ '2NByiBUaEXrhmqAsg7BbLpcQSAQs1EDwt5w',
480
+ networks.testnet,
481
+ );
482
+ console.log(script.toASM(testnetP2sh));
483
+ // 'OP_HASH160 cd7b44d0b03f2d026d1e586d7ae18903b0d385f6 OP_EQUAL'
484
+ ```
485
+
486
+ #### Example: With ToOutputScriptOptions
487
+
488
+ ```typescript
489
+ import { address, networks } from '@btc-vision/bitcoin';
490
+
491
+ // Use the options form to capture future segwit version warnings
492
+ const output = address.toOutputScript('bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs', {
493
+ network: networks.bitcoin,
494
+ onFutureSegwitWarning: (warning) => {
495
+ console.warn('Segwit warning:', warning);
496
+ // WARNING: Sending to a future segwit version address can lead to loss of funds...
497
+ },
498
+ });
499
+ ```
500
+
501
+ #### Address Type Routing
502
+
503
+ `toOutputScript` automatically routes addresses to the correct payment constructor:
504
+
505
+ | Decoded Result | Condition | Payment Constructor |
506
+ |----------------|-----------|-------------------|
507
+ | Base58Check, version = `pubKeyHash` | Version matches network | `p2pkh()` |
508
+ | Base58Check, version = `scriptHash` | Version matches network | `p2sh()` |
509
+ | Bech32, version 0, 20-byte data | | `p2wpkh()` |
510
+ | Bech32, version 0, 32-byte data | | `p2wsh()` |
511
+ | Bech32m, version 1, 32-byte data | | `p2tr()` |
512
+ | Bech32m, version 2, 32-byte data | | `p2mr()` |
513
+ | Bech32m, version 16 | Network has `bech32Opnet` defined | `p2op()` |
514
+ | Bech32m, version 2-15, 2-40 byte data | Future SegWit | Raw `OP_n <data>` script |
515
+
516
+ ---
517
+
518
+ ### toFutureOPNetAddress()
519
+
520
+ Encodes an output script into a future OPNet address using Bech32m. This handles witness versions 15-16 with the OPNet-specific Bech32m prefix (`bech32Opnet`). The function parses the opcode and push-data from the raw output script to extract the witness version and program.
521
+
522
+ ```typescript
523
+ function toFutureOPNetAddress(output: Uint8Array, network: Network): string
524
+ ```
525
+
526
+ | Parameter | Type | Description |
527
+ |-----------|------|-------------|
528
+ | `output` | `Uint8Array` | Output script buffer containing version opcode and witness program |
529
+ | `network` | `Network` | Network object (must have `bech32Opnet` defined) |
530
+
531
+ **Returns:** Bech32m-encoded OPNet address string.
532
+
533
+ **Throws:**
534
+ - `TypeError` if `output` is not a `Uint8Array`
535
+ - `Error` if the network does not support OPNet (`bech32Opnet` is falsy)
536
+ - `TypeError` if the program length is outside the valid range (2-40 bytes)
537
+ - `TypeError` if the witness version is outside the valid range (15-16)
538
+
539
+ #### Example
540
+
541
+ ```typescript
542
+ import { address, networks, script } from '@btc-vision/bitcoin';
543
+
544
+ // Build a P2OP output script: OP_16 <program>
545
+ const opScript = script.fromASM('OP_16 751e');
546
+ const opAddress = address.toFutureOPNetAddress(opScript, networks.bitcoin);
547
+ console.log(opAddress); // 'op1sw50qcspuvz'
548
+ ```
549
+
550
+ ---
551
+
552
+ ### _toFutureSegwitAddress()
553
+
554
+ Encodes an output script for future SegWit versions (v2-v15) into a Bech32m address. This is an internal helper used by `fromOutputScript()` as a fallback for non-standard future SegWit scripts. The function expects the output script to be in the format `[version_opcode, data_length, ...data]`.
555
+
556
+ ```typescript
557
+ function _toFutureSegwitAddress(output: Uint8Array, network: Network): string
558
+ ```
559
+
560
+ | Parameter | Type | Description |
561
+ |-----------|------|-------------|
562
+ | `output` | `Uint8Array` | Output script with version opcode at byte 0, length at byte 1, then data |
563
+ | `network` | `Network` | Network object with `bech32` prefix |
564
+
565
+ **Returns:** Bech32m-encoded address string.
566
+
567
+ **Throws:**
568
+ - `TypeError` if the program length is outside 2-40 bytes
569
+ - `TypeError` if the version is outside 2-15
570
+ - `TypeError` if byte 1 does not match the actual data length
571
+
572
+ #### Example
573
+
574
+ ```typescript
575
+ import { address, networks } from '@btc-vision/bitcoin';
576
+
577
+ // Build a raw future segwit output: OP_2 (0x52) + length + data
578
+ const output = new Uint8Array([
579
+ 0x52, // OP_2
580
+ 0x10, // 16 bytes of data
581
+ 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4,
582
+ 0x54, 0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23,
583
+ ]);
584
+ const addr = address._toFutureSegwitAddress(output, networks.bitcoin);
585
+ console.log(addr); // 'bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs'
586
+ ```
587
+
588
+ ---
589
+
590
+ ### isUnknownSegwitVersion()
591
+
592
+ Checks whether an output script corresponds to an unknown (future) SegWit version. Returns `true` if the script has a valid future SegWit structure (version 2-16, program length 2-40 bytes), excluding version 1 (Taproot, which is a known version).
593
+
594
+ ```typescript
595
+ const isUnknownSegwitVersion: (output: Uint8Array) => boolean
596
+ ```
597
+
598
+ | Parameter | Type | Description |
599
+ |-----------|------|-------------|
600
+ | `output` | `Uint8Array` | The output script to check |
601
+
602
+ **Returns:** `true` if the script matches a future/unknown SegWit version pattern, `false` otherwise.
603
+
604
+ #### Example
605
+
606
+ ```typescript
607
+ import { address, script } from '@btc-vision/bitcoin';
608
+
609
+ // A SegWit v2 output is considered "unknown" (future)
610
+ const v2Script = new Uint8Array([
611
+ 0x52, // OP_2
612
+ 0x10, // 16 bytes
613
+ 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4,
614
+ 0x54, 0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23,
615
+ ]);
616
+ console.log(address.isUnknownSegwitVersion(v2Script)); // true
617
+
618
+ // A SegWit v0 output (P2WPKH) is NOT unknown
619
+ const v0Script = new Uint8Array([
620
+ 0x00, // OP_0
621
+ 0x14, // 20 bytes
622
+ ...new Uint8Array(20),
623
+ ]);
624
+ console.log(address.isUnknownSegwitVersion(v0Script)); // false
625
+
626
+ // A SegWit v1 output (Taproot) is NOT unknown (it's recognized)
627
+ const v1Script = new Uint8Array([
628
+ 0x51, // OP_1
629
+ 0x20, // 32 bytes
630
+ ...new Uint8Array(32),
631
+ ]);
632
+ console.log(address.isUnknownSegwitVersion(v1Script)); // false
633
+ ```
634
+
635
+ ---
636
+
637
+ ## Complete Workflow Examples
638
+
639
+ ### Round-Trip: Address to Script and Back
640
+
641
+ ```typescript
642
+ import { address, script, networks } from '@btc-vision/bitcoin';
643
+
644
+ const originalAddress = 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4';
645
+
646
+ // Address -> Output Script
647
+ const outputScript = address.toOutputScript(originalAddress);
648
+ console.log(script.toASM(outputScript));
649
+ // 'OP_0 751e76e8199196d454941c45d1b3a323f1433bd6'
650
+
651
+ // Output Script -> Address
652
+ const recoveredAddress = address.fromOutputScript(outputScript);
653
+ console.log(recoveredAddress === originalAddress); // true
654
+ ```
655
+
656
+ ### Detecting Address Type from a String
657
+
658
+ ```typescript
659
+ import { address } from '@btc-vision/bitcoin';
660
+
661
+ function getAddressType(addr: string): string {
662
+ // Try Base58Check first
663
+ try {
664
+ const decoded = address.fromBase58Check(addr);
665
+ if (decoded.version === 0x00) return 'P2PKH';
666
+ if (decoded.version === 0x05) return 'P2SH';
667
+ return `Base58Check (version ${decoded.version})`;
668
+ } catch {}
669
+
670
+ // Try Bech32/Bech32m
671
+ try {
672
+ const decoded = address.fromBech32(addr);
673
+ if (decoded.version === 0 && decoded.data.length === 20) return 'P2WPKH';
674
+ if (decoded.version === 0 && decoded.data.length === 32) return 'P2WSH';
675
+ if (decoded.version === 1 && decoded.data.length === 32) return 'P2TR';
676
+ if (decoded.version === 2 && decoded.data.length === 32) return 'P2MR';
677
+ if (decoded.version === 16) return 'P2OP';
678
+ return `Future SegWit v${decoded.version}`;
679
+ } catch {}
680
+
681
+ return 'Unknown';
682
+ }
683
+
684
+ console.log(getAddressType('1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH')); // 'P2PKH'
685
+ console.log(getAddressType('3LRW7jeCvQCRdPF8S3yUCfRAx4eqXFmdcr')); // 'P2SH'
686
+ console.log(getAddressType('bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4')); // 'P2WPKH'
687
+ console.log(getAddressType('bc1p3efq8ujsj0qr5xvms7mv89p8cz0crqdtuxe9ms6grqgxc9sgsntslthf6w')); // 'P2TR'
688
+ console.log(getAddressType('bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs')); // 'P2MR'
689
+ ```
690
+
691
+ ### Multi-Network Address Generation
692
+
693
+ ```typescript
694
+ import { address, networks } from '@btc-vision/bitcoin';
695
+ import type { Bytes20 } from '@btc-vision/bitcoin';
696
+ import { fromHex } from '@btc-vision/bitcoin';
697
+
698
+ const pubkeyHash = fromHex('751e76e8199196d454941c45d1b3a323f1433bd6') as Bytes20;
699
+
700
+ // Same hash, different networks produce different addresses
701
+ const mainnet = address.toBase58Check(pubkeyHash, networks.bitcoin.pubKeyHash);
702
+ const testnet = address.toBase58Check(pubkeyHash, networks.testnet.pubKeyHash);
703
+ const regtest = address.toBase58Check(pubkeyHash, networks.regtest.pubKeyHash);
704
+
705
+ console.log(mainnet); // '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH'
706
+ console.log(testnet); // 'mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r'
707
+ console.log(regtest); // 'mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r' (same version as testnet)
708
+
709
+ // SegWit addresses use the bech32 prefix
710
+ const mainnetBech32 = address.toBech32(pubkeyHash, 0, networks.bitcoin.bech32);
711
+ const testnetBech32 = address.toBech32(pubkeyHash, 0, networks.testnet.bech32);
712
+ const regtestBech32 = address.toBech32(pubkeyHash, 0, networks.regtest.bech32);
713
+
714
+ console.log(mainnetBech32); // 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'
715
+ console.log(testnetBech32); // 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx'
716
+ console.log(regtestBech32); // 'bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7k0fey5p'
717
+ ```
718
+
719
+ ### Handling Future SegWit Version Warnings
720
+
721
+ ```typescript
722
+ import { address, networks } from '@btc-vision/bitcoin';
723
+
724
+ // When decoding a future segwit address, you may want to warn users
725
+ const futureAddr = 'bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs';
726
+
727
+ const output = address.toOutputScript(futureAddr, {
728
+ network: networks.bitcoin,
729
+ onFutureSegwitWarning: (warning: string) => {
730
+ // Display this warning to the user before proceeding
731
+ console.warn(warning);
732
+ // "WARNING: Sending to a future segwit version address can lead to loss of funds..."
733
+ },
734
+ });
735
+ ```
736
+
737
+ ### Using with Payment Constructors
738
+
739
+ ```typescript
740
+ import { payments, address, networks } from '@btc-vision/bitcoin';
741
+
742
+ // Generate address from a payment, then convert back to script
743
+ const payment = payments.p2wpkh({
744
+ hash: fromHex('751e76e8199196d454941c45d1b3a323f1433bd6') as Bytes20,
745
+ });
746
+ console.log(payment.address); // 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'
747
+
748
+ // Convert the address back to the output script
749
+ const outputScript = address.toOutputScript(payment.address!);
750
+ // outputScript is identical to payment.output
751
+ ```
752
+
753
+ ---
754
+
755
+ ## Error Handling
756
+
757
+ All address functions throw typed errors for invalid input:
758
+
759
+ ```typescript
760
+ import { address } from '@btc-vision/bitcoin';
761
+
762
+ // Base58Check: too short
763
+ try {
764
+ address.fromBase58Check('7SeEnXWPaCCALbVrTnszCVGfRU8cGfx');
765
+ } catch (e) {
766
+ console.log(e.message); // '7SeEnXWPaCCALbVrTnszCVGfRU8cGfx is too short'
767
+ }
768
+
769
+ // Base58Check: too long
770
+ try {
771
+ address.fromBase58Check('j9ywUkWg2fTQrouxxh5rSZhRvrjMkEUfuiKe');
772
+ } catch (e) {
773
+ console.log(e.message); // 'j9ywUkWg2fTQrouxxh5rSZhRvrjMkEUfuiKe is too long'
774
+ }
775
+
776
+ // Bech32: wrong encoding (bech32 used with non-zero version)
777
+ try {
778
+ address.fromBech32('bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du');
779
+ } catch (e) {
780
+ console.log(e.message); // '... uses wrong encoding'
781
+ }
782
+
783
+ // toOutputScript: no matching script
784
+ try {
785
+ address.toOutputScript('24kPZCmVgzfkpGdXExy56234MRHrsqQxNWE');
786
+ } catch (e) {
787
+ console.log(e.message); // '24kPZCmVgzfkpGdXExy56234MRHrsqQxNWE has no matching Script'
788
+ }
789
+
790
+ // toOutputScript: invalid prefix for network
791
+ try {
792
+ address.toOutputScript('bc1sw50qgdz25j', { bech32: 'foo' } as any);
793
+ } catch (e) {
794
+ console.log(e.message); // 'bc1sw50qgdz25j has an invalid prefix'
795
+ }
796
+
797
+ // fromOutputScript: unrecognized script
798
+ try {
799
+ address.fromOutputScript(new Uint8Array([0xff, 0x00]));
800
+ } catch (e) {
801
+ console.log(e.message); // '... has no matching Address'
802
+ }
803
+ ```
804
+
805
+ ---
806
+
807
+ ## Script Pattern Detection (Internal)
808
+
809
+ `fromOutputScript()` uses fast byte-level matching for performance. Here are the exact patterns it checks, in order:
810
+
811
+ | Type | Length | Byte 0 | Byte 1 | Byte 2 | Tail Bytes |
812
+ |------|--------|--------|--------|--------|------------|
813
+ | P2PKH | 25 | `0x76` (OP_DUP) | `0xa9` (OP_HASH160) | `0x14` (push 20) | `[23]=0x88, [24]=0xac` |
814
+ | P2SH | 23 | `0xa9` (OP_HASH160) | `0x14` (push 20) | - | `[22]=0x87` |
815
+ | P2WPKH | 22 | `0x00` (OP_0) | `0x14` (push 20) | - | - |
816
+ | P2WSH | 34 | `0x00` (OP_0) | `0x20` (push 32) | - | - |
817
+ | P2TR | 34 | `0x51` (OP_1) | `0x20` (push 32) | - | - |
818
+ | P2MR | 34 | `0x52` (OP_2) | `0x20` (push 32) | - | - |
819
+
820
+ If none of these match, it falls back to `toFutureOPNetAddress()` and then `_toFutureSegwitAddress()`.