@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,1485 @@
1
+ # Payments Reference
2
+
3
+ Complete reference for all Bitcoin payment types in the `@btc-vision/bitcoin` library.
4
+
5
+ Each payment type is implemented as a class with lazy-computed getters, static factory methods, and a legacy factory function for backwards compatibility.
6
+
7
+ ---
8
+
9
+ ## Overview
10
+
11
+ | Payment Type | Full Name | Class | Factory | Address Format | SegWit Version | BIP |
12
+ |---|---|---|---|---|---|---|
13
+ | P2PK | Pay-to-Public-Key | `P2PK` | `p2pk()` | None | N/A (legacy) | - |
14
+ | P2PKH | Pay-to-Public-Key-Hash | `P2PKH` | `p2pkh()` | `1...` (Base58Check) | N/A (legacy) | - |
15
+ | P2SH | Pay-to-Script-Hash | `P2SH` | `p2sh()` | `3...` (Base58Check) | N/A (legacy) | 16 |
16
+ | P2MS | Pay-to-Multisig | `P2MS` | `p2ms()` | None | N/A (legacy) | 11 |
17
+ | P2WPKH | Pay-to-Witness-Public-Key-Hash | `P2WPKH` | `p2wpkh()` | `bc1q...` (bech32) | 0 | 141 |
18
+ | P2WSH | Pay-to-Witness-Script-Hash | `P2WSH` | `p2wsh()` | `bc1q...` (bech32) | 0 | 141 |
19
+ | P2TR | Pay-to-Taproot | `P2TR` | `p2tr()` | `bc1p...` (bech32m) | 1 | 341 |
20
+ | P2MR | Pay-to-Merkle-Root | `P2MR` | `p2mr()` | `bc1z...` (bech32m) | 2 | 360 |
21
+ | P2OP | Pay-to-OPNet | `P2OP` | `p2op()` | bech32m (custom prefix) | 16 | - |
22
+ | Embed | OP_RETURN Data | `Embed` | `p2data()` | None | N/A | - |
23
+
24
+ ---
25
+
26
+ ## Import
27
+
28
+ ```typescript
29
+ import {
30
+ // Types and interfaces
31
+ PaymentType,
32
+ type BasePayment,
33
+ type ScriptRedeem,
34
+ type Payment,
35
+ type PaymentCreator,
36
+ type PaymentOpts,
37
+
38
+ // Payment classes and factory functions
39
+ P2PK, p2pk,
40
+ P2PKH, p2pkh,
41
+ P2SH, p2sh,
42
+ P2MS, p2ms,
43
+ P2WPKH, p2wpkh,
44
+ P2WSH, p2wsh,
45
+ P2TR, p2tr,
46
+ P2MR, p2mr,
47
+ P2OP, p2op,
48
+ Embed, p2data,
49
+
50
+ // Individual payment type interfaces
51
+ type P2PKPayment,
52
+ type P2PKHPayment,
53
+ type P2SHPayment,
54
+ type P2MSPayment,
55
+ type P2WPKHPayment,
56
+ type P2WSHPayment,
57
+ type P2TRPayment,
58
+ type P2MRPayment,
59
+ type P2OPPayment,
60
+ type P2OPPaymentParams,
61
+ type EmbedPayment,
62
+
63
+ // BIP341 Taproot utilities
64
+ findScriptPath,
65
+ LEAF_VERSION_TAPSCRIPT,
66
+ MAX_TAPTREE_DEPTH,
67
+ rootHashFromPath,
68
+ rootHashFromPathP2MR,
69
+ tapBranchHash,
70
+ tapleafHash,
71
+ toHashTree,
72
+ tweakKey,
73
+ type HashTree,
74
+ } from '@btc-vision/bitcoin';
75
+ ```
76
+
77
+ ---
78
+
79
+ ## PaymentType Enum
80
+
81
+ `PaymentType` is a const object used as a discriminant for the `Payment` union type. Each payment class returns its corresponding `PaymentType` value from the `name` getter.
82
+
83
+ ```typescript
84
+ const PaymentType = {
85
+ P2PK: 'p2pk',
86
+ P2PKH: 'p2pkh',
87
+ P2SH: 'p2sh',
88
+ P2MS: 'p2ms',
89
+ P2WPKH: 'p2wpkh',
90
+ P2WSH: 'p2wsh',
91
+ P2TR: 'p2tr',
92
+ P2MR: 'p2mr',
93
+ P2OP: 'p2op',
94
+ Embed: 'embed',
95
+ ScriptRedeem: 'scriptRedeem',
96
+ } as const;
97
+
98
+ type PaymentType = (typeof PaymentType)[keyof typeof PaymentType];
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Common Interfaces
104
+
105
+ ### BasePayment
106
+
107
+ The base interface shared by all payment types.
108
+
109
+ ```typescript
110
+ interface BasePayment {
111
+ readonly name?: string | undefined;
112
+ readonly network?: Network | undefined;
113
+ readonly output?: Script | undefined;
114
+ readonly input?: Script | undefined;
115
+ readonly address?: string | undefined;
116
+ readonly witness?: Uint8Array[] | undefined;
117
+ readonly redeem?: ScriptRedeem | undefined;
118
+ readonly useHybrid?: boolean | undefined;
119
+ readonly useUncompressed?: boolean | undefined;
120
+ }
121
+ ```
122
+
123
+ | Property | Type | Description |
124
+ |---|---|---|
125
+ | `name` | `string` | Discriminant label for the union type (e.g., `'p2pkh'`, `'p2tr'`). |
126
+ | `network` | `Network` | Network parameters (mainnet if omitted). |
127
+ | `output` | `Script` | Fully-assembled scriptPubKey. |
128
+ | `input` | `Script` | Raw scriptSig (legacy types only). |
129
+ | `address` | `string` | Human-readable address. |
130
+ | `witness` | `Uint8Array[]` | SegWit witness stack (empty for legacy). |
131
+ | `redeem` | `ScriptRedeem` | Script template for P2SH, P2WSH, P2TR, etc. |
132
+ | `useHybrid` | `boolean` | Use hybrid public key format (non-standard). |
133
+ | `useUncompressed` | `boolean` | Use uncompressed public key format (non-standard). |
134
+
135
+ ### ScriptRedeem
136
+
137
+ Helper interface used by redeeming script-template outputs (P2SH, P2WSH, P2TR, P2MR).
138
+
139
+ ```typescript
140
+ interface ScriptRedeem extends BasePayment {
141
+ readonly output?: Script | undefined;
142
+ readonly redeemVersion?: number | undefined;
143
+ readonly network?: Network | undefined;
144
+ }
145
+ ```
146
+
147
+ ### PaymentOpts
148
+
149
+ Options passed to constructors and factory functions.
150
+
151
+ ```typescript
152
+ interface PaymentOpts {
153
+ readonly validate?: boolean; // Validate inputs (default: true)
154
+ readonly allowIncomplete?: boolean; // Allow incomplete signatures (default: false)
155
+ }
156
+ ```
157
+
158
+ ### PaymentCreator
159
+
160
+ Generic factory function type.
161
+
162
+ ```typescript
163
+ type PaymentCreator = <T extends BasePayment>(a: T, opts?: PaymentOpts) => T;
164
+ ```
165
+
166
+ ### Payment (Union Type)
167
+
168
+ The discriminated union of all payment types.
169
+
170
+ ```typescript
171
+ type Payment =
172
+ | P2PKPayment
173
+ | P2PKHPayment
174
+ | P2SHPayment
175
+ | P2MSPayment
176
+ | P2WPKHPayment
177
+ | P2WSHPayment
178
+ | P2TRPayment
179
+ | P2MRPayment
180
+ | P2OPPayment
181
+ | EmbedPayment
182
+ | ScriptRedeem;
183
+ ```
184
+
185
+ ---
186
+
187
+ ## P2PK (Pay-to-Public-Key)
188
+
189
+ P2PK is the simplest Bitcoin payment type. The output script contains a public key directly, and spending requires a single signature from that key. P2PK has no address format.
190
+
191
+ ### Overview
192
+
193
+ | Property | Value |
194
+ |----------|-------|
195
+ | SegWit version | N/A (legacy) |
196
+ | Address format | None |
197
+ | Script size | 35 bytes (compressed) or 67 bytes (uncompressed) |
198
+
199
+ ### Script Structure
200
+
201
+ ```
202
+ Output: {pubKey} OP_CHECKSIG
203
+ Input: {signature}
204
+ Witness: [] (empty)
205
+ ```
206
+
207
+ ### Class: P2PK
208
+
209
+ ```typescript
210
+ class P2PK {
211
+ static readonly NAME = 'p2pk';
212
+
213
+ constructor(params: {
214
+ pubkey?: Uint8Array;
215
+ signature?: Uint8Array;
216
+ output?: Uint8Array;
217
+ input?: Uint8Array;
218
+ network?: Network;
219
+ }, opts?: PaymentOpts);
220
+
221
+ // Getters
222
+ get name(): 'p2pk';
223
+ get network(): Network;
224
+ get pubkey(): PublicKey | undefined;
225
+ get signature(): Signature | undefined;
226
+ get output(): Script | undefined;
227
+ get input(): Script | undefined;
228
+ get witness(): Uint8Array[] | undefined;
229
+
230
+ // Static factory methods
231
+ static fromPubkey(pubkey: PublicKey, network?: Network): P2PK;
232
+ static fromOutput(output: Uint8Array, network?: Network): P2PK;
233
+ static fromSignature(signature: Signature, pubkey?: PublicKey, network?: Network): P2PK;
234
+
235
+ toPayment(): P2PKPayment;
236
+ }
237
+ ```
238
+
239
+ ### Factory Function
240
+
241
+ ```typescript
242
+ function p2pk(a: Omit<P2PKPayment, 'name'>, opts?: PaymentOpts): P2PKPayment;
243
+ ```
244
+
245
+ ### P2PKPayment Interface
246
+
247
+ ```typescript
248
+ interface P2PKPayment extends BasePayment {
249
+ readonly name: 'p2pk';
250
+ readonly pubkey?: PublicKey | undefined;
251
+ readonly signature?: Signature | undefined;
252
+ }
253
+ ```
254
+
255
+ ### Examples
256
+
257
+ ```typescript
258
+ import { P2PK, p2pk } from '@btc-vision/bitcoin';
259
+
260
+ // Create from public key (class)
261
+ const payment = P2PK.fromPubkey(pubkey);
262
+ console.log(payment.output); // {pubKey} OP_CHECKSIG
263
+
264
+ // Create from output script (class)
265
+ const decoded = P2PK.fromOutput(scriptPubKey);
266
+ console.log(decoded.pubkey); // extracted public key
267
+
268
+ // Create from signature for spending
269
+ const spender = P2PK.fromSignature(signature, pubkey);
270
+ console.log(spender.input); // {signature}
271
+
272
+ // Legacy factory function
273
+ const legacy = p2pk({ pubkey });
274
+ console.log(legacy.output);
275
+ ```
276
+
277
+ ---
278
+
279
+ ## P2PKH (Pay-to-Public-Key-Hash)
280
+
281
+ P2PKH is the most common legacy Bitcoin payment type. The output script contains the hash of a public key, and spending requires both the full public key and a valid signature. Addresses start with `1` on mainnet.
282
+
283
+ ### Overview
284
+
285
+ | Property | Value |
286
+ |----------|-------|
287
+ | SegWit version | N/A (legacy) |
288
+ | Address format | Base58Check (`1...` mainnet, `m...`/`n...` testnet) |
289
+ | Hash algorithm | RIPEMD160(SHA256(pubkey)) = 20 bytes |
290
+ | Script size | 25 bytes |
291
+
292
+ ### Script Structure
293
+
294
+ ```
295
+ Output: OP_DUP OP_HASH160 {hash160(pubkey)} OP_EQUALVERIFY OP_CHECKSIG
296
+ Input: {signature} {pubkey}
297
+ Witness: [] (empty)
298
+ ```
299
+
300
+ ### Class: P2PKH
301
+
302
+ ```typescript
303
+ class P2PKH {
304
+ static readonly NAME = 'p2pkh';
305
+
306
+ constructor(params: {
307
+ address?: string;
308
+ hash?: Uint8Array;
309
+ pubkey?: Uint8Array;
310
+ signature?: Uint8Array;
311
+ output?: Uint8Array;
312
+ input?: Uint8Array;
313
+ network?: Network;
314
+ useHybrid?: boolean;
315
+ useUncompressed?: boolean;
316
+ }, opts?: PaymentOpts);
317
+
318
+ // Getters
319
+ get name(): 'p2pkh';
320
+ get network(): Network;
321
+ get address(): string | undefined;
322
+ get hash(): Bytes20 | undefined;
323
+ get pubkey(): PublicKey | undefined;
324
+ get signature(): Signature | undefined;
325
+ get output(): Script | undefined;
326
+ get input(): Script | undefined;
327
+ get witness(): Uint8Array[] | undefined;
328
+
329
+ // Static factory methods
330
+ static fromPubkey(pubkey: PublicKey, network?: Network): P2PKH;
331
+ static fromAddress(address: string, network?: Network): P2PKH;
332
+ static fromHash(hash: Bytes20, network?: Network): P2PKH;
333
+ static fromOutput(output: Uint8Array, network?: Network): P2PKH;
334
+
335
+ toPayment(): P2PKHPayment;
336
+ }
337
+ ```
338
+
339
+ ### Factory Function
340
+
341
+ ```typescript
342
+ function p2pkh(a: Omit<P2PKHPayment, 'name'>, opts?: PaymentOpts): P2PKHPayment;
343
+ ```
344
+
345
+ ### P2PKHPayment Interface
346
+
347
+ ```typescript
348
+ interface P2PKHPayment extends BasePayment {
349
+ readonly name: 'p2pkh';
350
+ readonly hash?: Bytes20 | undefined;
351
+ readonly pubkey?: PublicKey | undefined;
352
+ readonly signature?: Signature | undefined;
353
+ }
354
+ ```
355
+
356
+ ### Examples
357
+
358
+ ```typescript
359
+ import { P2PKH, p2pkh } from '@btc-vision/bitcoin';
360
+
361
+ // Create from public key
362
+ const payment = P2PKH.fromPubkey(pubkey);
363
+ console.log(payment.address); // 1BvBMSEYstWetq...
364
+ console.log(payment.hash); // 20-byte hash
365
+ console.log(payment.output); // OP_DUP OP_HASH160 {hash} OP_EQUALVERIFY OP_CHECKSIG
366
+
367
+ // Create from address
368
+ const fromAddr = P2PKH.fromAddress('1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2');
369
+ console.log(fromAddr.hash); // 20-byte pubkey hash
370
+
371
+ // Create from 20-byte hash
372
+ const fromHash = P2PKH.fromHash(hash160);
373
+ console.log(fromHash.address);
374
+
375
+ // Legacy factory function
376
+ const legacy = p2pkh({ pubkey });
377
+ const fromAddrLegacy = p2pkh({ address: '1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2' });
378
+ ```
379
+
380
+ ---
381
+
382
+ ## P2SH (Pay-to-Script-Hash)
383
+
384
+ P2SH allows spending to be based on a hash of a script, with the actual script revealed only at spend time. This enables complex spending conditions while keeping addresses short. Addresses start with `3` on mainnet.
385
+
386
+ ### Overview
387
+
388
+ | Property | Value |
389
+ |----------|-------|
390
+ | SegWit version | N/A (legacy, but can wrap SegWit) |
391
+ | Address format | Base58Check (`3...` mainnet, `2...` testnet) |
392
+ | Hash algorithm | HASH160(redeemScript) = 20 bytes |
393
+ | Script size | 23 bytes |
394
+ | BIP | 16 |
395
+
396
+ ### Script Structure
397
+
398
+ ```
399
+ Output: OP_HASH160 {hash160(redeemScript)} OP_EQUAL
400
+ Input: {redeemScriptSig...} {redeemScript}
401
+ Witness: [] (or forwarded from wrapped SegWit)
402
+ ```
403
+
404
+ ### Dynamic Name
405
+
406
+ The `name` getter returns a dynamic string based on the nested redeem type:
407
+ - `'p2sh'` when no redeem type is known
408
+ - `'p2sh-p2wpkh'` when wrapping P2WPKH
409
+ - `'p2sh-p2wsh'` when wrapping P2WSH
410
+
411
+ ### Class: P2SH
412
+
413
+ ```typescript
414
+ class P2SH {
415
+ static readonly NAME = 'p2sh';
416
+
417
+ constructor(params: {
418
+ address?: string;
419
+ hash?: Uint8Array;
420
+ output?: Uint8Array;
421
+ input?: Uint8Array;
422
+ redeem?: ScriptRedeem;
423
+ witness?: Uint8Array[];
424
+ network?: Network;
425
+ }, opts?: PaymentOpts);
426
+
427
+ // Getters
428
+ get name(): string; // Dynamic: 'p2sh' or 'p2sh-{redeemName}'
429
+ get network(): Network;
430
+ get address(): string | undefined;
431
+ get hash(): Bytes20 | undefined;
432
+ get output(): Script | undefined;
433
+ get input(): Script | undefined;
434
+ get redeem(): ScriptRedeem | undefined;
435
+ get witness(): Uint8Array[] | undefined;
436
+
437
+ // Static factory methods
438
+ static fromRedeem(redeem: ScriptRedeem, network?: Network): P2SH;
439
+ static fromAddress(address: string, network?: Network): P2SH;
440
+ static fromHash(hash: Bytes20, network?: Network): P2SH;
441
+ static fromOutput(output: Uint8Array, network?: Network): P2SH;
442
+
443
+ toPayment(): P2SHPayment;
444
+ }
445
+ ```
446
+
447
+ ### Factory Function
448
+
449
+ ```typescript
450
+ function p2sh(a: Omit<P2SHPayment, 'name'>, opts?: PaymentOpts): P2SHPayment;
451
+ ```
452
+
453
+ ### P2SHPayment Interface
454
+
455
+ ```typescript
456
+ interface P2SHPayment extends BasePayment {
457
+ readonly name: string; // Dynamic name
458
+ readonly hash?: Bytes20 | undefined;
459
+ readonly signatures?: Uint8Array[] | undefined;
460
+ }
461
+ ```
462
+
463
+ ### Examples
464
+
465
+ ```typescript
466
+ import { P2SH, P2MS, p2sh, p2ms } from '@btc-vision/bitcoin';
467
+
468
+ // Wrap a multisig in P2SH (class)
469
+ const multisig = P2MS.fromPubkeys(2, [pubkey1, pubkey2, pubkey3]);
470
+ const p2shPayment = P2SH.fromRedeem({ output: multisig.output });
471
+ console.log(p2shPayment.address); // 3... address
472
+ console.log(p2shPayment.hash); // 20-byte script hash
473
+
474
+ // Decode an existing P2SH output
475
+ const decoded = P2SH.fromOutput(scriptPubKey);
476
+ console.log(decoded.hash); // 20-byte script hash
477
+
478
+ // Create from address
479
+ const fromAddr = P2SH.fromAddress('3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy');
480
+
481
+ // Legacy factory function
482
+ const msig = p2ms({ m: 2, pubkeys: [pk1, pk2, pk3] });
483
+ const legacy = p2sh({ redeem: msig });
484
+ ```
485
+
486
+ ---
487
+
488
+ ## P2MS (Pay-to-Multisig)
489
+
490
+ P2MS is a bare multisig script where M-of-N signatures are required to spend the output. The public keys are embedded directly in the output script. P2MS has no address format and is typically wrapped in P2SH or P2WSH.
491
+
492
+ ### Overview
493
+
494
+ | Property | Value |
495
+ |----------|-------|
496
+ | SegWit version | N/A (legacy) |
497
+ | Address format | None |
498
+ | Max N | 16 |
499
+ | BIP | 11 |
500
+
501
+ ### Script Structure
502
+
503
+ ```
504
+ Output: OP_{m} {pubKey1} {pubKey2} ... {pubKeyN} OP_{n} OP_CHECKMULTISIG
505
+ Input: OP_0 {sig1} {sig2} ... {sigM}
506
+ Witness: [] (empty)
507
+ ```
508
+
509
+ ### Dynamic Name
510
+
511
+ The `name` getter returns a dynamic string including the M-of-N parameters:
512
+ - `'p2ms'` when M and N are unknown
513
+ - `'p2ms(2 of 3)'` when M=2, N=3
514
+
515
+ ### Class: P2MS
516
+
517
+ ```typescript
518
+ class P2MS {
519
+ static readonly NAME = 'p2ms';
520
+
521
+ constructor(params: {
522
+ m?: number;
523
+ n?: number;
524
+ pubkeys?: Uint8Array[];
525
+ signatures?: Uint8Array[];
526
+ output?: Uint8Array;
527
+ input?: Uint8Array;
528
+ network?: Network;
529
+ }, opts?: PaymentOpts);
530
+
531
+ // Getters
532
+ get name(): string; // Dynamic: 'p2ms' or 'p2ms(M of N)'
533
+ get network(): Network;
534
+ get m(): number | undefined;
535
+ get n(): number | undefined;
536
+ get pubkeys(): PublicKey[] | undefined;
537
+ get signatures(): Signature[] | undefined;
538
+ get output(): Script | undefined;
539
+ get input(): Script | undefined;
540
+ get witness(): Uint8Array[] | undefined;
541
+
542
+ // Static factory methods
543
+ static fromPubkeys(m: number, pubkeys: PublicKey[], network?: Network): P2MS;
544
+ static fromOutput(output: Uint8Array, network?: Network): P2MS;
545
+ static fromSignatures(
546
+ signatures: Signature[],
547
+ m?: number,
548
+ pubkeys?: PublicKey[],
549
+ network?: Network,
550
+ ): P2MS;
551
+
552
+ toPayment(): P2MSPayment;
553
+ }
554
+ ```
555
+
556
+ ### Factory Function
557
+
558
+ ```typescript
559
+ function p2ms(a: Omit<P2MSPayment, 'name'>, opts?: PaymentOpts): P2MSPayment;
560
+ ```
561
+
562
+ ### P2MSPayment Interface
563
+
564
+ ```typescript
565
+ interface P2MSPayment extends BasePayment {
566
+ readonly name: string; // Dynamic name
567
+ readonly m?: number | undefined;
568
+ readonly n?: number | undefined;
569
+ readonly pubkeys?: PublicKey[] | undefined;
570
+ readonly signatures?: Signature[] | undefined;
571
+ }
572
+ ```
573
+
574
+ ### Examples
575
+
576
+ ```typescript
577
+ import { P2MS, p2ms } from '@btc-vision/bitcoin';
578
+
579
+ // Create a 2-of-3 multisig (class)
580
+ const payment = P2MS.fromPubkeys(2, [pubkey1, pubkey2, pubkey3]);
581
+ console.log(payment.output); // OP_2 {pk1} {pk2} {pk3} OP_3 OP_CHECKMULTISIG
582
+ console.log(payment.m); // 2
583
+ console.log(payment.n); // 3
584
+ console.log(payment.name); // 'p2ms(2 of 3)'
585
+
586
+ // Decode an existing output
587
+ const decoded = P2MS.fromOutput(scriptPubKey);
588
+ console.log(decoded.pubkeys); // array of public keys
589
+ console.log(decoded.m); // required signatures
590
+ console.log(decoded.n); // total keys
591
+
592
+ // Create from signatures for spending
593
+ const spender = P2MS.fromSignatures([sig1, sig2], 2, [pk1, pk2, pk3]);
594
+ console.log(spender.input); // OP_0 {sig1} {sig2}
595
+
596
+ // Legacy factory function
597
+ const legacy = p2ms({ m: 2, pubkeys: [pubkey1, pubkey2, pubkey3] });
598
+ ```
599
+
600
+ ---
601
+
602
+ ## P2WPKH (Pay-to-Witness-Public-Key-Hash)
603
+
604
+ P2WPKH is the native SegWit version of P2PKH. The witness program is a 20-byte pubkey hash, and spending requires the signature and public key in the witness stack (not the scriptSig). Addresses use bech32 encoding with the `bc1q` prefix on mainnet.
605
+
606
+ ### Overview
607
+
608
+ | Property | Value |
609
+ |----------|-------|
610
+ | SegWit version | 0 (`OP_0`) |
611
+ | Address format | bech32 (`bc1q...` mainnet, `tb1q...` testnet, `bcrt1q...` regtest) |
612
+ | Hash algorithm | RIPEMD160(SHA256(pubkey)) = 20 bytes |
613
+ | Script size | 22 bytes |
614
+ | BIP | 141, 143 |
615
+ | Key requirement | Compressed keys only (33 bytes) |
616
+
617
+ ### Script Structure
618
+
619
+ ```
620
+ Output: OP_0 {hash160(pubkey)}
621
+ Input: (empty)
622
+ Witness: [{signature}, {pubkey}]
623
+ ```
624
+
625
+ ### Class: P2WPKH
626
+
627
+ ```typescript
628
+ class P2WPKH {
629
+ static readonly NAME = 'p2wpkh';
630
+
631
+ constructor(params: {
632
+ address?: string;
633
+ hash?: Uint8Array;
634
+ pubkey?: Uint8Array;
635
+ signature?: Uint8Array;
636
+ output?: Uint8Array;
637
+ witness?: Uint8Array[];
638
+ network?: Network;
639
+ }, opts?: PaymentOpts);
640
+
641
+ // Getters
642
+ get name(): 'p2wpkh';
643
+ get network(): Network;
644
+ get address(): string | undefined;
645
+ get hash(): Bytes20 | undefined;
646
+ get pubkey(): PublicKey | undefined;
647
+ get signature(): Signature | undefined;
648
+ get output(): Script | undefined;
649
+ get input(): Script | undefined; // Always empty for native SegWit
650
+ get witness(): Uint8Array[] | undefined;
651
+
652
+ // Static factory methods
653
+ static fromPubkey(pubkey: PublicKey, network?: Network): P2WPKH;
654
+ static fromAddress(address: string, network?: Network): P2WPKH;
655
+ static fromHash(hash: Bytes20, network?: Network): P2WPKH;
656
+ static fromOutput(output: Uint8Array, network?: Network): P2WPKH;
657
+
658
+ toPayment(): P2WPKHPayment;
659
+ }
660
+ ```
661
+
662
+ ### Factory Function
663
+
664
+ ```typescript
665
+ function p2wpkh(a: Omit<P2WPKHPayment, 'name'>, opts?: PaymentOpts): P2WPKHPayment;
666
+ ```
667
+
668
+ ### P2WPKHPayment Interface
669
+
670
+ ```typescript
671
+ interface P2WPKHPayment extends BasePayment {
672
+ readonly name: 'p2wpkh';
673
+ readonly hash?: Bytes20 | undefined;
674
+ readonly pubkey?: PublicKey | undefined;
675
+ readonly signature?: Signature | undefined;
676
+ }
677
+ ```
678
+
679
+ ### Examples
680
+
681
+ ```typescript
682
+ import { P2WPKH, p2wpkh } from '@btc-vision/bitcoin';
683
+
684
+ // Create from public key (class)
685
+ const payment = P2WPKH.fromPubkey(pubkey);
686
+ console.log(payment.address); // bc1q...
687
+ console.log(payment.hash); // 20-byte witness program
688
+ console.log(payment.output); // OP_0 {20-byte hash}
689
+
690
+ // Create from bech32 address
691
+ const fromAddr = P2WPKH.fromAddress('bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4');
692
+ console.log(fromAddr.hash); // 20-byte witness program
693
+
694
+ // Create from hash
695
+ const fromHash = P2WPKH.fromHash(hash160);
696
+ console.log(fromHash.address);
697
+
698
+ // Legacy factory function
699
+ const legacy = p2wpkh({ pubkey });
700
+ const fromAddrLegacy = p2wpkh({ address: 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4' });
701
+ ```
702
+
703
+ ---
704
+
705
+ ## P2WSH (Pay-to-Witness-Script-Hash)
706
+
707
+ P2WSH is the native SegWit version of P2SH. The witness program is a 32-byte SHA256 hash of the redeem script, and spending requires the witness stack with the script inputs and the script itself. Addresses use bech32 encoding.
708
+
709
+ ### Overview
710
+
711
+ | Property | Value |
712
+ |----------|-------|
713
+ | SegWit version | 0 (`OP_0`) |
714
+ | Address format | bech32 (`bc1q...` mainnet, `tb1q...` testnet, `bcrt1q...` regtest) |
715
+ | Hash algorithm | SHA256(redeemScript) = 32 bytes |
716
+ | Script size | 34 bytes |
717
+ | BIP | 141, 143 |
718
+ | Max script size | 3600 bytes |
719
+ | Max non-push ops | 201 |
720
+
721
+ ### Script Structure
722
+
723
+ ```
724
+ Output: OP_0 {sha256(redeemScript)}
725
+ Input: (empty)
726
+ Witness: [{scriptSig...}, {redeemScript}]
727
+ ```
728
+
729
+ ### Dynamic Name
730
+
731
+ The `name` getter returns a dynamic string based on the nested redeem type:
732
+ - `'p2wsh'` when no redeem type is known
733
+ - `'p2wsh-p2pk'` when wrapping P2PK
734
+
735
+ ### Class: P2WSH
736
+
737
+ ```typescript
738
+ class P2WSH {
739
+ static readonly NAME = 'p2wsh';
740
+
741
+ constructor(params: {
742
+ address?: string;
743
+ hash?: Uint8Array;
744
+ output?: Uint8Array;
745
+ redeem?: ScriptRedeem;
746
+ witness?: Uint8Array[];
747
+ network?: Network;
748
+ }, opts?: PaymentOpts);
749
+
750
+ // Getters
751
+ get name(): string; // Dynamic: 'p2wsh' or 'p2wsh-{redeemName}'
752
+ get network(): Network;
753
+ get address(): string | undefined;
754
+ get hash(): Bytes32 | undefined;
755
+ get output(): Script | undefined;
756
+ get input(): Script | undefined; // Always empty for native SegWit
757
+ get redeem(): ScriptRedeem | undefined;
758
+ get witness(): Uint8Array[] | undefined;
759
+
760
+ // Static factory methods
761
+ static fromRedeem(redeem: ScriptRedeem, network?: Network): P2WSH;
762
+ static fromAddress(address: string, network?: Network): P2WSH;
763
+ static fromHash(hash: Bytes32, network?: Network): P2WSH;
764
+ static fromOutput(output: Uint8Array, network?: Network): P2WSH;
765
+
766
+ toPayment(): P2WSHPayment;
767
+ }
768
+ ```
769
+
770
+ ### Factory Function
771
+
772
+ ```typescript
773
+ function p2wsh(a: Omit<P2WSHPayment, 'name'>, opts?: PaymentOpts): P2WSHPayment;
774
+ ```
775
+
776
+ ### P2WSHPayment Interface
777
+
778
+ ```typescript
779
+ interface P2WSHPayment extends BasePayment {
780
+ readonly name: string; // Dynamic name
781
+ readonly hash?: Bytes32 | undefined;
782
+ readonly redeem?: ScriptRedeem | undefined;
783
+ }
784
+ ```
785
+
786
+ ### Examples
787
+
788
+ ```typescript
789
+ import { P2WSH, P2MS, p2wsh, p2ms } from '@btc-vision/bitcoin';
790
+
791
+ // Wrap a multisig in P2WSH (class)
792
+ const multisig = P2MS.fromPubkeys(2, [pubkey1, pubkey2, pubkey3]);
793
+ const p2wshPayment = P2WSH.fromRedeem({ output: multisig.output });
794
+ console.log(p2wshPayment.address); // bc1q... (62-character bech32)
795
+ console.log(p2wshPayment.hash); // 32-byte SHA256 hash
796
+
797
+ // Decode an existing output
798
+ const decoded = P2WSH.fromOutput(scriptPubKey);
799
+ console.log(decoded.hash); // 32-byte witness program
800
+
801
+ // Create from address
802
+ const fromAddr = P2WSH.fromAddress('bc1q...');
803
+
804
+ // Legacy factory function
805
+ const msig = p2ms({ m: 2, pubkeys: [pk1, pk2, pk3] });
806
+ const legacy = p2wsh({ redeem: msig });
807
+ ```
808
+
809
+ ---
810
+
811
+ ## P2TR (Pay-to-Taproot)
812
+
813
+ P2TR is the Taproot output type (BIP 341). It supports both key-path spending (single Schnorr signature) and script-path spending (Merkle tree of scripts). Addresses use bech32m encoding with the `bc1p` prefix on mainnet.
814
+
815
+ ### Overview
816
+
817
+ | Property | Value |
818
+ |----------|-------|
819
+ | SegWit version | 1 (`OP_1`) |
820
+ | Address format | bech32m (`bc1p...` mainnet, `tb1p...` testnet, `bcrt1p...` regtest) |
821
+ | BIP | 341, 342 |
822
+ | Key type | x-only public keys (32 bytes) |
823
+ | Key-path spend | Yes |
824
+ | Script-path spend | Yes |
825
+
826
+ ### Script Structure
827
+
828
+ ```
829
+ Output: OP_1 {32-byte x-only tweaked pubkey}
830
+
831
+ Key-path witness: [{schnorr_signature}]
832
+
833
+ Script-path witness: [{script inputs...}, {script}, {control block}]
834
+ Control block: [{version | parity}, {32-byte internal pubkey}, {merkle path...}]
835
+ Size: 33 + 32*m bytes (0 <= m <= 128)
836
+ ```
837
+
838
+ ### Class: P2TR
839
+
840
+ ```typescript
841
+ class P2TR {
842
+ static readonly NAME = 'p2tr';
843
+
844
+ constructor(params: {
845
+ address?: string;
846
+ pubkey?: Uint8Array;
847
+ internalPubkey?: Uint8Array;
848
+ hash?: Uint8Array;
849
+ scriptTree?: Taptree;
850
+ signature?: Uint8Array;
851
+ output?: Uint8Array;
852
+ witness?: Uint8Array[];
853
+ redeem?: ScriptRedeem;
854
+ redeemVersion?: number;
855
+ network?: Network;
856
+ }, opts?: PaymentOpts);
857
+
858
+ // Getters
859
+ get name(): 'p2tr';
860
+ get network(): Network;
861
+ get address(): string | undefined;
862
+ get pubkey(): XOnlyPublicKey | undefined; // Tweaked output pubkey
863
+ get internalPubkey(): XOnlyPublicKey | undefined; // Untweaked internal pubkey
864
+ get hash(): Bytes32 | undefined; // Merkle root
865
+ get signature(): SchnorrSignature | undefined;
866
+ get output(): Script | undefined;
867
+ get redeem(): ScriptRedeem | undefined;
868
+ get redeemVersion(): number; // Default: 0xc0
869
+ get witness(): Uint8Array[] | undefined;
870
+
871
+ // Static factory methods
872
+ static fromInternalPubkey(
873
+ internalPubkey: XOnlyPublicKey,
874
+ scriptTree?: Taptree,
875
+ network?: Network,
876
+ ): P2TR;
877
+ static fromAddress(address: string, network?: Network): P2TR;
878
+ static fromOutput(output: Uint8Array, network?: Network): P2TR;
879
+ static fromSignature(
880
+ signature: SchnorrSignature,
881
+ internalPubkey?: XOnlyPublicKey,
882
+ network?: Network,
883
+ ): P2TR;
884
+
885
+ toPayment(): P2TRPayment;
886
+ }
887
+ ```
888
+
889
+ ### Factory Function
890
+
891
+ ```typescript
892
+ function p2tr(a: Omit<P2TRPayment, 'name'>, opts?: PaymentOpts): P2TRPayment;
893
+ ```
894
+
895
+ ### P2TRPayment Interface
896
+
897
+ ```typescript
898
+ interface P2TRPayment extends BasePayment {
899
+ readonly name: 'p2tr';
900
+ readonly pubkey?: XOnlyPublicKey | undefined;
901
+ readonly internalPubkey?: XOnlyPublicKey | undefined;
902
+ readonly hash?: Bytes32 | undefined;
903
+ readonly scriptTree?: Taptree | undefined;
904
+ readonly signature?: SchnorrSignature | undefined;
905
+ readonly redeemVersion?: number | undefined;
906
+ readonly redeem?: ScriptRedeem | undefined;
907
+ }
908
+ ```
909
+
910
+ ### Examples
911
+
912
+ ```typescript
913
+ import { P2TR, p2tr } from '@btc-vision/bitcoin';
914
+ import * as script from '@btc-vision/bitcoin/script';
915
+
916
+ // Key-path only (no scripts)
917
+ const keyOnly = P2TR.fromInternalPubkey(internalPubkey);
918
+ console.log(keyOnly.address); // bc1p...
919
+ console.log(keyOnly.pubkey); // 32-byte tweaked x-only pubkey
920
+ console.log(keyOnly.output); // OP_1 {32-byte pubkey}
921
+
922
+ // With script tree
923
+ const scriptTree = [
924
+ { output: script1 },
925
+ { output: script2 },
926
+ ];
927
+ const withScripts = P2TR.fromInternalPubkey(internalPubkey, scriptTree);
928
+ console.log(withScripts.address);
929
+
930
+ // Script-path spending (with witness construction)
931
+ const spending = new P2TR({
932
+ internalPubkey,
933
+ scriptTree,
934
+ redeem: { output: script1 },
935
+ });
936
+ console.log(spending.witness);
937
+ // [script1, controlBlock]
938
+ // controlBlock = [version | parity, internalPubkey, ...merklePath]
939
+
940
+ // Decode from address
941
+ const fromAddr = P2TR.fromAddress('bc1p...');
942
+ console.log(fromAddr.pubkey); // 32-byte x-only pubkey
943
+
944
+ // Key-path spending with signature
945
+ const signed = P2TR.fromSignature(schnorrSignature, internalPubkey);
946
+ console.log(signed.witness); // [signature]
947
+
948
+ // Legacy factory function
949
+ const legacy = p2tr({ internalPubkey });
950
+ const withTree = p2tr({ internalPubkey, scriptTree });
951
+ ```
952
+
953
+ ---
954
+
955
+ ## P2MR (Pay-to-Merkle-Root)
956
+
957
+ P2MR is a SegWit version 2 output type (BIP 360) that commits directly to the Merkle root of a script tree, removing the quantum-vulnerable key-path spend found in P2TR. There is no internal public key or key tweaking. Addresses use bech32m encoding with the `bc1z` prefix on mainnet.
958
+
959
+ ### Overview
960
+
961
+ | Property | Value |
962
+ |----------|-------|
963
+ | SegWit version | 2 (`OP_2` = `0x52`) |
964
+ | Address format | bech32m (`bc1z...` mainnet, `tb1z...` testnet, `bcrt1z...` regtest) |
965
+ | BIP | 360 |
966
+ | Key-path spend | None (quantum-safe) |
967
+ | Script-path spend | Yes |
968
+ | Witness program | 32-byte Merkle root |
969
+
970
+ ### Comparison with P2TR
971
+
972
+ | Aspect | P2TR (BIP 341) | P2MR (BIP 360) |
973
+ |--------|----------------|----------------|
974
+ | SegWit version | 1 (`OP_1`) | 2 (`OP_2`) |
975
+ | Address prefix | `bc1p` | `bc1z` |
976
+ | Key-path spend | Yes | No |
977
+ | Output commitment | `tweakKey(internalPubkey, merkleRoot)` | `merkleRoot` directly |
978
+ | Control block | `33 + 32*m` bytes (includes internal pubkey) | `1 + 32*m` bytes (no internal pubkey) |
979
+ | Control byte parity bit | 0 or 1 | Always 1 |
980
+
981
+ ### Script Structure
982
+
983
+ ```
984
+ Output: OP_2 {32-byte merkle root}
985
+
986
+ Script-path witness: [{script inputs...}, {script}, {control block}]
987
+ Control block: [{version_byte | 0x01}, {merkle_path...}]
988
+ Size: 1 + 32*m bytes (0 <= m <= 128)
989
+ ```
990
+
991
+ ### Class: P2MR
992
+
993
+ ```typescript
994
+ class P2MR {
995
+ static readonly NAME = 'p2mr';
996
+
997
+ constructor(params: {
998
+ address?: string;
999
+ hash?: Uint8Array;
1000
+ scriptTree?: Taptree;
1001
+ output?: Uint8Array;
1002
+ witness?: Uint8Array[];
1003
+ redeem?: ScriptRedeem;
1004
+ redeemVersion?: number;
1005
+ network?: Network;
1006
+ }, opts?: PaymentOpts);
1007
+
1008
+ // Getters
1009
+ get name(): 'p2mr';
1010
+ get network(): Network;
1011
+ get address(): string | undefined;
1012
+ get hash(): Bytes32 | undefined; // Merkle root (= witness program)
1013
+ get output(): Script | undefined;
1014
+ get redeem(): ScriptRedeem | undefined;
1015
+ get redeemVersion(): number; // Default: 0xc0
1016
+ get witness(): Uint8Array[] | undefined;
1017
+
1018
+ // Static factory methods
1019
+ static fromScriptTree(scriptTree: Taptree, network?: Network): P2MR;
1020
+ static fromAddress(address: string, network?: Network): P2MR;
1021
+ static fromOutput(output: Uint8Array, network?: Network): P2MR;
1022
+ static fromHash(hash: Bytes32, network?: Network): P2MR;
1023
+
1024
+ toPayment(): P2MRPayment;
1025
+ }
1026
+ ```
1027
+
1028
+ ### Factory Function
1029
+
1030
+ ```typescript
1031
+ function p2mr(a: Omit<P2MRPayment, 'name'>, opts?: PaymentOpts): P2MRPayment;
1032
+ ```
1033
+
1034
+ ### P2MRPayment Interface
1035
+
1036
+ ```typescript
1037
+ interface P2MRPayment extends BasePayment {
1038
+ readonly name: 'p2mr';
1039
+ readonly hash?: Bytes32 | undefined;
1040
+ readonly scriptTree?: Taptree | undefined;
1041
+ readonly redeemVersion?: number | undefined;
1042
+ readonly redeem?: ScriptRedeem | undefined;
1043
+ }
1044
+ ```
1045
+
1046
+ ### Examples
1047
+
1048
+ ```typescript
1049
+ import { P2MR, p2mr } from '@btc-vision/bitcoin';
1050
+ import * as script from '@btc-vision/bitcoin/script';
1051
+
1052
+ // Create from a script tree
1053
+ const scriptTree = {
1054
+ output: script.compile([script.opcodes.OP_1]),
1055
+ };
1056
+ const payment = P2MR.fromScriptTree(scriptTree);
1057
+ console.log(payment.address); // bc1z...
1058
+ console.log(payment.hash); // 32-byte Merkle root
1059
+ console.log(payment.output); // OP_2 {32-byte hash}
1060
+
1061
+ // Multi-leaf tree
1062
+ const multiLeaf = [
1063
+ { output: script1 },
1064
+ { output: script2 },
1065
+ ];
1066
+ const multi = P2MR.fromScriptTree(multiLeaf);
1067
+
1068
+ // Create from merkle root hash
1069
+ const fromHash = P2MR.fromHash(merkleRoot);
1070
+ console.log(fromHash.address); // bc1z...
1071
+
1072
+ // Create from address
1073
+ const fromAddr = P2MR.fromAddress('bc1z...');
1074
+ console.log(fromAddr.hash); // 32-byte Merkle root
1075
+
1076
+ // Script-path spending
1077
+ const spending = new P2MR({
1078
+ scriptTree: multiLeaf,
1079
+ redeem: { output: script1 },
1080
+ });
1081
+ console.log(spending.witness);
1082
+ // [script1, controlBlock]
1083
+ // controlBlock = [version | 0x01, ...merklePath]
1084
+
1085
+ // Legacy factory function
1086
+ const legacy = p2mr({ scriptTree });
1087
+ const legacyHash = p2mr({ hash: merkleRoot });
1088
+ ```
1089
+
1090
+ ### P2MR Utilities
1091
+
1092
+ P2MR reuses the BIP 341 Merkle tree construction but with a simplified control block. Use `rootHashFromPathP2MR` instead of `rootHashFromPath` for P2MR:
1093
+
1094
+ ```typescript
1095
+ import {
1096
+ rootHashFromPathP2MR,
1097
+ tapleafHash,
1098
+ toHashTree,
1099
+ findScriptPath,
1100
+ tapBranchHash,
1101
+ LEAF_VERSION_TAPSCRIPT,
1102
+ } from '@btc-vision/bitcoin';
1103
+
1104
+ // Compute leaf hash
1105
+ const leafHash = tapleafHash({
1106
+ output: redeemScript,
1107
+ version: LEAF_VERSION_TAPSCRIPT,
1108
+ });
1109
+
1110
+ // Reconstruct merkle root from control block
1111
+ const merkleRoot = rootHashFromPathP2MR(controlBlock, leafHash);
1112
+
1113
+ // Build hash tree and find path
1114
+ const hashTree = toHashTree(scriptTree);
1115
+ const path = findScriptPath(hashTree, leafHash);
1116
+ ```
1117
+
1118
+ ---
1119
+
1120
+ ## P2OP (Pay-to-OPNet)
1121
+
1122
+ P2OP is a custom witness version 16 output type for the OPNet network. The witness program contains a deployment version byte followed by a hash160.
1123
+
1124
+ ### Overview
1125
+
1126
+ | Property | Value |
1127
+ |----------|-------|
1128
+ | SegWit version | 16 (`OP_16`) |
1129
+ | Address format | bech32m (custom OPNet prefix from `network.bech32Opnet`) |
1130
+ | Witness program | 2-40 bytes (`{deploymentVersion:uint8}{hash160:20-bytes}`) |
1131
+
1132
+ ### Script Structure
1133
+
1134
+ ```
1135
+ Output: OP_16 {program}
1136
+ program = {deploymentVersion:uint8}{hash160:20-bytes|...}
1137
+ ```
1138
+
1139
+ ### Class: P2OP
1140
+
1141
+ ```typescript
1142
+ class P2OP {
1143
+ static readonly NAME = 'p2op';
1144
+
1145
+ constructor(params: {
1146
+ address?: string;
1147
+ program?: Uint8Array;
1148
+ deploymentVersion?: number;
1149
+ hash160?: Uint8Array;
1150
+ output?: Uint8Array;
1151
+ network?: Network;
1152
+ }, opts?: PaymentOpts);
1153
+
1154
+ // Getters
1155
+ get name(): 'p2op';
1156
+ get network(): Network;
1157
+ get address(): string | undefined;
1158
+ get program(): Uint8Array | undefined; // Full witness program (2-40 bytes)
1159
+ get deploymentVersion(): number | undefined; // First byte of program
1160
+ get hash160(): Bytes20 | undefined; // Remaining bytes of program
1161
+ get output(): Uint8Array | undefined;
1162
+
1163
+ // Static factory methods
1164
+ static fromProgram(program: Uint8Array, network?: Network): P2OP;
1165
+ static fromParts(deploymentVersion: number, hash160: Uint8Array, network?: Network): P2OP;
1166
+ static fromAddress(address: string, network?: Network): P2OP;
1167
+ static fromOutput(output: Uint8Array, network?: Network): P2OP;
1168
+
1169
+ toPayment(): P2OPPayment;
1170
+ }
1171
+ ```
1172
+
1173
+ ### Factory Function
1174
+
1175
+ ```typescript
1176
+ function p2op(a: {
1177
+ address?: string;
1178
+ program?: Uint8Array;
1179
+ deploymentVersion?: number;
1180
+ hash160?: Uint8Array;
1181
+ output?: Uint8Array;
1182
+ network?: Network;
1183
+ }, opts?: PaymentOpts): P2OPPayment;
1184
+ ```
1185
+
1186
+ ### P2OPPayment Interface
1187
+
1188
+ ```typescript
1189
+ interface P2OPPayment extends BasePayment {
1190
+ readonly name: 'p2op';
1191
+ readonly program?: Uint8Array | undefined;
1192
+ readonly deploymentVersion?: number | undefined;
1193
+ readonly hash160?: Bytes20 | undefined;
1194
+ }
1195
+ ```
1196
+
1197
+ ### P2OPPaymentParams Interface
1198
+
1199
+ `P2OPPaymentParams` is the input type for the `p2op()` factory function. It is identical to `P2OPPayment` except that `name` is omitted and `deploymentVersion` defaults to `0` if not provided.
1200
+
1201
+ ```typescript
1202
+ interface P2OPPaymentParams extends Omit<P2OPPayment, 'name' | 'deploymentVersion'> {
1203
+ readonly deploymentVersion?: number | undefined;
1204
+ }
1205
+ ```
1206
+
1207
+ ### Examples
1208
+
1209
+ ```typescript
1210
+ import { P2OP, p2op } from '@btc-vision/bitcoin';
1211
+
1212
+ // Create from witness program
1213
+ const payment = P2OP.fromProgram(programBytes);
1214
+ console.log(payment.address); // bech32m OPNet address
1215
+ console.log(payment.deploymentVersion); // first byte
1216
+ console.log(payment.hash160); // remaining bytes
1217
+ console.log(payment.output); // OP_16 {program}
1218
+
1219
+ // Create from deployment version and hash160
1220
+ const fromParts = P2OP.fromParts(0, hash160Bytes);
1221
+ console.log(fromParts.address);
1222
+ console.log(fromParts.program);
1223
+
1224
+ // Create from address
1225
+ const fromAddr = P2OP.fromAddress(opnetAddress);
1226
+ console.log(fromAddr.program);
1227
+
1228
+ // Decode from output script
1229
+ const decoded = P2OP.fromOutput(scriptPubKey);
1230
+ console.log(decoded.deploymentVersion);
1231
+ console.log(decoded.hash160);
1232
+
1233
+ // Legacy factory function
1234
+ const legacy = p2op({ program: programBytes });
1235
+ const legacyParts = p2op({ deploymentVersion: 0, hash160: hash160Bytes });
1236
+ ```
1237
+
1238
+ ---
1239
+
1240
+ ## Embed (OP_RETURN Data)
1241
+
1242
+ Embed payments use OP_RETURN to store arbitrary data in the blockchain. These outputs are provably unspendable and are used for data storage, timestamping, and metadata.
1243
+
1244
+ ### Overview
1245
+
1246
+ | Property | Value |
1247
+ |----------|-------|
1248
+ | SegWit version | N/A |
1249
+ | Address format | None |
1250
+ | Spendable | No (provably unspendable) |
1251
+
1252
+ ### Script Structure
1253
+
1254
+ ```
1255
+ Output: OP_RETURN {data1} {data2} ...
1256
+ ```
1257
+
1258
+ ### Class: Embed
1259
+
1260
+ ```typescript
1261
+ class Embed {
1262
+ static readonly NAME = 'embed';
1263
+
1264
+ constructor(params: {
1265
+ data?: Uint8Array[];
1266
+ output?: Uint8Array;
1267
+ network?: Network;
1268
+ }, opts?: PaymentOpts);
1269
+
1270
+ // Getters
1271
+ get name(): 'embed';
1272
+ get network(): Network;
1273
+ get data(): Uint8Array[];
1274
+ get output(): Script | undefined;
1275
+
1276
+ // Static factory methods
1277
+ static fromData(data: Uint8Array[], network?: Network): Embed;
1278
+ static fromOutput(output: Uint8Array, network?: Network): Embed;
1279
+
1280
+ toPayment(): EmbedPayment;
1281
+ }
1282
+ ```
1283
+
1284
+ ### Factory Function
1285
+
1286
+ ```typescript
1287
+ function p2data(a: Omit<EmbedPayment, 'name'>, opts?: PaymentOpts): EmbedPayment;
1288
+ ```
1289
+
1290
+ ### EmbedPayment Interface
1291
+
1292
+ ```typescript
1293
+ interface EmbedPayment extends BasePayment {
1294
+ readonly name: 'embed';
1295
+ readonly data: Uint8Array[];
1296
+ }
1297
+ ```
1298
+
1299
+ ### Examples
1300
+
1301
+ ```typescript
1302
+ import { Embed, p2data } from '@btc-vision/bitcoin';
1303
+
1304
+ // Create from data chunks (class)
1305
+ const payment = Embed.fromData([
1306
+ new TextEncoder().encode('Hello'),
1307
+ new TextEncoder().encode('Bitcoin'),
1308
+ ]);
1309
+ console.log(payment.output); // OP_RETURN {data1} {data2}
1310
+ console.log(payment.data); // [Uint8Array, Uint8Array]
1311
+
1312
+ // Decode from output script
1313
+ const decoded = Embed.fromOutput(scriptPubKey);
1314
+ console.log(decoded.data); // array of data chunks
1315
+
1316
+ // Legacy factory function
1317
+ const legacy = p2data({ data: [new TextEncoder().encode('Hello')] });
1318
+ const decodedLegacy = p2data({ output: scriptPubKey });
1319
+ ```
1320
+
1321
+ ---
1322
+
1323
+ ## Detecting Payment Types
1324
+
1325
+ The library provides factory-based detection functions for identifying script types from output scripts. These are located in `psbtutils` and work by attempting to parse the script with each payment factory, returning `true` on success and `false` on failure.
1326
+
1327
+ ```typescript
1328
+ import {
1329
+ isP2PK,
1330
+ isP2PKH,
1331
+ isP2MS,
1332
+ isP2WPKH,
1333
+ isP2WSHScript,
1334
+ isP2SHScript,
1335
+ isP2TR,
1336
+ isP2MR,
1337
+ isP2OP,
1338
+ isP2A,
1339
+ } from '@btc-vision/bitcoin';
1340
+ ```
1341
+
1342
+ ### Detection Functions
1343
+
1344
+ | Function | Detects | Script Pattern |
1345
+ |----------|---------|----------------|
1346
+ | `isP2PK(script)` | P2PK | `{pubkey} OP_CHECKSIG` |
1347
+ | `isP2PKH(script)` | P2PKH | `OP_DUP OP_HASH160 {20-byte} OP_EQUALVERIFY OP_CHECKSIG` |
1348
+ | `isP2MS(script)` | P2MS | `OP_m {pubkeys...} OP_n OP_CHECKMULTISIG` |
1349
+ | `isP2WPKH(script)` | P2WPKH | `OP_0 {20-byte}` |
1350
+ | `isP2WSHScript(script)` | P2WSH | `OP_0 {32-byte}` |
1351
+ | `isP2SHScript(script)` | P2SH | `OP_HASH160 {20-byte} OP_EQUAL` |
1352
+ | `isP2TR(script)` | P2TR | `OP_1 {32-byte}` |
1353
+ | `isP2MR(script)` | P2MR | `OP_2 {32-byte}` |
1354
+ | `isP2OP(script)` | P2OP | `OP_16 {2-40 bytes}` |
1355
+ | `isP2A(script)` | P2A (Anchor) | `OP_1 {0x4e73}` (exactly 4 bytes) |
1356
+
1357
+ ### How Detection Works
1358
+
1359
+ Each detection function is created via `isPaymentFactory`, which wraps the corresponding legacy factory function in a try/catch:
1360
+
1361
+ ```typescript
1362
+ function isPaymentFactory(payment: PaymentFunction): (script: Uint8Array) => boolean {
1363
+ return (script: Uint8Array): boolean => {
1364
+ try {
1365
+ payment({ output: script });
1366
+ return true;
1367
+ } catch {
1368
+ return false;
1369
+ }
1370
+ };
1371
+ }
1372
+ ```
1373
+
1374
+ ### Example Usage
1375
+
1376
+ ```typescript
1377
+ import { isP2PKH, isP2TR, isP2MR, isP2WPKH } from '@btc-vision/bitcoin';
1378
+
1379
+ function classifyOutput(scriptPubKey: Uint8Array): string {
1380
+ if (isP2PKH(scriptPubKey)) return 'P2PKH';
1381
+ if (isP2WPKH(scriptPubKey)) return 'P2WPKH';
1382
+ if (isP2TR(scriptPubKey)) return 'P2TR';
1383
+ if (isP2MR(scriptPubKey)) return 'P2MR';
1384
+ return 'Unknown';
1385
+ }
1386
+ ```
1387
+
1388
+ ---
1389
+
1390
+ ## Class vs. Factory Function Pattern
1391
+
1392
+ Every payment type exposes two APIs:
1393
+
1394
+ ### Class API (recommended for new code)
1395
+
1396
+ ```typescript
1397
+ // Static factory methods return the class instance
1398
+ const payment = P2PKH.fromPubkey(pubkey);
1399
+ const address = payment.address; // lazy-computed getter
1400
+ ```
1401
+
1402
+ ### Legacy Factory Function
1403
+
1404
+ ```typescript
1405
+ // Factory functions return a plain payment object
1406
+ const payment = p2pkh({ pubkey });
1407
+ const address = payment.address; // pre-computed property
1408
+ ```
1409
+
1410
+ Both APIs accept the same parameters and produce equivalent results. The class API is preferred for new code because:
1411
+
1412
+ 1. Static factory methods are more discoverable and type-safe.
1413
+ 2. Getters are lazy-computed (only calculated when accessed).
1414
+ 3. The class instance can be extended.
1415
+
1416
+ The `toPayment()` method on each class converts the instance to a plain payment object, which is what the factory functions return internally.
1417
+
1418
+ ---
1419
+
1420
+ ## Common Patterns
1421
+
1422
+ ### Wrapping Scripts in P2SH
1423
+
1424
+ ```typescript
1425
+ import { P2SH, P2MS, P2WPKH } from '@btc-vision/bitcoin';
1426
+
1427
+ // P2SH-P2MS (multisig in P2SH)
1428
+ const multisig = P2MS.fromPubkeys(2, [pk1, pk2, pk3]);
1429
+ const p2shMultisig = P2SH.fromRedeem({ output: multisig.output });
1430
+
1431
+ // P2SH-P2WPKH (wrapped SegWit)
1432
+ const segwit = P2WPKH.fromPubkey(pubkey);
1433
+ const p2shSegwit = P2SH.fromRedeem({ output: segwit.output });
1434
+ ```
1435
+
1436
+ ### Wrapping Scripts in P2WSH
1437
+
1438
+ ```typescript
1439
+ import { P2WSH, P2MS } from '@btc-vision/bitcoin';
1440
+
1441
+ // P2WSH-P2MS (multisig in P2WSH)
1442
+ const multisig = P2MS.fromPubkeys(2, [pk1, pk2, pk3]);
1443
+ const p2wshMultisig = P2WSH.fromRedeem({ output: multisig.output });
1444
+ ```
1445
+
1446
+ ### Converting Between Representations
1447
+
1448
+ ```typescript
1449
+ import { P2PKH } from '@btc-vision/bitcoin';
1450
+
1451
+ // Address -> Hash -> Output
1452
+ const fromAddr = P2PKH.fromAddress('1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2');
1453
+ const hash = fromAddr.hash;
1454
+ const output = fromAddr.output;
1455
+
1456
+ // Output -> Hash -> Address
1457
+ const fromOutput = P2PKH.fromOutput(scriptPubKey);
1458
+ const address = fromOutput.address;
1459
+
1460
+ // All getters are cross-derived lazily
1461
+ ```
1462
+
1463
+ ### Disabling Validation
1464
+
1465
+ ```typescript
1466
+ import { P2PKH } from '@btc-vision/bitcoin';
1467
+
1468
+ // Skip validation for performance
1469
+ const payment = new P2PKH(
1470
+ { address: untrustedAddress },
1471
+ { validate: false },
1472
+ );
1473
+ ```
1474
+
1475
+ ### Allowing Incomplete Signatures
1476
+
1477
+ ```typescript
1478
+ import { P2MS } from '@btc-vision/bitcoin';
1479
+
1480
+ // Allow OP_0 placeholders for missing signatures
1481
+ const payment = new P2MS(
1482
+ { m: 2, pubkeys: [pk1, pk2, pk3], signatures: [sig1, placeholder] },
1483
+ { allowIncomplete: true },
1484
+ );
1485
+ ```