@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,942 @@
1
+ # I/O Utilities
2
+
3
+ High-performance binary I/O module providing encoding, decoding, buffer manipulation, and stateful binary reading/writing with zero-allocation operations through reused DataView instances.
4
+
5
+ ## Overview
6
+
7
+ | Category | Functions / Classes |
8
+ |----------|-------------------|
9
+ | Hex encoding | `toHex()`, `fromHex()`, `isHex()` |
10
+ | Base64 encoding | `fromBase64()`, `toBase64()` |
11
+ | Base58Check encoding | `base58check.encode()`, `base58check.decode()`, `base58check.decodeUnsafe()` |
12
+ | Buffer utilities | `concat()`, `equals()`, `compare()`, `isZero()`, `clone()`, `reverse()`, `reverseCopy()`, `alloc()`, `xor()` |
13
+ | UTF-8 utilities | `fromUtf8()`, `toUtf8()` |
14
+ | Variable-length integers | `varuint.encode()`, `varuint.decode()`, `varuint.encodingLength()` |
15
+ | Binary reading | `BinaryReader` class |
16
+ | Binary writing | `BinaryWriter`, `GrowableBinaryWriter` classes |
17
+
18
+ ---
19
+
20
+ ## Installation
21
+
22
+ Most I/O utilities (hex, base64, buffer utilities, UTF-8, varuint) are re-exported from the main entry point. However, `base58check`, `BinaryReader`, `BinaryWriter`, and `GrowableBinaryWriter` are only available from the `@btc-vision/bitcoin/io` subpath.
23
+
24
+ ```typescript
25
+ // These are available from the main entry point:
26
+ import {
27
+ // Hex
28
+ toHex, fromHex, isHex,
29
+ // Base64
30
+ fromBase64, toBase64,
31
+ // Buffer utilities
32
+ concat, equals, compare, isZero, clone, reverse, reverseCopy, alloc, xor,
33
+ // UTF-8
34
+ fromUtf8, toUtf8,
35
+ // Variable-length integers
36
+ varuint,
37
+ } from '@btc-vision/bitcoin';
38
+
39
+ // These are only available from the io subpath:
40
+ import {
41
+ base58check,
42
+ BinaryReader, BinaryWriter, GrowableBinaryWriter,
43
+ } from '@btc-vision/bitcoin/io';
44
+ ```
45
+
46
+ > **Note:** `@btc-vision/bs58check` (the underlying Base58Check implementation) is listed under `devDependencies`, not `dependencies`. If your project uses `base58check` directly, ensure that `@btc-vision/bs58check` is installed in your own project's dependencies.
47
+
48
+ ---
49
+
50
+ ## Hex Encoding
51
+
52
+ Optimized hex encoding and decoding using pre-computed lookup tables for O(1) per-byte conversion. Zero dependencies.
53
+
54
+ ### toHex
55
+
56
+ Converts a `Uint8Array` to a lowercase hex string.
57
+
58
+ ```typescript
59
+ function toHex(bytes: Uint8Array): string;
60
+ ```
61
+
62
+ ```typescript
63
+ import { toHex } from '@btc-vision/bitcoin';
64
+
65
+ const bytes = new Uint8Array([0xde, 0xad, 0xbe, 0xef]);
66
+ const hex = toHex(bytes);
67
+ console.log(hex); // 'deadbeef'
68
+ ```
69
+
70
+ ### fromHex
71
+
72
+ Converts a hex string to a `Uint8Array`. Accepts hex strings with or without `0x` prefix. Case-insensitive.
73
+
74
+ ```typescript
75
+ function fromHex(hex: string): Uint8Array;
76
+ ```
77
+
78
+ | Parameter | Type | Description |
79
+ |-----------|------|-------------|
80
+ | `hex` | `string` | Hex string to convert (with or without `0x` prefix) |
81
+
82
+ | Throws | Condition |
83
+ |--------|-----------|
84
+ | `TypeError` | Hex string has odd length |
85
+ | `TypeError` | Hex string contains invalid characters |
86
+
87
+ ```typescript
88
+ import { fromHex, toHex } from '@btc-vision/bitcoin';
89
+
90
+ const bytes = fromHex('deadbeef');
91
+ console.log(bytes); // Uint8Array [222, 173, 190, 239]
92
+
93
+ // Works with 0x prefix
94
+ const bytes2 = fromHex('0xCAFEBABE');
95
+ console.log(toHex(bytes2)); // 'cafebabe'
96
+ ```
97
+
98
+ ### isHex
99
+
100
+ Checks if a string is valid hexadecimal. Validates even length and valid hex characters. Accepts optional `0x` prefix.
101
+
102
+ ```typescript
103
+ function isHex(value: string): boolean;
104
+ ```
105
+
106
+ ```typescript
107
+ import { isHex } from '@btc-vision/bitcoin';
108
+
109
+ isHex('deadbeef'); // true
110
+ isHex('0xdeadbeef'); // true
111
+ isHex('DEADBEEF'); // true
112
+ isHex('deadbee'); // false (odd length)
113
+ isHex('deadbeeg'); // false (invalid char 'g')
114
+ ```
115
+
116
+ ---
117
+
118
+ ## Base64 Encoding
119
+
120
+ Base64 encoding and decoding using the native `atob()`/`btoa()` functions available in both browser and service worker contexts.
121
+
122
+ ### fromBase64
123
+
124
+ Decodes a base64 string to a `Uint8Array`.
125
+
126
+ ```typescript
127
+ function fromBase64(base64: string): Uint8Array;
128
+ ```
129
+
130
+ ```typescript
131
+ import { fromBase64, toHex } from '@btc-vision/bitcoin';
132
+
133
+ const bytes = fromBase64('3q2+7w==');
134
+ console.log(toHex(bytes)); // 'deadbeef'
135
+ ```
136
+
137
+ ### toBase64
138
+
139
+ Encodes a `Uint8Array` into a base64 string.
140
+
141
+ ```typescript
142
+ function toBase64(bytes: Uint8Array): string;
143
+ ```
144
+
145
+ ```typescript
146
+ import { toBase64, fromHex } from '@btc-vision/bitcoin';
147
+
148
+ const bytes = fromHex('deadbeef');
149
+ const encoded = toBase64(bytes);
150
+ console.log(encoded); // '3q2+7w=='
151
+ ```
152
+
153
+ ---
154
+
155
+ ## Base58Check Encoding
156
+
157
+ Base58Check encoding with checksum verification, re-exported from `@btc-vision/bs58check`. Used for legacy Bitcoin addresses and WIF private keys.
158
+
159
+ > **Note:** `@btc-vision/bs58check` is a `devDependency` of this package, not a runtime `dependency`. If your project relies on `base58check`, you should add `@btc-vision/bs58check` to your own project's `dependencies`.
160
+
161
+ ### base58check.encode
162
+
163
+ Encodes a `Uint8Array` payload into a Base58Check string (with 4-byte checksum appended).
164
+
165
+ ```typescript
166
+ function encode(payload: Uint8Array): string;
167
+ ```
168
+
169
+ ```typescript
170
+ import { base58check } from '@btc-vision/bitcoin/io';
171
+ import { fromHex } from '@btc-vision/bitcoin';
172
+
173
+ // Encode a version byte + hash160 into a legacy address
174
+ const payload = fromHex('0014...'); // version prefix + payload
175
+ const address = base58check.encode(payload);
176
+ console.log(address); // '1...' or '3...'
177
+ ```
178
+
179
+ ### base58check.decode
180
+
181
+ Decodes a Base58Check string into a `Uint8Array`. Verifies the 4-byte checksum and throws on invalid input.
182
+
183
+ ```typescript
184
+ function decode(str: string): Uint8Array;
185
+ ```
186
+
187
+ ```typescript
188
+ import { base58check } from '@btc-vision/bitcoin/io';
189
+ import { toHex } from '@btc-vision/bitcoin';
190
+
191
+ const payload = base58check.decode('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa');
192
+ console.log(toHex(payload)); // version byte + 20-byte pubkey hash
193
+ ```
194
+
195
+ ### base58check.decodeUnsafe
196
+
197
+ Decodes a Base58Check string, returning `undefined` instead of throwing on invalid input.
198
+
199
+ ```typescript
200
+ function decodeUnsafe(str: string): Uint8Array | undefined;
201
+ ```
202
+
203
+ ```typescript
204
+ import { base58check } from '@btc-vision/bitcoin/io';
205
+
206
+ const result = base58check.decodeUnsafe('invalidstring');
207
+ if (result === undefined) {
208
+ console.log('Invalid Base58Check string');
209
+ }
210
+ ```
211
+
212
+ ---
213
+
214
+ ## Buffer Utilities
215
+
216
+ Pure utility functions for `Uint8Array` operations. No DataView allocations. Optimized for performance with minimal allocations.
217
+
218
+ ### concat
219
+
220
+ Concatenates multiple `Uint8Array` instances into a single array. Allocates exactly once for the result.
221
+
222
+ ```typescript
223
+ function concat(arrays: readonly Uint8Array[]): Uint8Array;
224
+ ```
225
+
226
+ ```typescript
227
+ import { concat, fromHex, toHex } from '@btc-vision/bitcoin';
228
+
229
+ const a = fromHex('deadbeef');
230
+ const b = fromHex('cafebabe');
231
+ const result = concat([a, b]);
232
+ console.log(toHex(result)); // 'deadbeefcafebabe'
233
+ ```
234
+
235
+ ### equals
236
+
237
+ Checks if two `Uint8Array` instances have identical contents.
238
+
239
+ ```typescript
240
+ function equals(a: Uint8Array, b: Uint8Array): boolean;
241
+ ```
242
+
243
+ ```typescript
244
+ import { equals, fromHex } from '@btc-vision/bitcoin';
245
+
246
+ const a = fromHex('deadbeef');
247
+ const b = fromHex('deadbeef');
248
+ const c = fromHex('cafebabe');
249
+
250
+ equals(a, b); // true
251
+ equals(a, c); // false
252
+ ```
253
+
254
+ ### compare
255
+
256
+ Compares two `Uint8Array` instances lexicographically. Returns a negative number if `a < b`, positive if `a > b`, and `0` if equal.
257
+
258
+ > **Note:** The return value is the arithmetic difference between the first differing bytes (or the difference in lengths), not a normalized -1/0/1. For example, comparing `0x01` to `0x03` returns `-2`, not `-1`.
259
+
260
+ ```typescript
261
+ function compare(a: Uint8Array, b: Uint8Array): number;
262
+ ```
263
+
264
+ ```typescript
265
+ import { compare, fromHex } from '@btc-vision/bitcoin';
266
+
267
+ const a = fromHex('0001');
268
+ const b = fromHex('0002');
269
+
270
+ compare(a, b); // -1 (a < b, difference: 0x01 - 0x02)
271
+ compare(b, a); // 1 (b > a, difference: 0x02 - 0x01)
272
+ compare(a, a); // 0 (equal)
273
+
274
+ // The return value is the arithmetic difference, not normalized to -1/0/1:
275
+ const x = fromHex('0001');
276
+ const y = fromHex('0005');
277
+ compare(x, y); // -4 (difference: 0x01 - 0x05)
278
+ ```
279
+
280
+ ### isZero
281
+
282
+ Checks if a `Uint8Array` contains only zero bytes.
283
+
284
+ ```typescript
285
+ function isZero(bytes: Uint8Array): boolean;
286
+ ```
287
+
288
+ ```typescript
289
+ import { isZero } from '@btc-vision/bitcoin';
290
+
291
+ isZero(new Uint8Array(32)); // true
292
+ isZero(new Uint8Array([0, 0, 1])); // false
293
+ ```
294
+
295
+ ### clone
296
+
297
+ Creates an independent copy of a `Uint8Array`. Modifications to the clone do not affect the original.
298
+
299
+ ```typescript
300
+ function clone(bytes: Uint8Array): Uint8Array;
301
+ ```
302
+
303
+ ```typescript
304
+ import { clone, fromHex } from '@btc-vision/bitcoin';
305
+
306
+ const original = fromHex('deadbeef');
307
+ const copy = clone(original);
308
+ copy[0] = 0; // Modifying copy doesn't affect original
309
+ ```
310
+
311
+ ### reverse
312
+
313
+ Reverses a `Uint8Array` **in place**. Returns the same array reference.
314
+
315
+ ```typescript
316
+ function reverse(bytes: Uint8Array): Uint8Array;
317
+ ```
318
+
319
+ ```typescript
320
+ import { reverse, fromHex, toHex } from '@btc-vision/bitcoin';
321
+
322
+ const bytes = fromHex('01020304');
323
+ reverse(bytes);
324
+ console.log(toHex(bytes)); // '04030201'
325
+ ```
326
+
327
+ ### reverseCopy
328
+
329
+ Creates a **new** reversed copy of a `Uint8Array`. The original array is not modified.
330
+
331
+ ```typescript
332
+ function reverseCopy(bytes: Uint8Array): Uint8Array;
333
+ ```
334
+
335
+ ```typescript
336
+ import { reverseCopy, fromHex, toHex } from '@btc-vision/bitcoin';
337
+
338
+ const bytes = fromHex('01020304');
339
+ const reversed = reverseCopy(bytes);
340
+ console.log(toHex(reversed)); // '04030201'
341
+ console.log(toHex(bytes)); // '01020304' (original unchanged)
342
+ ```
343
+
344
+ ### alloc
345
+
346
+ Allocates a new `Uint8Array` of the specified size, optionally filled with a byte value.
347
+
348
+ ```typescript
349
+ function alloc(size: number, fill?: number): Uint8Array;
350
+ ```
351
+
352
+ | Parameter | Type | Default | Description |
353
+ |-----------|------|---------|-------------|
354
+ | `size` | `number` | - | Number of bytes to allocate |
355
+ | `fill` | `number` | `0` | Byte value to fill with |
356
+
357
+ ```typescript
358
+ import { alloc, toHex } from '@btc-vision/bitcoin';
359
+
360
+ const zeros = alloc(4); // 4 zero bytes: 00000000
361
+ const ones = alloc(4, 0xff); // 4 bytes of 0xff
362
+ console.log(toHex(ones)); // 'ffffffff'
363
+ ```
364
+
365
+ ### xor
366
+
367
+ XORs two `Uint8Array` instances together, returning a new array with the result.
368
+
369
+ ```typescript
370
+ function xor(a: Uint8Array, b: Uint8Array): Uint8Array;
371
+ ```
372
+
373
+ | Throws | Condition |
374
+ |--------|-----------|
375
+ | `TypeError` | Arrays have different lengths |
376
+
377
+ ```typescript
378
+ import { xor, fromHex, toHex } from '@btc-vision/bitcoin';
379
+
380
+ const a = fromHex('ff00ff00');
381
+ const b = fromHex('0f0f0f0f');
382
+ const result = xor(a, b);
383
+ console.log(toHex(result)); // 'f00ff00f'
384
+ ```
385
+
386
+ ---
387
+
388
+ ## UTF-8 Utilities
389
+
390
+ UTF-8 string encoding and decoding using the standard `TextEncoder`/`TextDecoder` APIs.
391
+
392
+ ### fromUtf8
393
+
394
+ Creates a `Uint8Array` from a UTF-8 string.
395
+
396
+ ```typescript
397
+ function fromUtf8(str: string): Uint8Array;
398
+ ```
399
+
400
+ ```typescript
401
+ import { fromUtf8, toHex } from '@btc-vision/bitcoin';
402
+
403
+ const bytes = fromUtf8('hello');
404
+ console.log(toHex(bytes)); // '68656c6c6f'
405
+ ```
406
+
407
+ ### toUtf8
408
+
409
+ Decodes a `Uint8Array` to a UTF-8 string.
410
+
411
+ ```typescript
412
+ function toUtf8(bytes: Uint8Array): string;
413
+ ```
414
+
415
+ ```typescript
416
+ import { toUtf8, fromHex } from '@btc-vision/bitcoin';
417
+
418
+ const bytes = fromHex('68656c6c6f');
419
+ const str = toUtf8(bytes);
420
+ console.log(str); // 'hello'
421
+ ```
422
+
423
+ ---
424
+
425
+ ## Variable-Length Integers (varuint)
426
+
427
+ Bitcoin CompactSize variable-length integer encoding, re-exported from `varuint-bitcoin`. Used throughout the Bitcoin protocol for encoding lengths and counts.
428
+
429
+ ### Encoding Format
430
+
431
+ | First byte | Total size | Value range |
432
+ |------------|-----------|-------------|
433
+ | `0x00` - `0xFC` | 1 byte | 0 - 252 |
434
+ | `0xFD` | 3 bytes | 253 - 65535 (0xFD + 2-byte LE uint16) |
435
+ | `0xFE` | 5 bytes | 65536 - 4294967295 (0xFE + 4-byte LE uint32) |
436
+ | `0xFF` | 9 bytes | 4294967296+ (0xFF + 8-byte LE uint64) |
437
+
438
+ ### varuint.encode
439
+
440
+ Encodes a number or bigint as a CompactSize variable-length integer into a buffer.
441
+
442
+ ```typescript
443
+ function encode(
444
+ n: number | bigint,
445
+ buffer?: Uint8Array,
446
+ offset?: number,
447
+ ): { buffer: Uint8Array; bytes: number };
448
+ ```
449
+
450
+ | Parameter | Type | Description |
451
+ |-----------|------|-------------|
452
+ | `n` | `number \| bigint` | Value to encode |
453
+ | `buffer` | `Uint8Array` | Optional target buffer |
454
+ | `offset` | `number` | Optional offset within buffer |
455
+
456
+ Returns an object with the `buffer` containing the encoded data and `bytes` indicating how many bytes were written.
457
+
458
+ ```typescript
459
+ import { varuint } from '@btc-vision/bitcoin';
460
+
461
+ // Encode a small value (1 byte)
462
+ const small = varuint.encode(100);
463
+ console.log(small.bytes); // 1
464
+
465
+ // Encode a larger value (3 bytes)
466
+ const medium = varuint.encode(515);
467
+ console.log(medium.bytes); // 3
468
+
469
+ // Encode into an existing buffer
470
+ const buf = new Uint8Array(9);
471
+ const result = varuint.encode(70000, buf, 0);
472
+ console.log(result.bytes); // 5
473
+ ```
474
+
475
+ ### varuint.decode
476
+
477
+ Decodes a CompactSize variable-length integer from a buffer.
478
+
479
+ ```typescript
480
+ function decode(
481
+ buffer: Uint8Array,
482
+ offset?: number,
483
+ ): { numberValue: number | null; bigintValue: bigint; bytes: number };
484
+ ```
485
+
486
+ Returns an object with `bigintValue` (always present), `numberValue` (null if the value exceeds `Number.MAX_SAFE_INTEGER`), and `bytes` indicating how many bytes were consumed.
487
+
488
+ ```typescript
489
+ import { varuint, fromHex } from '@btc-vision/bitcoin';
490
+
491
+ // Decode a single-byte varint
492
+ const small = varuint.decode(fromHex('64'));
493
+ console.log(small.numberValue); // 100
494
+ console.log(small.bytes); // 1
495
+
496
+ // Decode a 3-byte varint
497
+ const medium = varuint.decode(fromHex('fd0302'));
498
+ console.log(medium.numberValue); // 515
499
+ console.log(medium.bytes); // 3
500
+ ```
501
+
502
+ ### varuint.encodingLength
503
+
504
+ Returns the number of bytes required to encode a given value.
505
+
506
+ ```typescript
507
+ function encodingLength(n: number | bigint): number;
508
+ ```
509
+
510
+ ```typescript
511
+ import { varuint } from '@btc-vision/bitcoin';
512
+
513
+ varuint.encodingLength(100); // 1
514
+ varuint.encodingLength(252); // 1
515
+ varuint.encodingLength(253); // 3
516
+ varuint.encodingLength(65535); // 3
517
+ varuint.encodingLength(65536); // 5
518
+ varuint.encodingLength(4294967295); // 5
519
+ varuint.encodingLength(4294967296); // 9
520
+ ```
521
+
522
+ ---
523
+
524
+ ## Class: BinaryReader
525
+
526
+ Stateful binary reader for parsing binary data. Creates exactly one `DataView` instance that is reused for all read operations, eliminating garbage collection pressure.
527
+
528
+ ```typescript
529
+ class BinaryReader {
530
+ constructor(data: Uint8Array, offset?: number);
531
+
532
+ // Properties
533
+ get offset(): number;
534
+ set offset(value: number);
535
+ get length(): number;
536
+ get remaining(): number;
537
+ get data(): Uint8Array;
538
+
539
+ // Static factory
540
+ static fromHex(hex: string): BinaryReader;
541
+
542
+ // Integer reads (little-endian)
543
+ readUInt8(): number;
544
+ readInt8(): number;
545
+ readUInt16LE(): number;
546
+ readInt16LE(): number;
547
+ readUInt32LE(): number;
548
+ readInt32LE(): number;
549
+ readUInt64LE(): bigint;
550
+ readInt64LE(): bigint;
551
+
552
+ // Byte reads
553
+ readBytes(length: number): Uint8Array; // returns subarray view (no copy)
554
+ readBytesCopy(length: number): Uint8Array; // returns independent copy
555
+
556
+ // Bitcoin CompactSize reads
557
+ readVarInt(): number;
558
+ readVarIntBig(): bigint;
559
+ readVarBytes(): Uint8Array;
560
+ readVector(): Uint8Array[];
561
+
562
+ // Navigation
563
+ peek(): number | undefined;
564
+ skip(length: number): void;
565
+ reset(): void;
566
+ hasMore(): boolean;
567
+ }
568
+ ```
569
+
570
+ ### Properties
571
+
572
+ | Property | Type | Description |
573
+ |----------|------|-------------|
574
+ | `offset` | `number` | Current read position (get/set) |
575
+ | `length` | `number` | Total length of the underlying buffer |
576
+ | `remaining` | `number` | Number of bytes remaining to read |
577
+ | `data` | `Uint8Array` | The underlying data buffer |
578
+
579
+ ### Read Methods
580
+
581
+ | Method | Return Type | Description |
582
+ |--------|-------------|-------------|
583
+ | `readUInt8()` | `number` | Reads an 8-bit unsigned integer (0-255) |
584
+ | `readInt8()` | `number` | Reads an 8-bit signed integer (-128 to 127) |
585
+ | `readUInt16LE()` | `number` | Reads a 16-bit unsigned integer, little-endian |
586
+ | `readInt16LE()` | `number` | Reads a 16-bit signed integer, little-endian |
587
+ | `readUInt32LE()` | `number` | Reads a 32-bit unsigned integer, little-endian |
588
+ | `readInt32LE()` | `number` | Reads a 32-bit signed integer, little-endian |
589
+ | `readUInt64LE()` | `bigint` | Reads a 64-bit unsigned integer, little-endian |
590
+ | `readInt64LE()` | `bigint` | Reads a 64-bit signed integer, little-endian |
591
+ | `readBytes(length)` | `Uint8Array` | Reads bytes as a subarray view (no copy) |
592
+ | `readBytesCopy(length)` | `Uint8Array` | Reads bytes as an independent copy |
593
+ | `readVarInt()` | `number` | Reads a Bitcoin CompactSize varint |
594
+ | `readVarIntBig()` | `bigint` | Reads a CompactSize varint as bigint |
595
+ | `readVarBytes()` | `Uint8Array` | Reads a length-prefixed byte array |
596
+ | `readVector()` | `Uint8Array[]` | Reads an array of length-prefixed byte arrays |
597
+
598
+ ### Navigation Methods
599
+
600
+ | Method | Return Type | Description |
601
+ |--------|-------------|-------------|
602
+ | `peek()` | `number \| undefined` | Returns next byte without advancing position |
603
+ | `skip(length)` | `void` | Skips specified number of bytes |
604
+ | `reset()` | `void` | Resets read position to beginning |
605
+ | `hasMore()` | `boolean` | Returns true if there are remaining bytes |
606
+
607
+ ### Example: Parsing a Bitcoin Transaction
608
+
609
+ ```typescript
610
+ import { BinaryReader } from '@btc-vision/bitcoin/io';
611
+ import { fromHex } from '@btc-vision/bitcoin';
612
+
613
+ const rawTx = fromHex('01000000...');
614
+ const reader = new BinaryReader(rawTx);
615
+
616
+ // Read transaction version
617
+ const version = reader.readInt32LE();
618
+
619
+ // Read input count
620
+ const inputCount = reader.readVarInt();
621
+
622
+ for (let i = 0; i < inputCount; i++) {
623
+ const txid = reader.readBytes(32); // Previous tx hash
624
+ const vout = reader.readUInt32LE(); // Previous output index
625
+ const scriptSig = reader.readVarBytes(); // Script signature
626
+ const sequence = reader.readUInt32LE(); // Sequence number
627
+ }
628
+
629
+ // Read output count
630
+ const outputCount = reader.readVarInt();
631
+
632
+ for (let i = 0; i < outputCount; i++) {
633
+ const value = reader.readUInt64LE(); // Satoshi value
634
+ const scriptPubKey = reader.readVarBytes(); // Output script
635
+ }
636
+
637
+ const locktime = reader.readUInt32LE();
638
+ ```
639
+
640
+ ### Example: Using fromHex Factory
641
+
642
+ ```typescript
643
+ import { BinaryReader } from '@btc-vision/bitcoin/io';
644
+
645
+ const reader = BinaryReader.fromHex('01000000');
646
+ const version = reader.readInt32LE(); // 1
647
+ ```
648
+
649
+ ### readBytes vs readBytesCopy
650
+
651
+ `readBytes()` returns a subarray view into the underlying buffer for zero-copy performance. If the original data might be modified or if you need to store the result independently, use `readBytesCopy()` instead.
652
+
653
+ ```typescript
654
+ const reader = new BinaryReader(data);
655
+
656
+ // Fast: returns a view (shares memory with original)
657
+ const view = reader.readBytes(32);
658
+
659
+ // Safe: returns an independent copy
660
+ const copy = reader.readBytesCopy(32);
661
+ ```
662
+
663
+ ---
664
+
665
+ ## Class: BinaryWriter
666
+
667
+ Stateful binary writer for serializing binary data. Creates exactly one `DataView` instance that is reused for all write operations. All write methods return `this` for method chaining.
668
+
669
+ ```typescript
670
+ class BinaryWriter {
671
+ constructor(size: number);
672
+ constructor(buffer: Uint8Array, offset?: number);
673
+
674
+ // Properties
675
+ get offset(): number;
676
+ set offset(value: number);
677
+ get capacity(): number;
678
+ get remaining(): number;
679
+ get data(): Uint8Array;
680
+
681
+ // Static factory
682
+ static growable(initialCapacity?: number): GrowableBinaryWriter;
683
+
684
+ // Integer writes (little-endian)
685
+ writeUInt8(value: number): this;
686
+ writeInt8(value: number): this;
687
+ writeUInt16LE(value: number): this;
688
+ writeInt16LE(value: number): this;
689
+ writeUInt32LE(value: number): this;
690
+ writeInt32LE(value: number): this;
691
+ writeUInt64LE(value: bigint): this;
692
+ writeInt64LE(value: bigint): this;
693
+
694
+ // Byte writes
695
+ writeBytes(bytes: Uint8Array): this;
696
+
697
+ // Bitcoin CompactSize writes
698
+ writeVarInt(value: number): this;
699
+ writeVarIntBig(value: bigint): this;
700
+ writeVarBytes(bytes: Uint8Array): this;
701
+ writeVector(vector: readonly Uint8Array[]): this;
702
+
703
+ // Buffer operations
704
+ fill(value: number, length: number): this;
705
+ skip(length: number): this;
706
+ reset(): this;
707
+
708
+ // Finalization
709
+ end(): Uint8Array;
710
+ finish(): Uint8Array;
711
+ toHex(): string;
712
+ }
713
+ ```
714
+
715
+ ### Properties
716
+
717
+ | Property | Type | Description |
718
+ |----------|------|-------------|
719
+ | `offset` | `number` | Current write position (get/set) |
720
+ | `capacity` | `number` | Total capacity of the underlying buffer |
721
+ | `remaining` | `number` | Number of bytes remaining in the buffer |
722
+ | `data` | `Uint8Array` | The underlying data buffer |
723
+
724
+ ### Write Methods
725
+
726
+ | Method | Parameter Type | Description |
727
+ |--------|---------------|-------------|
728
+ | `writeUInt8(value)` | `number` | Writes an 8-bit unsigned integer (0-255) |
729
+ | `writeInt8(value)` | `number` | Writes an 8-bit signed integer (-128 to 127) |
730
+ | `writeUInt16LE(value)` | `number` | Writes a 16-bit unsigned integer, little-endian |
731
+ | `writeInt16LE(value)` | `number` | Writes a 16-bit signed integer, little-endian |
732
+ | `writeUInt32LE(value)` | `number` | Writes a 32-bit unsigned integer, little-endian |
733
+ | `writeInt32LE(value)` | `number` | Writes a 32-bit signed integer, little-endian |
734
+ | `writeUInt64LE(value)` | `bigint` | Writes a 64-bit unsigned integer, little-endian |
735
+ | `writeInt64LE(value)` | `bigint` | Writes a 64-bit signed integer, little-endian |
736
+ | `writeBytes(bytes)` | `Uint8Array` | Writes raw bytes |
737
+ | `writeVarInt(value)` | `number` | Writes a Bitcoin CompactSize varint |
738
+ | `writeVarIntBig(value)` | `bigint` | Writes a CompactSize varint from bigint |
739
+ | `writeVarBytes(bytes)` | `Uint8Array` | Writes a length-prefixed byte array |
740
+ | `writeVector(vector)` | `readonly Uint8Array[]` | Writes an array of length-prefixed byte arrays |
741
+
742
+ ### Finalization Methods
743
+
744
+ | Method | Return Type | Description |
745
+ |--------|-------------|-------------|
746
+ | `end()` | `Uint8Array` | Returns the buffer; **throws** `Error` if not fully written |
747
+ | `finish()` | `Uint8Array` | Returns the written portion (subarray if partially written) |
748
+ | `toHex()` | `string` | Returns the written portion as a hex string |
749
+
750
+ ### end() vs finish()
751
+
752
+ - `end()` verifies the buffer was **fully** written (offset equals capacity). Throws a plain `Error` (not a typed error subclass) if any bytes remain unwritten. Use this when you know the exact output size.
753
+ - `finish()` returns whatever has been written so far, without verification. Returns a subarray view if the buffer was only partially filled.
754
+
755
+ ### Example: Serializing with Fixed Size
756
+
757
+ ```typescript
758
+ import { BinaryWriter } from '@btc-vision/bitcoin/io';
759
+
760
+ const writer = new BinaryWriter(16);
761
+ writer
762
+ .writeInt32LE(1) // version
763
+ .writeUInt32LE(0) // input count
764
+ .writeUInt32LE(0) // output count
765
+ .writeUInt32LE(0); // locktime
766
+
767
+ const bytes = writer.end(); // OK: wrote exactly 16 bytes
768
+ ```
769
+
770
+ ### Example: Method Chaining
771
+
772
+ ```typescript
773
+ import { BinaryWriter } from '@btc-vision/bitcoin/io';
774
+ import { fromHex } from '@btc-vision/bitcoin';
775
+
776
+ const writer = new BinaryWriter(100);
777
+ writer
778
+ .writeUInt8(0x01)
779
+ .writeVarBytes(fromHex('deadbeef'))
780
+ .writeUInt32LE(0xffffffff);
781
+
782
+ const result = writer.finish(); // Returns only the written portion
783
+ console.log(writer.toHex());
784
+ ```
785
+
786
+ ### Example: Writing into an Existing Buffer
787
+
788
+ ```typescript
789
+ import { BinaryWriter } from '@btc-vision/bitcoin/io';
790
+
791
+ const buffer = new Uint8Array(1024);
792
+ const writer = new BinaryWriter(buffer, 10); // Start writing at offset 10
793
+ writer.writeUInt32LE(42);
794
+ ```
795
+
796
+ ---
797
+
798
+ ## Class: GrowableBinaryWriter
799
+
800
+ A variant of `BinaryWriter` that automatically grows its internal buffer as needed. Use when the final serialized size is unknown.
801
+
802
+ > **Note:** `GrowableBinaryWriter` provides a subset of `BinaryWriter`'s write methods. The following `BinaryWriter` methods are **not available** on `GrowableBinaryWriter`:
803
+ > - `writeInt8()` -- use `writeUInt8(value & 0xff)` as a workaround
804
+ > - `writeInt16LE()`
805
+ > - `writeInt64LE()`
806
+ > - `writeVarIntBig()`
807
+ > - `fill()`
808
+ > - `skip()`
809
+ > - `reset()`
810
+ > - `end()`
811
+ >
812
+ > The `remaining` and `data` properties are also not available.
813
+
814
+ ```typescript
815
+ class GrowableBinaryWriter {
816
+ constructor(initialCapacity?: number);
817
+
818
+ // Properties
819
+ get offset(): number;
820
+ set offset(value: number);
821
+ get capacity(): number;
822
+
823
+ // Write methods (subset of BinaryWriter)
824
+ writeUInt8(value: number): this;
825
+ writeUInt16LE(value: number): this;
826
+ writeUInt32LE(value: number): this;
827
+ writeInt32LE(value: number): this;
828
+ writeUInt64LE(value: bigint): this;
829
+ writeBytes(bytes: Uint8Array): this;
830
+ writeVarInt(value: number): this;
831
+ writeVarBytes(bytes: Uint8Array): this;
832
+ writeVector(vector: readonly Uint8Array[]): this;
833
+
834
+ // Finalization
835
+ finish(): Uint8Array;
836
+ toHex(): string;
837
+ }
838
+ ```
839
+
840
+ The buffer starts at the given initial capacity (default 256 bytes) and doubles in size whenever more space is needed.
841
+
842
+ ### Example: Dynamic Serialization
843
+
844
+ ```typescript
845
+ import { BinaryWriter } from '@btc-vision/bitcoin/io';
846
+ import { fromHex } from '@btc-vision/bitcoin';
847
+
848
+ const writer = BinaryWriter.growable();
849
+
850
+ // Write variable amounts of data without worrying about buffer size
851
+ writer.writeUInt32LE(1);
852
+ writer.writeBytes(fromHex('aa'.repeat(500))); // Automatically grows
853
+ writer.writeVarInt(1000);
854
+
855
+ const result = writer.finish(); // Returns a copy of exactly the written bytes
856
+ ```
857
+
858
+ ---
859
+
860
+ ## Common Patterns
861
+
862
+ ### Round-Trip Encoding
863
+
864
+ ```typescript
865
+ import { toHex, fromHex, toBase64, fromBase64 } from '@btc-vision/bitcoin';
866
+
867
+ const original = new Uint8Array([1, 2, 3, 4]);
868
+
869
+ // Hex round-trip
870
+ const hex = toHex(original);
871
+ const fromHexBytes = fromHex(hex);
872
+
873
+ // Base64 round-trip
874
+ const b64 = toBase64(original);
875
+ const fromB64Bytes = fromBase64(b64);
876
+ ```
877
+
878
+ ### Bitcoin Transaction ID (Reversed Hash Display)
879
+
880
+ ```typescript
881
+ import { reverseCopy, toHex } from '@btc-vision/bitcoin';
882
+
883
+ // Bitcoin displays transaction hashes in reversed byte order
884
+ const txHashInternal = /* 32-byte hash from double-SHA256 */;
885
+ const txid = toHex(reverseCopy(txHashInternal));
886
+ ```
887
+
888
+ ### Building and Parsing a Length-Prefixed Message
889
+
890
+ ```typescript
891
+ import { BinaryWriter, BinaryReader } from '@btc-vision/bitcoin/io';
892
+ import { fromHex } from '@btc-vision/bitcoin';
893
+
894
+ // Write
895
+ const writer = BinaryWriter.growable();
896
+ const payload = fromHex('deadbeefcafebabe');
897
+ writer.writeVarBytes(payload);
898
+ const serialized = writer.finish();
899
+
900
+ // Read
901
+ const reader = new BinaryReader(serialized);
902
+ const decoded = reader.readVarBytes();
903
+ // decoded contains deadbeefcafebabe
904
+ ```
905
+
906
+ ### Witness Vector Serialization
907
+
908
+ ```typescript
909
+ import { BinaryWriter, BinaryReader } from '@btc-vision/bitcoin/io';
910
+ import { fromHex } from '@btc-vision/bitcoin';
911
+
912
+ // Write a witness stack
913
+ const witnessItems = [
914
+ fromHex('3045022100...'), // signature
915
+ fromHex('0279be667e...'), // public key
916
+ ];
917
+
918
+ const writer = BinaryWriter.growable();
919
+ writer.writeVector(witnessItems);
920
+ const serialized = writer.finish();
921
+
922
+ // Read it back
923
+ const reader = new BinaryReader(serialized);
924
+ const decoded = reader.readVector();
925
+ // decoded[0] = signature, decoded[1] = public key
926
+ ```
927
+
928
+ ### Buffer Comparison for Sorting
929
+
930
+ ```typescript
931
+ import { compare, fromHex } from '@btc-vision/bitcoin';
932
+
933
+ const hashes = [
934
+ fromHex('ff00'),
935
+ fromHex('0001'),
936
+ fromHex('aa00'),
937
+ ];
938
+
939
+ // Sort in lexicographic order
940
+ hashes.sort(compare);
941
+ // Result: [0001, aa00, ff00]
942
+ ```