@btc-vision/bitcoin 7.0.0-alpha.1 → 7.0.0-alpha.10

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 (290) hide show
  1. package/README.md +455 -155
  2. package/browser/address.d.ts +5 -1
  3. package/browser/address.d.ts.map +1 -1
  4. package/browser/branded.d.ts +3 -14
  5. package/browser/branded.d.ts.map +1 -1
  6. package/browser/chunks/psbt-parallel-BBFlkmiv.js +10717 -0
  7. package/browser/ecc/context.d.ts +22 -21
  8. package/browser/ecc/context.d.ts.map +1 -1
  9. package/browser/ecc/index.d.ts +1 -1
  10. package/browser/ecc/index.d.ts.map +1 -1
  11. package/browser/ecc/types.d.ts +10 -123
  12. package/browser/ecc/types.d.ts.map +1 -1
  13. package/browser/env.d.ts +13 -0
  14. package/browser/env.d.ts.map +1 -0
  15. package/browser/index.d.ts +6 -6
  16. package/browser/index.d.ts.map +1 -1
  17. package/browser/index.js +2602 -11786
  18. package/browser/io/hex.d.ts.map +1 -1
  19. package/browser/io/index.d.ts +0 -1
  20. package/browser/io/index.d.ts.map +1 -1
  21. package/browser/opcodes.d.ts +11 -0
  22. package/browser/opcodes.d.ts.map +1 -1
  23. package/browser/payments/p2tr.d.ts.map +1 -1
  24. package/browser/psbt/PsbtCache.d.ts +54 -0
  25. package/browser/psbt/PsbtCache.d.ts.map +1 -0
  26. package/browser/psbt/PsbtFinalizer.d.ts +21 -0
  27. package/browser/psbt/PsbtFinalizer.d.ts.map +1 -0
  28. package/browser/psbt/PsbtSigner.d.ts +32 -0
  29. package/browser/psbt/PsbtSigner.d.ts.map +1 -0
  30. package/browser/psbt/PsbtTransaction.d.ts +25 -0
  31. package/browser/psbt/PsbtTransaction.d.ts.map +1 -0
  32. package/browser/psbt/types.d.ts +4 -70
  33. package/browser/psbt/types.d.ts.map +1 -1
  34. package/browser/psbt/validation.d.ts +1 -1
  35. package/browser/psbt/validation.d.ts.map +1 -1
  36. package/browser/psbt.d.ts +26 -40
  37. package/browser/psbt.d.ts.map +1 -1
  38. package/browser/script.d.ts.map +1 -1
  39. package/browser/transaction.d.ts +4 -4
  40. package/browser/transaction.d.ts.map +1 -1
  41. package/browser/types.d.ts +5 -3
  42. package/browser/types.d.ts.map +1 -1
  43. package/browser/workers/WorkerSigningPool.d.ts +7 -0
  44. package/browser/workers/WorkerSigningPool.d.ts.map +1 -1
  45. package/browser/workers/WorkerSigningPool.node.d.ts +7 -0
  46. package/browser/workers/WorkerSigningPool.node.d.ts.map +1 -1
  47. package/browser/workers/WorkerSigningPool.sequential.d.ts +67 -0
  48. package/browser/workers/WorkerSigningPool.sequential.d.ts.map +1 -0
  49. package/browser/workers/WorkerSigningPool.worklet.d.ts +64 -0
  50. package/browser/workers/WorkerSigningPool.worklet.d.ts.map +1 -0
  51. package/browser/workers/index.browser.d.ts +16 -0
  52. package/browser/workers/index.browser.d.ts.map +1 -0
  53. package/browser/workers/index.d.ts +4 -64
  54. package/browser/workers/index.d.ts.map +1 -1
  55. package/browser/workers/index.js +28 -0
  56. package/browser/workers/index.node.d.ts +17 -0
  57. package/browser/workers/index.node.d.ts.map +1 -0
  58. package/browser/workers/index.react-native.d.ts +28 -0
  59. package/browser/workers/index.react-native.d.ts.map +1 -0
  60. package/browser/workers/index.shared.d.ts +15 -0
  61. package/browser/workers/index.shared.d.ts.map +1 -0
  62. package/browser/workers/psbt-parallel.d.ts +2 -3
  63. package/browser/workers/psbt-parallel.d.ts.map +1 -1
  64. package/browser/workers/types.d.ts +17 -0
  65. package/browser/workers/types.d.ts.map +1 -1
  66. package/build/address.d.ts +5 -1
  67. package/build/address.d.ts.map +1 -1
  68. package/build/address.js +29 -17
  69. package/build/address.js.map +1 -1
  70. package/build/bech32utils.js.map +1 -1
  71. package/build/block.js.map +1 -1
  72. package/build/branded.d.ts +3 -14
  73. package/build/branded.d.ts.map +1 -1
  74. package/build/branded.js +0 -5
  75. package/build/branded.js.map +1 -1
  76. package/build/ecc/context.d.ts +22 -21
  77. package/build/ecc/context.d.ts.map +1 -1
  78. package/build/ecc/context.js +23 -95
  79. package/build/ecc/context.js.map +1 -1
  80. package/build/ecc/index.d.ts +1 -1
  81. package/build/ecc/index.d.ts.map +1 -1
  82. package/build/ecc/types.d.ts +7 -126
  83. package/build/ecc/types.d.ts.map +1 -1
  84. package/build/ecc/types.js +4 -1
  85. package/build/ecc/types.js.map +1 -1
  86. package/build/env.d.ts +13 -0
  87. package/build/env.d.ts.map +1 -0
  88. package/build/env.js +198 -0
  89. package/build/env.js.map +1 -0
  90. package/build/index.d.ts +7 -6
  91. package/build/index.d.ts.map +1 -1
  92. package/build/index.js +7 -5
  93. package/build/index.js.map +1 -1
  94. package/build/io/hex.d.ts.map +1 -1
  95. package/build/io/hex.js +2 -1
  96. package/build/io/hex.js.map +1 -1
  97. package/build/io/index.d.ts +0 -1
  98. package/build/io/index.d.ts.map +1 -1
  99. package/build/io/index.js +0 -2
  100. package/build/io/index.js.map +1 -1
  101. package/build/opcodes.d.ts +11 -0
  102. package/build/opcodes.d.ts.map +1 -1
  103. package/build/opcodes.js +19 -4
  104. package/build/opcodes.js.map +1 -1
  105. package/build/payments/bip341.js.map +1 -1
  106. package/build/payments/embed.js.map +1 -1
  107. package/build/payments/p2ms.js.map +1 -1
  108. package/build/payments/p2pk.js.map +1 -1
  109. package/build/payments/p2pkh.js.map +1 -1
  110. package/build/payments/p2sh.js.map +1 -1
  111. package/build/payments/p2tr.d.ts.map +1 -1
  112. package/build/payments/p2tr.js +2 -3
  113. package/build/payments/p2tr.js.map +1 -1
  114. package/build/payments/p2wpkh.js.map +1 -1
  115. package/build/payments/p2wsh.js.map +1 -1
  116. package/build/psbt/PsbtCache.d.ts +54 -0
  117. package/build/psbt/PsbtCache.d.ts.map +1 -0
  118. package/build/psbt/PsbtCache.js +249 -0
  119. package/build/psbt/PsbtCache.js.map +1 -0
  120. package/build/psbt/PsbtFinalizer.d.ts +21 -0
  121. package/build/psbt/PsbtFinalizer.d.ts.map +1 -0
  122. package/build/psbt/PsbtFinalizer.js +157 -0
  123. package/build/psbt/PsbtFinalizer.js.map +1 -0
  124. package/build/psbt/PsbtSigner.d.ts +32 -0
  125. package/build/psbt/PsbtSigner.d.ts.map +1 -0
  126. package/build/psbt/PsbtSigner.js +192 -0
  127. package/build/psbt/PsbtSigner.js.map +1 -0
  128. package/build/psbt/PsbtTransaction.d.ts +25 -0
  129. package/build/psbt/PsbtTransaction.d.ts.map +1 -0
  130. package/build/psbt/PsbtTransaction.js +61 -0
  131. package/build/psbt/PsbtTransaction.js.map +1 -0
  132. package/build/psbt/types.d.ts +4 -70
  133. package/build/psbt/types.d.ts.map +1 -1
  134. package/build/psbt/validation.d.ts +1 -1
  135. package/build/psbt/validation.d.ts.map +1 -1
  136. package/build/psbt.d.ts +26 -40
  137. package/build/psbt.d.ts.map +1 -1
  138. package/build/psbt.js +177 -799
  139. package/build/psbt.js.map +1 -1
  140. package/build/script.d.ts.map +1 -1
  141. package/build/script.js +2 -2
  142. package/build/script.js.map +1 -1
  143. package/build/transaction.d.ts +4 -4
  144. package/build/transaction.d.ts.map +1 -1
  145. package/build/transaction.js +5 -4
  146. package/build/transaction.js.map +1 -1
  147. package/build/tsconfig.build.tsbuildinfo +1 -1
  148. package/build/types.d.ts +5 -3
  149. package/build/types.d.ts.map +1 -1
  150. package/build/types.js +11 -16
  151. package/build/types.js.map +1 -1
  152. package/build/workers/WorkerSigningPool.d.ts +7 -0
  153. package/build/workers/WorkerSigningPool.d.ts.map +1 -1
  154. package/build/workers/WorkerSigningPool.js +12 -1
  155. package/build/workers/WorkerSigningPool.js.map +1 -1
  156. package/build/workers/WorkerSigningPool.node.d.ts +7 -0
  157. package/build/workers/WorkerSigningPool.node.d.ts.map +1 -1
  158. package/build/workers/WorkerSigningPool.node.js +37 -5
  159. package/build/workers/WorkerSigningPool.node.js.map +1 -1
  160. package/build/workers/WorkerSigningPool.sequential.d.ts +76 -0
  161. package/build/workers/WorkerSigningPool.sequential.d.ts.map +1 -0
  162. package/build/workers/WorkerSigningPool.sequential.js +160 -0
  163. package/build/workers/WorkerSigningPool.sequential.js.map +1 -0
  164. package/build/workers/WorkerSigningPool.worklet.d.ts +79 -0
  165. package/build/workers/WorkerSigningPool.worklet.d.ts.map +1 -0
  166. package/build/workers/WorkerSigningPool.worklet.js +390 -0
  167. package/build/workers/WorkerSigningPool.worklet.js.map +1 -0
  168. package/build/workers/index.browser.d.ts +24 -0
  169. package/build/workers/index.browser.d.ts.map +1 -0
  170. package/build/workers/index.browser.js +30 -0
  171. package/build/workers/index.browser.js.map +1 -0
  172. package/build/workers/index.d.ts +6 -18
  173. package/build/workers/index.d.ts.map +1 -1
  174. package/build/workers/index.js +12 -14
  175. package/build/workers/index.js.map +1 -1
  176. package/build/workers/index.node.d.ts +38 -0
  177. package/build/workers/index.node.d.ts.map +1 -0
  178. package/build/workers/index.node.js +45 -0
  179. package/build/workers/index.node.js.map +1 -0
  180. package/build/workers/index.react-native.d.ts +28 -0
  181. package/build/workers/index.react-native.d.ts.map +1 -0
  182. package/build/workers/index.react-native.js +67 -0
  183. package/build/workers/index.react-native.js.map +1 -0
  184. package/build/workers/index.shared.d.ts +15 -0
  185. package/build/workers/index.shared.d.ts.map +1 -0
  186. package/build/workers/index.shared.js +20 -0
  187. package/build/workers/index.shared.js.map +1 -0
  188. package/build/workers/psbt-parallel.d.ts +2 -3
  189. package/build/workers/psbt-parallel.d.ts.map +1 -1
  190. package/build/workers/psbt-parallel.js +4 -4
  191. package/build/workers/psbt-parallel.js.map +1 -1
  192. package/build/workers/types.d.ts +17 -0
  193. package/build/workers/types.d.ts.map +1 -1
  194. package/package.json +46 -8
  195. package/src/address.ts +41 -18
  196. package/src/bech32utils.ts +3 -3
  197. package/src/block.ts +2 -2
  198. package/src/branded.ts +15 -13
  199. package/src/ecc/context.ts +30 -133
  200. package/src/ecc/index.ts +2 -2
  201. package/src/ecc/types.ts +7 -138
  202. package/src/env.ts +239 -0
  203. package/src/index.ts +45 -9
  204. package/src/io/hex.ts +2 -1
  205. package/src/io/index.ts +0 -3
  206. package/src/opcodes.ts +21 -4
  207. package/src/payments/bip341.ts +3 -3
  208. package/src/payments/embed.ts +1 -1
  209. package/src/payments/p2ms.ts +2 -2
  210. package/src/payments/p2pk.ts +2 -2
  211. package/src/payments/p2pkh.ts +3 -3
  212. package/src/payments/p2sh.ts +4 -4
  213. package/src/payments/p2tr.ts +9 -9
  214. package/src/payments/p2wpkh.ts +5 -5
  215. package/src/payments/p2wsh.ts +2 -2
  216. package/src/psbt/PsbtCache.ts +325 -0
  217. package/src/psbt/PsbtFinalizer.ts +213 -0
  218. package/src/psbt/PsbtSigner.ts +302 -0
  219. package/src/psbt/PsbtTransaction.ts +82 -0
  220. package/src/psbt/types.ts +4 -86
  221. package/src/psbt/validation.ts +1 -1
  222. package/src/psbt.ts +349 -1198
  223. package/src/script.ts +2 -2
  224. package/src/transaction.ts +10 -9
  225. package/src/types.ts +18 -28
  226. package/src/workers/WorkerSigningPool.node.ts +41 -5
  227. package/src/workers/WorkerSigningPool.sequential.ts +191 -0
  228. package/src/workers/WorkerSigningPool.ts +14 -1
  229. package/src/workers/WorkerSigningPool.worklet.ts +522 -0
  230. package/src/workers/index.browser.ts +34 -0
  231. package/src/workers/index.node.ts +50 -0
  232. package/src/workers/index.react-native.ts +110 -0
  233. package/src/workers/index.shared.ts +58 -0
  234. package/src/workers/index.ts +14 -65
  235. package/src/workers/psbt-parallel.ts +7 -7
  236. package/src/workers/types.ts +21 -0
  237. package/test/address.spec.ts +2 -2
  238. package/test/bitcoin.core.spec.ts +5 -2
  239. package/test/browser/payments.spec.ts +151 -0
  240. package/test/browser/psbt.spec.ts +1510 -0
  241. package/test/browser/script.spec.ts +223 -0
  242. package/test/browser/setup.ts +13 -0
  243. package/test/browser/workers-signing.spec.ts +537 -0
  244. package/test/crypto.spec.ts +2 -2
  245. package/test/env.spec.ts +418 -0
  246. package/test/fixtures/core/base58_encode_decode.json +12 -48
  247. package/test/fixtures/core/base58_keys_invalid.json +50 -150
  248. package/test/fixtures/core/sighash.json +1 -3
  249. package/test/fixtures/core/tx_valid.json +133 -501
  250. package/test/fixtures/embed.json +3 -11
  251. package/test/fixtures/p2ms.json +21 -91
  252. package/test/fixtures/p2pk.json +5 -24
  253. package/test/fixtures/p2pkh.json +7 -36
  254. package/test/fixtures/p2sh.json +8 -54
  255. package/test/fixtures/p2tr.json +2 -6
  256. package/test/fixtures/p2wpkh.json +7 -36
  257. package/test/fixtures/p2wsh.json +14 -59
  258. package/test/fixtures/psbt.json +2 -6
  259. package/test/fixtures/script.json +12 -48
  260. package/test/integration/addresses.spec.ts +11 -5
  261. package/test/integration/bip32.spec.ts +1 -1
  262. package/test/integration/cltv.spec.ts +10 -6
  263. package/test/integration/csv.spec.ts +10 -9
  264. package/test/integration/payments.spec.ts +8 -4
  265. package/test/integration/taproot.spec.ts +26 -6
  266. package/test/integration/transactions.spec.ts +22 -8
  267. package/test/payments.spec.ts +1 -1
  268. package/test/payments.utils.ts +1 -1
  269. package/test/psbt.spec.ts +250 -64
  270. package/test/script_signature.spec.ts +1 -1
  271. package/test/transaction.spec.ts +18 -5
  272. package/test/tsconfig.json +6 -20
  273. package/test/workers-pool.spec.ts +65 -23
  274. package/test/workers-sequential.spec.ts +669 -0
  275. package/test/workers-signing.spec.ts +7 -3
  276. package/test/workers-worklet.spec.ts +500 -0
  277. package/test/workers.spec.ts +6 -7
  278. package/typedoc.json +11 -1
  279. package/vite.config.browser.ts +31 -6
  280. package/vitest.config.browser.ts +68 -0
  281. package/browser/ecpair.d.ts +0 -99
  282. package/browser/io/MemoryPool.d.ts +0 -220
  283. package/browser/io/MemoryPool.d.ts.map +0 -1
  284. package/build/io/MemoryPool.d.ts +0 -220
  285. package/build/io/MemoryPool.d.ts.map +0 -1
  286. package/build/io/MemoryPool.js +0 -309
  287. package/build/io/MemoryPool.js.map +0 -1
  288. package/src/ecpair.d.ts +0 -99
  289. package/src/io/MemoryPool.ts +0 -343
  290. package/test/taproot-cache.spec.ts +0 -694
