@btc-vision/bitcoin 7.0.0-alpha.2 → 7.0.0-alpha.4

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 (134) hide show
  1. package/README.md +455 -155
  2. package/browser/chunks/WorkerSigningPool.sequential-DHha7j0b.js +113 -0
  3. package/browser/ecc/context.d.ts +22 -21
  4. package/browser/ecc/context.d.ts.map +1 -1
  5. package/browser/ecc/index.d.ts +1 -1
  6. package/browser/ecc/index.d.ts.map +1 -1
  7. package/browser/ecc/types.d.ts +10 -123
  8. package/browser/ecc/types.d.ts.map +1 -1
  9. package/browser/env.d.ts +13 -0
  10. package/browser/env.d.ts.map +1 -0
  11. package/browser/index.d.ts +3 -3
  12. package/browser/index.d.ts.map +1 -1
  13. package/browser/index.js +5790 -4295
  14. package/browser/io/index.d.ts +0 -1
  15. package/browser/io/index.d.ts.map +1 -1
  16. package/browser/payments/p2tr.d.ts.map +1 -1
  17. package/browser/psbt/types.d.ts +2 -68
  18. package/browser/psbt/types.d.ts.map +1 -1
  19. package/browser/psbt.d.ts +9 -11
  20. package/browser/psbt.d.ts.map +1 -1
  21. package/browser/types.d.ts +1 -1
  22. package/browser/types.d.ts.map +1 -1
  23. package/browser/workers/WorkerSigningPool.d.ts +6 -0
  24. package/browser/workers/WorkerSigningPool.d.ts.map +1 -1
  25. package/browser/workers/WorkerSigningPool.node.d.ts +6 -0
  26. package/browser/workers/WorkerSigningPool.node.d.ts.map +1 -1
  27. package/browser/workers/WorkerSigningPool.sequential.d.ts +69 -0
  28. package/browser/workers/WorkerSigningPool.sequential.d.ts.map +1 -0
  29. package/browser/workers/WorkerSigningPool.worklet.d.ts +64 -0
  30. package/browser/workers/WorkerSigningPool.worklet.d.ts.map +1 -0
  31. package/browser/workers/index.d.ts +2 -2
  32. package/browser/workers/index.d.ts.map +1 -1
  33. package/browser/workers/index.react-native.d.ts +28 -0
  34. package/browser/workers/index.react-native.d.ts.map +1 -0
  35. package/browser/workers/psbt-parallel.d.ts +2 -3
  36. package/browser/workers/psbt-parallel.d.ts.map +1 -1
  37. package/browser/workers/types.d.ts +12 -0
  38. package/browser/workers/types.d.ts.map +1 -1
  39. package/build/ecc/context.d.ts +22 -21
  40. package/build/ecc/context.d.ts.map +1 -1
  41. package/build/ecc/context.js +19 -114
  42. package/build/ecc/context.js.map +1 -1
  43. package/build/ecc/index.d.ts +1 -1
  44. package/build/ecc/index.d.ts.map +1 -1
  45. package/build/ecc/types.d.ts +7 -126
  46. package/build/ecc/types.d.ts.map +1 -1
  47. package/build/ecc/types.js +4 -1
  48. package/build/ecc/types.js.map +1 -1
  49. package/build/env.d.ts +13 -0
  50. package/build/env.d.ts.map +1 -0
  51. package/build/env.js +198 -0
  52. package/build/env.js.map +1 -0
  53. package/build/index.d.ts +4 -3
  54. package/build/index.d.ts.map +1 -1
  55. package/build/index.js +2 -1
  56. package/build/index.js.map +1 -1
  57. package/build/io/index.d.ts +0 -1
  58. package/build/io/index.d.ts.map +1 -1
  59. package/build/io/index.js +0 -2
  60. package/build/io/index.js.map +1 -1
  61. package/build/payments/p2tr.d.ts.map +1 -1
  62. package/build/payments/p2tr.js +2 -3
  63. package/build/payments/p2tr.js.map +1 -1
  64. package/build/psbt/types.d.ts +2 -68
  65. package/build/psbt/types.d.ts.map +1 -1
  66. package/build/psbt.d.ts +9 -11
  67. package/build/psbt.d.ts.map +1 -1
  68. package/build/psbt.js +38 -53
  69. package/build/psbt.js.map +1 -1
  70. package/build/tsconfig.build.tsbuildinfo +1 -1
  71. package/build/types.d.ts +1 -1
  72. package/build/types.d.ts.map +1 -1
  73. package/build/types.js +2 -16
  74. package/build/types.js.map +1 -1
  75. package/build/workers/WorkerSigningPool.d.ts +6 -0
  76. package/build/workers/WorkerSigningPool.d.ts.map +1 -1
  77. package/build/workers/WorkerSigningPool.js +8 -0
  78. package/build/workers/WorkerSigningPool.js.map +1 -1
  79. package/build/workers/WorkerSigningPool.node.d.ts +6 -0
  80. package/build/workers/WorkerSigningPool.node.d.ts.map +1 -1
  81. package/build/workers/WorkerSigningPool.node.js +9 -2
  82. package/build/workers/WorkerSigningPool.node.js.map +1 -1
  83. package/build/workers/WorkerSigningPool.sequential.d.ts +78 -0
  84. package/build/workers/WorkerSigningPool.sequential.d.ts.map +1 -0
  85. package/build/workers/WorkerSigningPool.sequential.js +160 -0
  86. package/build/workers/WorkerSigningPool.sequential.js.map +1 -0
  87. package/build/workers/WorkerSigningPool.worklet.d.ts +79 -0
  88. package/build/workers/WorkerSigningPool.worklet.d.ts.map +1 -0
  89. package/build/workers/WorkerSigningPool.worklet.js +388 -0
  90. package/build/workers/WorkerSigningPool.worklet.js.map +1 -0
  91. package/build/workers/index.d.ts +2 -2
  92. package/build/workers/index.d.ts.map +1 -1
  93. package/build/workers/index.js +9 -0
  94. package/build/workers/index.js.map +1 -1
  95. package/build/workers/index.react-native.d.ts +28 -0
  96. package/build/workers/index.react-native.d.ts.map +1 -0
  97. package/build/workers/index.react-native.js +67 -0
  98. package/build/workers/index.react-native.js.map +1 -0
  99. package/build/workers/psbt-parallel.d.ts +2 -3
  100. package/build/workers/psbt-parallel.d.ts.map +1 -1
  101. package/build/workers/psbt-parallel.js +4 -4
  102. package/build/workers/psbt-parallel.js.map +1 -1
  103. package/build/workers/types.d.ts +12 -0
  104. package/build/workers/types.d.ts.map +1 -1
  105. package/package.json +14 -4
  106. package/src/ecc/context.ts +26 -147
  107. package/src/ecc/index.ts +2 -2
  108. package/src/ecc/types.ts +7 -138
  109. package/src/env.ts +237 -0
  110. package/src/index.ts +2 -4
  111. package/src/io/index.ts +0 -3
  112. package/src/payments/p2tr.ts +2 -2
  113. package/src/psbt/types.ts +2 -84
  114. package/src/psbt.ts +63 -121
  115. package/src/types.ts +5 -28
  116. package/src/workers/WorkerSigningPool.node.ts +10 -2
  117. package/src/workers/WorkerSigningPool.sequential.ts +190 -0
  118. package/src/workers/WorkerSigningPool.ts +9 -0
  119. package/src/workers/WorkerSigningPool.worklet.ts +519 -0
  120. package/src/workers/index.react-native.ts +110 -0
  121. package/src/workers/index.ts +10 -1
  122. package/src/workers/psbt-parallel.ts +8 -8
  123. package/src/workers/types.ts +16 -0
  124. package/test/env.spec.ts +418 -0
  125. package/test/workers-pool.spec.ts +43 -0
  126. package/test/workers-sequential.spec.ts +669 -0
  127. package/test/workers-worklet.spec.ts +500 -0
  128. package/browser/io/MemoryPool.d.ts +0 -220
  129. package/browser/io/MemoryPool.d.ts.map +0 -1
  130. package/build/io/MemoryPool.d.ts +0 -220
  131. package/build/io/MemoryPool.d.ts.map +0 -1
  132. package/build/io/MemoryPool.js +0 -309
  133. package/build/io/MemoryPool.js.map +0 -1
  134. package/src/io/MemoryPool.ts +0 -343
