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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (456) hide show
  1. package/HOW_TO_WRITE_GOOD_CODE.md +2436 -0
  2. package/benchmark/psbt-2000-inputs.bench.ts +178 -0
  3. package/benchmark/signing.bench.ts +147 -0
  4. package/browser/address.d.ts +57 -10
  5. package/browser/address.d.ts.map +1 -0
  6. package/browser/bech32utils.d.ts +9 -1
  7. package/browser/bech32utils.d.ts.map +1 -0
  8. package/browser/bip66.d.ts +11 -6
  9. package/browser/bip66.d.ts.map +1 -0
  10. package/browser/block.d.ts +117 -11
  11. package/browser/block.d.ts.map +1 -0
  12. package/browser/branded.d.ts +20 -0
  13. package/browser/branded.d.ts.map +1 -0
  14. package/browser/crypto/crypto.d.ts +1 -0
  15. package/browser/crypto/crypto.d.ts.map +1 -0
  16. package/browser/crypto.d.ts +46 -7
  17. package/browser/crypto.d.ts.map +1 -0
  18. package/browser/ecc/context.d.ts +129 -0
  19. package/browser/ecc/context.d.ts.map +1 -0
  20. package/browser/ecc/index.d.ts +11 -0
  21. package/browser/ecc/index.d.ts.map +1 -0
  22. package/browser/ecc/types.d.ts +128 -0
  23. package/browser/ecc/types.d.ts.map +1 -0
  24. package/browser/ecpair.d.ts +99 -0
  25. package/browser/errors.d.ts +124 -0
  26. package/browser/errors.d.ts.map +1 -0
  27. package/browser/index.d.ts +32 -5
  28. package/browser/index.d.ts.map +1 -0
  29. package/browser/index.js +12477 -101
  30. package/browser/io/BinaryReader.d.ts +276 -0
  31. package/browser/io/BinaryReader.d.ts.map +1 -0
  32. package/browser/io/BinaryWriter.d.ts +391 -0
  33. package/browser/io/BinaryWriter.d.ts.map +1 -0
  34. package/browser/io/MemoryPool.d.ts +220 -0
  35. package/browser/io/MemoryPool.d.ts.map +1 -0
  36. package/browser/io/base64.d.ts +13 -0
  37. package/browser/io/base64.d.ts.map +1 -0
  38. package/browser/io/hex.d.ts +67 -0
  39. package/browser/io/hex.d.ts.map +1 -0
  40. package/browser/io/index.d.ts +17 -0
  41. package/browser/io/index.d.ts.map +1 -0
  42. package/browser/io/utils.d.ts +199 -0
  43. package/browser/io/utils.d.ts.map +1 -0
  44. package/browser/merkle.d.ts +10 -1
  45. package/browser/merkle.d.ts.map +1 -0
  46. package/browser/networks.d.ts +70 -9
  47. package/browser/networks.d.ts.map +1 -0
  48. package/browser/opcodes.d.ts +1 -0
  49. package/browser/opcodes.d.ts.map +1 -0
  50. package/browser/payments/bip341.d.ts +35 -9
  51. package/browser/payments/bip341.d.ts.map +1 -0
  52. package/browser/payments/embed.d.ts +112 -1
  53. package/browser/payments/embed.d.ts.map +1 -0
  54. package/browser/payments/index.d.ts +17 -10
  55. package/browser/payments/index.d.ts.map +1 -0
  56. package/browser/payments/p2ms.d.ts +150 -0
  57. package/browser/payments/p2ms.d.ts.map +1 -0
  58. package/browser/payments/p2op.d.ts +150 -24
  59. package/browser/payments/p2op.d.ts.map +1 -0
  60. package/browser/payments/p2pk.d.ts +154 -1
  61. package/browser/payments/p2pk.d.ts.map +1 -0
  62. package/browser/payments/p2pkh.d.ts +176 -1
  63. package/browser/payments/p2pkh.d.ts.map +1 -0
  64. package/browser/payments/p2sh.d.ts +150 -1
  65. package/browser/payments/p2sh.d.ts.map +1 -0
  66. package/browser/payments/p2tr.d.ts +185 -1
  67. package/browser/payments/p2tr.d.ts.map +1 -0
  68. package/browser/payments/p2wpkh.d.ts +161 -1
  69. package/browser/payments/p2wpkh.d.ts.map +1 -0
  70. package/browser/payments/p2wsh.d.ts +146 -1
  71. package/browser/payments/p2wsh.d.ts.map +1 -0
  72. package/browser/payments/types.d.ts +94 -64
  73. package/browser/payments/types.d.ts.map +1 -0
  74. package/browser/psbt/bip371.d.ts +34 -8
  75. package/browser/psbt/bip371.d.ts.map +1 -0
  76. package/browser/psbt/psbtutils.d.ts +56 -16
  77. package/browser/psbt/psbtutils.d.ts.map +1 -0
  78. package/browser/psbt/types.d.ts +245 -0
  79. package/browser/psbt/types.d.ts.map +1 -0
  80. package/browser/psbt/utils.d.ts +64 -0
  81. package/browser/psbt/utils.d.ts.map +1 -0
  82. package/browser/psbt/validation.d.ts +84 -0
  83. package/browser/psbt/validation.d.ts.map +1 -0
  84. package/browser/psbt.d.ts +82 -118
  85. package/browser/psbt.d.ts.map +1 -0
  86. package/browser/pubkey.d.ts +27 -6
  87. package/browser/pubkey.d.ts.map +1 -0
  88. package/browser/push_data.d.ts +24 -2
  89. package/browser/push_data.d.ts.map +1 -0
  90. package/browser/script.d.ts +33 -8
  91. package/browser/script.d.ts.map +1 -0
  92. package/browser/script_number.d.ts +17 -0
  93. package/browser/script_number.d.ts.map +1 -0
  94. package/browser/script_signature.d.ts +23 -5
  95. package/browser/script_signature.d.ts.map +1 -0
  96. package/browser/transaction.d.ts +160 -18
  97. package/browser/transaction.d.ts.map +1 -0
  98. package/browser/types.d.ts +36 -38
  99. package/browser/types.d.ts.map +1 -0
  100. package/browser/workers/WorkerSigningPool.d.ts +143 -0
  101. package/browser/workers/WorkerSigningPool.d.ts.map +1 -0
  102. package/browser/workers/WorkerSigningPool.node.d.ts +116 -0
  103. package/browser/workers/WorkerSigningPool.node.d.ts.map +1 -0
  104. package/browser/workers/ecc-bundle.d.ts +25 -0
  105. package/browser/workers/ecc-bundle.d.ts.map +1 -0
  106. package/browser/workers/index.d.ts +91 -0
  107. package/browser/workers/index.d.ts.map +1 -0
  108. package/browser/workers/psbt-parallel.d.ts +88 -0
  109. package/browser/workers/psbt-parallel.d.ts.map +1 -0
  110. package/browser/workers/signing-worker.d.ts +37 -0
  111. package/browser/workers/signing-worker.d.ts.map +1 -0
  112. package/browser/workers/types.d.ts +365 -0
  113. package/browser/workers/types.d.ts.map +1 -0
  114. package/build/address.d.ts +58 -11
  115. package/build/address.d.ts.map +1 -0
  116. package/build/address.js +82 -25
  117. package/build/address.js.map +1 -0
  118. package/build/bech32utils.d.ts +9 -1
  119. package/build/bech32utils.d.ts.map +1 -0
  120. package/build/bech32utils.js +10 -2
  121. package/build/bech32utils.js.map +1 -0
  122. package/build/bip66.d.ts +11 -6
  123. package/build/bip66.d.ts.map +1 -0
  124. package/build/bip66.js +32 -3
  125. package/build/bip66.js.map +1 -0
  126. package/build/block.d.ts +117 -11
  127. package/build/block.d.ts.map +1 -0
  128. package/build/block.js +202 -72
  129. package/build/block.js.map +1 -0
  130. package/build/branded.d.ts +20 -0
  131. package/build/branded.d.ts.map +1 -0
  132. package/build/branded.js +7 -0
  133. package/build/branded.js.map +1 -0
  134. package/build/crypto/crypto.d.ts +1 -0
  135. package/build/crypto/crypto.d.ts.map +1 -0
  136. package/build/crypto/crypto.js +1 -0
  137. package/build/crypto/crypto.js.map +1 -0
  138. package/build/crypto.d.ts +46 -7
  139. package/build/crypto.d.ts.map +1 -0
  140. package/build/crypto.js +65 -20
  141. package/build/crypto.js.map +1 -0
  142. package/build/ecc/context.d.ts +135 -0
  143. package/build/ecc/context.d.ts.map +1 -0
  144. package/build/ecc/context.js +232 -0
  145. package/build/ecc/context.js.map +1 -0
  146. package/build/ecc/index.d.ts +11 -0
  147. package/build/ecc/index.d.ts.map +1 -0
  148. package/build/ecc/index.js +11 -0
  149. package/build/ecc/index.js.map +1 -0
  150. package/build/ecc/types.d.ts +134 -0
  151. package/build/ecc/types.d.ts.map +1 -0
  152. package/build/ecc/types.js +8 -0
  153. package/build/ecc/types.js.map +1 -0
  154. package/build/errors.d.ts +124 -0
  155. package/build/errors.d.ts.map +1 -0
  156. package/build/errors.js +155 -0
  157. package/build/errors.js.map +1 -0
  158. package/build/index.d.ts +32 -5
  159. package/build/index.d.ts.map +1 -0
  160. package/build/index.js +26 -3
  161. package/build/index.js.map +1 -0
  162. package/build/io/BinaryReader.d.ts +276 -0
  163. package/build/io/BinaryReader.d.ts.map +1 -0
  164. package/build/io/BinaryReader.js +425 -0
  165. package/build/io/BinaryReader.js.map +1 -0
  166. package/build/io/BinaryWriter.d.ts +391 -0
  167. package/build/io/BinaryWriter.d.ts.map +1 -0
  168. package/build/io/BinaryWriter.js +611 -0
  169. package/build/io/BinaryWriter.js.map +1 -0
  170. package/build/io/MemoryPool.d.ts +220 -0
  171. package/build/io/MemoryPool.d.ts.map +1 -0
  172. package/build/io/MemoryPool.js +309 -0
  173. package/build/io/MemoryPool.js.map +1 -0
  174. package/build/io/base64.d.ts +13 -0
  175. package/build/io/base64.d.ts.map +1 -0
  176. package/build/io/base64.js +20 -0
  177. package/build/io/base64.js.map +1 -0
  178. package/build/io/hex.d.ts +67 -0
  179. package/build/io/hex.d.ts.map +1 -0
  180. package/build/io/hex.js +138 -0
  181. package/build/io/hex.js.map +1 -0
  182. package/build/io/index.d.ts +17 -0
  183. package/build/io/index.d.ts.map +1 -0
  184. package/build/io/index.js +23 -0
  185. package/build/io/index.js.map +1 -0
  186. package/build/io/utils.d.ts +199 -0
  187. package/build/io/utils.d.ts.map +1 -0
  188. package/build/io/utils.js +271 -0
  189. package/build/io/utils.js.map +1 -0
  190. package/build/merkle.d.ts +10 -1
  191. package/build/merkle.d.ts.map +1 -0
  192. package/build/merkle.js +12 -1
  193. package/build/merkle.js.map +1 -0
  194. package/build/networks.d.ts +70 -9
  195. package/build/networks.d.ts.map +1 -0
  196. package/build/networks.js +90 -4
  197. package/build/networks.js.map +1 -0
  198. package/build/opcodes.d.ts +1 -0
  199. package/build/opcodes.d.ts.map +1 -0
  200. package/build/opcodes.js +1 -0
  201. package/build/opcodes.js.map +1 -0
  202. package/build/payments/bip341.d.ts +35 -9
  203. package/build/payments/bip341.d.ts.map +1 -0
  204. package/build/payments/bip341.js +34 -15
  205. package/build/payments/bip341.js.map +1 -0
  206. package/build/payments/embed.d.ts +120 -1
  207. package/build/payments/embed.d.ts.map +1 -0
  208. package/build/payments/embed.js +215 -34
  209. package/build/payments/embed.js.map +1 -0
  210. package/build/payments/index.d.ts +17 -10
  211. package/build/payments/index.d.ts.map +1 -0
  212. package/build/payments/index.js +20 -10
  213. package/build/payments/index.js.map +1 -0
  214. package/build/payments/p2ms.d.ts +159 -1
  215. package/build/payments/p2ms.d.ts.map +1 -0
  216. package/build/payments/p2ms.js +427 -108
  217. package/build/payments/p2ms.js.map +1 -0
  218. package/build/payments/p2op.d.ts +158 -24
  219. package/build/payments/p2op.d.ts.map +1 -0
  220. package/build/payments/p2op.js +379 -93
  221. package/build/payments/p2op.js.map +1 -0
  222. package/build/payments/p2pk.d.ts +162 -1
  223. package/build/payments/p2pk.d.ts.map +1 -0
  224. package/build/payments/p2pk.js +327 -58
  225. package/build/payments/p2pk.js.map +1 -0
  226. package/build/payments/p2pkh.d.ts +185 -1
  227. package/build/payments/p2pkh.d.ts.map +1 -0
  228. package/build/payments/p2pkh.js +467 -114
  229. package/build/payments/p2pkh.js.map +1 -0
  230. package/build/payments/p2sh.d.ts +159 -1
  231. package/build/payments/p2sh.d.ts.map +1 -0
  232. package/build/payments/p2sh.js +500 -150
  233. package/build/payments/p2sh.js.map +1 -0
  234. package/build/payments/p2tr.d.ts +193 -1
  235. package/build/payments/p2tr.d.ts.map +1 -0
  236. package/build/payments/p2tr.js +592 -174
  237. package/build/payments/p2tr.js.map +1 -0
  238. package/build/payments/p2wpkh.d.ts +170 -1
  239. package/build/payments/p2wpkh.d.ts.map +1 -0
  240. package/build/payments/p2wpkh.js +428 -103
  241. package/build/payments/p2wpkh.js.map +1 -0
  242. package/build/payments/p2wsh.d.ts +155 -1
  243. package/build/payments/p2wsh.d.ts.map +1 -0
  244. package/build/payments/p2wsh.js +465 -143
  245. package/build/payments/p2wsh.js.map +1 -0
  246. package/build/payments/types.d.ts +98 -64
  247. package/build/payments/types.d.ts.map +1 -0
  248. package/build/payments/types.js +17 -13
  249. package/build/payments/types.js.map +1 -0
  250. package/build/psbt/bip371.d.ts +35 -9
  251. package/build/psbt/bip371.d.ts.map +1 -0
  252. package/build/psbt/bip371.js +117 -28
  253. package/build/psbt/bip371.js.map +1 -0
  254. package/build/psbt/psbtutils.d.ts +56 -16
  255. package/build/psbt/psbtutils.d.ts.map +1 -0
  256. package/build/psbt/psbtutils.js +71 -16
  257. package/build/psbt/psbtutils.js.map +1 -0
  258. package/build/psbt/types.d.ts +249 -0
  259. package/build/psbt/types.d.ts.map +1 -0
  260. package/build/psbt/types.js +6 -0
  261. package/build/psbt/types.js.map +1 -0
  262. package/build/psbt/utils.d.ts +68 -0
  263. package/build/psbt/utils.d.ts.map +1 -0
  264. package/build/psbt/utils.js +171 -0
  265. package/build/psbt/utils.js.map +1 -0
  266. package/build/psbt/validation.d.ts +88 -0
  267. package/build/psbt/validation.d.ts.map +1 -0
  268. package/build/psbt/validation.js +149 -0
  269. package/build/psbt/validation.js.map +1 -0
  270. package/build/psbt.d.ts +84 -120
  271. package/build/psbt.d.ts.map +1 -0
  272. package/build/psbt.js +406 -413
  273. package/build/psbt.js.map +1 -0
  274. package/build/pubkey.d.ts +27 -6
  275. package/build/pubkey.d.ts.map +1 -0
  276. package/build/pubkey.js +36 -12
  277. package/build/pubkey.js.map +1 -0
  278. package/build/push_data.d.ts +24 -2
  279. package/build/push_data.d.ts.map +1 -0
  280. package/build/push_data.js +44 -12
  281. package/build/push_data.js.map +1 -0
  282. package/build/script.d.ts +33 -8
  283. package/build/script.d.ts.map +1 -0
  284. package/build/script.js +101 -37
  285. package/build/script.js.map +1 -0
  286. package/build/script_number.d.ts +17 -0
  287. package/build/script_number.d.ts.map +1 -0
  288. package/build/script_number.js +19 -0
  289. package/build/script_number.js.map +1 -0
  290. package/build/script_signature.d.ts +23 -5
  291. package/build/script_signature.d.ts.map +1 -0
  292. package/build/script_signature.js +48 -15
  293. package/build/script_signature.js.map +1 -0
  294. package/build/transaction.d.ts +160 -18
  295. package/build/transaction.d.ts.map +1 -0
  296. package/build/transaction.js +443 -176
  297. package/build/transaction.js.map +1 -0
  298. package/build/tsconfig.build.tsbuildinfo +1 -0
  299. package/build/types.d.ts +36 -38
  300. package/build/types.d.ts.map +1 -0
  301. package/build/types.js +169 -57
  302. package/build/types.js.map +1 -0
  303. package/build/workers/WorkerSigningPool.d.ts +174 -0
  304. package/build/workers/WorkerSigningPool.d.ts.map +1 -0
  305. package/build/workers/WorkerSigningPool.js +553 -0
  306. package/build/workers/WorkerSigningPool.js.map +1 -0
  307. package/build/workers/WorkerSigningPool.node.d.ts +124 -0
  308. package/build/workers/WorkerSigningPool.node.d.ts.map +1 -0
  309. package/build/workers/WorkerSigningPool.node.js +753 -0
  310. package/build/workers/WorkerSigningPool.node.js.map +1 -0
  311. package/build/workers/ecc-bundle.d.ts +25 -0
  312. package/build/workers/ecc-bundle.d.ts.map +1 -0
  313. package/build/workers/ecc-bundle.js +25 -0
  314. package/build/workers/ecc-bundle.js.map +1 -0
  315. package/build/workers/index.d.ts +91 -0
  316. package/build/workers/index.d.ts.map +1 -0
  317. package/build/workers/index.js +114 -0
  318. package/build/workers/index.js.map +1 -0
  319. package/build/workers/psbt-parallel.d.ts +117 -0
  320. package/build/workers/psbt-parallel.d.ts.map +1 -0
  321. package/build/workers/psbt-parallel.js +233 -0
  322. package/build/workers/psbt-parallel.js.map +1 -0
  323. package/build/workers/signing-worker.d.ts +37 -0
  324. package/build/workers/signing-worker.d.ts.map +1 -0
  325. package/build/workers/signing-worker.js +350 -0
  326. package/build/workers/signing-worker.js.map +1 -0
  327. package/build/workers/types.d.ts +365 -0
  328. package/build/workers/types.d.ts.map +1 -0
  329. package/build/workers/types.js +60 -0
  330. package/build/workers/types.js.map +1 -0
  331. package/package.json +68 -9
  332. package/scripts/bundle-ecc.ts +111 -0
  333. package/src/address.ts +91 -45
  334. package/src/bech32utils.ts +3 -3
  335. package/src/bip66.ts +34 -24
  336. package/src/block.ts +205 -86
  337. package/src/branded.ts +18 -0
  338. package/src/crypto.ts +64 -26
  339. package/src/ecc/context.ts +280 -0
  340. package/src/ecc/index.ts +14 -0
  341. package/src/ecc/types.ts +147 -0
  342. package/src/ecpair.d.ts +99 -0
  343. package/src/errors.ts +163 -0
  344. package/src/index.ts +112 -9
  345. package/src/io/BinaryReader.ts +461 -0
  346. package/src/io/BinaryWriter.ts +696 -0
  347. package/src/io/MemoryPool.ts +343 -0
  348. package/src/io/base64.ts +20 -0
  349. package/src/io/hex.ts +155 -0
  350. package/src/io/index.ts +41 -0
  351. package/src/io/utils.ts +283 -0
  352. package/src/merkle.ts +14 -9
  353. package/src/networks.ts +9 -9
  354. package/src/payments/bip341.ts +32 -33
  355. package/src/payments/embed.ts +244 -41
  356. package/src/payments/index.ts +12 -10
  357. package/src/payments/p2ms.ts +497 -118
  358. package/src/payments/p2op.ts +432 -134
  359. package/src/payments/p2pk.ts +370 -72
  360. package/src/payments/p2pkh.ts +524 -130
  361. package/src/payments/p2sh.ts +572 -169
  362. package/src/payments/p2tr.ts +686 -194
  363. package/src/payments/p2wpkh.ts +482 -105
  364. package/src/payments/p2wsh.ts +524 -162
  365. package/src/payments/types.ts +80 -66
  366. package/src/psbt/bip371.ts +72 -51
  367. package/src/psbt/psbtutils.ts +39 -40
  368. package/src/psbt/types.ts +324 -0
  369. package/src/psbt/utils.ts +188 -0
  370. package/src/psbt/validation.ts +185 -0
  371. package/src/psbt.ts +608 -827
  372. package/src/pubkey.ts +22 -23
  373. package/src/push_data.ts +18 -16
  374. package/src/script.ts +81 -66
  375. package/src/script_number.ts +6 -6
  376. package/src/script_signature.ts +33 -36
  377. package/src/transaction.ts +462 -239
  378. package/src/types.ts +229 -100
  379. package/src/workers/WorkerSigningPool.node.ts +887 -0
  380. package/src/workers/WorkerSigningPool.ts +666 -0
  381. package/src/workers/ecc-bundle.ts +26 -0
  382. package/src/workers/index.ts +165 -0
  383. package/src/workers/psbt-parallel.ts +327 -0
  384. package/src/workers/signing-worker.ts +353 -0
  385. package/src/workers/types.ts +417 -0
  386. package/test/address.spec.ts +9 -6
  387. package/test/bitcoin.core.spec.ts +16 -17
  388. package/test/block.spec.ts +8 -7
  389. package/test/bufferutils.spec.ts +228 -214
  390. package/test/crypto.spec.ts +19 -11
  391. package/test/fixtures/p2pk.json +0 -8
  392. package/test/fixtures/p2pkh.json +1 -1
  393. package/test/fixtures/p2sh.json +1 -1
  394. package/test/fixtures/script.json +1 -1
  395. package/test/fixtures/transaction.json +2 -2
  396. package/test/integration/_regtest.ts +25 -0
  397. package/test/integration/addresses.spec.ts +4 -3
  398. package/test/integration/bip32.spec.ts +2 -1
  399. package/test/integration/blocks.spec.ts +1 -1
  400. package/test/integration/cltv.spec.ts +18 -16
  401. package/test/integration/csv.spec.ts +37 -64
  402. package/test/integration/payments.spec.ts +5 -3
  403. package/test/integration/taproot.spec.ts +76 -83
  404. package/test/integration/transactions.spec.ts +38 -35
  405. package/test/payments.spec.ts +35 -13
  406. package/test/payments.utils.ts +17 -16
  407. package/test/psbt.spec.ts +111 -100
  408. package/test/script.spec.ts +11 -10
  409. package/test/script_signature.spec.ts +9 -11
  410. package/test/taproot-cache.spec.ts +694 -0
  411. package/test/transaction.spec.ts +32 -40
  412. package/test/types.spec.ts +74 -29
  413. package/test/workers-pool.spec.ts +963 -0
  414. package/test/workers-signing.spec.ts +635 -0
  415. package/test/workers.spec.ts +1390 -0
  416. package/tsconfig.base.json +34 -18
  417. package/tsconfig.browser.json +15 -0
  418. package/tsconfig.build.json +5 -0
  419. package/tsconfig.json +5 -14
  420. package/typedoc.json +29 -0
  421. package/vite.config.browser.ts +3 -42
  422. package/vitest.config.integration.ts +2 -0
  423. package/browser/bufferutils.d.ts +0 -34
  424. package/browser/chunks/crypto-BhCpKpek.js +0 -2033
  425. package/browser/chunks/payments-B1wlSccx.js +0 -1089
  426. package/browser/chunks/psbt-BCNk7JUx.js +0 -4055
  427. package/browser/chunks/script-DyPItFEl.js +0 -318
  428. package/browser/chunks/transaction-C_UbhMGn.js +0 -432
  429. package/browser/chunks/utils-DNZi-T5W.js +0 -761
  430. package/browser/ecc_lib.d.ts +0 -3
  431. package/browser/hooks/AdvancedSignatureManager.d.ts +0 -16
  432. package/browser/hooks/HookedSigner.d.ts +0 -4
  433. package/browser/hooks/SignatureManager.d.ts +0 -13
  434. package/browser/payments/lazy.d.ts +0 -2
  435. package/browser/typeforce.d.ts +0 -38
  436. package/build/bufferutils.d.ts +0 -34
  437. package/build/bufferutils.js +0 -141
  438. package/build/ecc_lib.d.ts +0 -3
  439. package/build/ecc_lib.js +0 -61
  440. package/build/hooks/AdvancedSignatureManager.d.ts +0 -16
  441. package/build/hooks/AdvancedSignatureManager.js +0 -52
  442. package/build/hooks/HookedSigner.d.ts +0 -4
  443. package/build/hooks/HookedSigner.js +0 -64
  444. package/build/hooks/SignatureManager.d.ts +0 -13
  445. package/build/hooks/SignatureManager.js +0 -45
  446. package/build/payments/lazy.d.ts +0 -2
  447. package/build/payments/lazy.js +0 -28
  448. package/build/tsconfig.tsbuildinfo +0 -1
  449. package/src/bufferutils.ts +0 -188
  450. package/src/ecc_lib.ts +0 -94
  451. package/src/hooks/AdvancedSignatureManager.ts +0 -104
  452. package/src/hooks/HookedSigner.ts +0 -108
  453. package/src/hooks/SignatureManager.ts +0 -84
  454. package/src/payments/lazy.ts +0 -28
  455. package/src/typeforce.d.ts +0 -38
  456. package/tsconfig.webpack.json +0 -18