@@ -4,9 +4,8 @@
4
4
  *
5
5
  * @packageDocumentation
6
6
  */
7
- import type { EccLib } from './types.js';
8
- import { equals, fromHex } from '../io/index.js';
9
- import type { Bytes32, XOnlyPublicKey } from '../types.js';
7
+ import type { CryptoBackend } from '@btc-vision/ecpair';
8
+ import { verifyCryptoBackend } from '@btc-vision/ecpair';
10
9
 
11
10
  /**
12
11
  * Context class for managing the ECC library instance.
@@ -15,10 +14,11 @@ import type { Bytes32, XOnlyPublicKey } from '../types.js';
15
14
  * @example
16
15
  * ```typescript
17
16
  * import { EccContext } from '@btc-vision/bitcoin';
18
- * import * as secp256k1 from 'tiny-secp256k1';
17
+ * import { createNobleBackend } from '@btc-vision/ecpair';
19
18
  *
20
19
  * // Initialize once at app startup
21
- * EccContext.init(secp256k1);
20
+ * const backend = createNobleBackend();
21
+ * EccContext.init(backend);
22
22
  *
23
23
  * // Get instance anywhere in your code
24
24
  * const ecc = EccContext.get();
@@ -29,16 +29,16 @@ import type { Bytes32, XOnlyPublicKey } from '../types.js';
29
29
  */
