@vbyte/btc-dev 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/LICENSE +21 -121
  3. package/README.md +36 -227
  4. package/dist/error.d.ts +11 -0
  5. package/dist/error.js +20 -0
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.js +1 -0
  8. package/dist/lib/address/api.js +3 -2
  9. package/dist/lib/address/encode.js +6 -4
  10. package/dist/lib/address/p2pkh.js +4 -4
  11. package/dist/lib/address/p2sh.js +3 -3
  12. package/dist/lib/address/p2tr.js +3 -3
  13. package/dist/lib/address/p2wpkh.js +4 -4
  14. package/dist/lib/address/p2wsh.js +3 -3
  15. package/dist/lib/address/util.js +3 -1
  16. package/dist/lib/meta/locktime.js +3 -2
  17. package/dist/lib/meta/ref.js +4 -3
  18. package/dist/lib/meta/scribe.js +26 -6
  19. package/dist/lib/meta/sequence.js +8 -7
  20. package/dist/lib/script/decode.js +10 -9
  21. package/dist/lib/script/encode.js +4 -3
  22. package/dist/lib/script/words.js +4 -3
  23. package/dist/lib/sighash/segwit.js +9 -6
  24. package/dist/lib/sighash/taproot.js +7 -4
  25. package/dist/lib/sighash/util.js +4 -3
  26. package/dist/lib/signer/sign.js +7 -6
  27. package/dist/lib/signer/verify.js +8 -9
  28. package/dist/lib/taproot/cblock.js +3 -2
  29. package/dist/lib/taproot/encode.d.ts +1 -1
  30. package/dist/lib/taproot/encode.js +4 -3
  31. package/dist/lib/taproot/parse.js +9 -7
  32. package/dist/lib/taproot/tree.js +3 -2
  33. package/dist/lib/tx/create.js +1 -1
  34. package/dist/lib/tx/decode.js +13 -11
  35. package/dist/lib/tx/encode.js +1 -1
  36. package/dist/lib/tx/parse.js +3 -3
  37. package/dist/lib/tx/size.js +2 -4
  38. package/dist/lib/tx/util.js +2 -3
  39. package/dist/lib/tx/validate.js +36 -8
  40. package/dist/lib/witness/util.js +1 -1
  41. package/dist/main.cjs +1127 -1160
  42. package/dist/main.cjs.map +1 -1
  43. package/dist/module.mjs +1125 -1161
  44. package/dist/module.mjs.map +1 -1
  45. package/dist/package.json +13 -11
  46. package/dist/script.js +10 -12
  47. package/dist/script.js.map +1 -1
  48. package/docs/API.md +1145 -0
  49. package/docs/CONVENTIONS.md +316 -0
  50. package/docs/FAQ.md +396 -0
  51. package/docs/GUIDE.md +1102 -0
  52. package/package.json +13 -11