@@ -1,309 +1,801 @@
1
+ /**
2
+ * Pay-to-Taproot (P2TR) payment class.
3
+ *
4
+ * P2TR is the Taproot output type (BIP341). It supports both key-path spending
5
+ * (single signature) and script-path spending (merkle tree of scripts).
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+
1
10
  import { bech32m } from 'bech32';
2
- import { Buffer as NBuffer } from 'buffer';
3
11
  import { fromBech32 } from '../bech32utils.js';
4
- import { getEccLib } from '../ecc_lib.js';
5
- import { bitcoin as BITCOIN_NETWORK } from '../networks.js';
12
+ import { getEccLib } from '../ecc/context.js';
13
+ import { bitcoin as BITCOIN_NETWORK, type Network } from '../networks.js';
6
14
  import * as bscript from '../script.js';
7
- import { isTaptree, stacksEqual, TAPLEAF_VERSION_MASK, typeforce as typef } from '../types.js';
15
+ import {
16
+ type Bytes32,
17
+ type SchnorrSignature,
18
+ type Script,
19
+ stacksEqual,
20
+ TAPLEAF_VERSION_MASK,
21
+ type Taptree,
22
+ type XOnlyPublicKey,
23
+ } from '../types.js';
8
24
  import {
9
25
  findScriptPath,
26
+ type HashTree,
10
27
  LEAF_VERSION_TAPSCRIPT,
11
28
  rootHashFromPath,
12
29
  tapleafHash,
13
30
  toHashTree,
14
31
  tweakKey,
15
32
  } from './bip341.js';
16
- import { P2TRPayment, PaymentOpts, PaymentType } from './types.js';
17
- import * as lazy from './lazy.js';
33
+ import { concat, equals } from '../io/index.js';
34
+ import { type P2TRPayment, type PaymentOpts, PaymentType, type ScriptRedeem } from './types.js';
18
35
 
19
36
  const OPS = bscript.opcodes;
20
37
  const TAPROOT_WITNESS_VERSION = 0x01;
21
38
  const ANNEX_PREFIX = 0x50;
22
39
 
23
40
  /**
24
- * Creates a Pay-to-Taproot (P2TR) payment object.
41
+ * Pay-to-Taproot (P2TR) payment class.
42
+ *
43
+ * Creates locking scripts of the form: `OP_1 {x-only pubkey}`
44
+ *
45
+ * Key-path spending witness: `[signature]`
46
+ * Script-path spending witness: `[script inputs..., script, control block]`
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * import { P2TR } from '@btc-vision/bitcoin';
51
+ *
52
+ * // Key-path only (no scripts)
53
+ * const keyOnly = P2TR.fromInternalPubkey(internalPubkey);
54
+ * console.log(keyOnly.address); // bc1p... address
25
55
  *
26
- * @param a - The payment object containing the necessary data for P2TR.
27
- * @param opts - Optional payment options.
28
- * @returns The P2TR payment object.
29
- * @throws {TypeError} If the provided data is invalid or insufficient.
56
+ * // With script tree
57
+ * const withScripts = P2TR.fromInternalPubkey(internalPubkey, scriptTree);
58
+ *
59
+ * // Decode an existing output
60
+ * const decoded = P2TR.fromOutput(scriptPubKey);
61
+ * console.log(decoded.pubkey); // 32-byte x-only pubkey
62
+ * ```
30
63
  */