package/src/env.ts ADDED
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Runtime capability verification and polyfills.
3
+ *
4
+ * Polyfills features that can be shimmed (TextEncoder, Map, Promise.allSettled, Symbol.dispose).
5
+ * Throws early with a clear error for features that cannot be polyfilled (BigInt, Uint8Array,
6
+ * structuredClone, DataView BigInt methods).
7
+ *
8
+ * Imported as a side effect by the main entry point.
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+
13
+ // ---------------------------------------------------------------------------
14
+ // Hard requirements — cannot be polyfilled
15
+ // ---------------------------------------------------------------------------
16
+
17
+ const missing: string[] = [];
18
+
19
+ if (typeof BigInt === 'undefined') {
20
+ missing.push('BigInt (ES2020 — required for satoshi values)');
21
+ }
22
+
23
+ if (typeof Uint8Array === 'undefined') {
24
+ missing.push('Uint8Array (TypedArrays — required for all binary operations)');
25
+ }
26
+
27
+ if (typeof DataView !== 'undefined' && typeof DataView.prototype.getBigInt64 !== 'function') {
28
+ missing.push('DataView.prototype.getBigInt64 (ES2020 — required for transaction parsing)');
29
+ }
30
+
31
+ if (missing.length > 0) {
32
+ throw new Error(
33
+ `@btc-vision/bitcoin: unsupported runtime. Missing capabilities:\n` +
34
+ missing.map((cap) => ` - ${cap}`).join('\n') +
35
+ `\n\nThese features cannot be polyfilled. This library requires a modern JavaScript engine (ES2022+).`,
36
+ );
37
+ }
38
+
39
+ // ---------------------------------------------------------------------------
40
+ // Polyfills — shim features that can be reasonably implemented
41
+ // ---------------------------------------------------------------------------
42
+
43
+ // TextEncoder / TextDecoder (for older WebView / jsdom environments)
44
+ if (typeof globalThis.TextEncoder === 'undefined') {
45
+ globalThis.TextEncoder = class TextEncoder {
46
+ readonly encoding = 'utf-8';
47
+
48
+ encode(input: string = ''): Uint8Array {
49
+ // Fast path for ASCII
50
+ const utf8: number[] = [];
51
+ for (let i = 0; i < input.length; i++) {
52
+ let code = input.charCodeAt(i);
53
+ if (code < 0x80) {
54
+ utf8.push(code);
55
+ } else if (code < 0x800) {
56
+ utf8.push(0xc0 | (code >> 6), 0x80 | (code & 0x3f));
57
+ } else if (code >= 0xd800 && code <= 0xdbff) {
58
+ // Surrogate pair
59
+ const next = input.charCodeAt(++i);
60
+ code = 0x10000 + ((code - 0xd800) << 10) + (next - 0xdc00);
61
+ utf8.push(
62
+ 0xf0 | (code >> 18),
63
+ 0x80 | ((code >> 12) & 0x3f),
64
+ 0x80 | ((code >> 6) & 0x3f),
65
+ 0x80 | (code & 0x3f),
66
+ );
67
+ } else {
68
+ utf8.push(0xe0 | (code >> 12), 0x80 | ((code >> 6) & 0x3f), 0x80 | (code & 0x3f));
69
+ }
70
+ }
71
+ return new Uint8Array(utf8);
72
+ }
73
+
74
+ encodeInto(src: string, dest: Uint8Array): { read: number; written: number } {
75
+ const encoded = this.encode(src);
76
+ const written = Math.min(encoded.length, dest.length);
77
+ dest.set(encoded.subarray(0, written));
78
+ return { read: src.length, written };
79
+ }
80
+ } as unknown as typeof TextEncoder;
81
+ }
82
+
83
+ if (typeof globalThis.TextDecoder === 'undefined') {
84
+ globalThis.TextDecoder = class TextDecoder {
85
+ readonly encoding = 'utf-8';
86
+ readonly fatal = false;
87
+ readonly ignoreBOM = false;
88
+
89
+ decode(input?: ArrayBufferView | ArrayBuffer): string {
90
+ if (!input) return '';
91
+ const bytes =
92
+ input instanceof ArrayBuffer
93
+ ? new Uint8Array(input)
94
+ : new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
95
+
96
+ let result = '';
97
+ for (let i = 0; i < bytes.length; ) {
98
+ const byte = bytes[i]!;
99
+ let code: number;
100
+ if (byte < 0x80) {
101
+ code = byte;
102
+ i++;
103
+ } else if ((byte & 0xe0) === 0xc0) {
104
+ code = ((byte & 0x1f) << 6) | (bytes[i + 1]! & 0x3f);
105
+ i += 2;
106
+ } else if ((byte & 0xf0) === 0xe0) {
107
+ code = ((byte & 0x0f) << 12) | ((bytes[i + 1]! & 0x3f) << 6) | (bytes[i + 2]! & 0x3f);
108
+ i += 3;
109
+ } else {
110
+ code =
111
+ ((byte & 0x07) << 18) |
112
+ ((bytes[i + 1]! & 0x3f) << 12) |
113
+ ((bytes[i + 2]! & 0x3f) << 6) |
114
+ (bytes[i + 3]! & 0x3f);
115
+ i += 4;
116
+ }
117
+
118
+ if (code <= 0xffff) {
119
+ result += String.fromCharCode(code);
120
+ } else {
121
+ // Surrogate pair
122
+ code -= 0x10000;
123
+ result += String.fromCharCode(0xd800 + (code >> 10), 0xdc00 + (code & 0x3ff));
124
+ }
125
+ }
126
+ return result;
127
+ }
128
+ } as unknown as typeof TextDecoder;
129
+ }
130
+
131
+ // Map (for extremely old environments)
132
+ if (typeof globalThis.Map === 'undefined') {
133
+ globalThis.Map = class Map<K, V> {
134
+ readonly #entries: Array<[K, V]> = [];
135
+
136
+ constructor(entries?: Iterable<[K, V]> | null) {
137
+ if (entries) {
138
+ for (const [k, v] of entries) {
139
+ this.set(k, v);
140
+ }
141
+ }
142
+ }
143
+
144
+ get size(): number {
145
+ return this.#entries.length;
146
+ }
147
+
148
+ has(key: K): boolean {
149
+ return this.#entries.some(([k]) => k === key);
150
+ }
151
+
152
+ get(key: K): V | undefined {
153
+ const entry = this.#entries.find(([k]) => k === key);
154
+ return entry?.[1];
155
+ }
156
+
157
+ set(key: K, value: V): this {
158
+ const idx = this.#entries.findIndex(([k]) => k === key);
159
+ if (idx >= 0) {
160
+ this.#entries[idx] = [key, value];
161
+ } else {
162
+ this.#entries.push([key, value]);
163
+ }
164
+ return this;
165
+ }
166
+
167
+ delete(key: K): boolean {
168
+ const idx = this.#entries.findIndex(([k]) => k === key);
169
+ if (idx >= 0) {
170
+ this.#entries.splice(idx, 1);
171
+ return true;
172
+ }
173
+ return false;
174
+ }
175
+
176
+ clear(): void {
177
+ this.#entries.length = 0;
178
+ }
179
+
180
+ forEach(cb: (value: V, key: K, map: Map<K, V>) => void): void {
181
+ for (const [k, v] of this.#entries) {
182
+ cb(v, k, this);
183
+ }
184
+ }
185
+
186
+ keys(): IterableIterator<K> {
187
+ return this.#entries.map(([k]) => k)[Symbol.iterator]() as IterableIterator<K>;
188
+ }
189
+
190
+ values(): IterableIterator<V> {
191
+ return this.#entries.map(([, v]) => v)[Symbol.iterator]() as IterableIterator<V>;
192
+ }
193
+
194
+ entries(): IterableIterator<[K, V]> {
195
+ return this.#entries[Symbol.iterator]() as IterableIterator<[K, V]>;
196
+ }
197
+
198
+ [Symbol.iterator](): IterableIterator<[K, V]> {
199
+ return this.entries();
200
+ }
201
+
202
+ get [Symbol.toStringTag](): string {
203
+ return 'Map';
204
+ }
205
+ } as unknown as MapConstructor;
206
+ }
207
+
208
+ // Promise.allSettled (ES2020)
209
+ if (typeof Promise.allSettled !== 'function') {
210
+ Promise.allSettled = function allSettled<T extends readonly unknown[]>(
211
+ promises: T,
212
+ ): Promise<{
213
+ -readonly [K in keyof T]: PromiseSettledResult<Awaited<T[K]>>;
214
+ }> {
215
+ return Promise.all(
216
+ Array.from(promises as Iterable<unknown>, (p) =>
217
+ Promise.resolve(p).then(
218
+ (value) => ({ status: 'fulfilled' as const, value }),
219
+ (reason: unknown) => ({ status: 'rejected' as const, reason }),
220
+ ),
221
+ ),
222
+ ) as Promise<any>;
223
+ };
224
+ }
225
+
226
+ // structuredClone (ES2022 — used for PSBT cloning)
227
+ if (typeof globalThis.structuredClone === 'undefined') {
228
+ globalThis.structuredClone = <T>(value: T): T => JSON.parse(JSON.stringify(value));
229
+ }
230
+
231
+ // Symbol.dispose / Symbol.asyncDispose (ES2024 — Explicit Resource Management)
232
+ if (typeof Symbol['dispose'] === 'undefined') {
233
+ (Symbol as unknown as Record<string, symbol>)['dispose'] = Symbol.for('Symbol.dispose');
234
+ }
235
+ if (typeof Symbol['asyncDispose'] === 'undefined') {
236
+ (Symbol as unknown as Record<string, symbol>)['asyncDispose'] = Symbol.for('Symbol.asyncDispose');
237
+ }
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import './env.js';
1
2
  import type {
2
3
  PsbtInput as _PsbtInput,
3
4
  PsbtInputUpdate as _PsbtInputUpdate,
@@ -63,7 +64,6 @@ export type {
63
64
  PsbtOutputExtendedScript,
64
65
  HDSigner,
65
66
  HDSignerAsync,
66
- SignerAlternative,
67
67
  Signer,
68
68
  SignerAsync,
69
69
  TaprootHashCheckSigner,
@@ -83,7 +83,7 @@ export type { TaprootHashCache } from './transaction.js';
83
83
  export type { Network } from './networks.js';
84
84
  /** @hidden */
85
85
  export { initEccLib, getEccLib, EccContext } from './ecc/context.js';
86
- export type { EccLib } from './ecc/types.js';
86
+ export type { CryptoBackend, EccLib } from './ecc/types.js';
87
87
  export { PaymentType } from './payments/index.js';
88
88
  export type {
89
89
  Payment,
@@ -143,8 +143,6 @@ export {
143
143
  xor,
144
144
  fromUtf8,
145
145
  toUtf8,
146
- MemoryPool,
147
- SimpleMemoryPool,
148
146
  varuint,
149
147
  } from './io/index.js';
150
148
  export * from './payments/bip341.js';
package/src/io/index.ts CHANGED
@@ -34,8 +34,5 @@ export {
34
34
  toUtf8,
35
35
  } from './utils.js';
36
36
 
37
- // Memory pools
38
- export { MemoryPool, SimpleMemoryPool } from './MemoryPool.js';
39
-
40
37
  // Re-export varuint for Bitcoin CompactSize encoding
41
38
  export { varuint };
@@ -9,11 +9,11 @@
9
9
 
10
10
  import { bech32m } from 'bech32';
11
11
  import { fromBech32 } from '../bech32utils.js';
12
- import { getEccLib } from '../ecc/context.js';
13
12
  import { bitcoin as BITCOIN_NETWORK, type Network } from '../networks.js';
14
13
  import * as bscript from '../script.js';
15
14
  import {
16
15
  type Bytes32,
16
+ isXOnlyPublicKey,
17
17
  type SchnorrSignature,
18
18
  type Script,
19
19
  stacksEqual,
@@ -716,7 +716,7 @@ export class P2TR {
716
716
  throw new TypeError('Internal pubkey mismatch');
717
717
  }
718
718
 
719
- if (!getEccLib().isXOnlyPoint(internalPk)) {
719
+ if (!isXOnlyPublicKey(internalPk)) {
720
720
  throw new TypeError('Invalid internalPubkey for p2tr witness');
721
721
  }
722
722
 
package/src/psbt/types.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  import type { Psbt as PsbtBase, PsbtGlobal, PsbtInput, PsbtOutput } from 'bip174';
7
7
  import type { Network } from '../networks.js';
8
8
  import type { TaprootHashCache, Transaction } from '../transaction.js';
9
- import type { Bytes32, MessageHash, PublicKey, Satoshi, SchnorrSignature, Script, Signature } from '../types.js';
9
+ import type { Bytes32, MessageHash, PublicKey, Satoshi, Script } from '../types.js';
10
10
 
11
11
  /**
12
12
  * Transaction input interface for PSBT.
@@ -102,89 +102,7 @@ export interface PsbtOutputExtendedScript extends PsbtOutput {
102
102
  readonly value: Satoshi;
103
103
  }
104
104
 
105
- /**
106
- * Base interface for HD signers.
107
- */
108
- interface HDSignerBase {
109
- /**
110
- * DER format compressed publicKey Uint8Array
111
- */
112
- readonly publicKey: PublicKey;
113
- /**
114
- * The first 4 bytes of the sha256-ripemd160 of the publicKey
115
- */
116
- readonly fingerprint: Uint8Array;
117
- }
118
-
119
- /**
120
- * HD signer interface for synchronous signing.
121
- */
122
- export interface HDSigner extends HDSignerBase {
123
- /**
124
- * The path string must match /^m(\/\d+'?)+$/
125
- * ex. m/44'/0'/0'/1/23 levels with ' must be hard derivations
126
- */
127
- derivePath(path: string): HDSigner;
128
-
129
- /**
130
- * Input hash (the "message digest") for the signature algorithm
131
- * Return a 64 byte signature (32 byte r and 32 byte s in that order)
132
- */
133
- sign(hash: MessageHash): Uint8Array;
134
- }
135
-
136
- /**
137
- * HD signer interface for asynchronous signing.
138
- */
139
- export interface HDSignerAsync extends HDSignerBase {
140
- derivePath(path: string): HDSignerAsync;
141
-
142
- sign(hash: MessageHash): Promise<Uint8Array>;
143
- }
144
-
145
- /**
146
- * Alternative signer interface with lowR support.
147
- */
148
- export interface SignerAlternative {
149
- readonly publicKey: PublicKey;
150
- readonly lowR: boolean;
151
-
152
- sign(hash: MessageHash, lowR?: boolean): Signature;
153
-
154
- verify(hash: MessageHash, signature: Signature): boolean;
155
-
156
- signSchnorr(hash: MessageHash): SchnorrSignature;
157
-
158
- verifySchnorr(hash: MessageHash, signature: SchnorrSignature): boolean;
159
- }
160
-
161
- /**
162
- * Basic signer interface for synchronous signing.
163
- */
164
- export interface Signer {
165
- readonly publicKey: PublicKey;
166
- readonly network?: Network | undefined;
167
-
168
- sign(hash: MessageHash, lowR?: boolean): Signature;
169
-
170
- signSchnorr?(hash: MessageHash): SchnorrSignature;
171
-
172
- getPublicKey?(): PublicKey;
173
- }
174
-
175
- /**
176
- * Basic signer interface for asynchronous signing.
177
- */
178
- export interface SignerAsync {
179
- readonly publicKey: PublicKey;
180
- readonly network?: Network | undefined;
181
-
182
- sign(hash: MessageHash, lowR?: boolean): Promise<Signature>;
183
-
184
- signSchnorr?(hash: MessageHash): Promise<SchnorrSignature>;
185
-
186
- getPublicKey?(): PublicKey;
187
- }
105
+ export type { Signer, SignerAsync, HDSigner, HDSignerAsync } from '@btc-vision/ecpair';
188
106
 
189
107
  /**
190
108
  * Minimal key pair interface for checking Taproot hashes.