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

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 (296) hide show
  1. package/browser/address.d.ts +6 -2
  2. package/browser/address.d.ts.map +1 -1
  3. package/browser/block.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/crypto.d.ts +1 -1
  7. package/browser/ecc/context.d.ts +4 -4
  8. package/browser/ecc/context.d.ts.map +1 -1
  9. package/browser/ecc/types.d.ts +1 -1
  10. package/browser/ecc/types.d.ts.map +1 -1
  11. package/browser/index.d.ts +3 -2
  12. package/browser/index.d.ts.map +1 -1
  13. package/browser/index.js +3579 -3539
  14. package/browser/io/BinaryReader.d.ts +15 -15
  15. package/browser/io/BinaryReader.d.ts.map +1 -1
  16. package/browser/io/BinaryWriter.d.ts +17 -17
  17. package/browser/io/BinaryWriter.d.ts.map +1 -1
  18. package/browser/io/MemoryPool.d.ts +20 -20
  19. package/browser/io/MemoryPool.d.ts.map +1 -1
  20. package/browser/opcodes.d.ts +11 -0
  21. package/browser/opcodes.d.ts.map +1 -1
  22. package/browser/payments/bip341.d.ts +1 -1
  23. package/browser/payments/bip341.d.ts.map +1 -1
  24. package/browser/payments/embed.d.ts +1 -1
  25. package/browser/payments/embed.d.ts.map +1 -1
  26. package/browser/payments/p2ms.d.ts.map +1 -1
  27. package/browser/payments/p2op.d.ts +1 -1
  28. package/browser/payments/p2op.d.ts.map +1 -1
  29. package/browser/payments/p2pk.d.ts +1 -1
  30. package/browser/payments/p2pk.d.ts.map +1 -1
  31. package/browser/payments/p2pkh.d.ts +1 -1
  32. package/browser/payments/p2pkh.d.ts.map +1 -1
  33. package/browser/payments/p2sh.d.ts.map +1 -1
  34. package/browser/payments/p2tr.d.ts +2 -2
  35. package/browser/payments/p2tr.d.ts.map +1 -1
  36. package/browser/payments/p2wpkh.d.ts +1 -1
  37. package/browser/payments/p2wpkh.d.ts.map +1 -1
  38. package/browser/payments/p2wsh.d.ts.map +1 -1
  39. package/browser/payments/types.d.ts +1 -1
  40. package/browser/payments/types.d.ts.map +1 -1
  41. package/browser/psbt/PsbtCache.d.ts +54 -0
  42. package/browser/psbt/PsbtCache.d.ts.map +1 -0
  43. package/browser/psbt/PsbtFinalizer.d.ts +21 -0
  44. package/browser/psbt/PsbtFinalizer.d.ts.map +1 -0
  45. package/browser/psbt/PsbtSigner.d.ts +32 -0
  46. package/browser/psbt/PsbtSigner.d.ts.map +1 -0
  47. package/browser/psbt/PsbtTransaction.d.ts +25 -0
  48. package/browser/psbt/PsbtTransaction.d.ts.map +1 -0
  49. package/browser/psbt/bip371.d.ts.map +1 -1
  50. package/browser/psbt/types.d.ts +14 -14
  51. package/browser/psbt/types.d.ts.map +1 -1
  52. package/browser/psbt/validation.d.ts +1 -1
  53. package/browser/psbt/validation.d.ts.map +1 -1
  54. package/browser/psbt.d.ts +27 -39
  55. package/browser/psbt.d.ts.map +1 -1
  56. package/browser/script.d.ts.map +1 -1
  57. package/browser/transaction.d.ts +4 -4
  58. package/browser/transaction.d.ts.map +1 -1
  59. package/browser/types.d.ts +4 -2
  60. package/browser/types.d.ts.map +1 -1
  61. package/browser/workers/WorkerSigningPool.d.ts +17 -17
  62. package/browser/workers/WorkerSigningPool.d.ts.map +1 -1
  63. package/browser/workers/WorkerSigningPool.node.d.ts +12 -12
  64. package/browser/workers/WorkerSigningPool.node.d.ts.map +1 -1
  65. package/browser/workers/index.d.ts +3 -50
  66. package/browser/workers/index.d.ts.map +1 -1
  67. package/browser/workers/index.node.d.ts +24 -0
  68. package/browser/workers/index.node.d.ts.map +1 -0
  69. package/browser/workers/psbt-parallel.d.ts +1 -1
  70. package/browser/workers/psbt-parallel.d.ts.map +1 -1
  71. package/browser/workers/types.d.ts.map +1 -1
  72. package/build/address.d.ts +6 -2
  73. package/build/address.d.ts.map +1 -1
  74. package/build/address.js +32 -19
  75. package/build/address.js.map +1 -1
  76. package/build/block.d.ts.map +1 -1
  77. package/build/block.js +2 -4
  78. package/build/block.js.map +1 -1
  79. package/build/branded.d.ts +3 -14
  80. package/build/branded.d.ts.map +1 -1
  81. package/build/branded.js +0 -5
  82. package/build/branded.js.map +1 -1
  83. package/build/crypto.d.ts +1 -1
  84. package/build/ecc/context.d.ts +4 -4
  85. package/build/ecc/context.d.ts.map +1 -1
  86. package/build/ecc/context.js +75 -52
  87. package/build/ecc/context.js.map +1 -1
  88. package/build/ecc/types.d.ts +1 -1
  89. package/build/ecc/types.d.ts.map +1 -1
  90. package/build/index.d.ts +3 -2
  91. package/build/index.d.ts.map +1 -1
  92. package/build/index.js +3 -3
  93. package/build/index.js.map +1 -1
  94. package/build/io/BinaryReader.d.ts +15 -15
  95. package/build/io/BinaryReader.d.ts.map +1 -1
  96. package/build/io/BinaryReader.js +17 -17
  97. package/build/io/BinaryReader.js.map +1 -1
  98. package/build/io/BinaryWriter.d.ts +17 -17
  99. package/build/io/BinaryWriter.d.ts.map +1 -1
  100. package/build/io/BinaryWriter.js +39 -39
  101. package/build/io/BinaryWriter.js.map +1 -1
  102. package/build/io/MemoryPool.d.ts +20 -20
  103. package/build/io/MemoryPool.d.ts.map +1 -1
  104. package/build/io/MemoryPool.js +28 -28
  105. package/build/io/MemoryPool.js.map +1 -1
  106. package/build/opcodes.d.ts +11 -0
  107. package/build/opcodes.d.ts.map +1 -1
  108. package/build/opcodes.js +19 -4
  109. package/build/opcodes.js.map +1 -1
  110. package/build/payments/bip341.d.ts +1 -2
  111. package/build/payments/bip341.d.ts.map +1 -1
  112. package/build/payments/bip341.js +1 -2
  113. package/build/payments/bip341.js.map +1 -1
  114. package/build/payments/embed.d.ts +1 -1
  115. package/build/payments/embed.d.ts.map +1 -1
  116. package/build/payments/embed.js +14 -14
  117. package/build/payments/embed.js.map +1 -1
  118. package/build/payments/p2ms.d.ts.map +1 -1
  119. package/build/payments/p2ms.js +21 -21
  120. package/build/payments/p2ms.js.map +1 -1
  121. package/build/payments/p2op.d.ts +1 -1
  122. package/build/payments/p2op.d.ts.map +1 -1
  123. package/build/payments/p2op.js +18 -18
  124. package/build/payments/p2op.js.map +1 -1
  125. package/build/payments/p2pk.d.ts +1 -1
  126. package/build/payments/p2pk.d.ts.map +1 -1
  127. package/build/payments/p2pk.js +17 -17
  128. package/build/payments/p2pk.js.map +1 -1
  129. package/build/payments/p2pkh.d.ts +1 -1
  130. package/build/payments/p2pkh.d.ts.map +1 -1
  131. package/build/payments/p2pkh.js +20 -20
  132. package/build/payments/p2pkh.js.map +1 -1
  133. package/build/payments/p2sh.d.ts.map +1 -1
  134. package/build/payments/p2sh.js +22 -20
  135. package/build/payments/p2sh.js.map +1 -1
  136. package/build/payments/p2tr.d.ts +2 -2
  137. package/build/payments/p2tr.d.ts.map +1 -1
  138. package/build/payments/p2tr.js +23 -23
  139. package/build/payments/p2tr.js.map +1 -1
  140. package/build/payments/p2wpkh.d.ts +1 -1
  141. package/build/payments/p2wpkh.d.ts.map +1 -1
  142. package/build/payments/p2wpkh.js +20 -20
  143. package/build/payments/p2wpkh.js.map +1 -1
  144. package/build/payments/p2wsh.d.ts.map +1 -1
  145. package/build/payments/p2wsh.js +22 -22
  146. package/build/payments/p2wsh.js.map +1 -1
  147. package/build/payments/types.d.ts +1 -1
  148. package/build/payments/types.d.ts.map +1 -1
  149. package/build/psbt/PsbtCache.d.ts +54 -0
  150. package/build/psbt/PsbtCache.d.ts.map +1 -0
  151. package/build/psbt/PsbtCache.js +249 -0
  152. package/build/psbt/PsbtCache.js.map +1 -0
  153. package/build/psbt/PsbtFinalizer.d.ts +21 -0
  154. package/build/psbt/PsbtFinalizer.d.ts.map +1 -0
  155. package/build/psbt/PsbtFinalizer.js +157 -0
  156. package/build/psbt/PsbtFinalizer.js.map +1 -0
  157. package/build/psbt/PsbtSigner.d.ts +32 -0
  158. package/build/psbt/PsbtSigner.d.ts.map +1 -0
  159. package/build/psbt/PsbtSigner.js +192 -0
  160. package/build/psbt/PsbtSigner.js.map +1 -0
  161. package/build/psbt/PsbtTransaction.d.ts +25 -0
  162. package/build/psbt/PsbtTransaction.d.ts.map +1 -0
  163. package/build/psbt/PsbtTransaction.js +61 -0
  164. package/build/psbt/PsbtTransaction.js.map +1 -0
  165. package/build/psbt/bip371.d.ts.map +1 -1
  166. package/build/psbt/bip371.js +6 -2
  167. package/build/psbt/bip371.js.map +1 -1
  168. package/build/psbt/psbtutils.js +1 -1
  169. package/build/psbt/psbtutils.js.map +1 -1
  170. package/build/psbt/types.d.ts +14 -14
  171. package/build/psbt/types.d.ts.map +1 -1
  172. package/build/psbt/validation.d.ts +1 -1
  173. package/build/psbt/validation.d.ts.map +1 -1
  174. package/build/psbt/validation.js +1 -1
  175. package/build/psbt/validation.js.map +1 -1
  176. package/build/psbt.d.ts +27 -39
  177. package/build/psbt.d.ts.map +1 -1
  178. package/build/psbt.js +142 -755
  179. package/build/psbt.js.map +1 -1
  180. package/build/script.d.ts.map +1 -1
  181. package/build/script.js +4 -4
  182. package/build/script.js.map +1 -1
  183. package/build/transaction.d.ts +4 -4
  184. package/build/transaction.d.ts.map +1 -1
  185. package/build/transaction.js +6 -5
  186. package/build/transaction.js.map +1 -1
  187. package/build/tsconfig.build.tsbuildinfo +1 -1
  188. package/build/types.d.ts +4 -2
  189. package/build/types.d.ts.map +1 -1
  190. package/build/types.js +12 -9
  191. package/build/types.js.map +1 -1
  192. package/build/workers/WorkerSigningPool.d.ts +17 -17
  193. package/build/workers/WorkerSigningPool.d.ts.map +1 -1
  194. package/build/workers/WorkerSigningPool.js +25 -25
  195. package/build/workers/WorkerSigningPool.js.map +1 -1
  196. package/build/workers/WorkerSigningPool.node.d.ts +12 -12
  197. package/build/workers/WorkerSigningPool.node.d.ts.map +1 -1
  198. package/build/workers/WorkerSigningPool.node.js +23 -23
  199. package/build/workers/WorkerSigningPool.node.js.map +1 -1
  200. package/build/workers/index.d.ts +3 -3
  201. package/build/workers/index.d.ts.map +1 -1
  202. package/build/workers/index.js +0 -3
  203. package/build/workers/index.js.map +1 -1
  204. package/build/workers/index.node.d.ts +24 -0
  205. package/build/workers/index.node.d.ts.map +1 -0
  206. package/build/workers/index.node.js +26 -0
  207. package/build/workers/index.node.js.map +1 -0
  208. package/build/workers/psbt-parallel.d.ts +1 -1
  209. package/build/workers/psbt-parallel.d.ts.map +1 -1
  210. package/build/workers/psbt-parallel.js.map +1 -1
  211. package/build/workers/types.d.ts.map +1 -1
  212. package/build/workers/types.js.map +1 -1
  213. package/package.json +30 -10
  214. package/src/address.ts +53 -21
  215. package/src/block.ts +15 -8
  216. package/src/branded.ts +15 -13
  217. package/src/crypto.ts +1 -1
  218. package/src/ecc/context.ts +85 -64
  219. package/src/ecc/types.ts +1 -8
  220. package/src/index.ts +48 -14
  221. package/src/io/BinaryReader.ts +18 -18
  222. package/src/io/BinaryWriter.ts +43 -43
  223. package/src/io/MemoryPool.ts +32 -32
  224. package/src/opcodes.ts +21 -4
  225. package/src/payments/bip341.ts +2 -4
  226. package/src/payments/embed.ts +18 -18
  227. package/src/payments/p2ms.ts +32 -25
  228. package/src/payments/p2op.ts +22 -22
  229. package/src/payments/p2pk.ts +20 -20
  230. package/src/payments/p2pkh.ts +25 -25
  231. package/src/payments/p2sh.ts +30 -27
  232. package/src/payments/p2tr.ts +31 -31
  233. package/src/payments/p2wpkh.ts +25 -25
  234. package/src/payments/p2wsh.ts +27 -27
  235. package/src/payments/types.ts +1 -1
  236. package/src/psbt/PsbtCache.ts +325 -0
  237. package/src/psbt/PsbtFinalizer.ts +213 -0
  238. package/src/psbt/PsbtSigner.ts +302 -0
  239. package/src/psbt/PsbtTransaction.ts +82 -0
  240. package/src/psbt/bip371.ts +7 -3
  241. package/src/psbt/psbtutils.ts +1 -1
  242. package/src/psbt/types.ts +14 -21
  243. package/src/psbt/validation.ts +5 -12
  244. package/src/psbt.ts +363 -1130
  245. package/src/script.ts +6 -9
  246. package/src/transaction.ts +18 -14
  247. package/src/types.ts +28 -17
  248. package/src/workers/WorkerSigningPool.node.ts +31 -31
  249. package/src/workers/WorkerSigningPool.ts +35 -39
  250. package/src/workers/index.node.ts +27 -0
  251. package/src/workers/index.ts +7 -9
  252. package/src/workers/psbt-parallel.ts +2 -7
  253. package/src/workers/types.ts +5 -1
  254. package/test/address.spec.ts +2 -2
  255. package/test/bitcoin.core.spec.ts +5 -2
  256. package/test/browser/payments.spec.ts +151 -0
  257. package/test/browser/psbt.spec.ts +1510 -0
  258. package/test/browser/script.spec.ts +223 -0
  259. package/test/browser/setup.ts +13 -0
  260. package/test/browser/workers-signing.spec.ts +537 -0
  261. package/test/crypto.spec.ts +2 -2
  262. package/test/fixtures/core/base58_encode_decode.json +12 -48
  263. package/test/fixtures/core/base58_keys_invalid.json +50 -150
  264. package/test/fixtures/core/sighash.json +1 -3
  265. package/test/fixtures/core/tx_valid.json +133 -501
  266. package/test/fixtures/embed.json +3 -11
  267. package/test/fixtures/p2ms.json +21 -91
  268. package/test/fixtures/p2pk.json +5 -24
  269. package/test/fixtures/p2pkh.json +7 -36
  270. package/test/fixtures/p2sh.json +8 -54
  271. package/test/fixtures/p2tr.json +2 -6
  272. package/test/fixtures/p2wpkh.json +7 -36
  273. package/test/fixtures/p2wsh.json +14 -59
  274. package/test/fixtures/psbt.json +2 -6
  275. package/test/fixtures/script.json +12 -48
  276. package/test/integration/addresses.spec.ts +11 -5
  277. package/test/integration/bip32.spec.ts +1 -1
  278. package/test/integration/cltv.spec.ts +10 -6
  279. package/test/integration/csv.spec.ts +10 -9
  280. package/test/integration/payments.spec.ts +8 -4
  281. package/test/integration/taproot.spec.ts +26 -6
  282. package/test/integration/transactions.spec.ts +22 -8
  283. package/test/payments.spec.ts +1 -1
  284. package/test/payments.utils.ts +1 -1
  285. package/test/psbt.spec.ts +250 -64
  286. package/test/script_signature.spec.ts +1 -1
  287. package/test/transaction.spec.ts +18 -5
  288. package/test/tsconfig.json +6 -20
  289. package/test/workers-pool.spec.ts +22 -23
  290. package/test/workers-signing.spec.ts +7 -3
  291. package/test/workers.spec.ts +6 -7
  292. package/typedoc.json +39 -0
  293. package/vitest.config.browser.ts +68 -0
  294. package/browser/ecpair.d.ts +0 -99
  295. package/src/ecpair.d.ts +0 -99
  296. package/test/taproot-cache.spec.ts +0 -694