31
- export function p2tr(a: Omit<P2TRPayment, 'name'>, opts?: PaymentOpts): P2TRPayment {
32
- if (
33
- !a.address &&
34
- !a.output &&
35
- !a.pubkey &&
36
- !a.internalPubkey &&
37
- !(a.witness && a.witness.length > 1)
38
- )
39
- throw new TypeError('Not enough data');
64
+ export class P2TR {
65
+ // Static public fields
66
+ static readonly NAME = PaymentType.P2TR;
67
+
68
+ // Private instance fields
69
+ readonly #network: Network;
70
+ readonly #opts: Required<PaymentOpts>;
71
+
72
+ // Input data (provided by user)
73
+ #inputAddress?: string | undefined;
74
+ #inputPubkey?: Uint8Array | undefined;
75
+ #inputInternalPubkey?: Uint8Array | undefined;
76
+ #inputHash?: Uint8Array | undefined;
77
+ #inputScriptTree?: Taptree | undefined;
78
+ #inputSignature?: Uint8Array | undefined;
79
+ #inputOutput?: Uint8Array | undefined;
80
+ #inputWitness?: Uint8Array[] | undefined;
81
+ #inputRedeem?: ScriptRedeem | undefined;
82
+ #inputRedeemVersion?: number | undefined;
83
+
84
+ // Cached computed values
85
+ #address?: string | undefined;
86
+ #pubkey?: XOnlyPublicKey | undefined;
87
+ #internalPubkey?: XOnlyPublicKey | undefined;
88
+ #hash?: Bytes32 | undefined;
89
+ #signature?: SchnorrSignature | undefined;
90
+ #output?: Script | undefined;
91
+ #redeem?: ScriptRedeem | undefined;
92
+ #redeemVersion?: number | undefined;
93
+ #witness?: Uint8Array[] | undefined;
94
+
95
+ // Cache flags
96
+ #addressComputed = false;
97
+ #pubkeyComputed = false;
98
+ #internalPubkeyComputed = false;
99
+ #hashComputed = false;
100
+ #signatureComputed = false;
101
+ #outputComputed = false;
102
+ #redeemComputed = false;
103
+ #redeemVersionComputed = false;
104
+ #witnessComputed = false;
105
+
106
+ // Decoded address cache
107
+ #decodedAddress?: { version: number; prefix: string; data: Uint8Array } | undefined;
108
+ #decodedAddressComputed = false;
109
+
110
+ // Witness without annex
111
+ #witnessWithoutAnnex?: Uint8Array[] | undefined;
112
+ #witnessWithoutAnnexComputed = false;
113
+
114
+ // Hash tree cache
115
+ #hashTree?: HashTree | undefined;
116
+ #hashTreeComputed = false;
117
+
118
+ /**
119
+ * Creates a new P2TR payment instance.
120
+ *
121
+ * @param params - Payment parameters
122
+ * @param params.address - Bech32m encoded address (bc1p...)
123
+ * @param params.pubkey - x-only output pubkey (32 bytes)
124
+ * @param params.internalPubkey - x-only internal pubkey (32 bytes)
125
+ * @param params.hash - Merkle root (32 bytes, or empty for key-path only)
126
+ * @param params.scriptTree - Full script tree definition
127
+ * @param params.signature - Schnorr signature (for key-path spending)
128
+ * @param params.output - The scriptPubKey
129
+ * @param params.witness - The witness stack
130
+ * @param params.redeem - Redeem script for script-path spending
131
+ * @param params.redeemVersion - Leaf version (defaults to LEAF_VERSION_TAPSCRIPT)
132
+ * @param params.network - Network parameters (defaults to mainnet)
133
+ * @param opts - Payment options
134
+ * @param opts.validate - Whether to validate inputs (default: true)
135
+ *
136
+ * @throws {TypeError} If validation is enabled and data is invalid
137
+ */
138
+ constructor(
139
+ params: {
140
+ address?: string | undefined;
141
+ pubkey?: Uint8Array | undefined;
142
+ internalPubkey?: Uint8Array | undefined;
143
+ hash?: Uint8Array | undefined;
144
+ scriptTree?: Taptree | undefined;
145
+ signature?: Uint8Array | undefined;
146
+ output?: Uint8Array | undefined;
147
+ witness?: Uint8Array[] | undefined;
148
+ redeem?: ScriptRedeem | undefined;
149
+ redeemVersion?: number | undefined;
150
+ network?: Network | undefined;
151
+ },
152
+ opts?: PaymentOpts,
153
+ ) {
154
+ this.#network = params.network ?? BITCOIN_NETWORK;
155
+ this.#opts = {
156
+ validate: opts?.validate ?? true,
157
+ allowIncomplete: opts?.allowIncomplete ?? false,
158
+ };
40
159
 
41
- opts = Object.assign({ validate: true }, opts || {});
160
+ // Store input data
161
+ this.#inputAddress = params.address;
162
+ this.#inputPubkey = params.pubkey;
163
+ this.#inputInternalPubkey = params.internalPubkey;
164
+ this.#inputHash = params.hash;
165
+ this.#inputScriptTree = params.scriptTree;
166
+ this.#inputSignature = params.signature;
167
+ this.#inputOutput = params.output;
168
+ this.#inputWitness = params.witness;
169
+ this.#inputRedeem = params.redeem;
170
+ this.#inputRedeemVersion = params.redeemVersion;
171
+
172
+ // Validate if requested
173
+ if (this.#opts.validate) {
174
+ this.#validate();
175
+ }
176
+ }
42
177
 
43
- typef(
44
- {
45
- address: typef.maybe(typef.String),
46
- input: typef.maybe(typef.BufferN(0)),
47
- network: typef.maybe(typef.Object),
48
- output: typef.maybe(typef.BufferN(34)),
49
- internalPubkey: typef.maybe(typef.BufferN(32)),
50
- hash: typef.maybe(typef.BufferN(32)), // merkle root hash, the tweak
51
- pubkey: typef.maybe(typef.BufferN(32)), // tweaked with `hash` from `internalPubkey`
52
- signature: typef.maybe(typef.anyOf(typef.BufferN(64), typef.BufferN(65))),
53
- witness: typef.maybe(typef.arrayOf(typef.Buffer)),
54
- scriptTree: typef.maybe(isTaptree),
55
- redeem: typef.maybe({
56
- output: typef.maybe(typef.Buffer), // tapleaf script
57
- redeemVersion: typef.maybe(typef.Number), // tapleaf version
58
- witness: typef.maybe(typef.arrayOf(typef.Buffer)),
59
- }),
60
- redeemVersion: typef.maybe(typef.Number),
61
- },
62
- a,
63
- );
178
+ // Public getters
179
+
180
+ /**
181
+ * Payment type discriminant.
182
+ */
183
+ get name(): typeof PaymentType.P2TR {
184
+ return PaymentType.P2TR;
185
+ }
186
+
187
+ /**
188
+ * Network parameters.
189
+ */
190
+ get network(): Network {
191
+ return this.#network;
192
+ }
64
193
 
65
- const _address = lazy.value(() => {
66
- return fromBech32(a.address!);
67
- });
194
+ /**
195
+ * Bech32m encoded address (bc1p... for mainnet).
196
+ */
197
+ get address(): string | undefined {
198
+ if (!this.#addressComputed) {
199
+ this.#address = this.#computeAddress();
200
+ this.#addressComputed = true;
201
+ }
202
+ return this.#address;
203
+ }
68
204
 
69
- // remove annex if present, ignored by taproot
70
- const _witness = lazy.value(() => {
71
- if (!a.witness || !a.witness.length) return;
72
- if (a.witness.length >= 2 && a.witness[a.witness.length - 1][0] === ANNEX_PREFIX) {
73
- return a.witness.slice(0, -1);
205
+ /**
206
+ * x-only output pubkey (32 bytes).
207
+ * This is the tweaked pubkey that appears in the output.
208
+ */
209
+ get pubkey(): XOnlyPublicKey | undefined {
210
+ if (!this.#pubkeyComputed) {
211
+ this.#pubkey = this.#computePubkey();
212
+ this.#pubkeyComputed = true;
74
213
  }
75
- return a.witness.slice();
76
- });
214
+ return this.#pubkey;
215
+ }
77
216
 
78
- const _hashTree = lazy.value(() => {
79
- if (a.scriptTree) return toHashTree(a.scriptTree);
80
- if (a.hash) return { hash: a.hash };
81
- return;
82
- });
217
+ /**
218
+ * x-only internal pubkey (32 bytes).
219
+ * This is the untweaked pubkey before adding the merkle root tweak.
220
+ */
221
+ get internalPubkey(): XOnlyPublicKey | undefined {
222
+ if (!this.#internalPubkeyComputed) {
223
+ this.#internalPubkey = this.#computeInternalPubkey();
224
+ this.#internalPubkeyComputed = true;
225
+ }
226
+ return this.#internalPubkey;
227
+ }
83
228
 
84
- const network = a.network || BITCOIN_NETWORK;
85
- const o: P2TRPayment = {
86
- name: PaymentType.P2TR,
87
- network,
88
- };
229
+ /**
230
+ * Merkle root hash (32 bytes).
231
+ * Present when a script tree is defined.
232
+ */
233
+ get hash(): Bytes32 | undefined {
234
+ if (!this.#hashComputed) {
235
+ this.#hash = this.#computeHash();
236
+ this.#hashComputed = true;
237
+ }
238
+ return this.#hash;
239
+ }
89
240
 
90
- lazy.prop(o, 'address', () => {
91
- if (!o.pubkey) return;
241
+ /**
242
+ * Schnorr signature (for key-path spending).
243
+ */
244
+ get signature(): SchnorrSignature | undefined {
245
+ if (!this.#signatureComputed) {
246
+ this.#signature = this.#computeSignature();
247
+ this.#signatureComputed = true;
248
+ }
249
+ return this.#signature;
250
+ }
92
251
 
93
- const words = bech32m.toWords(o.pubkey);
252
+ /**
253
+ * The scriptPubKey: `OP_1 {32-byte x-only pubkey}`
254
+ */
255
+ get output(): Script | undefined {
256
+ if (!this.#outputComputed) {
257
+ this.#output = this.#computeOutput();
258
+ this.#outputComputed = true;
259
+ }
260
+ return this.#output;
261
+ }
262
+
263
+ /**
264
+ * Redeem script information (for script-path spending).
265
+ */
266
+ get redeem(): ScriptRedeem | undefined {
267
+ if (!this.#redeemComputed) {
268
+ this.#redeem = this.#computeRedeem();
269
+ this.#redeemComputed = true;
270
+ }
271
+ return this.#redeem;
272
+ }
273
+
274
+ /**
275
+ * Leaf version (defaults to LEAF_VERSION_TAPSCRIPT = 0xc0).
276
+ */
277
+ get redeemVersion(): number {
278
+ if (!this.#redeemVersionComputed) {
279
+ this.#redeemVersion = this.#computeRedeemVersion();
280
+ this.#redeemVersionComputed = true;
281
+ }
282
+ return this.#redeemVersion ?? LEAF_VERSION_TAPSCRIPT;
283
+ }
284
+
285
+ /**
286
+ * Witness stack.
287
+ * Key-path: `[signature]`
288
+ * Script-path: `[script inputs..., script, control block]`
289
+ */
290
+ get witness(): Uint8Array[] | undefined {
291
+ if (!this.#witnessComputed) {
292
+ this.#witness = this.#computeWitness();
293
+ this.#witnessComputed = true;
294
+ }
295
+ return this.#witness;
296
+ }
297
+
298
+ // Static factory methods
299
+
300
+ /**
301
+ * Creates a P2TR payment from an internal pubkey (key-path only).
302
+ *
303
+ * @param internalPubkey - x-only internal pubkey (32 bytes)
304
+ * @param scriptTree - Optional script tree
305
+ * @param network - Network parameters (defaults to mainnet)
306
+ * @returns A new P2TR payment instance
307
+ *
308
+ * @example
309
+ * ```typescript
310
+ * // Key-path only
311
+ * const p2tr = P2TR.fromInternalPubkey(internalPubkey);
312
+ *
313
+ * // With script tree
314
+ * const withScripts = P2TR.fromInternalPubkey(internalPubkey, scriptTree);
315
+ * ```
316
+ */
317
+ static fromInternalPubkey(
318
+ internalPubkey: XOnlyPublicKey,
319
+ scriptTree?: Taptree,
320
+ network?: Network,
321
+ ): P2TR {
322
+ return new P2TR({ internalPubkey, scriptTree, network });
323
+ }
324
+
325
+ /**
326
+ * Creates a P2TR payment from a bech32m address.
327
+ *
328
+ * @param address - Bech32m encoded address (bc1p...)
329
+ * @param network - Network parameters (defaults to mainnet)
330
+ * @returns A new P2TR payment instance
331
+ */
332
+ static fromAddress(address: string, network?: Network): P2TR {
333
+ return new P2TR({ address, network });
334
+ }
335
+
336
+ /**
337
+ * Creates a P2TR payment from a scriptPubKey.
338
+ *
339
+ * @param output - The scriptPubKey
340
+ * @param network - Network parameters (defaults to mainnet)
341
+ * @returns A new P2TR payment instance
342
+ */
343
+ static fromOutput(output: Uint8Array, network?: Network): P2TR {
344
+ return new P2TR({ output, network });
345
+ }
346
+
347
+ /**
348
+ * Creates a P2TR payment from a signature (for key-path spending).
349
+ *
350
+ * @param signature - Schnorr signature
351
+ * @param internalPubkey - x-only internal pubkey
352
+ * @param network - Network parameters (defaults to mainnet)
353
+ * @returns A new P2TR payment instance
354
+ */
355
+ static fromSignature(
356
+ signature: SchnorrSignature,
357
+ internalPubkey?: XOnlyPublicKey,
358
+ network?: Network,
359
+ ): P2TR {
360
+ return new P2TR({ signature, internalPubkey, network });
361
+ }
362
+
363
+ // Private helper methods
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
+
387
+ #getDecodedAddress(): { version: number; prefix: string; data: Uint8Array } | undefined {
388
+ if (!this.#decodedAddressComputed) {
389
+ if (this.#inputAddress) {
390
+ const decoded = fromBech32(this.#inputAddress);
391
+ if (decoded) {
392
+ this.#decodedAddress = {
393
+ version: decoded.version,
394
+ prefix: decoded.prefix,
395
+ data: decoded.data,
396
+ };
397
+ }
398
+ }
399
+ this.#decodedAddressComputed = true;
400
+ }
401
+ return this.#decodedAddress;
402
+ }
403
+
404
+ #getWitnessWithoutAnnex(): Uint8Array[] | undefined {
405
+ if (!this.#witnessWithoutAnnexComputed) {
406
+ if (this.#inputWitness && this.#inputWitness.length > 0) {
407
+ // Remove annex if present
408
+ if (
409
+ this.#inputWitness.length >= 2 &&
410
+ this.#inputWitness[this.#inputWitness.length - 1]![0] === ANNEX_PREFIX
411
+ ) {
412
+ this.#witnessWithoutAnnex = this.#inputWitness.slice(0, -1);
413
+ } else {
414
+ this.#witnessWithoutAnnex = this.#inputWitness.slice();
415
+ }
416
+ }
417
+ this.#witnessWithoutAnnexComputed = true;
418
+ }
419
+ return this.#witnessWithoutAnnex;
420
+ }
421
+
422
+ // Private computation methods
423
+
424
+ #getHashTree(): HashTree | undefined {
425
+ if (!this.#hashTreeComputed) {
426
+ if (this.#inputScriptTree) {
427
+ this.#hashTree = toHashTree(this.#inputScriptTree);
428
+ } else if (this.#inputHash) {
429
+ this.#hashTree = { hash: this.#inputHash as Bytes32 };
430
+ }
431
+ this.#hashTreeComputed = true;
432
+ }
433
+ return this.#hashTree;
434
+ }
435
+
436
+ #computeAddress(): string | undefined {
437
+ if (this.#inputAddress) {
438
+ return this.#inputAddress;
439
+ }
440
+ const pk = this.pubkey;
441
+ if (!pk) return undefined;
442
+
443
+ const words = bech32m.toWords(pk);
94
444
  words.unshift(TAPROOT_WITNESS_VERSION);
95
- return bech32m.encode(network.bech32, words);
96
- });
445
+ return bech32m.encode(this.#network.bech32, words);
446
+ }
97
447
 
