@vbyte/btc-dev 1.1.7 → 2.0.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 (174) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/README.md +260 -3
  3. package/dist/const.d.ts +3 -0
  4. package/dist/const.js +23 -22
  5. package/dist/index.d.ts +11 -11
  6. package/dist/index.js +10 -10
  7. package/dist/lib/address/api.d.ts +2 -2
  8. package/dist/lib/address/api.js +12 -12
  9. package/dist/lib/address/encode.d.ts +1 -1
  10. package/dist/lib/address/encode.js +24 -24
  11. package/dist/lib/address/index.d.ts +6 -6
  12. package/dist/lib/address/index.js +6 -6
  13. package/dist/lib/address/p2pkh.d.ts +2 -2
  14. package/dist/lib/address/p2pkh.js +14 -14
  15. package/dist/lib/address/p2sh.d.ts +2 -2
  16. package/dist/lib/address/p2sh.js +13 -13
  17. package/dist/lib/address/p2tr.d.ts +2 -2
  18. package/dist/lib/address/p2tr.js +13 -13
  19. package/dist/lib/address/p2wpkh.d.ts +2 -2
  20. package/dist/lib/address/p2wpkh.js +14 -14
  21. package/dist/lib/address/p2wsh.d.ts +2 -2
  22. package/dist/lib/address/p2wsh.js +13 -13
  23. package/dist/lib/address/script.d.ts +1 -1
  24. package/dist/lib/address/script.js +16 -16
  25. package/dist/lib/address/util.d.ts +1 -1
  26. package/dist/lib/address/util.js +22 -22
  27. package/dist/lib/meta/index.d.ts +4 -4
  28. package/dist/lib/meta/index.js +4 -4
  29. package/dist/lib/meta/locktime.d.ts +1 -1
  30. package/dist/lib/meta/locktime.js +12 -12
  31. package/dist/lib/meta/ref.js +9 -6
  32. package/dist/lib/meta/scribe.d.ts +2 -2
  33. package/dist/lib/meta/scribe.js +48 -53
  34. package/dist/lib/meta/sequence.d.ts +1 -1
  35. package/dist/lib/meta/sequence.js +16 -15
  36. package/dist/lib/script/decode.d.ts +2 -2
  37. package/dist/lib/script/decode.js +50 -15
  38. package/dist/lib/script/encode.d.ts +1 -1
  39. package/dist/lib/script/encode.js +20 -16
  40. package/dist/lib/script/index.d.ts +5 -13
  41. package/dist/lib/script/index.js +5 -14
  42. package/dist/lib/script/lock.d.ts +2 -2
  43. package/dist/lib/script/lock.js +15 -12
  44. package/dist/lib/script/util.js +4 -4
  45. package/dist/lib/script/words.js +129 -129
  46. package/dist/lib/sighash/index.d.ts +3 -3
  47. package/dist/lib/sighash/index.js +3 -3
  48. package/dist/lib/sighash/segwit.d.ts +2 -2
  49. package/dist/lib/sighash/segwit.js +15 -14
  50. package/dist/lib/sighash/taproot.d.ts +2 -2
  51. package/dist/lib/sighash/taproot.js +24 -23
  52. package/dist/lib/sighash/util.d.ts +2 -2
  53. package/dist/lib/sighash/util.js +7 -7
  54. package/dist/lib/signer/index.d.ts +2 -2
  55. package/dist/lib/signer/index.js +2 -2
  56. package/dist/lib/signer/sign.d.ts +1 -1
  57. package/dist/lib/signer/sign.js +42 -7
  58. package/dist/lib/signer/verify.d.ts +17 -3
  59. package/dist/lib/signer/verify.js +233 -3
  60. package/dist/lib/taproot/cblock.d.ts +1 -1
  61. package/dist/lib/taproot/cblock.js +14 -16
  62. package/dist/lib/taproot/encode.d.ts +1 -1
  63. package/dist/lib/taproot/encode.js +7 -7
  64. package/dist/lib/taproot/index.d.ts +4 -4
  65. package/dist/lib/taproot/index.js +4 -4
  66. package/dist/lib/taproot/parse.d.ts +1 -1
  67. package/dist/lib/taproot/parse.js +12 -14
  68. package/dist/lib/taproot/tree.d.ts +2 -2
  69. package/dist/lib/taproot/tree.js +11 -7
  70. package/dist/lib/tx/create.d.ts +1 -1
  71. package/dist/lib/tx/create.js +28 -12
  72. package/dist/lib/tx/decode.d.ts +2 -2
  73. package/dist/lib/tx/decode.js +50 -17
  74. package/dist/lib/tx/encode.d.ts +2 -2
  75. package/dist/lib/tx/encode.js +13 -16
  76. package/dist/lib/tx/index.d.ts +7 -7
  77. package/dist/lib/tx/index.js +7 -7
  78. package/dist/lib/tx/parse.d.ts +1 -1
  79. package/dist/lib/tx/parse.js +9 -9
  80. package/dist/lib/tx/size.d.ts +2 -2
  81. package/dist/lib/tx/size.js +9 -9
  82. package/dist/lib/tx/util.d.ts +2 -2
  83. package/dist/lib/tx/util.js +23 -22
  84. package/dist/lib/tx/validate.d.ts +1 -1
  85. package/dist/lib/tx/validate.js +3 -3
  86. package/dist/lib/witness/index.d.ts +2 -2
  87. package/dist/lib/witness/index.js +2 -2
  88. package/dist/lib/witness/parse.d.ts +2 -2
  89. package/dist/lib/witness/parse.js +24 -23
  90. package/dist/lib/witness/util.d.ts +2 -2
  91. package/dist/lib/witness/util.js +5 -5
  92. package/dist/main.cjs +2308 -1007
  93. package/dist/main.cjs.map +1 -1
  94. package/dist/module.mjs +2308 -1007
  95. package/dist/module.mjs.map +1 -1
  96. package/dist/package.json +20 -17
  97. package/dist/schema/base.d.ts +1 -1
  98. package/dist/schema/base.js +17 -13
  99. package/dist/schema/index.d.ts +2 -2
  100. package/dist/schema/index.js +2 -2
  101. package/dist/schema/taproot.d.ts +1 -1
  102. package/dist/schema/taproot.js +2 -2
  103. package/dist/schema/tx.d.ts +1 -1
  104. package/dist/schema/tx.js +4 -4
  105. package/dist/script.js +8 -8
  106. package/dist/script.js.map +1 -1
  107. package/dist/types/address.d.ts +4 -4
  108. package/dist/types/index.d.ts +8 -8
  109. package/dist/types/index.js +8 -8
  110. package/dist/types/meta.d.ts +4 -4
  111. package/dist/types/psbt.d.ts +2 -2
  112. package/dist/types/script.d.ts +2 -2
  113. package/dist/types/sighash.d.ts +2 -2
  114. package/dist/types/witness.d.ts +5 -5
  115. package/package.json +20 -17
  116. package/src/const.ts +0 -61
  117. package/src/index.ts +0 -13
  118. package/src/lib/address/api.ts +0 -50
  119. package/src/lib/address/encode.ts +0 -183
  120. package/src/lib/address/index.ts +0 -7
  121. package/src/lib/address/p2pkh.ts +0 -94
  122. package/src/lib/address/p2sh.ts +0 -96
  123. package/src/lib/address/p2tr.ts +0 -91
  124. package/src/lib/address/p2wpkh.ts +0 -94
  125. package/src/lib/address/p2wsh.ts +0 -92
  126. package/src/lib/address/script.ts +0 -63
  127. package/src/lib/address/util.ts +0 -87
  128. package/src/lib/meta/index.ts +0 -4
  129. package/src/lib/meta/locktime.ts +0 -57
  130. package/src/lib/meta/ref.ts +0 -107
  131. package/src/lib/meta/scribe.ts +0 -256
  132. package/src/lib/meta/sequence.ts +0 -146
  133. package/src/lib/script/decode.ts +0 -85
  134. package/src/lib/script/encode.ts +0 -129
  135. package/src/lib/script/index.ts +0 -20
  136. package/src/lib/script/lock.ts +0 -73
  137. package/src/lib/script/util.ts +0 -78
  138. package/src/lib/script/words.ts +0 -182
  139. package/src/lib/sighash/index.ts +0 -3
  140. package/src/lib/sighash/segwit.ts +0 -152
  141. package/src/lib/sighash/taproot.ts +0 -206
  142. package/src/lib/sighash/util.ts +0 -51
  143. package/src/lib/signer/index.ts +0 -2
  144. package/src/lib/signer/sign.ts +0 -39
  145. package/src/lib/signer/verify.ts +0 -88
  146. package/src/lib/taproot/cblock.ts +0 -96
  147. package/src/lib/taproot/encode.ts +0 -49
  148. package/src/lib/taproot/index.ts +0 -4
  149. package/src/lib/taproot/parse.ts +0 -65
  150. package/src/lib/taproot/tree.ts +0 -94
  151. package/src/lib/tx/create.ts +0 -90
  152. package/src/lib/tx/decode.ts +0 -123
  153. package/src/lib/tx/encode.ts +0 -155
  154. package/src/lib/tx/index.ts +0 -7
  155. package/src/lib/tx/parse.ts +0 -69
  156. package/src/lib/tx/size.ts +0 -68
  157. package/src/lib/tx/util.ts +0 -113
  158. package/src/lib/tx/validate.ts +0 -49
  159. package/src/lib/witness/index.ts +0 -2
  160. package/src/lib/witness/parse.ts +0 -127
  161. package/src/lib/witness/util.ts +0 -18
  162. package/src/schema/base.ts +0 -57
  163. package/src/schema/index.ts +0 -2
  164. package/src/schema/taproot.ts +0 -12
  165. package/src/schema/tx.ts +0 -48
  166. package/src/types/address.ts +0 -35
  167. package/src/types/index.ts +0 -8
  168. package/src/types/meta.ts +0 -48
  169. package/src/types/psbt.ts +0 -15
  170. package/src/types/script.ts +0 -18
  171. package/src/types/sighash.ts +0 -16
  172. package/src/types/taproot.ts +0 -41
  173. package/src/types/txdata.ts +0 -85
  174. package/src/types/witness.ts +0 -42