@@ -13,25 +13,25 @@ import { getEccLib } from '../ecc/context.js';
13
13
  import { bitcoin as BITCOIN_NETWORK, type Network } from '../networks.js';
14
14
  import * as bscript from '../script.js';
15
15
  import {
16
- stacksEqual,
17
- TAPLEAF_VERSION_MASK,
18
16
  type Bytes32,
19
- type Script,
20
17
  type SchnorrSignature,
18
+ type Script,
19
+ stacksEqual,
20
+ TAPLEAF_VERSION_MASK,
21
21
  type Taptree,
22
22
  type XOnlyPublicKey,
23
23
  } from '../types.js';
24
24
  import {
25
25
  findScriptPath,
26
+ type HashTree,
26
27
  LEAF_VERSION_TAPSCRIPT,
27
28
  rootHashFromPath,
28
29
  tapleafHash,
29
30
  toHashTree,
30
31
  tweakKey,
31
- type HashTree,
32
32
  } from './bip341.js';
33
33
  import { concat, equals } from '../io/index.js';
34
- import { PaymentType, type P2TRPayment, type PaymentOpts, type ScriptRedeem } from './types.js';
34
+ import { type P2TRPayment, type PaymentOpts, PaymentType, type ScriptRedeem } from './types.js';
35
35
 