98
- lazy.prop(o, 'hash', () => {
99
- const hashTree = _hashTree();
100
- if (hashTree) return hashTree.hash;
448
+ #computePubkey(): XOnlyPublicKey | undefined {
449
+ if (this.#inputPubkey) {
450
+ return this.#inputPubkey as XOnlyPublicKey;
451
+ }
452
+ if (this.#inputOutput) {
453
+ return this.#inputOutput.subarray(2) as XOnlyPublicKey;
454
+ }
455
+ if (this.#inputAddress) {
456
+ return this.#getDecodedAddress()?.data as XOnlyPublicKey | undefined;
457
+ }
458
+ const internalPk = this.internalPubkey;
459
+ if (internalPk) {
460
+ const tweakedKey = tweakKey(internalPk, this.hash);
461
+ if (tweakedKey) {
462
+ return tweakedKey.x as XOnlyPublicKey;
463
+ }
464
+ }
465
+ return undefined;
466
+ }
101
467
 
102
- const w = _witness();
468
+ #computeInternalPubkey(): XOnlyPublicKey | undefined {
469
+ if (this.#inputInternalPubkey) {
470
+ return this.#inputInternalPubkey as XOnlyPublicKey;
471
+ }
472
+ const witness = this.#getWitnessWithoutAnnex();
473
+ if (witness && witness.length > 1) {
474
+ return witness[witness.length - 1]!.subarray(1, 33) as XOnlyPublicKey;
475
+ }
476
+ return undefined;
477
+ }
478
+
479
+ #computeHash(): Bytes32 | undefined {
480
+ const hashTree = this.#getHashTree();
481
+ if (hashTree) {
482
+ return hashTree.hash as Bytes32;
483
+ }
484
+
485
+ const w = this.#getWitnessWithoutAnnex();
103
486
  if (w && w.length > 1) {
104
- const controlBlock = w[w.length - 1];
105
- const leafVersion = controlBlock[0] & TAPLEAF_VERSION_MASK;
106
- const script = w[w.length - 2];
487
+ const controlBlock = w[w.length - 1]!;
488
+ const leafVersion = controlBlock[0]! & TAPLEAF_VERSION_MASK;
489
+ const script = w[w.length - 2]!;
107
490
  const leafHash = tapleafHash({
108
491
  output: script,
109
492
  version: leafVersion,
110
493
  });
111
- return rootHashFromPath(controlBlock, leafHash);
494
+ return rootHashFromPath(controlBlock, leafHash) as Bytes32;
112
495
  }