package/CHANGELOG.md ADDED
@@ -0,0 +1,94 @@
1
+ # CHANGELOG
2
+
3
+ ## [2.0.0] - 2026-01-23
4
+
5
+ ### Security Fixes
6
+
7
+ - **Fixed witness parsing bug**: Added missing `break` statements in switch block in `src/lib/witness/parse.ts` that could cause incorrect script extraction for p2ts and p2wsh witness types.
8
+ - **Implemented `verify_tx()` function**: Full signature verification for segwit (ECDSA) and taproot (Schnorr) transactions, supporting all sighash types.
9
+ - **Added input validation to sign functions**: Secret key format validation in `sign_segwit_tx()` and `sign_taproot_tx()` to prevent invalid key errors.
10
+ - **Added transaction size limits**: Maximum transaction size (4MB), varint size (10MB), and element count (100k) limits in decoder to prevent memory exhaustion attacks.
11
+ - **Added taproot tree depth limits**: Maximum depth of 128 levels in merkle tree construction to prevent stack overflow from deeply nested trees.
12
+ - **Sanitized error messages**: Removed sensitive data from error messages in address and transaction modules.
13
+ - **Fixed taproot verification null check**: Added proper null check for `prevout` in taproot input verification to prevent runtime errors.
14
+
15
+ ### New Features
16
+
17
+ - **Full signature verification**: `verify_tx()` now returns detailed verification results including per-input status and error messages.
18
+ - **Enhanced witness parsing**: Improved annex detection and control block parsing for taproot witnesses.
19
+
20
+ ### Code Quality
21
+
22
+ - **Biome linting compliance**: Applied comprehensive linting fixes across all 59 source files in `src/`
23
+ - Converted string concatenation to template literals
24
+ - Added explicit radix parameter to all `parseInt()` calls
25
+ - Converted `import` statements to `import type` where appropriate
26
+ - Replaced `isNaN()` with `Number.isNaN()` for type safety
27
+ - Simplified computed property access to literal keys
28
+ - Standardized code formatting (quotes, semicolons, indentation)
29
+ - **Improved control block construction**: Replaced `forEach` with spread operator in taproot control block building
30
+
31
+ ### Testing
32
+
33
+ - Added 843+ new tests (total: 1063 tests passing)
34
+ - **SIGNER module tests**: Essential signing function tests, transaction scenarios, and sighash coverage
35
+ - **WITNESS module tests**: Full witness parsing coverage (p2wpkh, p2wsh, p2tr, p2ts, annex) plus edge cases
36
+ - **SCRIPT module tests**: Lock script detection, decode/encode roundtrips, malformed script handling, size limits
37
+ - **SIGHASH module tests**: Bounds checking and edge cases
38
+ - **META module tests**: BIP-65 locktime, BIP-68 sequence, and reference pointer encoding/decoding
39
+ - **TX module tests**: Size calculation, essential operations, create functions, encoding functions, error handling
40
+ - **TAPROOT module tests**: Parse operations coverage
41
+ - **Integration tests**: End-to-end workflows for address creation, transaction building, and signing
42
+
43
+ ### Documentation
44
+
45
+ - **README.md**: Expanded with installation instructions, quick start guide, module overview, and API examples
46
+ - **SECURITY.md**: New security guidelines document covering private key handling, input validation, and best practices
47
+ - **EXAMPLES.md**: New examples document with practical code for common Bitcoin development tasks
48
+ - **CONVENTIONS.md**: Added project coding conventions documentation
49
+ - **JSDoc**: Added comprehensive documentation to exported functions with @param, @returns, @throws, and @example
50
+ - **Type definitions**: Documented all interfaces in `src/types/`
51
+ - **Schemas**: Added inline documentation for validation schemas
52
+
53
+ ### Breaking Changes
54
+
55
+ - `verify_tx()` now returns a `VerifyResult` object instead of a boolean. Access the `.valid` property for boolean result.
56
+
57
+ ## [1.1.8]
58
+
59
+ - Removed excess logging.
60
+
61
+ ## [1.1.7]
62
+
63
+ - Removed schema dependency.
64
+ - Fixed an issue with the transaction encoder.
65
+
66
+ ## [1.1.6]
67
+
68
+ - Changed `create_address` to `get_address`, fixed issues with interface.
69
+
70
+ ## [1.1.5]
71
+
72
+ - Updated exports for Script module.
73
+
74
+ ## [1.1.4]
75
+
76
+ - Updates to API for Address module.
77
+ - Updates to API for Script module.
78
+ - Updates to API for TX module.
79
+
80
+ ## [1.1.3]
81
+
82
+ - Updated transaction utils to have a better input interface.
83
+
84
+ ## [1.1.2]
85
+
86
+ - Methods `get_tx_output_type` and `get_tx_output_version` have been updated and replaced with `get_script_pk_type` and `get_script_pk_version`.
87
+
88
+ ## [1.1.1]
89
+
90
+ - Updated `encode_script`
91
+
92
+ ## [1.1.0]
93
+
94
+ - Public release.
package/README.md CHANGED
@@ -1,5 +1,262 @@
1
- # btc-dev
1
+ # @vbyte/btc-dev
2
2
 
