@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
@@ -0,0 +1,316 @@
1
+ # Code Conventions
2
+
3
+ Coding conventions for the btc-dev Bitcoin development library. Reference this when writing or editing code.
4
+
5
+ ## Quick Reference
6
+
7
+ | Element | Convention | Example |
8
+ |---------|------------|---------|
9
+ | Functions | `snake_case` | `encode_address`, `parse_witness`, `create_tx_input` |
10
+ | Variables | `snake_case` | `txid`, `witness`, `sequence`, `prevout` |
11
+ | Types/Interfaces | `PascalCase` | `TxData`, `AddressInfo`, `SigHashOptions` |
12
+ | Constants | `SCREAMING_SNAKE_CASE` | `SIGHASH_DEFAULT`, `COINBASE`, `LOCK_SCRIPT_TYPE` |
13
+ | Files | `snake_case.ts` | `encode.ts`, `parse.ts`, `create.ts` |
14
+ | Directories | `snake_case` | `address/`, `script/`, `tx/`, `signer/` |
15
+
16
+ ## Naming Conventions
17
+
18
+ ### Functions and Variables
19
+
20
+ Use `snake_case` for all functions, variables, and object properties:
21
+
22
+ ```typescript
23
+ // Functions
24
+ export function create_tx_input(config: TxInputTemplate) { }
25
+ export function sign_segwit_tx(seckey: string, txdata: TxData) { }
26
+
27
+ // Variables
28
+ const sequence = normalize_sequence(config.sequence)
29
+ const witness = config.witness ?? []
30
+ const prevout = normalize_prevout(config.prevout)
31
+ ```
32
+
33
+ ### Types and Interfaces
34
+
35
+ Use `PascalCase` with semantic suffixes:
36
+
37
+ | Suffix | Purpose | Example |
38
+ |--------|---------|---------|
39
+ | `Config` | User-provided configuration | `TaprootConfig`, `AddressConfig` |
40
+ | `Template` | Input structure for creation | `TxTemplate`, `TxInputTemplate` |
41
+ | `Data` | Generic data structure | `TxData`, `TxDecodedData` |
42
+ | `Info` | Enriched/parsed information | `AddressInfo`, `ScriptInfo` |
43
+ | `Options` | Optional parameters | `SigHashOptions` |
44
+
45
+ ```typescript
46
+ // Template (user input for creation)
47
+ export interface TxInputTemplate extends TxOutpoint {
48
+ coinbase? : string | null
49
+ prevout? : TxOutput | null
50
+ script_sig? : string | null
51
+ sequence? : number
52
+ witness? : string[]
53
+ }
54
+
55
+ // Data (normalized output)
56
+ export interface TxData {
57
+ locktime : number
58
+ vin : TxInput[]
59
+ vout : TxOutput[]
60
+ version : number
61
+ }
62
+
63
+ // Options (configuration for operations)
64
+ export interface SigHashOptions {
65
+ extension? : string
66
+ sigflag? : number
67
+ txindex? : number
68
+ pubkey? : string
69
+ script? : string
70
+ }
71
+ ```
72
+
73
+ ### Constants
74
+
75
+ Use `SCREAMING_SNAKE_CASE`:
76
+
77
+ ```typescript
78
+ export const SIGHASH_DEFAULT = 0x01
79
+ export const TAPLEAF_DEFAULT_VERSION = 0xc0
80
+
81
+ // Grouped constants use nested objects
82
+ export const COINBASE = {
83
+ TXID : '00'.repeat(32),
84
+ VOUT : 0xFFFFFFFF,
85
+ }
86
+
87
+ export const LOCK_SCRIPT_TYPE = {
88
+ P2PKH : 'p2pkh',
89
+ P2SH : 'p2sh',
90
+ P2WPKH : 'p2wpkh',
91
+ P2WSH : 'p2wsh',
92
+ P2TR : 'p2tr',
93
+ OPRETURN : 'opreturn',
94
+ } as const
95
+ ```
96
+
97
+ ## API Namespace Pattern
98
+
99
+ Each module exports a namespace using `export * as NAMESPACE`:
100
+
101
+ ```typescript
102
+ // src/index.ts
103
+ export * as ADDRESS from './lib/address/index.js'
104
+ export * as SCRIPT from './lib/script/index.js'
105
+ export * as SIGNER from './lib/signer/index.js'
106
+ export * as TX from './lib/tx/index.js'
107
+
108
+ export * as CONST from './const.js'
109
+ export * as SCHEMA from './schema/index.js'
110
+
111
+ export type * from './types/index.js'
112
+ ```
113
+
114
+ **Usage pattern:**
115
+ ```typescript
116
+ import { ADDRESS, TX, SCRIPT } from '@vbyte/btc-dev'
117
+
118
+ // Access module functions via namespace
119
+ const address_info = ADDRESS.P2PKH.decode(address)
120
+ const tx_data = TX.create_tx(template)
121
+ const script_hex = SCRIPT.encode_script(script)
122
+ ```
123
+
124
+ ## Import Organization
125
+
126
+ Three groups in order, with aligned `from` keywords:
127
+
128
+ ```typescript
129
+ // 1. External dependencies
130
+ import { Buff } from '@vbyte/buff'
131
+ import { Assert } from '@vbyte/util'
132
+ import { ECC } from '@vbyte/crypto'
133
+ import { schnorr } from '@noble/curves/secp256k1'
134
+
135
+ // 2. Internal imports (path alias)
136
+ import { COINBASE, DEFAULT } from '@/const.js'
137
+ import { parse_tx } from '@/lib/tx/parse.js'
138
+ import { hash_segwit_tx } from '@/lib/sighash/segwit.js'
139
+
140
+ // 3. Type imports (separate block)
141
+ import type {
142
+ TxData,
143
+ TxInputTemplate,
144
+ SigHashOptions
145
+ } from '@/types/index.js'
146
+ ```
147
+
148
+ ### Path Aliases
149
+
150
+ | Alias | Resolves To | Used In |
151
+ |-------|-------------|---------|
152
+ | `@/` | `src/` | All code (`src/`, `test/`) |
153
+
154
+ ```typescript
155
+ // In src/ files
156
+ import { DEFAULT } from '@/const.js'
157
+
158
+ // In test/ files
159
+ import { TX } from '@/index.js'
160
+ ```
161
+
162
+ ## Export Patterns
163
+
164
+ ```typescript
165
+ // Flat re-exports in index.ts
166
+ export * from './encode.js'
167
+ export * from './decode.js'
168
+ export * from './parse.js'
169
+
170
+ // Namespaced exports for modules
171
+ export * as SCHEMA from './schema/index.js'
172
+
173
+ // Type-only exports
174
+ export type * from './types/index.js'
175
+ ```
176
+
177
+ ## Error Handling
178
+
179
+ ### Assertions
180
+
181
+ Use `Assert` from `@vbyte/util`:
182
+
183
+ ```typescript
184
+ import { Assert } from '@vbyte/util'
185
+
186
+ Assert.exists(config.prevout, 'prevout is required')
187
+ Assert.is_empty(config.coinbase, 'coinbase is not allowed')
188
+ ```
189
+
190
+ ### Zod Validation
191
+
192
+ Use Zod schemas for runtime validation:
193
+
194
+ ```typescript
195
+ import { z } from 'zod'
196
+
197
+ export const tx_output = z.object({
198
+ value : z.bigint().min(0n).max(2_100_000_000_000_000n),
199
+ script_pk : hex,
200
+ }) satisfies z.ZodType<TxOutput>
201
+
202
+ export const tx_input = z.object({
203
+ coinbase : hex.nullable(),
204
+ txid : hex32,
205
+ vout : uint,
206
+ prevout : tx_output.nullable(),
207
+ script_sig : hex.nullable(),
208
+ sequence : uint,
209
+ witness : z.array(hex)
210
+ })
211
+ ```
212
+
213
+ ## Formatting
214
+
215
+ ### Vertical Alignment
216
+
217
+ Align colons in interfaces, objects, and parameters:
218
+
219
+ ```typescript
220
+ // Interface properties
221
+ export interface TxSize {
222
+ base : number
223
+ total : number
224
+ vsize : number
225
+ weight : number
226
+ }
227
+
228
+ // Function parameters
229
+ export function sign_segwit_tx (
230
+ seckey : string,
231
+ txdata : TxData,
232
+ options : SigHashOptions,
233
+ ) : string { }
234
+
235
+ // Object literals
236
+ const input = {
237
+ txid : config.txid,
238
+ vout : config.vout,
239
+ prevout : normalize_prevout(config.prevout),
240
+ sequence : normalize_sequence(config.sequence),
241
+ witness : config.witness ?? []
242
+ }
243
+ ```
244
+
245
+ ### Indentation
246
+
247
+ - 2 spaces (no tabs)
248
+ - Multi-line parameters aligned
249
+
250
+ ### Numbers
251
+
252
+ Use underscores for readability:
253
+
254
+ ```typescript
255
+ const MAX_SATS = 2_100_000_000_000_000n
256
+ const TIMEOUT_MS = 30_000
257
+ ```
258
+
259
+ ### File Extensions
260
+
261
+ Always use `.js` in imports (ES module compatibility):
262
+
263
+ ```typescript
264
+ import { DEFAULT } from '@/const.js'
265
+ import type { TxData } from '../types/index.js'
266
+ ```
267
+
268
+ ## Domain Abbreviations
269
+
270
+ | Abbrev | Meaning |
271
+ |--------|---------|
272
+ | `psbt` | Partially Signed Bitcoin Transaction |
273
+ | `txid` | Transaction ID (hex string) |
274
+ | `utxo` | Unspent Transaction Output |
275
+ | `sats` | Satoshis (1 BTC = 100,000,000 sats) |
276
+ | `vout` | Output index in transaction |
277
+ | `vin` | Input index in transaction |
278
+ | `tx` | Transaction |
279
+ | `sig` | Signature |
280
+ | `seckey` | Secret/private key |
281
+ | `pubkey` | Public key |
282
+ | `script_pk` | Script pubkey (locking script) |
283
+ | `script_sig` | Script signature (unlocking script) |
284
+ | `prevout` | Previous output (spent by input) |
285
+ | `segwit` | Segregated Witness |
286
+ | `taproot` | Taproot (BIP340/341/342) |
287
+
288
+ ## Comments
289
+
290
+ - Explain "why" not "what"
291
+ - Use `//` with space, sentence case
292
+ - JSDoc for exported functions
293
+
294
+ ```typescript
295
+ /**
296
+ * Sign a transaction input using segwit (BIP143) signature hashing.
297
+ * @param seckey - 32-byte secret key as hex string (64 characters)
298
+ * @param txdata - Transaction data
299
+ * @param options - Sighash options including txindex, sigflag, pubkey/script
300
+ * @returns ECDSA signature with sighash flag appended
301
+ * @throws Error if secret key format is invalid
302
+ */
303
+ export function sign_segwit_tx (
304
+ seckey : string,
305
+ txdata : TxData,
306
+ options : SigHashOptions,
307
+ ) {
308
+ // Validate inputs before processing.
309
+ validate_seckey(seckey)
310
+ validate_sighash_options(options, SIGHASH_SEGWIT)
311
+ // Hash and sign the transaction.
312
+ const tx = parse_tx(txdata)
313
+ const msg = hash_segwit_tx(tx, options)
314
+ return ECC.sign_ecdsa(seckey, msg).hex + format_sigflag(options.sigflag)
315
+ }
316
+ ```
package/docs/FAQ.md ADDED
@@ -0,0 +1,396 @@
1
+ # Frequently Asked Questions
2
+
3
+ Common questions and troubleshooting for `@vbyte/btc-dev`.
4
+
5
+ ## Installation
6
+
7
+ ### Why can't I import the library?
8
+
9
+ **ESM Only**: This library is ESM-only. Make sure your project is configured for ESM:
10
+
11
+ ```json
12
+ // package.json
13
+ {
14
+ "type": "module"
15
+ }
16
+ ```
17
+
18
+ Or use the `.mjs` extension for your files.
19
+
20
+ ### Can I use this with CommonJS?
21
+
22
+ The library provides a CommonJS build at `dist/main.cjs`, but ESM is recommended. For CommonJS:
23
+
24
+ ```javascript
25
+ const { ADDRESS, TX } = require('@vbyte/btc-dev')
26
+ ```
27
+
28
+ ### Can I use this in a browser?
29
+
30
+ Yes. Use the UMD bundle:
31
+
32
+ ```html
33
+ <script src="https://unpkg.com/@vbyte/btc-dev/dist/script.js"></script>
34
+ <script>
35
+ const { ADDRESS, TX } = btcDev
36
+ </script>
37
+ ```
38
+
39
+ Or use a bundler like Vite, Webpack, or Rollup with the ESM imports.
40
+
41
+ ## TypeScript
42
+
43
+ ### What TypeScript version is required?
44
+
45
+ TypeScript 5.0 or later is recommended. The library uses strict mode.
46
+
47
+ ### How do I import types?
48
+
49
+ ```typescript
50
+ import type { TxData, AddressInfo, SigHashOptions } from '@vbyte/btc-dev'
51
+ ```
52
+
53
+ ### Why am I getting type errors?
54
+
55
+ Make sure your `tsconfig.json` has:
56
+
57
+ ```json
58
+ {
59
+ "compilerOptions": {
60
+ "moduleResolution": "bundler",
61
+ "module": "ESNext",
62
+ "target": "ES2020"
63
+ }
64
+ }
65
+ ```
66
+
67
+ ## Addresses
68
+
69
+ ### Which address type should I use?
70
+
71
+ - **P2WPKH** (`bc1q...`): Best for single-signature wallets. Good balance of efficiency and compatibility.
72
+ - **P2TR** (`bc1p...`): Best for privacy and future-proofing. Some older wallets don't support it yet.
73
+ - **P2WSH**: For multisig or complex scripts.
74
+ - **P2PKH/P2SH**: Only for legacy compatibility.
75
+
76
+ ### Why does my address look different on testnet?
77
+
78
+ Testnet uses different prefixes:
79
+
80
+ | Type | Mainnet | Testnet |
81
+ |------|---------|---------|
82
+ | P2WPKH | `bc1q...` | `tb1q...` |
83
+ | P2TR | `bc1p...` | `tb1p...` |
84
+
85
+ Always specify the correct network: `'main'` or `'test'`.
86
+
87
+ ### How do I convert a compressed pubkey to x-only for taproot?
88
+
89
+ Remove the first byte (02 or 03):
90
+
91
+ ```typescript
92
+ const compressed = '02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c'
93
+ const xOnly = compressed.slice(2) // Remove 02/03 prefix
94
+ ```
95
+
96
+ ## Transactions
97
+
98
+ ### Why does my signature verification fail?
99
+
100
+ Common causes:
101
+
102
+ 1. **Wrong prevout data**: The prevout value and script must match exactly
103
+ 2. **Wrong pubkey**: For P2WPKH, use the compressed public key
104
+ 3. **Wrong sighash flag**: Make sure signing and verification use the same flag
105
+ 4. **Missing witness**: Add the witness data after signing
106
+
107
+ ```typescript
108
+ // Check prevout is correct
109
+ console.log('Prevout value:', tx.vin[0].prevout.value)
110
+ console.log('Prevout script:', tx.vin[0].prevout.script_pk)
111
+
112
+ // Verify witness is added
113
+ console.log('Witness:', tx.vin[0].witness)
114
+ ```
115
+
116
+ ### How do I calculate the transaction fee?
117
+
118
+ ```typescript
119
+ const inputTotal = tx.vin.reduce((sum, vin) => sum + vin.prevout.value, 0n)
120
+ const outputTotal = tx.vout.reduce((sum, vout) => sum + vout.value, 0n)
121
+ const fee = inputTotal - outputTotal
122
+ ```
123
+
124
+ ### What's the difference between size, vsize, and weight?
125
+
126
+ - **Size**: Raw byte count
127
+ - **Weight**: Size calculation that discounts witness data (base * 4 + witness)
128
+ - **vSize**: Virtual size = weight / 4, used for fee calculation
129
+
130
+ Always use `vsize` for fee estimation.
131
+
132
+ ### Why is my transaction rejected as "dust"?
133
+
134
+ Outputs below the dust limit (~546 sats for P2PKH, ~294 for P2WPKH) are rejected. Increase the output value.
135
+
136
+ ### How do I enable RBF (Replace-By-Fee)?
137
+
138
+ Set sequence to less than 0xfffffffe on at least one input:
139
+
140
+ ```typescript
141
+ {
142
+ txid: '...',
143
+ vout: 0,
144
+ sequence: 0xfffffffd // RBF enabled
145
+ }
146
+ ```
147
+
148
+ ## Signing
149
+
150
+ ### What format should the secret key be?
151
+
152
+ A 64-character hex string (32 bytes):
153
+
154
+ ```typescript
155
+ const secretKey = 'abcd1234...'.repeat(8) // 64 hex chars
156
+ ```
157
+
158
+ ### Why do I get "Invalid secret key format"?
159
+
160
+ The secret key must be:
161
+ - A string (not Buffer or Uint8Array)
162
+ - Exactly 64 hex characters
163
+ - Valid hex (0-9, a-f, A-F)
164
+
165
+ ### What's the difference between segwit and taproot signing?
166
+
167
+ - **Segwit** (`sign_segwit_tx`): Uses ECDSA signatures, requires compressed pubkey
168
+ - **Taproot** (`sign_taproot_tx`): Uses Schnorr signatures, uses x-only pubkeys
169
+
170
+ ### How do I sign multiple inputs?
171
+
172
+ Sign each input separately:
173
+
174
+ ```typescript
175
+ for (let i = 0; i < tx.vin.length; i++) {
176
+ const sig = SIGNER.sign_segwit_tx(secretKey, tx, {
177
+ txindex: i,
178
+ pubkey: pubkeys[i],
179
+ sigflag: 0x01
180
+ })
181
+ tx.vin[i].witness = [sig, pubkeys[i]]
182
+ }
183
+ ```
184
+
185
+ ## Taproot
186
+
187
+ ### When should I use key-path vs script-path?
188
+
189
+ - **Key-path**: Single signer, no complex conditions (cheapest, most private)
190
+ - **Script-path**: Multisig, timelocks, or alternative spending conditions
191
+
192
+ ### Do I need to tweak the secret key?
193
+
194
+ For key-path spending, yes:
195
+
196
+ ```typescript
197
+ import { tweak_seckey } from '@vbyte/crypto/ecc'
198
+ const taptweak = TAPROOT.encode_taptweak(internalPubkey, merkleRoot)
199
+ const tweakedSeckey = tweak_seckey(internalSeckey, taptweak, true)
200
+ ```
201
+
202
+ For script-path, use the original key for the script, not the tweaked key.
203
+
204
+ ### What's a control block?
205
+
206
+ A control block proves that a script is part of the taproot tree. It contains:
207
+ - Leaf version and parity byte
208
+ - Internal public key
209
+ - Merkle path (sibling hashes)
210
+
211
+ ## Scripts
212
+
213
+ ### How do I detect the script type of an output?
214
+
215
+ ```typescript
216
+ import { SCRIPT } from '@vbyte/btc-dev'
217
+
218
+ const type = SCRIPT.get_lock_script_type(scriptPubKey)
219
+ // Returns: 'p2pkh' | 'p2sh' | 'p2wpkh' | 'p2wsh' | 'p2tr' | 'opreturn' | null
220
+ ```
221
+
222
+ ### How do I create a multisig script?
223
+
224
+ ```typescript
225
+ // 2-of-3 multisig
226
+ import { SCRIPT } from '@vbyte/btc-dev'
227
+
228
+ const script = SCRIPT.encode([
229
+ 'OP_2',
230
+ pubkey1,
231
+ pubkey2,
232
+ pubkey3,
233
+ 'OP_3',
234
+ 'OP_CHECKMULTISIG'
235
+ ])
236
+ ```
237
+
238
+ ## Error Handling
239
+
240
+ ### What error types does the library throw?
241
+
242
+ The library provides three custom error classes for better error handling:
243
+
244
+ ```typescript
245
+ import { ValidationError, DecodingError, ConfigError } from '@vbyte/btc-dev'
246
+
247
+ try {
248
+ const tx = TX.decode(malformedData)
249
+ } catch (err) {
250
+ if (err instanceof DecodingError) {
251
+ console.log('Malformed data at position:', err.position)
252
+ } else if (err instanceof ValidationError) {
253
+ console.log('Invalid input field:', err.field)
254
+ } else if (err instanceof ConfigError) {
255
+ console.log('Configuration error:', err.message)
256
+ }
257
+ }
258
+ ```
259
+
260
+ | Error Class | When Thrown | Properties |
261
+ |-------------|-------------|------------|
262
+ | `ValidationError` | Invalid input format, wrong length, type mismatch | `field?: string` |
263
+ | `DecodingError` | Malformed data, truncated input, invalid structure | `position?: number` |
264
+ | `ConfigError` | Invalid sigflag, unknown network, bad configuration | - |
265
+
266
+ ### How do I catch specific errors?
267
+
268
+ Use `instanceof` to check the error type:
269
+
270
+ ```typescript
271
+ try {
272
+ SIGNER.sign_segwit_tx('invalid', tx, options)
273
+ } catch (err) {
274
+ if (err instanceof ValidationError) {
275
+ // Handle invalid secret key format
276
+ console.log(`Validation failed for: ${err.field}`)
277
+ }
278
+ }
279
+ ```
280
+
281
+ ### Which functions throw which errors?
282
+
283
+ **ValidationError:**
284
+ - `sign_segwit_tx`, `sign_taproot_tx` - Invalid secret key format
285
+ - Most functions with input validation
286
+
287
+ **DecodingError:**
288
+ - `decode_tx` - Malformed transaction data
289
+ - `decode_script` - Invalid script (truncated pushdata, invalid opcodes)
290
+
291
+ **ConfigError:**
292
+ - `sign_segwit_tx`, `sign_taproot_tx` - Invalid sigflag
293
+ - Address functions - Unknown network
294
+
295
+ ### How do I handle errors gracefully?
296
+
297
+ ```typescript
298
+ function safeDecode(hexData: string) {
299
+ try {
300
+ return { success: true, data: TX.decode(hexData) }
301
+ } catch (err) {
302
+ if (err instanceof DecodingError) {
303
+ return { success: false, error: `Decode error at ${err.position}: ${err.message}` }
304
+ }
305
+ return { success: false, error: err instanceof Error ? err.message : 'Unknown error' }
306
+ }
307
+ }
308
+ ```
309
+
310
+ ## Security
311
+
312
+ ### Is this library audited?
313
+
314
+ The cryptographic operations use audited libraries (`@noble/curves`, `@noble/hashes`). The Bitcoin-specific code has comprehensive tests but hasn't undergone a formal audit.
315
+
316
+ ### How do I securely handle private keys?
317
+
318
+ Key points:
319
+ - Never log or expose secret keys
320
+ - Clear from memory when possible
321
+ - Use cryptographically secure random number generation
322
+
323
+ See the [Security Best Practices section in the Guide](GUIDE.md#security-best-practices) for detailed examples.
324
+
325
+ ### What transaction size limits are enforced?
326
+
327
+ The library enforces limits to prevent denial-of-service attacks:
328
+
329
+ - **Maximum transaction size**: 4MB (Bitcoin consensus limit)
330
+ - **Maximum varint size**: 10MB (prevents memory exhaustion)
331
+ - **Maximum inputs/outputs**: 100,000 per transaction
332
+ - **Maximum taproot tree depth**: 128 levels
333
+
334
+ These limits are enforced automatically during decoding.
335
+
336
+ ### What are the known limitations?
337
+
338
+ 1. **OP_CODESEPARATOR**: Not fully supported in segwit scripts. The library will throw if encountered.
339
+
340
+ 2. **P2SH-wrapped scripts**: Legacy P2SH spending is not fully implemented. Use native segwit (P2WPKH/P2WSH) instead.
341
+
342
+ 3. **Multi-signature**: Complex multi-sig scripts require manual construction and may need custom handling.
343
+
344
+ ### What cryptographic dependencies does this library use?
345
+
346
+ This library depends on well-maintained, audited cryptographic libraries:
347
+
348
+ - `@noble/curves` - Audited cryptographic library for elliptic curves
349
+ - `@noble/hashes` - Audited hash functions
350
+ - `@scure/btc-signer` - Bitcoin signing utilities from the same author
351
+
352
+ Keep dependencies updated:
353
+
354
+ ```bash
355
+ npm audit
356
+ npm update
357
+ ```
358
+
359
+ ## Debugging
360
+
361
+ ### How do I inspect a raw transaction?
362
+
363
+ ```typescript
364
+ import { TX, SCRIPT } from '@vbyte/btc-dev'
365
+
366
+ const tx = TX.parse(rawTxHex)
367
+
368
+ console.log('Version:', tx.version)
369
+ console.log('Locktime:', tx.locktime)
370
+
371
+ tx.vin.forEach((vin, i) => {
372
+ console.log(`Input ${i}:`, vin.txid, vin.vout)
373
+ })
374
+
375
+ tx.vout.forEach((vout, i) => {
376
+ const type = SCRIPT.get_lock_script_type(vout.script_pk)
377
+ console.log(`Output ${i}:`, vout.value.toString(), 'sats', type)
378
+ })
379
+ ```
380
+
381
+ ### How do I decode a witness?
382
+
383
+ ```typescript
384
+ import { WITNESS } from '@vbyte/btc-dev'
385
+
386
+ const data = WITNESS.parse(tx.vin[0].witness)
387
+ console.log('Type:', data.type)
388
+ console.log('Version:', data.version)
389
+ console.log('Params:', data.params)
390
+ ```
391
+
392
+ ## Getting Help
393
+
394
+ - Check [GitHub Issues](https://github.com/cmdruid/btc-dev/issues)
395
+ - Read the [API Reference](API.md)
396
+ - See the [Guide](GUIDE.md) for tutorials and examples