30
30
  export class EccContext {
31
31
  static #instance: EccContext | undefined;
32
- readonly #lib: EccLib;
32
+ readonly #lib: CryptoBackend;
33
33
 
34
- private constructor(lib: EccLib) {
34
+ private constructor(lib: CryptoBackend) {
35
35
  this.#lib = lib;
36
36
  }
37
37
 
38
38
  /**
39
39
  * The underlying ECC library instance.
40
40
  */
41
- get lib(): EccLib {
41
+ get lib(): CryptoBackend {
42
42
  return this.#lib;
43
43
  }
44
44
 
@@ -46,20 +46,24 @@ export class EccContext {
46
46
  * Initializes the ECC context with the provided library.
47
47
  * The library is verified before being set as active.
48
48
  *
49
- * @param lib - The ECC library instance to initialize
49
+ * @param lib - The CryptoBackend instance to initialize
50
50
  * @returns The initialized EccContext instance
51
- * @throws Error if the ECC library fails verification
51
+ * @throws Error if the CryptoBackend fails verification
52
52
  *
53
53
  * @example
54
54
  * ```typescript
55
55
  * import { EccContext } from '@btc-vision/bitcoin';
56
- * import * as secp256k1 from 'tiny-secp256k1';
56
+ * import { createNobleBackend } from '@btc-vision/ecpair';
57
57
  *
58
- * const context = EccContext.init(secp256k1);
58
+ * const context = EccContext.init(createNobleBackend());
59
59
  * ```
60
60
  */
61
- static init(lib: EccLib): EccContext {
62
- verifyEcc(lib);
61
+ static init(lib: CryptoBackend): EccContext {
62
+ // Skip re-verification if same lib is already initialized
63
+ if (EccContext.#instance && EccContext.#instance.#lib === lib) {
64
+ return EccContext.#instance;
65
+ }
66
+ verifyCryptoBackend(lib);
63
67
  EccContext.#instance = new EccContext(lib);
64
68
  return EccContext.#instance;
65
69
  }
@@ -75,7 +79,7 @@ export class EccContext {
75
79
  * import { EccContext } from '@btc-vision/bitcoin';
76
80
  *
77
81
  * const context = EccContext.get();
78
- * const isValid = context.lib.isXOnlyPoint(someKey);
82
+ * const tweaked = context.lib.xOnlyPointAddTweak(key, tweak);
79
83
  * ```
80
84
  */
81
85
  static get(): EccContext {
@@ -113,7 +117,7 @@ export class EccContext {
113
117
  * import { EccContext } from '@btc-vision/bitcoin';
114
118
  *
115
119
  * if (!EccContext.isInitialized()) {
116
- * EccContext.init(secp256k1);
120
+ * EccContext.init(createNobleBackend());
117
121
  * }
118
122
  * ```
119
123
  */
@@ -127,22 +131,22 @@ export class EccContext {
127
131
  * This is a convenience function that wraps EccContext.init().
128
132
  * Pass `undefined` to clear the library.
129
133
  *
130
- * @param eccLib - The ECC library instance to initialize, or undefined to clear
131
- * @throws Error if the ECC library fails verification
134
+ * @param eccLib - The CryptoBackend instance to initialize, or undefined to clear
135
+ * @throws Error if the CryptoBackend fails verification
132
136
  *
133
137
  * @example
134
138
  * ```typescript
135
139
  * import { initEccLib } from '@btc-vision/bitcoin';
136
- * import * as secp256k1 from 'tiny-secp256k1';
140
+ * import { createNobleBackend } from '@btc-vision/ecpair';
137
141
  *
138
142
  * // Initialize the ECC library
139
- * initEccLib(secp256k1);
143
+ * initEccLib(createNobleBackend());
140
144
  *
141
145
  * // Clear the library
142
146
  * initEccLib(undefined);
143
147
  * ```
144
148
  */
145
- export function initEccLib(eccLib: EccLib | undefined): void {
149
+ export function initEccLib(eccLib: CryptoBackend | undefined): void {
146
150
  if (eccLib === undefined) {
147
151
  EccContext.clear();
148
152
  return;
@@ -154,127 +158,20 @@ export function initEccLib(eccLib: EccLib | undefined): void {
154
158
  * Retrieves the initialized ECC library instance.
155
159
  * This is a convenience function that wraps EccContext.get().lib.
156
160
  *
157
- * @returns The ECC library instance
161
+ * @returns The CryptoBackend instance
158
162
  * @throws Error if the ECC library has not been initialized
159
163
  *
160
164
  * @example
161
165
  * ```typescript
162
166
  * import { getEccLib, initEccLib } from '@btc-vision/bitcoin';
163
- * import * as secp256k1 from 'tiny-secp256k1';
167
+ * import { createNobleBackend } from '@btc-vision/ecpair';
164
168
  *
165
- * initEccLib(secp256k1);
169
+ * initEccLib(createNobleBackend());
166
170
  *
167
171
  * const ecc = getEccLib();
168
- * const isValid = ecc.isXOnlyPoint(somePublicKey);
172
+ * const tweaked = ecc.xOnlyPointAddTweak(pubkey, tweak);
169
173
  * ```
170
174
  */
171
- export function getEccLib(): EccLib {
175
+ export function getEccLib(): CryptoBackend {
172
176
  return EccContext.get().lib;
173
177
  }
174
-
175
- // ============================================================================
176
- // Verification
177
- // ============================================================================
178
-
179
- interface TweakAddVector {
180
- pubkey: string;
181
- tweak: string;
182
- parity: 0 | 1 | -1;
183
- result: string | null;
184
- }
185
-
186
- const TWEAK_ADD_VECTORS: TweakAddVector[] = [
187
- {
188
- pubkey: '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
189
- tweak: 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140',
190
- parity: -1,
191
- result: null,
192
- },
193
- {
194
- pubkey: '1617d38ed8d8657da4d4761e8057bc396ea9e4b9d29776d4be096016dbd2509b',
195
- tweak: 'a8397a935f0dfceba6ba9618f6451ef4d80637abf4e6af2669fbc9de6a8fd2ac',
196
- parity: 1,
197
- result: 'e478f99dab91052ab39a33ea35fd5e6e4933f4d28023cd597c9a1f6760346adf',
198
- },
199
- {
200
- pubkey: '2c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991',
201
- tweak: '823c3cd2142744b075a87eade7e1b8678ba308d566226a0056ca2b7a76f86b47',
202
- parity: 0,
203
- result: '9534f8dc8c6deda2dc007655981c78b49c5d96c778fbf363462a11ec9dfd948c',
204
- },
205
- ];
206
-
207
- /**
208
- * Verifies that the ECC library implementation is correct.
209
- * Tests `isXOnlyPoint` and `xOnlyPointAddTweak` with known test vectors.
210
- *
211
- * @param ecc - The ECC library to verify
212
- * @throws Error if any verification test fails
213
- */
214
- function verifyEcc(ecc: EccLib): void {
215
- if (typeof ecc.isXOnlyPoint !== 'function') {
216
- throw new Error('ECC library missing isXOnlyPoint function');
217
- }
218
-
219
- // Test isXOnlyPoint with valid points
220
- const validPoints = [
221
- '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
222
- 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffeeffffc2e',
223
- 'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9',
224
- '0000000000000000000000000000000000000000000000000000000000000001',
225
- ];
226
-
227
- for (const hex of validPoints) {
228
- if (!ecc.isXOnlyPoint(fromHex(hex))) {
229
- throw new Error(`ECC library isXOnlyPoint failed for valid point: ${hex}`);
230
- }
231
- }
232
-
233
- // Test isXOnlyPoint with invalid points
234
- const invalidPoints = [
235
- '0000000000000000000000000000000000000000000000000000000000000000',
236
- 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f',
237
- ];
238
-
239
- for (const hex of invalidPoints) {
240
- if (ecc.isXOnlyPoint(fromHex(hex))) {
241
- throw new Error(`ECC library isXOnlyPoint should reject invalid point: ${hex}`);
242
- }
243
- }
244
-
245
- // Test xOnlyPointAddTweak
246
- if (typeof ecc.xOnlyPointAddTweak !== 'function') {
247
- throw new Error('ECC library missing xOnlyPointAddTweak function');
248
- }
249
-
250
- for (const vector of TWEAK_ADD_VECTORS) {
251
- const result = ecc.xOnlyPointAddTweak(
252
- fromHex(vector.pubkey) as XOnlyPublicKey,
253
- fromHex(vector.tweak) as Bytes32,
254
- );
255
-
256
- if (vector.result === null) {
257
- if (result !== null) {
258
- throw new Error(
259
- `ECC library xOnlyPointAddTweak should return null for: ${vector.pubkey}`,
260
- );
261
- }
262
- } else {
263
- if (result === null) {
264
- throw new Error(
265
- `ECC library xOnlyPointAddTweak returned null unexpectedly for: ${vector.pubkey}`,
266
- );
267
- }
268
- if (result.parity !== vector.parity) {
269
- throw new Error(
270
- `ECC library xOnlyPointAddTweak parity mismatch for: ${vector.pubkey}`,
271
- );
272
- }
273
- if (!equals(result.xOnlyPubkey, fromHex(vector.result))) {
274
- throw new Error(
275
- `ECC library xOnlyPointAddTweak result mismatch for: ${vector.pubkey}`,
276
- );
277
- }
278
- }
279
- }
280
- }
package/src/ecc/index.ts CHANGED
@@ -7,8 +7,8 @@
7
7
  * @packageDocumentation
8
8
  */
9
9
 
10
- // Core types
11
- export type { EccLib, XOnlyPointAddTweakResult, Parity } from './types.js';
10
+ // Core types (CryptoBackend is the canonical name; EccLib is a deprecated alias)
11
+ export type { CryptoBackend, EccLib, XOnlyPointAddTweakResult, Parity } from './types.js';
12
12
 
13
13
  // Context management
14
14
  export { EccContext, initEccLib, getEccLib } from './context.js';
package/src/ecc/types.ts CHANGED
@@ -1,147 +1,16 @@
1
1
  /**
2
2
  * ECC (Elliptic Curve Cryptography) type definitions.
3
- * Defines interfaces for secp256k1 operations used in Taproot and signatures.
3
+ *
4
+ * Re-exports {@link CryptoBackend} from `@btc-vision/ecpair` as the canonical
5
+ * interface for secp256k1 operations. The legacy `EccLib` name is kept as a
6
+ * type alias for backward compatibility.
4
7
  *
5
8
  * @packageDocumentation
6
9
  */
7
10
 
8
- import type { Bytes32, PrivateKey, PublicKey, SchnorrSignature, Signature, XOnlyPublicKey, } from '../branded.js';
9
-
10
- /**
11
- * Parity of the y-coordinate for an x-only public key.
12
- * - 0: even y-coordinate
13
- * - 1: odd y-coordinate
14
- */
15
- export type Parity = 0 | 1;
16
-
17
- /**
18
- * Result of x-only point addition with tweak.
19
- */
20
- export interface XOnlyPointAddTweakResult {
21
- /** Parity of the resulting y-coordinate (0 = even, 1 = odd) */
22
- readonly parity: Parity;
23
- /** The resulting x-only public key */
24
- readonly xOnlyPubkey: XOnlyPublicKey;
25
- }
11
+ export type { CryptoBackend, XOnlyPointAddTweakResult, Parity } from '@btc-vision/ecpair';
26
12
 
27
13
  /**
28
- * Interface for the ECC library used by this library.
29
- * This is compatible with tiny-secp256k1 and @noble/secp256k1.
30
- *
31
- * @example
32
- * ```typescript
33
- * import { EccLib, initEccLib } from '@btc-vision/bitcoin';
34
- * import * as secp256k1 from 'tiny-secp256k1';
35
- *
36
- * // tiny-secp256k1 implements EccLib
37
- * const ecc: EccLib = secp256k1;
38
- * initEccLib(ecc);
39
- * ```
14
+ * @deprecated Use {@link CryptoBackend} from `@btc-vision/ecpair` instead.
40
15
  */
41
- export interface EccLib {
42
- /**
43
- * Checks if a 32-byte value is a valid x-only public key.
44
- *
45
- * @param p - 32-byte x-coordinate
46
- * @returns True if the point is valid on the secp256k1 curve
47
- */
48
- isXOnlyPoint(p: Uint8Array): boolean;
49
-
50
- /**
51
- * Adds a tweak to an x-only public key.
52
- *
53
- * @param p - 32-byte x-only public key
54
- * @param tweak - 32-byte scalar to add
55
- * @returns The tweaked public key with parity, or null if result is invalid
56
- */
57
- xOnlyPointAddTweak(p: XOnlyPublicKey, tweak: Bytes32): XOnlyPointAddTweakResult | null;
58
-
59
- /**
60
- * Signs a 32-byte message hash with a private key (ECDSA).
61
- * Optional - only needed for signing operations.
62
- *
63
- * @param hash - 32-byte message hash
64
- * @param privateKey - 32-byte private key
65
- * @returns DER-encoded signature
66
- */
67
- sign?(hash: Bytes32, privateKey: PrivateKey): Signature;
68
-
69
- /**
70
- * Signs a 32-byte message hash with a private key (Schnorr/BIP340).
71
- * Optional - only needed for Taproot key-path signing.
72
- *
73
- * @param hash - 32-byte message hash
74
- * @param privateKey - 32-byte private key
75
- * @returns 64-byte Schnorr signature
76
- */
77
- signSchnorr?(hash: Bytes32, privateKey: PrivateKey): SchnorrSignature;
78
-
79
- /**
80
- * Verifies an ECDSA signature.
81
- * Optional - only needed for signature verification.
82
- *
83
- * @param hash - 32-byte message hash
84
- * @param publicKey - 33 or 65-byte public key
85
- * @param signature - DER-encoded signature
86
- * @returns True if signature is valid
87
- */
88
- verify?(hash: Bytes32, publicKey: PublicKey, signature: Signature): boolean;
89
-
90
- /**
91
- * Verifies a Schnorr/BIP340 signature.
92
- * Optional - only needed for Taproot signature verification.
93
- *
94
- * @param hash - 32-byte message hash
95
- * @param publicKey - 32-byte x-only public key
96
- * @param signature - 64-byte Schnorr signature
97
- * @returns True if signature is valid
98
- */
99
- verifySchnorr?(hash: Bytes32, publicKey: XOnlyPublicKey, signature: SchnorrSignature): boolean;
100
-
101
- /**
102
- * Derives a public key from a private key.
103
- * Optional - only needed for key derivation.
104
- *
105
- * @param privateKey - 32-byte private key
106
- * @param compressed - Whether to return compressed (33-byte) or uncompressed (65-byte)
107
- * @returns The public key, or null if private key is invalid
108
- */
109
- pointFromScalar?(privateKey: PrivateKey, compressed?: boolean): PublicKey | null;
110
-
111
- /**
112
- * Computes the x-only public key from a private key.
113
- * Optional - only needed for Taproot key derivation.
114
- *
115
- * @param privateKey - 32-byte private key
116
- * @returns 32-byte x-only public key, or null if private key is invalid
117
- */
118
- xOnlyPointFromScalar?(privateKey: PrivateKey): XOnlyPublicKey | null;
119
-
120
- /**
121
- * Converts a full public key to x-only format.
122
- * Optional - only needed when working with x-only keys.
123
- *
124
- * @param pubkey - 33 or 65-byte public key
125
- * @returns 32-byte x-only public key
126
- */
127
- xOnlyPointFromPoint?(pubkey: PublicKey): XOnlyPublicKey;
128
-
129
- /**
130
- * Adds a scalar to a private key.
131
- * Optional - only needed for key tweaking.
132
- *
133
- * @param privateKey - 32-byte private key
134
- * @param tweak - 32-byte scalar to add
135
- * @returns The tweaked private key, or null if result is invalid
136
- */
137
- privateAdd?(privateKey: PrivateKey, tweak: Bytes32): PrivateKey | null;
138
-
139
- /**
140
- * Negates a private key.
141
- * Optional - only needed for Taproot parity handling.
142
- *
143
- * @param privateKey - 32-byte private key
144
- * @returns The negated private key
145
- */
146
- privateNegate?(privateKey: PrivateKey): PrivateKey;
147
- }
16
+ export type { CryptoBackend as EccLib } from '@btc-vision/ecpair';
package/src/env.ts ADDED
@@ -0,0 +1,239 @@
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<{
223
+ -readonly [K in keyof T]: PromiseSettledResult<Awaited<T[K]>>;
224
+ }>;
225
+ };
226
+ }
227
+
228
+ // structuredClone (ES2022 — used for PSBT cloning)
229
+ if (typeof globalThis.structuredClone === 'undefined') {
230
+ globalThis.structuredClone = <T>(value: T): T => JSON.parse(JSON.stringify(value)) as T;
231
+ }
232
+
233
+ // Symbol.dispose / Symbol.asyncDispose (ES2024 — Explicit Resource Management)
234
+ if (typeof Symbol['dispose'] === 'undefined') {
235
+ (Symbol as unknown as Record<string, symbol>)['dispose'] = Symbol.for('Symbol.dispose');
236
+ }
237
+ if (typeof Symbol['asyncDispose'] === 'undefined') {
238
+ (Symbol as unknown as Record<string, symbol>)['asyncDispose'] = Symbol.for('Symbol.asyncDispose');
239
+ }