3
- Experimental revision of the bitcoin [tapscript](https://www.npmjs.com/package/@cmdcode/tapscript) library.
3
+ A batteries-included TypeScript toolset for Bitcoin development. Create, sign, and verify Bitcoin transactions with full support for segwit and taproot.
4
4
 
5
- Documentation coming soon!
5
+ ## Features
6
+
7
+ - **Full Address Support**: P2PKH, P2SH, P2WPKH, P2WSH, P2TR (taproot)
8
+ - **Transaction Building**: Create, encode, decode, and parse Bitcoin transactions
9
+ - **Signature Hashing**: BIP-143 (segwit) and BIP-341 (taproot) sighash calculation
10
+ - **Signing & Verification**: ECDSA (segwit) and Schnorr (taproot) signatures
11
+ - **Taproot Scripts**: Merkle tree construction, control blocks, and script-path spends
12
+ - **Script Handling**: Encode/decode Bitcoin scripts, lock script detection
13
+ - **Metadata Utilities**: Locktime, sequence (BIP-68), outpoints, rune IDs, inscription IDs
14
+ - **Type Safety**: Full TypeScript support with strict types
15
+ - **Tree-shakeable**: Import only what you need
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install @vbyte/btc-dev
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```typescript
26
+ import { ADDRESS, TX, SIGNER } from '@vbyte/btc-dev'
27
+
28
+ // Create a P2WPKH address from a public key
29
+ const address = ADDRESS.p2wpkh(pubkey, 'main')
30
+ console.log(address.data) // bc1q...
31
+
32
+ // Parse a raw transaction
33
+ const tx = TX.parse(txhex)
34
+ console.log(tx.vin.length, 'inputs')
35
+ console.log(tx.vout.length, 'outputs')
36
+
37
+ // Sign a segwit transaction
38
+ const signature = SIGNER.sign_segwit_tx(secretKey, txdata, {
39
+ txindex: 0,
40
+ pubkey: publicKey,
41
+ sigflag: 0x01 // SIGHASH_ALL
42
+ })
43
+ ```
44
+
45
+ ## Module Overview
46
+
47
+ | Module | Description |
48
+ |--------|-------------|
49
+ | `ADDRESS` | Create and parse Bitcoin addresses (P2PKH, P2SH, P2WPKH, P2WSH, P2TR) |
50
+ | `TX` | Transaction creation, encoding, decoding, parsing, and validation |
51
+ | `SCRIPT` | Bitcoin script encoding, decoding, and lock script detection |
52
+ | `SIGHASH` | Signature hash calculation for segwit (BIP-143) and taproot (BIP-341) |
53
+ | `SIGNER` | Sign and verify transactions using ECDSA and Schnorr |
54
+ | `TAPROOT` | Taproot tree construction, control blocks, and tweaking |
55
+ | `WITNESS` | Parse and analyze witness data |
56
+ | `META` | Locktime, sequence, outpoints, and reference IDs |
57
+
58
+ ## Import Patterns
59
+
60
+ ```typescript
61
+ // Import all namespaces
62
+ import { ADDRESS, TX, SCRIPT, SIGHASH, SIGNER, TAPROOT, WITNESS, META } from '@vbyte/btc-dev'
63
+
64
+ // Tree-shaking: import specific modules
65
+ import { p2wpkh, p2tr } from '@vbyte/btc-dev/address'
66
+ import { parse_tx, encode_tx } from '@vbyte/btc-dev/tx'
67
+ import { sign_segwit_tx, sign_taproot_tx, verify_tx } from '@vbyte/btc-dev/signer'
68
+ ```
69
+
70
+ ## API Highlights
71
+
72
+ ### Address Creation
73
+
74
+ ```typescript
75
+ import { ADDRESS } from '@vbyte/btc-dev'
76
+
77
+ // P2PKH (legacy)
78
+ const p2pkh = ADDRESS.p2pkh(pubkey, 'main')
79
+
80
+ // P2WPKH (native segwit)
81
+ const p2wpkh = ADDRESS.p2wpkh(pubkey, 'main')
82
+
83
+ // P2WSH (segwit script hash)
84
+ const p2wsh = ADDRESS.p2wsh(redeemScript, 'main')
85
+
86
+ // P2TR (taproot)
87
+ const p2tr = ADDRESS.p2tr(xOnlyPubkey, 'main')
88
+ ```
89
+
90
+ ### Transaction Parsing
91
+
92
+ ```typescript
93
+ import { TX } from '@vbyte/btc-dev'
94
+
95
+ // Parse raw transaction hex
96
+ const tx = TX.parse(rawTxHex)
97
+
98
+ // Access transaction data
99
+ console.log(tx.version) // Transaction version
100
+ console.log(tx.vin) // Inputs array
101
+ console.log(tx.vout) // Outputs array
102
+ console.log(tx.locktime) // Locktime
103
+
104
+ // Encode transaction back to hex
105
+ const encoded = TX.encode(tx)
106
+ ```
107
+
108
+ ### Signing Transactions
109
+
110
+ ```typescript
111
+ import { SIGNER } from '@vbyte/btc-dev'
112
+
113
+ // Sign segwit (v0) transaction input
114
+ const segwitSig = SIGNER.sign_segwit_tx(secretKey, txdata, {
115
+ txindex: 0, // Input index to sign
116
+ pubkey: compressedPubkey, // For P2WPKH
117
+ sigflag: 0x01 // SIGHASH_ALL
118
+ })
119
+
120
+ // Sign taproot (v1) transaction input
121
+ const taprootSig = SIGNER.sign_taproot_tx(secretKey, txdata, {
122
+ txindex: 0,
123
+ sigflag: 0x00 // SIGHASH_DEFAULT (taproot)
124
+ })
125
+
126
+ // Verify all signatures in a transaction
127
+ const result = SIGNER.verify_tx(txdata)
128
+ if (result.valid) {
129
+ console.log('All signatures valid')
130
+ } else {
131
+ console.log('Verification failed:', result.error)
132
+ result.inputs.forEach(input => {
133
+ if (!input.valid) console.log(`Input ${input.index}: ${input.error}`)
134
+ })
135
+ }
136
+ ```
137
+
138
+ ### Taproot Scripts
139
+
140
+ ```typescript
141
+ import { TAPROOT } from '@vbyte/btc-dev'
142
+
143
+ // Create a taproot output with scripts
144
+ const taprootCtx = TAPROOT.create({
145
+ pubkey: internalPubkey,
146
+ leaves: [tapleaf1, tapleaf2] // Script leaves
147
+ })
148
+
149
+ console.log(taprootCtx.tapkey) // Tweaked public key
150
+ console.log(taprootCtx.cblock) // Control block for script-path
151
+ console.log(taprootCtx.taptweak) // Tweak value
152
+
153
+ // Verify control block
154
+ const isValid = TAPROOT.verify(tapkey, target, cblock)
155
+ ```
156
+
157
+ ### Script Detection
158
+
159
+ ```typescript
160
+ import { SCRIPT } from '@vbyte/btc-dev'
161
+
162
+ // Detect lock script type
163
+ const type = SCRIPT.get_lock_script_type(scriptPubKey)
164
+ // Returns: 'p2pkh' | 'p2sh' | 'p2wpkh' | 'p2wsh' | 'p2tr' | 'opreturn' | null
165
+
166
+ // Check specific types
167
+ SCRIPT.is_p2wpkh_script(script) // true/false
168
+ SCRIPT.is_p2tr_script(script) // true/false
169
+
170
+ // Get witness version
171
+ const version = SCRIPT.get_lock_script_version(script)
172
+ // Returns: 0 (segwit v0), 1 (taproot), or null (legacy)
173
+ ```
174
+
175
+ ### Witness Parsing
176
+
177
+ ```typescript
178
+ import { WITNESS } from '@vbyte/btc-dev'
179
+
180
+ // Parse witness data from transaction input
181
+ const witnessData = WITNESS.parse(witness)
182
+
183
+ console.log(witnessData.type) // 'p2wpkh' | 'p2wsh' | 'p2tr' | 'p2ts' | null
184
+ console.log(witnessData.version) // 0 | 1 | null
185
+ console.log(witnessData.params) // Signature and other params
186
+ console.log(witnessData.script) // Witness script (if p2wsh/p2ts)
187
+ console.log(witnessData.cblock) // Control block (if p2ts)
188
+ console.log(witnessData.annex) // Annex data (if present)
189
+ ```
190
+
191
+ ### Metadata Utilities
192
+
193
+ ```typescript
194
+ import { META } from '@vbyte/btc-dev'
195
+
196
+ // Encode/decode locktime (BIP-65)
197
+ const locktime = META.encode_locktime({ type: 'heightlock', height: 800000 })
198
+ const decoded = META.decode_locktime(locktime)
199
+
200
+ // Encode/decode sequence (BIP-68)
201
+ const sequence = META.encode_sequence({ mode: 'height', height: 144 }) // ~24 hours
202
+ const decodedSeq = META.decode_sequence(sequence)
203
+
204
+ // Reference pointers
205
+ const outpoint = META.RefPointer.outpoint.encode(txid, vout)
206
+ const inscriptionId = META.RefPointer.record_id.encode(txid, 0)
207
+ const runeId = META.RefPointer.rune_id.encode(840000, 15)
208
+ ```
209
+
210
+ ## Security Considerations
211
+
212
+ - Always validate inputs before signing transactions
213
+ - Never log or expose secret keys
214
+ - Use secure random number generation for key generation
215
+ - Verify signatures after signing to ensure correctness
216
+ - Be aware of sighash flag implications (ANYONECANPAY, SINGLE, NONE)
217
+
218
+ See [SECURITY.md](./docs/SECURITY.md) for detailed security guidelines.
219
+
220
+ ## Type Definitions
221
+
222
+ All types are exported from the main module:
223
+
224
+ ```typescript
225
+ import type {
226
+ TxData,
227
+ TxInput,
228
+ TxOutput,
229
+ SigHashOptions,
230
+ AddressData,
231
+ WitnessData,
232
+ TaprootContext
233
+ } from '@vbyte/btc-dev'
234
+ ```
235
+
236
+ ## Dependencies
237
+
238
+ - `@noble/curves` - Elliptic curve cryptography
239
+ - `@noble/hashes` - Cryptographic hash functions
240
+ - `@scure/btc-signer` - Bitcoin signing utilities
241
+ - `@vbyte/buff` - Buffer manipulation utilities
242
+ - `zod` - Runtime validation schemas
243
+
244
+ ## Development
245
+
246
+ ```bash
247
+ # Run tests
248
+ npm test
249
+
250
+ # Run specific test file
251
+ npm run script test/path/to/file.ts
252
+
253
+ # Build the package
254
+ npm run build
255
+
256
+ # Build and test
257
+ npm run package
258
+ ```
259
+
260
+ ## License
261
+
262
+ CC-BY-1.0
package/dist/const.d.ts CHANGED
@@ -36,3 +36,6 @@ export declare const TX_SIZE: {
36
36
  export declare const SIGHASH_DEFAULT = 1;
37
37
  export declare const SIGHASH_SEGWIT: number[];
38
38
  export declare const SIGHASH_TAPROOT: number[];
39
+ export declare const MAX_SCRIPT_SIZE = 10000;
40
+ export declare const MAX_VARINT_SIZE = 520000;
41
+ export declare const OP_1_OFFSET = 80;
package/dist/const.js CHANGED
@@ -1,36 +1,34 @@
1
1
  export const COINBASE = {
2
- TXID: '00'.repeat(32),
3
- VOUT: 0xFFFFFFFF,
2
+ TXID: "00".repeat(32),
3
+ VOUT: 0xffffffff,
4
4
  };
5
5
  export const DEFAULT = {
6
6
  LOCKTIME: 0,
7
- SEQUENCE: 0xFFFFFFFF,
7
+ SEQUENCE: 0xffffffff,
8
8
  VERSION: 2,
9
9
  };
10
10
  export const TAPLEAF_VERSIONS = [
11
- 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce,
12
- 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
13
- 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee,
14
- 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
15
- 0x66, 0x7e, 0x80, 0x84, 0x96, 0x98, 0xba, 0xbc,
16
- 0xbe
11
+ 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8,
12
+ 0xda, 0xdc, 0xde, 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2,
13
+ 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, 0x66, 0x7e, 0x80, 0x84, 0x96, 0x98, 0xba,
14
+ 0xbc, 0xbe,
17
15
  ];
18
16
  export const TAPLEAF_DEFAULT_VERSION = 0xc0;
19
17
  export const LOCK_SCRIPT_TYPE = {
20
- P2PKH: 'p2pkh',
21
- P2SH: 'p2sh',
22
- P2WPKH: 'p2wpkh',
23
- P2WSH: 'p2wsh',
24
- P2TR: 'p2tr',
25
- OPRETURN: 'opreturn',
18
+ P2PKH: "p2pkh",
19
+ P2SH: "p2sh",
20
+ P2WPKH: "p2wpkh",
21
+ P2WSH: "p2wsh",
22
+ P2TR: "p2tr",
23
+ OPRETURN: "opreturn",
26
24
  };
27
25
  export const SPEND_SCRIPT_TYPE = {
28
- P2PKH: 'p2pkh',
29
- P2SH: 'p2sh',
30
- P2WPKH: 'p2wpkh',
31
- P2WSH: 'p2wsh',
32
- P2TR: 'p2tr',
33
- P2TS: 'p2ts',
26
+ P2PKH: "p2pkh",
27
+ P2SH: "p2sh",
28
+ P2WPKH: "p2wpkh",
29
+ P2WSH: "p2wsh",
30
+ P2TR: "p2tr",
31
+ P2TS: "p2ts",
34
32
  };
35
33
  export const LOCK_SCRIPT_REGEX = {
36
34
  [LOCK_SCRIPT_TYPE.P2PKH]: /^76a914[0-9a-f]{40}88ac$/i,
@@ -40,7 +38,7 @@ export const LOCK_SCRIPT_REGEX = {
40
38
  [LOCK_SCRIPT_TYPE.P2TR]: /^5120[0-9a-f]{64}$/i,
41
39
  [LOCK_SCRIPT_TYPE.OPRETURN]: /^6a[0-9a-f]{2,}$/i,
42
40
  };
43
- export const SCRIPT_INT_KEY = '';
41
+ export const SCRIPT_INT_KEY = "";
44
42
  export const TX_SIZE = {
45
43
  GLOBAL_BASE: 8,
46
44
  GLOBAL_WIT: 10,
@@ -50,3 +48,6 @@ export const TX_SIZE = {
50
48
  export const SIGHASH_DEFAULT = 0x01;
51
49
  export const SIGHASH_SEGWIT = [0x01, 0x02, 0x03, 0x81, 0x82, 0x83];
52
50
  export const SIGHASH_TAPROOT = [0x00, ...SIGHASH_SEGWIT];
51
+ export const MAX_SCRIPT_SIZE = 10_000;
52
+ export const MAX_VARINT_SIZE = 520_000;
53
+ export const OP_1_OFFSET = 0x50;
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- export * as ADDRESS from './lib/address/index.js';
2
- export * as META from './lib/meta/index.js';
3
- export * as SCRIPT from './lib/script/index.js';
4
- export * as SIGHASH from './lib/sighash/index.js';
5
- export * as SIGNER from './lib/signer/index.js';
6
- export * as TAPROOT from './lib/taproot/index.js';
7
- export * as TX from './lib/tx/index.js';
8
- export * as WITNESS from './lib/witness/index.js';
9
- export * as CONST from './const.js';
10
- export * as SCHEMA from './schema/index.js';
11
- export type * from './types/index.js';
1
+ export * as CONST from "./const.js";
2
+ export * as ADDRESS from "./lib/address/index.js";
3
+ export * as META from "./lib/meta/index.js";
4
+ export * as SCRIPT from "./lib/script/index.js";
5
+ export * as SIGHASH from "./lib/sighash/index.js";
6
+ export * as SIGNER from "./lib/signer/index.js";
7
+ export * as TAPROOT from "./lib/taproot/index.js";
8
+ export * as TX from "./lib/tx/index.js";
9
+ export * as WITNESS from "./lib/witness/index.js";
10
+ export * as SCHEMA from "./schema/index.js";
11
+ export type * from "./types/index.js";
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
- export * as ADDRESS from './lib/address/index.js';
2
- export * as META from './lib/meta/index.js';
3
- export * as SCRIPT from './lib/script/index.js';
4
- export * as SIGHASH from './lib/sighash/index.js';
5
- export * as SIGNER from './lib/signer/index.js';
6
- export * as TAPROOT from './lib/taproot/index.js';
7
- export * as TX from './lib/tx/index.js';
8
- export * as WITNESS from './lib/witness/index.js';
9
- export * as CONST from './const.js';
10
- export * as SCHEMA from './schema/index.js';
1
+ export * as CONST from "./const.js";
2
+ export * as ADDRESS from "./lib/address/index.js";
3
+ export * as META from "./lib/meta/index.js";
4
+ export * as SCRIPT from "./lib/script/index.js";
5
+ export * as SIGHASH from "./lib/sighash/index.js";
6
+ export * as SIGNER from "./lib/signer/index.js";
7
+ export * as TAPROOT from "./lib/taproot/index.js";
8
+ export * as TX from "./lib/tx/index.js";
9
+ export * as WITNESS from "./lib/witness/index.js";
10
+ export * as SCHEMA from "./schema/index.js";
@@ -1,4 +1,4 @@
1
- import { Bytes } from '@vbyte/buff';
2
- import type { AddressInfo, ChainNetwork } from '../../types/index.js';
1
+ import { type Bytes } from "@vbyte/buff";
2
+ import type { AddressInfo, ChainNetwork } from "../../types/index.js";
3
3
  export declare function get_address(script: Bytes, network?: ChainNetwork): string;
4
4
  export declare function parse_address(address: string): AddressInfo;
@@ -1,17 +1,17 @@
1
- import { Buff } from '@vbyte/buff';
2
- import { get_lock_script_type } from '../../lib/script/lock.js';
3
- import { get_address_info } from './util.js';
4
- import { LOCK_SCRIPT_TYPE } from '../../const.js';
5
- import { P2PKH } from './p2pkh.js';
6
- import { P2SH } from './p2sh.js';
7
- import { P2TR } from './p2tr.js';
8
- import { P2WPKH } from './p2wpkh.js';
9
- import { P2WSH } from './p2wsh.js';
10
- export function get_address(script, network = 'main') {
1
+ import { Buff } from "@vbyte/buff";
2
+ import { LOCK_SCRIPT_TYPE } from "../../const.js";
3
+ import { get_lock_script_type } from "../../lib/script/lock.js";
4
+ import { P2PKH } from "./p2pkh.js";
5
+ import { P2SH } from "./p2sh.js";
6
+ import { P2TR } from "./p2tr.js";
7
+ import { P2WPKH } from "./p2wpkh.js";
8
+ import { P2WSH } from "./p2wsh.js";
9
+ import { get_address_info } from "./util.js";
10
+ export function get_address(script, network = "main") {
11
11
  const bytes = Buff.bytes(script);
12
12
  const type = get_lock_script_type(bytes);
13
13
  if (type === null)
14
- throw new Error('unknown locking script: ' + bytes.hex);
14
+ throw new Error("Unknown or unsupported locking script type");
15
15
  switch (type) {
16
16
  case LOCK_SCRIPT_TYPE.P2PKH:
17
17
  return P2PKH.encode_address(script, network);
@@ -24,7 +24,7 @@ export function get_address(script, network = 'main') {
24
24
  case LOCK_SCRIPT_TYPE.P2TR:
25
25
  return P2TR.encode_address(script, network);
26
26
  default:
27
- throw new Error('unknown script type: ' + type);
27
+ throw new Error(`unknown script type: ${type}`);
28
28
  }
29
29
  }
30
30
  export function parse_address(address) {
@@ -1,3 +1,3 @@
1
- import type { EncoderConfig } from '../../types/address.js';
1
+ import type { EncoderConfig } from "../../types/address.js";
2
2
  export declare function decode_address(address: string): EncoderConfig;
3
3
  export declare function encode_address(config: EncoderConfig): string;
@@ -1,34 +1,34 @@
1
- import { Buff } from '@vbyte/buff';
2
- import { Assert, B58chk, Bech32, Bech32m } from '@vbyte/micro-lib';
1
+ import { Buff } from "@vbyte/buff";
2
+ import { Assert, B58chk, Bech32, Bech32m } from "@vbyte/micro-lib";
3
3
  const ENCODING_REGEX = {
4
4
  base58: /^[13mn2][a-km-zA-HJ-NP-Z1-9]{25,34}$/,
5
5
  bech32: /^(bc|tb|bcrt)1q[ac-hj-np-z02-9]{6,87}$/,
6
- bech32m: /^(bc|tb|bcrt)1p[ac-hj-np-z02-9]{6,87}$/
6
+ bech32m: /^(bc|tb|bcrt)1p[ac-hj-np-z02-9]{6,87}$/,
7
7
  };
8
8
  const VERSION = {
9
9
  bech32: 0,
10
- bech32m: 1
10
+ bech32m: 1,
11
11
  };
12
12
  export function decode_address(address) {
13
13
  const format = get_address_format(address);
14
14
  if (format === null)
15
- throw new Error('unrecognized address format: ' + format);
16
- if (format === 'base58')
15
+ throw new Error(`unrecognized address format: ${address}`);
16
+ if (format === "base58")
17
17
  return base58_decode(address);
18
- if (format === 'bech32')
18
+ if (format === "bech32")
19
19
  return bech32_decode(address);
20
- if (format === 'bech32m')
20
+ if (format === "bech32m")
21
21
  return bech32m_decode(address);
22
- throw new Error('unable to find a matching address configuration');
22
+ throw new Error("unable to find a matching address configuration");
23
23
  }
24
24
  export function encode_address(config) {
25
- if (config.format === 'base58')
25
+ if (config.format === "base58")
26
26
  return base58_encode(config);
27
- if (config.format === 'bech32')
27
+ if (config.format === "bech32")
28
28
  return bech32_encode(config);
29
- if (config.format === 'bech32m')
29
+ if (config.format === "bech32m")
30
30
  return bech32m_encode(config);
31
- throw new Error('unrecognized encoding format: ' + config.format);
31
+ throw new Error(`unrecognized encoding format: ${config.format}`);
32
32
  }
33
33
  function get_address_format(address) {
34
34
  for (const [format, regex] of Object.entries(ENCODING_REGEX)) {
@@ -38,8 +38,8 @@ function get_address_format(address) {
38
38
  return null;
39
39
  }
40
40
  function base58_encode(config) {
41
- Assert.ok(config.format === 'base58', 'encoding mismatch');
42
- Assert.exists(config.version, 'must specify a version');
41
+ Assert.ok(config.format === "base58", "encoding mismatch");
42
+ Assert.exists(config.version, "must specify a version");
43
43
  const bytes = Buff.join([config.version, config.data]);
44
44
  return B58chk.encode(bytes);
45
45
  }
@@ -47,11 +47,11 @@ function base58_decode(encoded) {
47
47
  const bytes = B58chk.decode(encoded);
48
48
  const data = bytes.slice(1);
49
49
  const version = bytes[0];
50
- return { data, format: 'base58', version };
50
+ return { data, format: "base58", version };
51
51
  }
52
52
  function bech32_encode(config) {
53
- Assert.ok(config.format === 'bech32', 'encoding mismatch');
54
- Assert.exists(config.prefix, 'prefix is required');
53
+ Assert.ok(config.format === "bech32", "encoding mismatch");
54
+ Assert.exists(config.prefix, "prefix is required");
55
55
  const bytes = Buff.bytes(config.data);
56
56
  const words = Bech32.to_words(bytes);
57
57
  return Bech32.encode(config.prefix, [VERSION.bech32, ...words]);
@@ -59,13 +59,13 @@ function bech32_encode(config) {
59
59
  function bech32_decode(encoded) {
60
60
  const { prefix, words } = Bech32.decode(encoded);
61
61
  const [version, ...rest] = words;
62
- Assert.ok(version === VERSION.bech32, 'bech32 version mismatch');
62
+ Assert.ok(version === VERSION.bech32, "bech32 version mismatch");
63
63
  const data = Bech32.to_bytes(rest);
64
- return { data, format: 'bech32', prefix, version };
64
+ return { data, format: "bech32", prefix, version };
65
65
  }
66
66
  function bech32m_encode(config) {
67
- Assert.ok(config.format === 'bech32m', 'encoding mismatch');
68
- Assert.exists(config.prefix, 'prefix is required');
67
+ Assert.ok(config.format === "bech32m", "encoding mismatch");
68
+ Assert.exists(config.prefix, "prefix is required");
69
69
  const bytes = Buff.bytes(config.data);
70
70
  const words = Bech32m.to_words(bytes);
71
71
  return Bech32m.encode(config.prefix, [VERSION.bech32m, ...words]);
@@ -73,7 +73,7 @@ function bech32m_encode(config) {
73
73
  function bech32m_decode(encoded) {
74
74
  const { prefix, words } = Bech32m.decode(encoded);
75
75
  const [version, ...rest] = words;
76
- Assert.ok(version === VERSION.bech32m, 'bech32m version mismatch');
76
+ Assert.ok(version === VERSION.bech32m, "bech32m version mismatch");
77
77
  const data = Bech32m.to_bytes(rest);
78
- return { data, format: 'bech32m', prefix, version };
78
+ return { data, format: "bech32m", prefix, version };
79
79
  }
@@ -1,6 +1,6 @@
1
- export { P2PKH } from './p2pkh.js';
2
- export { P2SH } from './p2sh.js';
3
- export { P2WPKH } from './p2wpkh.js';
4
- export { P2WSH } from './p2wsh.js';
5
- export { P2TR } from './p2tr.js';
6
- export * from './api.js';
1
+ export * from "./api.js";
2
+ export { P2PKH } from "./p2pkh.js";
3
+ export { P2SH } from "./p2sh.js";
4
+ export { P2TR } from "./p2tr.js";
5
+ export { P2WPKH } from "./p2wpkh.js";
6
+ export { P2WSH } from "./p2wsh.js";