113
496
 
114
497
  return undefined;
115
- });
116
- lazy.prop(o, 'output', () => {
117
- if (!o.pubkey) return;
118
- return bscript.compile([OPS.OP_1, o.pubkey]);
119
- });
120
- lazy.prop(o, 'redeemVersion', () => {
121
- if (a.redeemVersion) return a.redeemVersion;
122
- if (a.redeem && a.redeem.redeemVersion !== undefined && a.redeem.redeemVersion !== null) {
123
- return a.redeem.redeemVersion;
498
+ }
499
+
500
+ #computeSignature(): SchnorrSignature | undefined {
501
+ if (this.#inputSignature) {
502
+ return this.#inputSignature as SchnorrSignature;
124
503
  }
504
+ const witness = this.#getWitnessWithoutAnnex();
505
+ if (witness && witness.length === 1) {
506
+ return witness[0] as SchnorrSignature;
507
+ }
508
+ return undefined;
509
+ }
125
510
 
126
- return LEAF_VERSION_TAPSCRIPT;
127
- });
128
- lazy.prop(o, 'redeem', () => {
129
- const witness = _witness(); // witness without annex
130
- if (!witness || witness.length < 2) return;
511
+ #computeOutput(): Script | undefined {
512
+ if (this.#inputOutput) {
513
+ return this.#inputOutput as Script;
514
+ }
515
+ const pk = this.pubkey;
516
+ if (!pk) return undefined;
131
517
 
518
+ return bscript.compile([OPS.OP_1, pk]) as Script;
519
+ }
520
+
521
+ #computeRedeem(): ScriptRedeem | undefined {
522
+ if (this.#inputRedeem) {
523
+ return this.#inputRedeem;
524
+ }
525
+ const witness = this.#getWitnessWithoutAnnex();
526
+ if (!witness || witness.length < 2) {
527
+ return undefined;
528
+ }
132
529
  return {
133
- output: witness[witness.length - 2],
530
+ output: witness[witness.length - 2] as Script,
134
531
  witness: witness.slice(0, -2),
135
- redeemVersion: witness[witness.length - 1][0] & TAPLEAF_VERSION_MASK,
532
+ redeemVersion: witness[witness.length - 1]![0]! & TAPLEAF_VERSION_MASK,
136
533
  };
137
- });
138
- lazy.prop(o, 'pubkey', () => {
139
- if (a.pubkey) return a.pubkey;
140
- if (a.output) return a.output.subarray(2);
141
- if (a.address) return _address().data;
142
- if (o.internalPubkey) {
143
- const tweakedKey = tweakKey(o.internalPubkey, o.hash);
144
- if (tweakedKey) return tweakedKey.x;
145
- }
146
- });
147
- lazy.prop(o, 'internalPubkey', () => {
148
- if (a.internalPubkey) return a.internalPubkey;
149
- const witness = _witness();
150
- if (witness && witness.length > 1) return witness[witness.length - 1].subarray(1, 33);
151
- });
152
- lazy.prop(o, 'signature', () => {
153
- if (a.signature) return a.signature;
154
- const witness = _witness(); // witness without annex
155
- if (!witness || witness.length !== 1) return;
156
- return witness[0];
157
- });
158
-
159
- lazy.prop(o, 'witness', () => {
160
- if (a.witness) return a.witness;
161
- const hashTree = _hashTree();
162
- if (hashTree && a.redeem && a.redeem.output && a.internalPubkey) {
534
+ }
535
+
536
+ #computeRedeemVersion(): number | undefined {
537
+ if (this.#inputRedeemVersion !== undefined) {
538
+ return this.#inputRedeemVersion;
539
+ }
540
+ if (
541
+ this.#inputRedeem &&
542
+ this.#inputRedeem.redeemVersion !== undefined &&
543
+ this.#inputRedeem.redeemVersion !== null
544
+ ) {
545
+ return this.#inputRedeem.redeemVersion;
546
+ }
547
+ return LEAF_VERSION_TAPSCRIPT;
548
+ }
549
+
550
+ // Validation
551
+
552
+ #computeWitness(): Uint8Array[] | undefined {
553
+ if (this.#inputWitness) {
554
+ return this.#inputWitness;
555
+ }
556
+
557
+ const hashTree = this.#getHashTree();
558
+ if (hashTree && this.#inputRedeem?.output && this.#inputInternalPubkey) {
163
559
  const leafHash = tapleafHash({
164
- output: a.redeem.output,
165
- version: o.redeemVersion,
560
+ output: this.#inputRedeem.output,
561
+ version: this.redeemVersion,
166
562
  });
167
563
  const path = findScriptPath(hashTree, leafHash);
168
- if (!path) return;
169
- const outputKey = tweakKey(a.internalPubkey, hashTree.hash);
170
- if (!outputKey) return;
171
- const controlBock = NBuffer.concat(
172
- [NBuffer.from([o.redeemVersion! | outputKey.parity]), a.internalPubkey].concat(
173
- path,
174
- ),
175
- );
176
- return [a.redeem.output, controlBock];
177
- }
178
- if (a.signature) return [a.signature];
179
- });
180
-
181
- // extended validation
182
- if (opts.validate) {
183
- let pubkey: Buffer = NBuffer.from([]);
184
- if (a.address) {
185
- if (network && network.bech32 !== _address().prefix)
564
+ if (!path) return undefined;
565
+
566
+ const outputKey = tweakKey(this.#inputInternalPubkey as XOnlyPublicKey, hashTree.hash);
567
+ if (!outputKey) return undefined;
568
+
569
+ const version = this.redeemVersion ?? 0xc0;
570
+ const controlBlock = concat([
571
+ new Uint8Array([version | outputKey.parity]),
572
+ this.#inputInternalPubkey,
573
+ ...path,
574
+ ]);
575
+ return [this.#inputRedeem.output, controlBlock];
576
+ }
577
+
578
+ if (this.#inputSignature) {
579
+ return [this.#inputSignature];
580
+ }
581
+
582
+ return undefined;
583
+ }
584
+
585
+ #validate(): void {
586
+ let pubkey: Uint8Array = new Uint8Array(0);
587
+
588
+ if (this.#inputAddress) {
589
+ const addr = this.#getDecodedAddress();
590
+ if (!addr) {
591
+ throw new TypeError('Invalid address');
592
+ }
593
+ if (this.#network && this.#network.bech32 !== addr.prefix) {
186
594
  throw new TypeError('Invalid prefix or Network mismatch');
187
- if (_address().version !== TAPROOT_WITNESS_VERSION)
595
+ }
596
+ if (addr.version !== TAPROOT_WITNESS_VERSION) {
188
597
  throw new TypeError('Invalid address version');
189
- if (_address().data.length !== 32) throw new TypeError('Invalid address data');
190
- pubkey = _address().data;
598
+ }
599
+ if (addr.data.length !== 32) {
600
+ throw new TypeError('Invalid address data');
601
+ }
602
+ pubkey = addr.data;
191
603
  }
192
604
 
193
- if (a.pubkey) {
194
- if (pubkey.length > 0 && !pubkey.equals(a.pubkey))
605
+ if (this.#inputPubkey) {
606
+ if (pubkey.length > 0 && !equals(pubkey, this.#inputPubkey)) {
195
607
  throw new TypeError('Pubkey mismatch');
196
- else pubkey = a.pubkey;
608
+ } else {
609
+ pubkey = this.#inputPubkey;
610
+ }
197
611
  }
198
612
 
199
- if (a.output) {
200
- if (a.output.length !== 34 || a.output[0] !== OPS.OP_1 || a.output[1] !== 0x20)
613
+ if (this.#inputOutput) {
614
+ if (
615
+ this.#inputOutput.length !== 34 ||
616
+ this.#inputOutput[0] !== OPS.OP_1 ||
617
+ this.#inputOutput[1] !== 0x20
618
+ ) {
201
619
  throw new TypeError('Output is invalid');
202
- if (pubkey.length > 0 && !pubkey.equals(a.output.subarray(2)))
620
+ }
621
+ if (pubkey.length > 0 && !equals(pubkey, this.#inputOutput.subarray(2))) {
203
622
  throw new TypeError('Pubkey mismatch');
204
- else pubkey = a.output.subarray(2);
623
+ } else {
624
+ pubkey = this.#inputOutput.subarray(2);
625
+ }
205
626
  }
206
627
 
207
- if (a.internalPubkey) {
208
- const tweakedKey = tweakKey(a.internalPubkey, o.hash);
209
- if (pubkey.length > 0 && !pubkey.equals(tweakedKey!.x))
628
+ if (this.#inputInternalPubkey) {
629
+ const tweakedKey = tweakKey(this.#inputInternalPubkey as XOnlyPublicKey, this.hash);
630
+ if (!tweakedKey) {
631
+ throw new TypeError('Invalid internal pubkey');
632
+ }
633
+ if (pubkey.length > 0 && !equals(pubkey, tweakedKey.x)) {
210
634
  throw new TypeError('Pubkey mismatch');
211
- else pubkey = tweakedKey!.x;
635
+ } else {
636
+ pubkey = tweakedKey.x;
637
+ }
212
638
  }
213
639
 
214
- /*if (pubkey && pubkey.length) {
215
- if (!getEccLib().isXOnlyPoint(pubkey))
216
- throw new TypeError('Invalid pubkey for p2tr');
217
- }*/
218
-
219
- const hashTree = _hashTree();
640
+ const hashTree = this.#getHashTree();
220
641
 
221
- if (a.hash && hashTree) {
222
- if (!a.hash.equals(hashTree.hash)) throw new TypeError('Hash mismatch');
642
+ if (this.#inputHash && hashTree) {
643
+ if (!equals(this.#inputHash, hashTree.hash)) {
644
+ throw new TypeError('Hash mismatch');
645
+ }
223
646
  }
224
647
 
225
- if (a.redeem && a.redeem.output && hashTree) {
648
+ if (this.#inputRedeem?.output && hashTree) {
226
649
  const leafHash = tapleafHash({
227
- output: a.redeem.output,
228
- version: o.redeemVersion,
650
+ output: this.#inputRedeem.output,
651
+ version: this.redeemVersion,
229
652
  });
230
- if (!findScriptPath(hashTree, leafHash))
653
+ if (!findScriptPath(hashTree, leafHash)) {
231
654
  throw new TypeError('Redeem script not in tree');
655
+ }
232
656
  }
233
657
 
234
- const witness = _witness();
658
+ const witness = this.#getWitnessWithoutAnnex();
235
659
 
236
- // compare the provided redeem data with the one computed from witness
237
- if (a.redeem && o.redeem) {
238
- if (a.redeem.redeemVersion) {
239
- if (a.redeem.redeemVersion !== o.redeem.redeemVersion)
660
+ // Compare provided redeem with computed from witness
661
+ if (this.#inputRedeem && this.redeem) {
662
+ if (this.#inputRedeem.redeemVersion) {
663
+ if (this.#inputRedeem.redeemVersion !== this.redeem.redeemVersion) {
240
664
  throw new TypeError('Redeem.redeemVersion and witness mismatch');
665
+ }
241
666
  }
242
667
 
243
- if (a.redeem.output) {
244
- if (bscript.decompile(a.redeem.output)!.length === 0)
668
+ if (this.#inputRedeem.output) {
669
+ const decompiled = bscript.decompile(this.#inputRedeem.output);
670
+ if (!decompiled || decompiled.length === 0) {
245
671
  throw new TypeError('Redeem.output is invalid');
672
+ }
246
673
 
247
- // output redeem is constructed from the witness
248
- if (o.redeem.output && !a.redeem.output.equals(o.redeem.output))
674
+ if (this.redeem.output && !equals(this.#inputRedeem.output, this.redeem.output)) {
249
675
  throw new TypeError('Redeem.output and witness mismatch');
676
+ }
250
677
  }
251
- if (a.redeem.witness) {
252
- if (o.redeem.witness && !stacksEqual(a.redeem.witness, o.redeem.witness))
678
+ if (this.#inputRedeem.witness) {
679
+ if (
680
+ this.redeem.witness &&
681
+ !stacksEqual(this.#inputRedeem.witness, this.redeem.witness)
682
+ ) {
253
683
  throw new TypeError('Redeem.witness and witness mismatch');
684
+ }
254
685
  }
255
686
  }
256
687
 
257
- if (witness && witness.length) {
688
+ if (witness && witness.length > 0) {
258
689
  if (witness.length === 1) {
259
- // key spending
260
- if (a.signature && !a.signature.equals(witness[0]))
690
+ // Key-path spending
691
+ if (this.#inputSignature && !equals(this.#inputSignature!, witness[0]!)) {
261
692
  throw new TypeError('Signature mismatch');
693
+ }
262
694
  } else {
263
- // script path spending
264
- const controlBlock = witness[witness.length - 1];
265
- if (controlBlock.length < 33)
695
+ // Script-path spending
696
+ const controlBlock = witness[witness.length - 1]!;
697
+ if (controlBlock.length < 33) {
266
698
  throw new TypeError(
267
699
  `The control-block length is too small. Got ${controlBlock.length}, expected min 33.`,
268
700
  );
701
+ }
269
702
 
270
- if ((controlBlock.length - 33) % 32 !== 0)
703
+ if ((controlBlock.length - 33) % 32 !== 0) {
271
704
  throw new TypeError(
272
705
  `The control-block length of ${controlBlock.length} is incorrect!`,
273
706
  );
707
+ }
274
708
 
275
709
  const m = (controlBlock.length - 33) / 32;
276
- if (m > 128)
710
+ if (m > 128) {
277
711
  throw new TypeError(`The script path is too long. Got ${m}, expected max 128.`);
712
+ }
278
713
 
279
- const internalPubkey = controlBlock.subarray(1, 33);
280
- if (a.internalPubkey && !a.internalPubkey.equals(internalPubkey))
714
+ const internalPk = controlBlock.subarray(1, 33);
715
+ if (this.#inputInternalPubkey && !equals(this.#inputInternalPubkey!, internalPk)) {
281
716
  throw new TypeError('Internal pubkey mismatch');
717
+ }
282
718
 
283
- if (!getEccLib().isXOnlyPoint(internalPubkey))
719
+ if (!getEccLib().isXOnlyPoint(internalPk)) {
284
720
  throw new TypeError('Invalid internalPubkey for p2tr witness');
721
+ }
285
722
 
286
- const leafVersion = controlBlock[0] & TAPLEAF_VERSION_MASK;
287
- const script = witness[witness.length - 2];
723
+ const leafVersion = controlBlock[0]! & TAPLEAF_VERSION_MASK;
724
+ const script = witness[witness.length - 2]!;
288
725
 
289
726
  const leafHash = tapleafHash({
290
727
  output: script,
291
728
  version: leafVersion,
292
729
  });
293
- const hash = rootHashFromPath(controlBlock, leafHash);
730
+ const computedHash = rootHashFromPath(controlBlock, leafHash);
294
731
 
295
- const outputKey = tweakKey(internalPubkey, hash);
296
- if (!outputKey)
297
- // todo: needs test data
732
+ const outputKey = tweakKey(internalPk as XOnlyPublicKey, computedHash);
733
+ if (!outputKey) {
298
734
  throw new TypeError('Invalid outputKey for p2tr witness');
735
+ }
299
736
 
300
- if (pubkey.length && !pubkey.equals(outputKey.x))
737
+ if (pubkey.length > 0 && !equals(pubkey, outputKey.x)) {
301
738
  throw new TypeError('Pubkey mismatch for p2tr witness');
739
+ }
302
740
 
303
- if (outputKey.parity !== (controlBlock[0] & 1)) throw new Error('Incorrect parity');
741
+ if (outputKey.parity !== (controlBlock[0]! & 1)) {
742
+ throw new Error('Incorrect parity');
743
+ }
304
744
  }
305
745
  }
306
746
  }
747
+ }
748
+
749
+ /**
750
+ * Creates a Pay-to-Taproot (P2TR) payment object.
751
+ *
752
+ * This is the legacy factory function for backwards compatibility.
753
+ * For new code, prefer using the P2TR class directly.
754
+ *
755
+ * @param a - The payment object containing the necessary data
756
+ * @param opts - Optional payment options
757
+ * @returns The P2TR payment object
758
+ * @throws {TypeError} If the required data is not provided or if the data is invalid
759
+ *
760
+ * @example
761
+ * ```typescript
762
+ * import { p2tr } from '@btc-vision/bitcoin';
763
+ *
764
+ * // Key-path only
765
+ * const payment = p2tr({ internalPubkey });
766
+ *
767
+ * // With script tree
768
+ * const withScripts = p2tr({ internalPubkey, scriptTree });
769
+ * ```
770
+ */
771
+ export function p2tr(a: Omit<P2TRPayment, 'name'>, opts?: PaymentOpts): P2TRPayment {
772
+ if (
773
+ !a.address &&
774
+ !a.output &&
775
+ !a.pubkey &&
776
+ !a.internalPubkey &&
777
+ !(a.witness && a.witness.length > 1)
778
+ ) {
779
+ throw new TypeError('Not enough data');
780
+ }
781
+
782
+ const instance = new P2TR(
783
+ {
784
+ address: a.address,
785
+ pubkey: a.pubkey,
786
+ internalPubkey: a.internalPubkey,
787
+ hash: a.hash,
788
+ scriptTree: a.scriptTree,
789
+ signature: a.signature,
790
+ output: a.output,
791
+ witness: a.witness,
792
+ redeem: a.redeem,
793
+ redeemVersion: a.redeemVersion,
794
+ network: a.network,
795
+ },
796
+ opts,
797
+ );
307
798
 
308
- return Object.assign(o, a);
799
+ // Return a merged object for backwards compatibility
800
+ return Object.assign(instance.toPayment(), a);
309
801
  }