36
36
  const OPS = bscript.opcodes;
37
37
  const TAPROOT_WITNESS_VERSION = 0x01;
@@ -362,6 +362,28 @@ export class P2TR {
362
362
 
363
363
  // Private helper methods
364
364
 
365
+ /**
366
+ * Converts to a plain P2TRPayment object for backwards compatibility.
367
+ *
368
+ * @returns A P2TRPayment object
369
+ */
370
+ toPayment(): P2TRPayment {
371
+ return {
372
+ name: this.name,
373
+ network: this.network,
374
+ address: this.address,
375
+ pubkey: this.pubkey,
376
+ internalPubkey: this.internalPubkey,
377
+ hash: this.hash,
378
+ scriptTree: this.#inputScriptTree,
379
+ signature: this.signature,
380
+ output: this.output,
381
+ redeem: this.redeem,
382
+ redeemVersion: this.redeemVersion,
383
+ witness: this.witness,
384
+ };
385
+ }
386
+
365
387
  #getDecodedAddress(): { version: number; prefix: string; data: Uint8Array } | undefined {
366
388
  if (!this.#decodedAddressComputed) {
367
389
  if (this.#inputAddress) {
@@ -397,6 +419,8 @@ export class P2TR {
397
419
  return this.#witnessWithoutAnnex;
398
420
  }
399
421
 
422
+ // Private computation methods
423
+
400
424
  #getHashTree(): HashTree | undefined {
401
425
  if (!this.#hashTreeComputed) {
402
426
  if (this.#inputScriptTree) {
@@ -409,8 +433,6 @@ export class P2TR {
409
433
  return this.#hashTree;
410
434
  }
411
435
 
412
- // Private computation methods
413
-
414
436
  #computeAddress(): string | undefined {
415
437
  if (this.#inputAddress) {
416
438
  return this.#inputAddress;
@@ -525,6 +547,8 @@ export class P2TR {
525
547
  return LEAF_VERSION_TAPSCRIPT;
526
548
  }
527
549
 
550
+ // Validation
551
+
528
552
  #computeWitness(): Uint8Array[] | undefined {
529
553
  if (this.#inputWitness) {
530
554
  return this.#inputWitness;
@@ -558,8 +582,6 @@ export class P2TR {
558
582
  return undefined;
559
583
  }
560
584
 
561
- // Validation
562
-
563
585
  #validate(): void {
564
586
  let pubkey: Uint8Array = new Uint8Array(0);
565
587
 
@@ -722,28 +744,6 @@ export class P2TR {
722
744
  }
723
745
  }
724
746
  }
725
-
726
- /**
727
- * Converts to a plain P2TRPayment object for backwards compatibility.
728
- *
729
- * @returns A P2TRPayment object
730
- */
731
- toPayment(): P2TRPayment {
732
- return {
733
- name: this.name,
734
- network: this.network,
735
- address: this.address,
736
- pubkey: this.pubkey,
737
- internalPubkey: this.internalPubkey,
738
- hash: this.hash,
739
- scriptTree: this.#inputScriptTree,
740
- signature: this.signature,
741
- output: this.output,
742
- redeem: this.redeem,
743
- redeemVersion: this.redeemVersion,
744
- witness: this.witness,
745
- };
746
- }
747
747
  }
748
748
 
749
749
  /**
@@ -12,10 +12,10 @@ import { bech32 } from 'bech32';
12
12
  import * as bcrypto from '../crypto.js';
13
13
  import { bitcoin as BITCOIN_NETWORK, type Network } from '../networks.js';
14
14
  import * as bscript from '../script.js';
15
- import { isPoint } from '../types.js';
16
15
  import type { Bytes20, PublicKey, Script, Signature } from '../types.js';
16
+ import { isPoint } from '../types.js';
17
17
  import { equals } from '../io/index.js';
18
- import { PaymentType, type P2WPKHPayment, type PaymentOpts } from './types.js';
18
+ import { type P2WPKHPayment, type PaymentOpts, PaymentType } from './types.js';
19
19
 
20
20
  const OPS = bscript.opcodes;
21
21
  const EMPTY_BUFFER = new Uint8Array(0);
@@ -279,6 +279,27 @@ export class P2WPKH {
279
279
 
280
280
  // Private helper methods
281
281
 
282
+ /**
283
+ * Converts to a plain P2WPKHPayment object for backwards compatibility.
284
+ *
285
+ * @returns A P2WPKHPayment object
286
+ */
287
+ toPayment(): P2WPKHPayment {
288
+ return {
289
+ name: this.name,
290
+ network: this.network,
291
+ address: this.address,
292
+ hash: this.hash,
293
+ pubkey: this.pubkey,
294
+ signature: this.signature,
295
+ output: this.output,
296
+ input: this.input,
297
+ witness: this.witness,
298
+ };
299
+ }
300
+
301
+ // Private computation methods
302
+
282
303
  #getDecodedAddress(): { version: number; prefix: string; data: Uint8Array } | undefined {
283
304
  if (!this.#decodedAddressComputed) {
284
305
  if (this.#inputAddress) {
@@ -296,8 +317,6 @@ export class P2WPKH {
296
317
  return this.#decodedAddress;
297
318
  }
298
319
 
299
- // Private computation methods
300
-
301
320
  #computeAddress(): string | undefined {
302
321
  if (this.#inputAddress) {
303
322
  return this.#inputAddress;
@@ -364,6 +383,8 @@ export class P2WPKH {
364
383
  return undefined;
365
384
  }
366
385
 
386
+ // Validation
387
+
367
388
  #computeWitness(): Uint8Array[] | undefined {
368
389
  if (this.#inputWitness) {
369
390
  return this.#inputWitness;
@@ -374,8 +395,6 @@ export class P2WPKH {
374
395
  return [this.#inputSignature, this.#inputPubkey];
375
396
  }
376
397
 
377
- // Validation
378
-
379
398
  #validate(): void {
380
399
  let hash: Uint8Array = new Uint8Array(0);
381
400
 
@@ -455,25 +474,6 @@ export class P2WPKH {
455
474
  }
456
475
  }
457
476
  }
458
-
459
- /**
460
- * Converts to a plain P2WPKHPayment object for backwards compatibility.
461
- *
462
- * @returns A P2WPKHPayment object
463
- */
464
- toPayment(): P2WPKHPayment {
465
- return {
466
- name: this.name,
467
- network: this.network,
468
- address: this.address,
469
- hash: this.hash,
470
- pubkey: this.pubkey,
471
- signature: this.signature,
472
- output: this.output,
473
- input: this.input,
474
- witness: this.witness,
475
- };
476
- }
477
477
  }
478
478
 
479
479
  /**
@@ -12,10 +12,10 @@ import { bech32 } from 'bech32';
12
12
  import * as bcrypto from '../crypto.js';
13
13
  import { bitcoin as BITCOIN_NETWORK, type Network } from '../networks.js';
14
14
  import * as bscript from '../script.js';
15
- import { isPoint, stacksEqual, type StackElement } from '../types.js';
16
15
  import type { Bytes32, Script } from '../types.js';
16
+ import { isPoint, type StackElement, stacksEqual } from '../types.js';
17
17
  import { equals } from '../io/index.js';
18
- import { PaymentType, type P2WSHPayment, type PaymentOpts, type ScriptRedeem } from './types.js';
18
+ import { type P2WSHPayment, type PaymentOpts, PaymentType, type ScriptRedeem } from './types.js';
19
19
 
20
20
  const OPS = bscript.opcodes;
21
21
  const EMPTY_BUFFER = new Uint8Array(0);
@@ -278,6 +278,27 @@ export class P2WSH {
278
278
 
279
279
  // Private helper methods
280
280
 
281
+ /**
282
+ * Converts to a plain P2WSHPayment object for backwards compatibility.
283
+ *
284
+ * @returns A P2WSHPayment object
285
+ */
286
+ toPayment(): P2WSHPayment {
287
+ // Access witness first as it may modify redeem (transform input to witness)
288
+ const witness = this.witness;
289
+ const redeem = this.redeem;
290
+ return {
291
+ name: this.name,
292
+ network: this.network,
293
+ address: this.address,
294
+ hash: this.hash,
295
+ output: this.output,
296
+ input: this.input,
297
+ redeem,
298
+ witness,
299
+ };
300
+ }
301
+
281
302
  #getDecodedAddress(): { version: number; prefix: string; data: Uint8Array } | undefined {
282
303
  if (!this.#decodedAddressComputed) {
283
304
  if (this.#inputAddress) {
@@ -295,6 +316,8 @@ export class P2WSH {
295
316
  return this.#decodedAddress;
296
317
  }
297
318
 
319
+ // Private computation methods
320
+
298
321
  #getRedeemChunks(): (Uint8Array | number)[] | undefined {
299
322
  if (!this.#redeemChunksComputed) {
300
323
  if (this.#inputRedeem?.input) {
@@ -305,8 +328,6 @@ export class P2WSH {
305
328
  return this.#redeemChunks;
306
329
  }
307
330
 
308
- // Private computation methods
309
-
310
331
  #computeAddress(): string | undefined {
311
332
  if (this.#inputAddress) {
312
333
  return this.#inputAddress;
@@ -367,6 +388,8 @@ export class P2WSH {
367
388
  return undefined;
368
389
  }
369
390
 
391
+ // Validation
392
+
370
393
  #computeWitness(): Uint8Array[] | undefined {
371
394
  if (this.#inputWitness) {
372
395
  return this.#inputWitness;
@@ -394,8 +417,6 @@ export class P2WSH {
394
417
  return undefined;
395
418
  }
396
419
 
397
- // Validation
398
-
399
420
  #validate(): void {
400
421
  let hash: Uint8Array = new Uint8Array(0);
401
422
 
@@ -518,27 +539,6 @@ export class P2WSH {
518
539
  }
519
540
  }
520
541
  }
521
-
522
- /**
523
- * Converts to a plain P2WSHPayment object for backwards compatibility.
524
- *
525
- * @returns A P2WSHPayment object
526
- */
527
- toPayment(): P2WSHPayment {
528
- // Access witness first as it may modify redeem (transform input to witness)
529
- const witness = this.witness;
530
- const redeem = this.redeem;
531
- return {
532
- name: this.name,
533
- network: this.network,
534
- address: this.address,
535
- hash: this.hash,
536
- output: this.output,
537
- input: this.input,
538
- redeem,
539
- witness,
540
- };
541
- }
542
542
  }
543
543
 
544
544
  /**
@@ -8,9 +8,9 @@ import type {
8
8
  Bytes20,
9
9
  Bytes32,
10
10
  PublicKey,
11
+ SchnorrSignature,
11
12
  Script,
12
13
  Signature,
13
- SchnorrSignature,
14
14
  Taptree,
15
15
  XOnlyPublicKey,
16
16
  } from '../types.js';
@@ -0,0 +1,325 @@
1
+ import type { PsbtInput, PsbtOutput } from 'bip174';
2
+ import * as bscript from '../script.js';
3
+ import type { TaprootHashCache, Transaction } from '../transaction.js';
4
+ import type { PublicKey, Satoshi, Script, XOnlyPublicKey } from '../types.js';
5
+ import { isP2TR, isP2WPKH, pubkeyInScript } from './psbtutils.js';
6
+ import { getMeaningfulScript, isPubkeyLike, isSigLike, scriptWitnessToWitnessStack, } from './utils.js';
7
+ import type { GetScriptReturn, PrevOut, PsbtOpts } from './types.js';
8
+ import { isFinalized } from './validation.js';
9
+ import { isUnknownSegwitVersion } from '../address.js';
10
+
11
+ /**
12
+ * Internal PSBT cache for computed values.
13
+ * Wraps all cache management previously handled by a plain interface + scattered helper functions.
14
+ */
15
+ export class PsbtCache {
16
+ public readonly nonWitnessUtxoTxCache: Transaction[];
17
+ public readonly nonWitnessUtxoBufCache: Uint8Array[];
18
+ public readonly txInCache: Record<string, number>;
19
+ public readonly tx: Transaction;
20
+ public unsafeSignNonSegwit: boolean;
21
+ public hasSignatures: boolean;
22
+ public fee: number | undefined;
23
+ public feeRate: number | undefined;
24
+ public extractedTx: Transaction | undefined;
25
+ public prevOuts: readonly PrevOut[] | undefined;
26
+ public signingScripts: readonly Script[] | undefined;
27
+ public values: readonly Satoshi[] | undefined;
28
+ public taprootHashCache: TaprootHashCache | undefined;
29
+
30
+ public constructor(tx: Transaction) {
31
+ this.nonWitnessUtxoTxCache = [];
32
+ this.nonWitnessUtxoBufCache = [];
33
+ this.txInCache = {};
34
+ this.tx = tx;
35
+ this.unsafeSignNonSegwit = false;
36
+ this.hasSignatures = false;
37
+ }
38
+
39
+ /**
40
+ * Invalidates cached computed values.
41
+ * @param scope - 'full' clears everything (for input changes), 'outputs' clears fee/extract/taproot caches
42
+ */
43
+ public invalidate(scope: 'full' | 'outputs'): void {
44
+ this.fee = undefined;
45
+ this.feeRate = undefined;
46
+ this.extractedTx = undefined;
47
+ this.taprootHashCache = undefined;
48
+ if (scope === 'full') {
49
+ this.prevOuts = undefined;
50
+ this.signingScripts = undefined;
51
+ this.values = undefined;
52
+ }
53
+ }
54
+
55
+ public addNonWitnessTxCache(
56
+ input: PsbtInput,
57
+ inputIndex: number,
58
+ txFromBuffer: (buf: Uint8Array) => Transaction,
59
+ ): void {
60
+ if (!input.nonWitnessUtxo) throw new Error('nonWitnessUtxo is required');
61
+ if (input === null || input === Object.prototype) {
62
+ throw new Error('Invalid input object');
63
+ }
64
+ const nonWitnessUtxoBuf = input.nonWitnessUtxo;
65
+ this.nonWitnessUtxoBufCache[inputIndex] = nonWitnessUtxoBuf;
66
+ this.nonWitnessUtxoTxCache[inputIndex] = txFromBuffer(nonWitnessUtxoBuf);
67
+ }
68
+
69
+ public getNonWitnessUtxoTx(
70
+ input: PsbtInput,
71
+ inputIndex: number,
72
+ txFromBuffer: (buf: Uint8Array) => Transaction,
73
+ ): Transaction {
74
+ const cached = this.nonWitnessUtxoTxCache[inputIndex];
75
+ if (!cached) {
76
+ this.addNonWitnessTxCache(input, inputIndex, txFromBuffer);
77
+ }
78
+ return this.nonWitnessUtxoTxCache[inputIndex]!;
79
+ }
80
+
81
+ public getScriptFromUtxo(
82
+ inputIndex: number,
83
+ input: PsbtInput,
84
+ txFromBuffer: (buf: Uint8Array) => Transaction,
85
+ ): Script {
86
+ const { script } = this.getScriptAndAmountFromUtxo(inputIndex, input, txFromBuffer);
87
+ return script;
88
+ }
89
+
90
+ public getScriptAndAmountFromUtxo(
91
+ inputIndex: number,
92
+ input: PsbtInput,
93
+ txFromBuffer: (buf: Uint8Array) => Transaction,
94
+ ): { script: Script; value: Satoshi } {
95
+ if (input.witnessUtxo !== undefined) {
96
+ return {
97
+ script: input.witnessUtxo.script as Script,
98
+ value: input.witnessUtxo.value as Satoshi,
99
+ };
100
+ } else if (input.nonWitnessUtxo !== undefined) {
101
+ const nonWitnessUtxoTx = this.getNonWitnessUtxoTx(input, inputIndex, txFromBuffer);
102
+ const o = nonWitnessUtxoTx.outs[this.tx.ins[inputIndex]!.index]!;
103
+ return { script: o.script, value: o.value };
104
+ } else {
105
+ throw new Error("Can't find pubkey in input without Utxo data");
106
+ }
107
+ }
108
+
109
+ public computeFee(
110
+ inputs: PsbtInput[],
111
+ disableOutputChecks: boolean = false,
112
+ txFromBuffer?: (buf: Uint8Array) => Transaction,
113
+ ): number {
114
+ if (!inputs.every(isFinalized)) throw new Error('PSBT must be finalized to calculate fee');
115
+ if (this.fee !== undefined) return this.fee;
116
+ let tx: Transaction;
117
+ let mustFinalize = true;
118
+ if (this.extractedTx) {
119
+ tx = this.extractedTx;
120
+ mustFinalize = false;
121
+ } else {
122
+ tx = this.tx.clone();
123
+ }
124
+ const { fee } = this.finalizeAndComputeAmounts(
125
+ inputs,
126
+ tx,
127
+ mustFinalize,
128
+ disableOutputChecks,
129
+ txFromBuffer,
130
+ );
131
+ return fee;
132
+ }
133
+
134
+ public computeFeeRate(
135
+ inputs: PsbtInput[],
136
+ disableOutputChecks: boolean = false,
137
+ txFromBuffer?: (buf: Uint8Array) => Transaction,
138
+ ): number {
139
+ if (!inputs.every(isFinalized))
140
+ throw new Error('PSBT must be finalized to calculate fee rate');
141
+ if (this.feeRate !== undefined) return this.feeRate;
142
+ let tx: Transaction;
143
+ let mustFinalize = true;
144
+ if (this.extractedTx) {
145
+ tx = this.extractedTx;
146
+ mustFinalize = false;
147
+ } else {
148
+ tx = this.tx.clone();
149
+ }
150
+ const { feeRate } = this.finalizeAndComputeAmounts(
151
+ inputs,
152
+ tx,
153
+ mustFinalize,
154
+ disableOutputChecks,
155
+ txFromBuffer,
156
+ );
157
+ return feeRate;
158
+ }
159
+
160
+ public checkFees(opts: PsbtOpts): void {
161
+ const feeRate = this.feeRate;
162
+ if (!this.extractedTx) throw new Error('Transaction not extracted');
163
+ if (feeRate === undefined) throw new Error('Fee rate not computed');
164
+ const vsize = this.extractedTx.virtualSize();
165
+ const satoshis = feeRate * vsize;
166
+ if (feeRate >= opts.maximumFeeRate) {
167
+ throw new Error(
168
+ `Warning: You are paying around ${(satoshis / 1e8).toFixed(8)} in ` +
169
+ `fees, which is ${feeRate} satoshi per byte for a transaction ` +
170
+ `with a VSize of ${vsize} bytes (segwit counted as 0.25 byte per ` +
171
+ `byte). Use setMaximumFeeRate method to raise your threshold, or ` +
172
+ `pass true to the first arg of extractTransaction.`,
173
+ );
174
+ }
175
+ }
176
+
177
+ public pubkeyInInput(
178
+ pubkey: PublicKey,
179
+ input: PsbtInput,
180
+ inputIndex: number,
181
+ txFromBuffer: (buf: Uint8Array) => Transaction,
182
+ ): boolean {
183
+ const script = this.getScriptFromUtxo(inputIndex, input, txFromBuffer);
184
+ const { meaningfulScript } = getMeaningfulScript(
185
+ script,
186
+ inputIndex,
187
+ 'input',
188
+ input.redeemScript,
189
+ input.witnessScript,
190
+ );
191
+ return pubkeyInScript(pubkey, meaningfulScript);
192
+ }
193
+
194
+ public pubkeyInOutput(pubkey: PublicKey, output: PsbtOutput, outputIndex: number): boolean {
195
+ const script = this.tx.outs[outputIndex]!.script;
196
+ const { meaningfulScript } = getMeaningfulScript(
197
+ script,
198
+ outputIndex,
199
+ 'output',
200
+ output.redeemScript,
201
+ output.witnessScript,
202
+ );
203
+ return pubkeyInScript(pubkey, meaningfulScript);
204
+ }
205
+
206
+ public redeemFromFinalScriptSig(finalScript: Uint8Array | undefined): Uint8Array | undefined {
207
+ if (!finalScript) return;
208
+ const decomp = bscript.decompile(finalScript);
209
+ if (!decomp) return;
210
+ const lastItem = decomp[decomp.length - 1]!;
211
+ if (!(lastItem instanceof Uint8Array) || isPubkeyLike(lastItem) || isSigLike(lastItem))
212
+ return;
213
+ const sDecomp = bscript.decompile(lastItem);
214
+ if (!sDecomp) return;
215
+ return lastItem;
216
+ }
217
+
218
+ public redeemFromFinalWitnessScript(
219
+ finalScript: Uint8Array | undefined,
220
+ ): Uint8Array | undefined {
221
+ if (!finalScript) return;
222
+ const decomp = scriptWitnessToWitnessStack(finalScript);
223
+ const lastItem = decomp[decomp.length - 1]!;
224
+ if (isPubkeyLike(lastItem)) return;
225
+ const sDecomp = bscript.decompile(lastItem);
226
+ if (!sDecomp) return;
227
+ return lastItem;
228
+ }
229
+
230
+ /**
231
+ * Finalize transaction inputs and compute fee amounts.
232
+ * Returns computed values instead of mutating cache parameters directly.
233
+ */
234
+ public finalizeAndComputeAmounts(
235
+ inputs: PsbtInput[],
236
+ tx: Transaction,
237
+ mustFinalize: boolean,
238
+ disableOutputChecks?: boolean,
239
+ txFromBuffer?: (buf: Uint8Array) => Transaction,
240
+ ): { fee: number; feeRate: number } {
241
+ let inputAmount = 0n;
242
+ inputs.forEach((input, idx) => {
243
+ if (mustFinalize && input.finalScriptSig)
244
+ tx.ins[idx]!.script = input.finalScriptSig as Script;
245
+ if (mustFinalize && input.finalScriptWitness) {
246
+ tx.ins[idx]!.witness = scriptWitnessToWitnessStack(input.finalScriptWitness);
247
+ }
248
+ if (input.witnessUtxo) {
249
+ inputAmount += input.witnessUtxo.value;
250
+ } else if (input.nonWitnessUtxo) {
251
+ if (!txFromBuffer)
252
+ throw new Error('txFromBuffer is required for nonWitnessUtxo inputs');
253
+ const nwTx = this.getNonWitnessUtxoTx(input, idx, txFromBuffer);
254
+ const vout = tx.ins[idx]!.index;
255
+ const out = nwTx.outs[vout]!;
256
+ inputAmount += out.value;
257
+ }
258
+ });
259
+ const outputAmount = tx.outs.reduce((total, o) => total + o.value, 0n);
260
+ const feeValue = inputAmount - outputAmount;
261
+ if (!disableOutputChecks) {
262
+ if (feeValue < 0n) {
263
+ throw new Error(
264
+ `Outputs are spending more than Inputs ${inputAmount} < ${outputAmount}`,
265
+ );
266
+ }
267
+ }
268
+ const bytes = tx.virtualSize();
269
+ const fee = Number(feeValue);
270
+ const feeRate = Math.floor(fee / bytes);
271
+
272
+ this.fee = fee;
273
+ this.extractedTx = tx;
274
+ this.feeRate = feeRate;
275
+
276
+ return { fee, feeRate };
277
+ }
278
+
279
+ public getScriptFromInput(
280
+ inputIndex: number,
281
+ input: PsbtInput,
282
+ txFromBuffer: (buf: Uint8Array) => Transaction,
283
+ ): GetScriptReturn {
284
+ const res: GetScriptReturn = {
285
+ script: null,
286
+ isSegwit: false,
287
+ isP2SH: false,
288
+ isP2WSH: false,
289
+ };
290
+ res.isP2SH = !!input.redeemScript;
291
+ res.isP2WSH = !!input.witnessScript;
292
+ if (input.witnessScript) {
293
+ res.script = input.witnessScript as Script;
294
+ } else if (input.redeemScript) {
295
+ res.script = input.redeemScript as Script;
296
+ } else {
297
+ if (input.nonWitnessUtxo) {
298
+ const nonWitnessUtxoTx = this.getNonWitnessUtxoTx(input, inputIndex, txFromBuffer);
299
+ const prevoutIndex = this.tx.ins[inputIndex]!.index;
300
+ res.script = nonWitnessUtxoTx.outs[prevoutIndex]!.script;
301
+ } else if (input.witnessUtxo) {
302
+ res.script = input.witnessUtxo.script as Script;
303
+ }
304
+ }
305
+
306
+ if (input.witnessScript || (res.script && isP2WPKH(res.script))) {
307
+ res.isSegwit = true;
308
+ } else {
309
+ if (res.script && isUnknownSegwitVersion(res.script)) {
310
+ res.isSegwit = true;
311
+ }
312
+ }
313
+
314
+ return res;
315
+ }
316
+
317
+ public getPrevoutTaprootKey(
318
+ inputIndex: number,
319
+ input: PsbtInput,
320
+ txFromBuffer: (buf: Uint8Array) => Transaction,
321
+ ): XOnlyPublicKey | null {
322
+ const { script } = this.getScriptAndAmountFromUtxo(inputIndex, input, txFromBuffer);
323
+ return isP2TR(script) ? (script.subarray(2, 34) as XOnlyPublicKey) : null;
324
+ }
325
+ }