package/docs/API.md ADDED
@@ -0,0 +1,1145 @@
1
+ # API Reference
2
+
3
+ Complete API reference for all `@vbyte/btc-dev` modules.
4
+
5
+ ## Import Patterns
6
+
7
+ ```typescript
8
+ // Namespace imports
9
+ import { ADDRESS, TX, SCRIPT, SIGHASH, SIGNER, TAPROOT, WITNESS, META, CONST, SCHEMA } from '@vbyte/btc-dev'
10
+
11
+ // Tree-shaking imports
12
+ import { p2wpkh, p2tr } from '@vbyte/btc-dev/address'
13
+ import { parse_tx, encode_tx } from '@vbyte/btc-dev/tx'
14
+ ```
15
+
16
+ ---
17
+
18
+ ## ADDRESS
19
+
20
+ Create and parse Bitcoin addresses.
21
+
22
+ ### `ADDRESS.p2pkh(pubkey, network)`
23
+
24
+ Create a P2PKH (legacy) address from a compressed public key.
25
+
26
+ ```typescript
27
+ ADDRESS.p2pkh(pubkey: Bytes, network: ChainNetwork): AddressData
28
+ ```
29
+
30
+ **Parameters:**
31
+ - `pubkey` - Compressed public key (33 bytes)
32
+ - `network` - `'main'` or `'test'`
33
+
34
+ **Returns:** `AddressData` with address string, script, format, network
35
+
36
+ ```typescript
37
+ const addr = ADDRESS.p2pkh('02aa...', 'main')
38
+ // addr.data = '1...'
39
+ // addr.format = 'p2pkh'
40
+ ```
41
+
42
+ ### `ADDRESS.p2sh(script, network)`
43
+
44
+ Create a P2SH address from a redeem script.
45
+
46
+ ```typescript
47
+ ADDRESS.p2sh(script: Bytes, network: ChainNetwork): AddressData
48
+ ```
49
+
50
+ ### `ADDRESS.p2wpkh(pubkey, network)`
51
+
52
+ Create a P2WPKH (native segwit) address from a compressed public key.
53
+
54
+ ```typescript
55
+ ADDRESS.p2wpkh(pubkey: Bytes, network: ChainNetwork): AddressData
56
+ ```
57
+
58
+ ```typescript
59
+ const addr = ADDRESS.p2wpkh('02bb...', 'main')
60
+ // addr.data = 'bc1q...'
61
+ // addr.format = 'p2wpkh'
62
+ // addr.version = 0
63
+ ```
64
+
65
+ ### `ADDRESS.p2wsh(script, network)`
66
+
67
+ Create a P2WSH address from a witness script.
68
+
69
+ ```typescript
70
+ ADDRESS.p2wsh(script: Bytes, network: ChainNetwork): AddressData
71
+ ```
72
+
73
+ ### `ADDRESS.p2tr(pubkey, network)`
74
+
75
+ Create a P2TR (taproot) address from an x-only public key.
76
+
77
+ ```typescript
78
+ ADDRESS.p2tr(xOnlyPubkey: Bytes, network: ChainNetwork): AddressData
79
+ ```
80
+
81
+ **Parameters:**
82
+ - `xOnlyPubkey` - x-only public key (32 bytes, no prefix)
83
+ - `network` - `'main'` or `'test'`
84
+
85
+ ```typescript
86
+ const addr = ADDRESS.p2tr('cc'.repeat(32), 'main')
87
+ // addr.data = 'bc1p...'
88
+ // addr.format = 'p2tr'
89
+ // addr.version = 1
90
+ ```
91
+
92
+ ### `ADDRESS.get_address(script, network)`
93
+
94
+ Get the address for a locking script.
95
+
96
+ ```typescript
97
+ get_address(script: Bytes, network?: ChainNetwork): string
98
+ ```
99
+
100
+ ### `ADDRESS.parse_address(address)`
101
+
102
+ Parse an address string into address info.
103
+
104
+ ```typescript
105
+ parse_address(address: string): AddressInfo
106
+ ```
107
+
108
+ ---
109
+
110
+ ## TX
111
+
112
+ Transaction creation, encoding, decoding, and parsing.
113
+
114
+ ### `TX.create(template)`
115
+
116
+ Create a transaction from a template.
117
+
118
+ ```typescript
119
+ create_tx(template?: Partial<TxTemplate>): TxData
120
+ ```
121
+
122
+ **Parameters:**
123
+ - `template.version` - Transaction version (default: 2)
124
+ - `template.locktime` - Locktime (default: 0)
125
+ - `template.vin` - Array of input templates
126
+ - `template.vout` - Array of output templates
127
+
128
+ ```typescript
129
+ const tx = TX.create({
130
+ version: 2,
131
+ locktime: 0,
132
+ vin: [{
133
+ txid: 'aa'.repeat(32),
134
+ vout: 0,
135
+ sequence: 0xffffffff,
136
+ prevout: { value: 100000n, script_pk: '0014...' }
137
+ }],
138
+ vout: [{
139
+ value: 90000n,
140
+ script_pk: '0014...'
141
+ }]
142
+ })
143
+ ```
144
+
145
+ ### `TX.parse(txdata, prevouts?)`
146
+
147
+ Parse transaction data from hex, bytes, or template.
148
+
149
+ ```typescript
150
+ parse_tx(txdata: unknown, prevouts?: TxOutputTemplate[]): TxData
151
+ ```
152
+
153
+ **Parameters:**
154
+ - `txdata` - Raw hex, Uint8Array, or TxTemplate object
155
+ - `prevouts` - Optional array of prevout data for inputs
156
+
157
+ ### `TX.decode(txdata, use_segwit?)`
158
+
159
+ Decode a raw transaction from hex or bytes.
160
+
161
+ ```typescript
162
+ decode_tx(txdata: string | Uint8Array, use_segwit?: boolean): TxDecodedData
163
+ ```
164
+
165
+ **Parameters:**
166
+ - `txdata` - Raw transaction hex or bytes
167
+ - `use_segwit` - Parse witness data (default: true)
168
+
169
+ ### `TX.encode(txdata, use_segwit?)`
170
+
171
+ Encode a transaction to bytes.
172
+
173
+ ```typescript
174
+ encode_tx(txdata: TxData, use_segwit?: boolean): Buff
175
+ ```
176
+
177
+ **Parameters:**
178
+ - `txdata` - Transaction data object
179
+ - `use_segwit` - Include witness data (default: true)
180
+
181
+ ```typescript
182
+ const rawTx = TX.encode(tx, true).hex // With witness
183
+ const legacyTx = TX.encode(tx, false).hex // Without witness
184
+ ```
185
+
186
+ ### `TX.get_size(txdata)`
187
+
188
+ Calculate transaction sizes.
189
+
190
+ ```typescript
191
+ get_txsize(txdata: string | TxData): TxSize
192
+ ```
193
+
194
+ **Returns:**
195
+ - `base` - Size without witness (bytes)
196
+ - `total` - Total size with witness (bytes)
197
+ - `vsize` - Virtual size (vbytes)
198
+ - `weight` - Weight units
199
+
200
+ ```typescript
201
+ const size = TX.get_size(tx)
202
+ console.log(size.vsize) // Use for fee calculation
203
+ ```
204
+
205
+ ### `TX.serialize(txdata)`
206
+
207
+ Serialize transaction to a plain object.
208
+
209
+ ```typescript
210
+ serialize_tx(txdata: unknown): Record<string, unknown>
211
+ ```
212
+
213
+ ---
214
+
215
+ ## SCRIPT
216
+
217
+ Bitcoin script encoding, decoding, and type detection.
218
+
219
+ ### `SCRIPT.encode(words, varint?)`
220
+
221
+ Encode script ASM words to bytes.
222
+
223
+ ```typescript
224
+ encode_script(words: (string | number | Uint8Array)[], varint?: boolean): Buff
225
+ ```
226
+
227
+ **Parameters:**
228
+ - `words` - Array of opcodes, hex data, strings, or numbers
229
+ - `varint` - Prefix with length varint (default: false)
230
+
231
+ ```typescript
232
+ const script = SCRIPT.encode(['OP_DUP', 'OP_HASH160', pubkeyHash, 'OP_EQUALVERIFY', 'OP_CHECKSIG'])
233
+ ```
234
+
235
+ ### `SCRIPT.decode(script)`
236
+
237
+ Decode script bytes to ASM words.
238
+
239
+ ```typescript
240
+ decode_script(script: Bytes): string[]
241
+ ```
242
+
243
+ ```typescript
244
+ const asm = SCRIPT.decode('76a914...88ac')
245
+ // ['OP_DUP', 'OP_HASH160', '...', 'OP_EQUALVERIFY', 'OP_CHECKSIG']
246
+ ```
247
+
248
+ ### `SCRIPT.parse(script)`
249
+
250
+ Parse script to info object with both ASM and hex.
251
+
252
+ ```typescript
253
+ parse_script(script: Bytes): ScriptInfo
254
+ ```
255
+
256
+ ### `SCRIPT.get_lock_script_type(script)`
257
+
258
+ Detect the lock script type.
259
+
260
+ ```typescript
261
+ get_lock_script_type(script: Bytes): LockScriptType | null
262
+ ```
263
+
264
+ **Returns:** `'p2pkh'` | `'p2sh'` | `'p2wpkh'` | `'p2wsh'` | `'p2tr'` | `'opreturn'` | `null`
265
+
266
+ ```typescript
267
+ SCRIPT.get_lock_script_type('0014' + '89'.repeat(20)) // 'p2wpkh'
268
+ SCRIPT.get_lock_script_type('5120' + '89'.repeat(32)) // 'p2tr'
269
+ ```
270
+
271
+ ### `SCRIPT.get_lock_script_version(script)`
272
+
273
+ Get the witness version of a script.
274
+
275
+ ```typescript
276
+ get_lock_script_version(script: Bytes): WitnessVersion | null
277
+ ```
278
+
279
+ **Returns:** `0` (segwit v0), `1` (taproot), or `null` (legacy)
280
+
281
+ ### `SCRIPT.is_p2pkh_script(script)`
282
+
283
+ Check if script is P2PKH.
284
+
285
+ ```typescript
286
+ is_p2pkh_script(script: Bytes): boolean
287
+ ```
288
+
289
+ ### `SCRIPT.is_p2sh_script(script)`
290
+
291
+ Check if script is P2SH.
292
+
293
+ ```typescript
294
+ is_p2sh_script(script: Bytes): boolean
295
+ ```
296
+
297
+ ### `SCRIPT.is_p2wpkh_script(script)`
298
+
299
+ Check if script is P2WPKH.
300
+
301
+ ```typescript
302
+ is_p2wpkh_script(script: Bytes): boolean
303
+ ```
304
+
305
+ ### `SCRIPT.is_p2wsh_script(script)`
306
+
307
+ Check if script is P2WSH.
308
+
309
+ ```typescript
310
+ is_p2wsh_script(script: Bytes): boolean
311
+ ```
312
+
313
+ ### `SCRIPT.is_p2tr_script(script)`
314
+
315
+ Check if script is P2TR (taproot).
316
+
317
+ ```typescript
318
+ is_p2tr_script(script: Bytes): boolean
319
+ ```
320
+
321
+ ### `SCRIPT.is_opreturn_script(script)`
322
+
323
+ Check if script is OP_RETURN.
324
+
325
+ ```typescript
326
+ is_opreturn_script(script: Bytes): boolean
327
+ ```
328
+
329
+ ### `SCRIPT.is_valid_script(script)`
330
+
331
+ Check if a script is valid.
332
+
333
+ ```typescript
334
+ is_valid_script(script: string | Uint8Array): boolean
335
+ ```
336
+
337
+ ---
338
+
339
+ ## SIGHASH
340
+
341
+ Signature hash calculation for segwit and taproot.
342
+
343
+ ### `SIGHASH.hash_segwit_tx(txdata, options)`
344
+
345
+ Calculate BIP-143 segwit sighash.
346
+
347
+ ```typescript
348
+ hash_segwit_tx(txdata: TxData, options: SigHashOptions): Buff
349
+ ```
350
+
351
+ **Options:**
352
+ - `txindex` - Input index to sign
353
+ - `pubkey` - Public key (for P2WPKH)
354
+ - `script` - Redeem script (for P2WSH)
355
+ - `sigflag` - Sighash flag (default: 0x01)
356
+
357
+ ### `SIGHASH.hash_taproot_tx(txdata, options)`
358
+
359
+ Calculate BIP-341 taproot sighash.
360
+
361
+ ```typescript
362
+ hash_taproot_tx(txdata: TxData, options: SigHashOptions): Buff
363
+ ```
364
+
365
+ **Options:**
366
+ - `txindex` - Input index to sign
367
+ - `sigflag` - Sighash flag (default: 0x00)
368
+ - `extension` - Tapleaf hash for script-path
369
+
370
+ ### Sighash Flags
371
+
372
+ | Flag | Value | Description |
373
+ |------|-------|-------------|
374
+ | SIGHASH_DEFAULT | 0x00 | Taproot default (equivalent to ALL) |
375
+ | SIGHASH_ALL | 0x01 | Sign all inputs and outputs |
376
+ | SIGHASH_NONE | 0x02 | Sign inputs only |
377
+ | SIGHASH_SINGLE | 0x03 | Sign only corresponding output |
378
+ | SIGHASH_ANYONECANPAY | 0x80 | Sign only own input (combine with above) |
379
+
380
+ ---
381
+
382
+ ## SIGNER
383
+
384
+ Transaction signing and verification.
385
+
386
+ ### `SIGNER.sign_segwit_tx(seckey, txdata, options)`
387
+
388
+ Sign a segwit (v0) transaction input.
389
+
390
+ ```typescript
391
+ sign_segwit_tx(
392
+ seckey: string,
393
+ txdata: TxData,
394
+ options: SigHashOptions
395
+ ): string
396
+ ```
397
+
398
+ **Parameters:**
399
+ - `seckey` - 32-byte secret key as hex (64 characters)
400
+ - `txdata` - Transaction data
401
+ - `options.txindex` - Input index to sign
402
+ - `options.pubkey` - Public key (for P2WPKH)
403
+ - `options.script` - Redeem script (for P2WSH)
404
+ - `options.sigflag` - Sighash flag (default: 0x01)
405
+
406
+ **Returns:** DER-encoded ECDSA signature with sighash flag appended
407
+
408
+ ```typescript
409
+ const sig = SIGNER.sign_segwit_tx(secretKey, tx, {
410
+ txindex: 0,
411
+ pubkey: publicKey,
412
+ sigflag: 0x01
413
+ })
414
+ tx.vin[0].witness = [sig, publicKey]
415
+ ```
416
+
417
+ ### `SIGNER.sign_taproot_tx(seckey, txdata, options)`
418
+
419
+ Sign a taproot (v1) transaction input.
420
+
421
+ ```typescript
422
+ sign_taproot_tx(
423
+ seckey: string,
424
+ txdata: TxData,
425
+ options: SigHashOptions
426
+ ): string
427
+ ```
428
+
429
+ **Parameters:**
430
+ - `seckey` - 32-byte secret key as hex (64 characters)
431
+ - `txdata` - Transaction data
432
+ - `options.txindex` - Input index to sign
433
+ - `options.sigflag` - Sighash flag (default: 0x00)
434
+ - `options.extension` - Tapleaf hash (for script-path)
435
+
436
+ **Returns:** 64-byte Schnorr signature (with optional sighash byte if not default)
437
+
438
+ ```typescript
439
+ const sig = SIGNER.sign_taproot_tx(tweakedSeckey, tx, {
440
+ txindex: 0,
441
+ sigflag: 0x00
442
+ })
443
+ tx.vin[0].witness = [sig]
444
+ ```
445
+
446
+ ### `SIGNER.verify_tx(txdata, options?)`
447
+
448
+ Verify all signatures in a transaction.
449
+
450
+ ```typescript
451
+ verify_tx(
452
+ txdata: TxData | Bytes,
453
+ options?: VerifyOptions
454
+ ): VerifyResult
455
+ ```
456
+
457
+ **Options:**
458
+ - `throws` - Throw on verification failure (default: false)
459
+
460
+ **Returns:**
461
+
462
+ ```typescript
463
+ interface VerifyResult {
464
+ valid: boolean
465
+ inputs: InputVerifyResult[]
466
+ error?: string
467
+ }
468
+
469
+ interface InputVerifyResult {
470
+ index: number
471
+ valid: boolean
472
+ type?: string | null
473
+ error?: string
474
+ }
475
+ ```
476
+
477
+ ```typescript
478
+ const result = SIGNER.verify_tx(tx)
479
+ if (!result.valid) {
480
+ console.log(result.error)
481
+ result.inputs.forEach(input => {
482
+ if (!input.valid) console.log(`Input ${input.index}: ${input.error}`)
483
+ })
484
+ }
485
+ ```
486
+
487
+ ---
488
+
489
+ ## TAPROOT
490
+
491
+ Taproot tree construction, control blocks, and key tweaking.
492
+
493
+ ### `TAPROOT.get_merkle_root(leaves)`
494
+
495
+ Get the merkle root of a taproot tree.
496
+
497
+ ```typescript
498
+ get_merkle_root(leaves: TapTree): string
499
+ ```
500
+
501
+ ### `TAPROOT.merkleize(taptree, target?, path?, depth?)`
502
+
503
+ Process a taproot tree into a merkle proof.
504
+
505
+ ```typescript
506
+ merkleize(
507
+ taptree: TapTree,
508
+ target?: string,
509
+ path?: string[],
510
+ depth?: number
511
+ ): MerkleProof
512
+ ```
513
+
514
+ **Returns:** `[root, target, path]`
515
+
516
+ ### `TAPROOT.encode_tapscript(script, version?)`
517
+
518
+ Encode a script as a tapleaf.
519
+
520
+ ```typescript
521
+ encode_tapscript(script: Bytes, version?: number): Buff
522
+ ```
523
+
524
+ **Parameters:**
525
+ - `script` - The tapscript bytes
526
+ - `version` - Leaf version (default: 0xc0)
527
+
528
+ ### `TAPROOT.encode_tapbranch(left, right)`
529
+
530
+ Encode two leaves/branches into a branch.
531
+
532
+ ```typescript
533
+ encode_tapbranch(left: Bytes, right: Bytes): Buff
534
+ ```
535
+
536
+ ### `TAPROOT.encode_taptweak(pubkey, root?)`
537
+
538
+ Calculate the taproot tweak.
539
+
540
+ ```typescript
541
+ encode_taptweak(pubkey: Bytes, root?: Bytes): Buff
542
+ ```
543
+
544
+ ### `TAPROOT.build_cblock(pubkey, path, parity?, version?)`
545
+
546
+ Build a control block for script-path spending.
547
+
548
+ ```typescript
549
+ build_cblock(
550
+ pubkey: Bytes,
551
+ path: string[],
552
+ parity?: number,
553
+ version?: number
554
+ ): Buff
555
+ ```
556
+
557
+ ### `TAPROOT.parse_cblock(cblock)`
558
+
559
+ Parse a control block.
560
+
561
+ ```typescript
562
+ parse_cblock(cblock: Bytes): ControlBlockData
563
+ ```
564
+
565
+ ### `TAPROOT.verify_taproot(tapkey, target, cblock)`
566
+
567
+ Verify a control block proof.
568
+
569
+ ```typescript
570
+ verify_taproot(tapkey: Bytes, target: Bytes, cblock: Bytes): boolean
571
+ ```
572
+
573
+ ### `TAPROOT.create_taproot(config)`
574
+
575
+ Create a taproot output with optional script tree.
576
+
577
+ ```typescript
578
+ create_taproot(config: TaprootConfig): TaprootContext
579
+ ```
580
+
581
+ **Parameters:**
582
+ - `config.pubkey` - Internal public key (32 bytes, x-only)
583
+ - `config.leaves` - Optional array of tapleaf hashes
584
+ - `config.target` - Optional target leaf for control block generation
585
+ - `config.version` - Leaf version (default: 0xc0)
586
+
587
+ **Returns:** `TaprootContext` with tapkey, control block, path, and tweaks
588
+
589
+ ```typescript
590
+ // Key-path only
591
+ const ctx = TAPROOT.create_taproot({ pubkey: internalKey })
592
+ console.log(ctx.tapkey) // Use in P2TR output
593
+
594
+ // With script tree
595
+ const ctx = TAPROOT.create_taproot({
596
+ pubkey: internalKey,
597
+ leaves: [scriptHash1, scriptHash2],
598
+ target: scriptHash1
599
+ })
600
+ console.log(ctx.cblock) // Control block for script-path spend
601
+ ```
602
+
603
+ ### `TAPROOT.parse_taproot_witness(witness)`
604
+
605
+ Parse a taproot script-path witness and extract spending data.
606
+
607
+ ```typescript
608
+ parse_taproot_witness(witness: string[]): {
609
+ cblock: ControlBlock
610
+ params: string[]
611
+ script: string
612
+ tapkey: string
613
+ tweak: string
614
+ }
615
+ ```
616
+
617
+ **Parameters:**
618
+ - `witness` - Array of witness stack elements (hex strings)
619
+
620
+ **Returns:** Parsed taproot spending data
621
+
622
+ ### `TAPROOT.parse_cblock(cblock)`
623
+
624
+ Parse a control block into its components.
625
+
626
+ ```typescript
627
+ parse_cblock(cblock: Bytes): ControlBlock
628
+ ```
629
+
630
+ **Returns:**
631
+ - `int_key` - Internal public key (32 bytes hex)
632
+ - `path` - Merkle path array
633
+ - `parity` - Y-coordinate parity (0x02 or 0x03)
634
+ - `version` - Leaf version
635
+
636
+ ```typescript
637
+ const { int_key, path, version } = TAPROOT.parse_cblock(controlBlock)
638
+ ```
639
+
640
+ ### `TAPROOT.parse_cblock_parity(cbits)`
641
+
642
+ Extract version and parity from control block version byte.
643
+
644
+ ```typescript
645
+ parse_cblock_parity(cbits: number): [number, number]
646
+ ```
647
+
648
+ **Returns:** Tuple of [version, parity]
649
+
650
+ ```typescript
651
+ const [version, parity] = TAPROOT.parse_cblock_parity(0xc1)
652
+ // [0xc0, 0x03] - version c0, odd parity
653
+ ```
654
+
655
+ ### `TAPROOT.parse_pubkey_parity(pubkey)`
656
+
657
+ Extract parity bit from compressed public key.
658
+
659
+ ```typescript
660
+ parse_pubkey_parity(pubkey: Bytes): number
661
+ ```
662
+
663
+ **Returns:** 0 for even y-coordinate, 1 for odd
664
+
665
+ ---
666
+
667
+ ## WITNESS
668
+
669
+ Witness data parsing and analysis.
670
+
671
+ ### `WITNESS.parse(witness)`
672
+
673
+ Parse witness data from a transaction input.
674
+
675
+ ```typescript
676
+ parse_witness(witness: Bytes[]): WitnessData
677
+ ```
678
+
679
+ **Returns:**
680
+
681
+ ```typescript
682
+ interface WitnessData {
683
+ type: 'p2wpkh' | 'p2wsh' | 'p2tr' | 'p2ts' | null
684
+ version: 0 | 1 | null
685
+ params: string[]
686
+ script: string | null
687
+ cblock: string | null
688
+ annex: string | null
689
+ }
690
+ ```
691
+
692
+ - `type` - Detected spend type
693
+ - `version` - Witness version (0 = segwit, 1 = taproot)
694
+ - `params` - Parameters (signatures, pubkeys)
695
+ - `script` - Witness script (P2WSH) or tapscript (P2TS)
696
+ - `cblock` - Control block (script-path taproot)
697
+ - `annex` - Annex data if present
698
+
699
+ ```typescript
700
+ const witnessData = WITNESS.parse(tx.vin[0].witness)
701
+ console.log(witnessData.type) // 'p2wpkh'
702
+ console.log(witnessData.params[0]) // Signature
703
+ ```
704
+
705
+ ### `WITNESS.get_witness_type(witness)`
706
+
707
+ Get the type of a witness stack.
708
+
709
+ ```typescript
710
+ get_witness_type(witness: Bytes[]): string | null
711
+ ```
712
+
713
+ ---
714
+
715
+ ## META
716
+
717
+ Locktime, sequence, and reference utilities.
718
+
719
+ ### `META.encode_locktime(data)`
720
+
721
+ Encode locktime data (BIP-65).
722
+
723
+ ```typescript
724
+ encode_locktime(data: LocktimeData): number
725
+ ```
726
+
727
+ **Parameters:**
728
+
729
+ ```typescript
730
+ // Block height lock
731
+ { type: 'heightlock', height: 850000 }
732
+
733
+ // Timestamp lock (Unix timestamp >= 500000000)
734
+ { type: 'timelock', stamp: 1704067200 }
735
+ ```
736
+
737
+ ### `META.decode_locktime(locktime)`
738
+
739
+ Decode a locktime value.
740
+
741
+ ```typescript
742
+ decode_locktime(locktime: number): LocktimeData | null
743
+ ```
744
+
745
+ ```typescript
746
+ META.decode_locktime(850000)
747
+ // { type: 'heightlock', height: 850000 }
748
+ ```
749
+
750
+ ### `META.encode_sequence(data)`
751
+
752
+ Encode sequence data (BIP-68).
753
+
754
+ ```typescript
755
+ encode_sequence(data: SequenceConfig): number
756
+ ```
757
+
758
+ **Parameters:**
759
+
760
+ ```typescript
761
+ // Block height relative lock
762
+ { mode: 'height', height: 144 } // ~24 hours
763
+
764
+ // Timestamp relative lock (in seconds, granularity: 512s)
765
+ { mode: 'stamp', stamp: 86400 } // 24 hours
766
+ ```
767
+
768
+ ### `META.decode_sequence(sequence)`
769
+
770
+ Decode a sequence value.
771
+
772
+ ```typescript
773
+ decode_sequence(sequence: number | string): SequenceData | null
774
+ ```
775
+
776
+ ```typescript
777
+ META.decode_sequence(144)
778
+ // { mode: 'height', height: 144 }
779
+ ```
780
+
781
+ ### `META.RefPointer`
782
+
783
+ Reference pointer utilities for outpoints, inscription IDs, and rune IDs.
784
+
785
+ ```typescript
786
+ // Outpoint encoding
787
+ META.RefPointer.outpoint.encode(txid, vout)
788
+ META.RefPointer.outpoint.decode(outpoint)
789
+
790
+ // Inscription/Record ID
791
+ META.RefPointer.record_id.encode(txid, index)
792
+ META.RefPointer.record_id.decode(recordId)
793
+
794
+ // Rune ID
795
+ META.RefPointer.rune_id.encode(blockHeight, txIndex)
796
+ META.RefPointer.rune_id.decode(runeId)
797
+ ```
798
+
799
+ ### `META.InscriptionUtil`
800
+
801
+ Bitcoin inscription (Ordinals) encoding and decoding utilities.
802
+
803
+ ```typescript
804
+ // Encode inscriptions to script
805
+ META.InscriptionUtil.encode(data: InscriptionData[]): Buff
806
+
807
+ // Decode inscriptions from script
808
+ META.InscriptionUtil.decode(script: Bytes): InscriptionData[]
809
+ ```
810
+
811
+ **InscriptionData:**
812
+
813
+ ```typescript
814
+ interface InscriptionData {
815
+ mimetype?: string // Content MIME type (e.g., 'text/plain')
816
+ content?: string // Content as hex string
817
+ parent?: string // Parent inscription ID
818
+ delegate?: string // Delegate inscription ID
819
+ pointer?: number // Output pointer
820
+ opcode?: number // Custom opcode
821
+ rune?: string // Rune name (A-Z only)
822
+ ref?: string // Reference data
823
+ }
824
+ ```
825
+
826
+ **Example:**
827
+
828
+ ```typescript
829
+ import { META } from '@vbyte/btc-dev'
830
+ import { Buff } from '@vbyte/buff'
831
+
832
+ // Create inscription
833
+ const script = META.InscriptionUtil.encode([{
834
+ mimetype: 'text/plain',
835
+ content: Buff.str('Hello, Bitcoin!').hex
836
+ }])
837
+
838
+ // Decode inscription from witness script
839
+ const inscriptions = META.InscriptionUtil.decode(witnessScript)
840
+ console.log(inscriptions[0].mimetype) // 'text/plain'
841
+ ```
842
+
843
+ ---
844
+
845
+ ## Error Classes
846
+
847
+ The library provides custom error classes for better error handling.
848
+
849
+ ### `ValidationError`
850
+
851
+ Thrown when input validation fails (invalid format, wrong length, type mismatch).
852
+
853
+ ```typescript
854
+ import { ValidationError } from '@vbyte/btc-dev'
855
+
856
+ class ValidationError extends Error {
857
+ name: 'ValidationError'
858
+ field?: string // The field that failed validation
859
+ }
860
+ ```
861
+
862
+ **Common scenarios:**
863
+ - Invalid secret key format in signing functions
864
+ - Wrong pubkey length
865
+ - Missing required fields
866
+
867
+ ```typescript
868
+ try {
869
+ SIGNER.sign_segwit_tx('invalid', tx, options)
870
+ } catch (err) {
871
+ if (err instanceof ValidationError) {
872
+ console.log(`Invalid ${err.field}: ${err.message}`)
873
+ }
874
+ }
875
+ ```
876
+
877
+ ### `DecodingError`
878
+
879
+ Thrown when decoding or parsing malformed data fails.
880
+
881
+ ```typescript
882
+ import { DecodingError } from '@vbyte/btc-dev'
883
+
884
+ class DecodingError extends Error {
885
+ name: 'DecodingError'
886
+ position?: number // Byte position where error occurred
887
+ }
888
+ ```
889
+
890
+ **Common scenarios:**
891
+ - Truncated transaction data
892
+ - Invalid script opcodes
893
+ - Malformed witness data
894
+
895
+ ```typescript
896
+ try {
897
+ TX.decode(malformedHex)
898
+ } catch (err) {
899
+ if (err instanceof DecodingError) {
900
+ console.log(`Decode error at position ${err.position}: ${err.message}`)
901
+ }
902
+ }
903
+ ```
904
+
905
+ ### `ConfigError`
906
+
907
+ Thrown when configuration is invalid.
908
+
909
+ ```typescript
910
+ import { ConfigError } from '@vbyte/btc-dev'
911
+
912
+ class ConfigError extends Error {
913
+ name: 'ConfigError'
914
+ }
915
+ ```
916
+
917
+ **Common scenarios:**
918
+ - Invalid sighash flag
919
+ - Unknown network type
920
+ - Incompatible option combinations
921
+
922
+ ```typescript
923
+ try {
924
+ SIGNER.sign_taproot_tx(seckey, tx, { sigflag: 0xFF })
925
+ } catch (err) {
926
+ if (err instanceof ConfigError) {
927
+ console.log(`Config error: ${err.message}`)
928
+ }
929
+ }
930
+ ```
931
+
932
+ ---
933
+
934
+ ## CONST
935
+
936
+ Constants used throughout the library.
937
+
938
+ ### Transaction Defaults
939
+
940
+ ```typescript
941
+ CONST.DEFAULT.VERSION // 2 - Default transaction version
942
+ CONST.DEFAULT.LOCKTIME // 0 - Default locktime
943
+ CONST.DEFAULT.SEQUENCE // 0xffffffff - Default sequence (no RBF, no timelock)
944
+ ```
945
+
946
+ ### Coinbase Constants
947
+
948
+ ```typescript
949
+ CONST.COINBASE.TXID // '00'.repeat(32) - Coinbase previous txid (all zeros)
950
+ CONST.COINBASE.VOUT // 0xffffffff - Coinbase previous vout
951
+ ```
952
+
953
+ ### Script Types
954
+
955
+ ```typescript
956
+ CONST.LOCK_SCRIPT_TYPE // { P2PKH, P2SH, P2WPKH, P2WSH, P2TR, OPRETURN }
957
+ CONST.SPEND_SCRIPT_TYPE // { P2PKH, P2SH, P2WPKH, P2WSH, P2TR, P2TS }
958
+ CONST.LOCK_SCRIPT_REGEX // Regex patterns for each script type
959
+ ```
960
+
961
+ ### Sighash Flags
962
+
963
+ ```typescript
964
+ CONST.SIGHASH_DEFAULT // 0x01 - Default sighash (SIGHASH_ALL)
965
+ CONST.SIGHASH_SEGWIT // [0x01, 0x02, 0x03, 0x81, 0x82, 0x83] - Valid segwit flags
966
+ CONST.SIGHASH_TAPROOT // [0x00, ...SIGHASH_SEGWIT] - Valid taproot flags (includes DEFAULT)
967
+ ```
968
+
969
+ ### Taproot Constants
970
+
971
+ ```typescript
972
+ CONST.TAPLEAF_DEFAULT_VERSION // 0xc0 - Default tapleaf version
973
+ CONST.TAPLEAF_VERSIONS // Array of all valid tapleaf versions
974
+ ```
975
+
976
+ ### Size Limits
977
+
978
+ ```typescript
979
+ CONST.MAX_SCRIPT_SIZE // 10,000 - Bitcoin consensus script size limit
980
+ CONST.MAX_VARINT_SIZE // 520,000 - Maximum varint payload size
981
+ CONST.OP_1_OFFSET // 0x50 - Offset to convert 1-16 to OP_1-OP_16
982
+ ```
983
+
984
+ ### Transaction Size Components
985
+
986
+ ```typescript
987
+ CONST.TX_SIZE.GLOBAL_BASE // 8 - Base size without witness
988
+ CONST.TX_SIZE.GLOBAL_WIT // 10 - Base size with witness
989
+ CONST.TX_SIZE.TXIN_BASE // 40 - Input base size (32+4+4)
990
+ CONST.TX_SIZE.TXOUT_BASE // 8 - Output base size
991
+ ```
992
+
993
+ ---
994
+
995
+ ## SCHEMA
996
+
997
+ Zod validation schemas for runtime type checking.
998
+
999
+ ### Transaction Schemas
1000
+
1001
+ ```typescript
1002
+ SCHEMA.tx.txid // 32-byte hex string
1003
+ SCHEMA.tx.output // { value: bigint, script_pk: string }
1004
+ SCHEMA.tx.input // Transaction input schema
1005
+ SCHEMA.tx.template // Transaction template for creation
1006
+ ```
1007
+
1008
+ ### Taproot Schemas
1009
+
1010
+ ```typescript
1011
+ SCHEMA.taproot.taptree // Single leaf or array of leaves
1012
+ SCHEMA.taproot.config // { pubkey, leaves?, target?, version? }
1013
+ ```
1014
+
1015
+ ### Usage
1016
+
1017
+ ```typescript
1018
+ import { SCHEMA } from '@vbyte/btc-dev'
1019
+
1020
+ // Validate transaction template
1021
+ const result = SCHEMA.tx.template.safeParse(userInput)
1022
+ if (!result.success) {
1023
+ console.error(result.error.issues)
1024
+ }
1025
+
1026
+ // Validate taproot config
1027
+ SCHEMA.taproot.config.parse({
1028
+ pubkey: '02'.repeat(32),
1029
+ leaves: ['aa'.repeat(32)]
1030
+ })
1031
+ ```
1032
+
1033
+ ---
1034
+
1035
+ ## Type Definitions
1036
+
1037
+ ### Core Types
1038
+
1039
+ ```typescript
1040
+ type ChainNetwork = 'main' | 'test'
1041
+ type LockScriptType = 'p2pkh' | 'p2sh' | 'p2wpkh' | 'p2wsh' | 'p2tr' | 'opreturn'
1042
+ type WitnessVersion = 0 | 1
1043
+
1044
+ interface TxData {
1045
+ version: number
1046
+ locktime: number
1047
+ vin: TxInput[]
1048
+ vout: TxOutput[]
1049
+ }
1050
+
1051
+ interface TxInput {
1052
+ txid: string
1053
+ vout: number
1054
+ sequence: number
1055
+ script_sig: string | null
1056
+ witness: string[]
1057
+ prevout: TxOutput | null
1058
+ coinbase: string | null
1059
+ }
1060
+
1061
+ interface TxOutput {
1062
+ value: bigint
1063
+ script_pk: string
1064
+ }
1065
+
1066
+ interface TxSize {
1067
+ base: number
1068
+ total: number
1069
+ vsize: number
1070
+ weight: number
1071
+ }
1072
+
1073
+ interface AddressData {
1074
+ data: string // The address string
1075
+ format: string // Address format
1076
+ network: string // Network name
1077
+ script: Buff // scriptPubKey
1078
+ version?: number // Witness version
1079
+ }
1080
+
1081
+ interface SigHashOptions {
1082
+ txindex?: number
1083
+ txinput?: TxInput
1084
+ pubkey?: string
1085
+ script?: string
1086
+ sigflag?: number
1087
+ extension?: string
1088
+ }
1089
+
1090
+ interface WitnessData {
1091
+ type: 'p2wpkh' | 'p2wsh' | 'p2tr' | 'p2ts' | null
1092
+ version: 0 | 1 | null
1093
+ params: string[]
1094
+ script: string | null
1095
+ cblock: string | null
1096
+ annex: string | null
1097
+ }
1098
+
1099
+ interface LocktimeData {
1100
+ type: 'heightlock' | 'timelock'
1101
+ height?: number
1102
+ stamp?: number
1103
+ }
1104
+
1105
+ interface SequenceData {
1106
+ mode: 'height' | 'stamp'
1107
+ height?: number
1108
+ stamp?: number
1109
+ }
1110
+
1111
+ interface ControlBlock {
1112
+ int_key: string // Internal public key (32 bytes hex)
1113
+ path: string[] // Merkle path
1114
+ parity: number // Y-coordinate parity (0x02 or 0x03)
1115
+ version: number // Tapleaf version
1116
+ }
1117
+
1118
+ interface TaprootConfig {
1119
+ pubkey: string // Internal public key (32 bytes)
1120
+ leaves?: string[][] // Optional tapleaf hashes
1121
+ target?: string // Target leaf for control block
1122
+ version?: number // Leaf version (default: 0xc0)
1123
+ }
1124
+
1125
+ interface TaprootContext {
1126
+ int_key: string // Internal public key
1127
+ path: string[] // Merkle proof path
1128
+ parity: number // Output key parity
1129
+ taproot: string | null // Merkle root
1130
+ cblock: string // Control block hex
1131
+ tapkey: string // Tweaked output key
1132
+ taptweak: string // Tweak value
1133
+ }
1134
+
1135
+ interface InscriptionData {
1136
+ mimetype?: string // Content MIME type
1137
+ content?: string // Content as hex string
1138
+ parent?: string // Parent inscription ID
1139
+ delegate?: string // Delegate inscription ID
1140
+ pointer?: number // Output pointer
1141
+ opcode?: number // Custom opcode
1142
+ rune?: string // Rune name (A-Z only)
1143
+ ref?: string // Reference data
1144
+ }
1145
+ ```