@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
package/src/psbt.ts CHANGED
@@ -1,16 +1,7 @@
1
- import { Psbt as PsbtBase } from 'bip174';
2
- import * as varuint from 'bip174/src/lib/converter/varint.js';
3
-
4
- interface VaruintDecode {
5
- (buffer: Buffer, offset?: number): number;
6
- bytes: number;
7
- }
8
- const varuintDecode = varuint.decode as VaruintDecode;
9
- import {
1
+ import type {
10
2
  Bip32Derivation,
11
3
  KeyValue,
12
4
  PartialSig,
13
- PsbtGlobal,
14
5
  PsbtGlobalUpdate,
15
6
  PsbtInput,
16
7
  PsbtInputUpdate,
@@ -20,62 +11,116 @@ import {
20
11
  TapScriptSig,
21
12
  Transaction as ITransaction,
22
13
  TransactionFromBuffer,
23
- } from 'bip174/src/lib/interfaces.js';
24
- import { checkForInput, checkForOutput } from 'bip174/src/lib/utils.js';
25
- import { BIP32Interface } from '@btc-vision/bip32';
26
- import { ECPairInterface } from 'ecpair';
14
+ } from 'bip174';
15
+ import { checkForInput, checkForOutput, Psbt as PsbtBase } from 'bip174';
16
+ import { clone, equals, fromBase64, fromHex, reverse, toHex } from './io/index.js';
17
+
18
+ import type { BIP32Interface } from '@btc-vision/bip32';
19
+ import type { ECPairInterface } from 'ecpair';
27
20
  import { fromOutputScript, isUnknownSegwitVersion, toOutputScript } from './address.js';
28
- import { cloneBuffer, reverseBuffer } from './bufferutils.js';
29
- import { bitcoin as btcNetwork, Network } from './networks.js';
21
+ import { bitcoin as btcNetwork } from './networks.js';
22
+ import type { P2SHPayment, P2WSHPayment } from './payments/index.js';
30
23
  import * as payments from './payments/index.js';
31
- import type { P2WSHPayment } from './payments/index.js';
32
24
  import { tapleafHash } from './payments/bip341.js';
33
- import { P2SHPayment, Payment, PaymentOpts } from './payments/index.js';
34
25
  import {
35
26
  checkTaprootInputFields,
36
- checkTaprootInputForSigs,
37
27
  checkTaprootOutputFields,
38
28
  isTaprootInput,
39
29
  serializeTaprootSignature,
40
30
  tapScriptFinalizer,
41
31
  } from './psbt/bip371.js';
42
32
  import { toXOnly } from './pubkey.js';
33
+ import { isP2TR, isP2WPKH, pubkeyInScript, witnessStackToScriptWitness } from './psbt/psbtutils.js';
43
34
  import {
44
- checkInputForSig,
45
- isP2MS,
46
- isP2PK,
47
- isP2PKH,
48
- isP2SHScript,
49
- isP2TR,
50
- isP2WPKH,
51
- isP2WSHScript,
52
- pubkeyInScript,
53
- witnessStackToScriptWitness,
54
- } from './psbt/psbtutils.js';
35
+ check32Bit,
36
+ checkCache,
37
+ checkInputsForPartialSig,
38
+ checkPartialSigSighashes,
39
+ checkScriptForPubkey,
40
+ checkTxEmpty,
41
+ checkTxForDupeIns,
42
+ checkTxInputCache,
43
+ isFinalized,
44
+ } from './psbt/validation.js';
45
+ import {
46
+ checkInvalidP2WSH,
47
+ classifyScript,
48
+ compressPubkey,
49
+ getMeaningfulScript,
50
+ isPubkeyLike,
51
+ isSigLike,
52
+ range,
53
+ scriptWitnessToWitnessStack,
54
+ sighashTypeToString,
55
+ } from './psbt/utils.js';
55
56
  import * as bscript from './script.js';
56
- import { Output, Transaction } from './transaction.js';
57
-
58
- export interface TransactionInput {
59
- hash: string | Buffer;
60
- index: number;
61
- sequence?: number;
62
- }
63
-
64
- export interface PsbtTxInput extends TransactionInput {
65
- hash: Buffer;
66
- }
67
-
68
- export interface TransactionOutput {
69
- script: Buffer;
70
- value: number;
71
- }
72
-
73
- export interface PsbtTxOutput extends TransactionOutput {
74
- address: string | undefined;
75
- }
76
-
77
- // msghash is 32 byte hash of preimage, signature is 64 byte compact signature (r,s 32 bytes each)
78
- export type ValidateSigFunction = (pubkey: Buffer, msghash: Buffer, signature: Buffer) => boolean;
57
+ import type { Output } from './transaction.js';
58
+ import { Transaction } from './transaction.js';
59
+ import type {
60
+ Bytes20,
61
+ Bytes32,
62
+ PublicKey,
63
+ Satoshi,
64
+ SchnorrSignature,
65
+ Script,
66
+ Signature,
67
+ XOnlyPublicKey,
68
+ } from './types.js';
69
+ // Import types for internal use
70
+ import type {
71
+ AllScriptType,
72
+ FinalScriptsFunc,
73
+ FinalTaprootScriptsFunc,
74
+ GetScriptReturn,
75
+ HDSigner,
76
+ HDSignerAsync,
77
+ PsbtBaseExtended,
78
+ PsbtCache,
79
+ PsbtInputExtended,
80
+ PsbtOpts,
81
+ PsbtOptsOptional,
82
+ PsbtOutputExtended,
83
+ PsbtOutputExtendedAddress,
84
+ PsbtTxInput,
85
+ PsbtTxOutput,
86
+ Signer,
87
+ SignerAlternative,
88
+ SignerAsync,
89
+ TaprootHashCheckSigner,
90
+ TransactionInput,
91
+ TransactionOutput,
92
+ TxCacheNumberKey,
93
+ ValidateSigFunction,
94
+ } from './psbt/types.js';
95
+
96
+ // Re-export types from the types module
97
+ export type {
98
+ TransactionInput,
99
+ PsbtTxInput,
100
+ TransactionOutput,
101
+ PsbtTxOutput,
102
+ ValidateSigFunction,
103
+ PsbtBaseExtended,
104
+ PsbtOptsOptional,
105
+ PsbtOpts,
106
+ PsbtInputExtended,
107
+ PsbtOutputExtended,
108
+ PsbtOutputExtendedAddress,
109
+ PsbtOutputExtendedScript,
110
+ HDSigner,
111
+ HDSignerAsync,
112
+ SignerAlternative,
113
+ Signer,
114
+ SignerAsync,
115
+ TaprootHashCheckSigner,
116
+ PsbtCache,
117
+ TxCacheNumberKey,
118
+ ScriptType,
119
+ AllScriptType,
120
+ GetScriptReturn,
121
+ FinalScriptsFunc,
122
+ FinalTaprootScriptsFunc,
123
+ } from './psbt/types.js';
79
124
 
80
125
  /**
81
126
  * These are the default arguments for a Psbt instance.
@@ -94,12 +139,6 @@ const DEFAULT_OPTS: PsbtOpts = {
94
139
  maximumFeeRate: 5000, // satoshi per byte
95
140
  };
96
141
 
97
- // Not a breaking change.
98
- export interface PsbtBaseExtended extends Omit<PsbtBase, 'inputs'> {
99
- inputs: PsbtInput[];
100
- globalMap: PsbtGlobal;
101
- }
102
-
103
142
  /**
104
143
  * Psbt class can parse and generate a PSBT binary based off of the BIP174.
105
144
  * There are 6 roles that this class fulfills. (Explained in BIP174)
@@ -110,9 +149,9 @@ export interface PsbtBaseExtended extends Omit<PsbtBase, 'inputs'> {
110
149
  * `psbt.addOutput(output)`, `psbt.addOutputs(outputs)` when you are looking to
111
150
  * add new inputs and outputs to the PSBT, and `psbt.updateGlobal(itemObject)`,
112
151
  * `psbt.updateInput(itemObject)`, `psbt.updateOutput(itemObject)`
113
- * addInput requires hash: Buffer | string; and index: number; as attributes
152
+ * addInput requires hash: Uint8Array | string; and index: number; as attributes
114
153
  * and can also include any attributes that are used in updateInput method.
115
- * addOutput requires script: Buffer; and value: number; and likewise can include
154
+ * addOutput requires script: Uint8Array; and value: bigint; and likewise can include
116
155
  * data for updateOutput.
117
156
  * For a list of what attributes should be what types. Check the bip174 library.
118
157
  * Also, check the integration tests for some examples of usage.
@@ -141,36 +180,37 @@ export interface PsbtBaseExtended extends Omit<PsbtBase, 'inputs'> {
141
180
  * Psbt class can parse and generate a PSBT binary based off of the BIP174.
142
181
  */
143
182
  export class Psbt {
144
- private readonly __CACHE: PsbtCache;
145
- private readonly opts: PsbtOpts;
183
+ readonly #cache: PsbtCache;
184
+ readonly #opts: PsbtOpts;
146
185
 
147
186
  constructor(
148
187
  opts: PsbtOptsOptional = {},
149
188
  public data: PsbtBaseExtended = new PsbtBase(new PsbtTransaction()),
150
189
  ) {
151
- this.opts = Object.assign({}, DEFAULT_OPTS, opts);
152
- this.__CACHE = {
153
- __NON_WITNESS_UTXO_TX_CACHE: [],
154
- __NON_WITNESS_UTXO_BUF_CACHE: [],
155
- __TX_IN_CACHE: {},
190
+ this.#opts = Object.assign({}, DEFAULT_OPTS, opts);
191
+ this.#cache = {
192
+ nonWitnessUtxoTxCache: [],
193
+ nonWitnessUtxoBufCache: [],
194
+ txInCache: {},
156
195
  // unsignedTx.tx property is dynamically added by PsbtBase
157
- __TX: (this.data.globalMap.unsignedTx as PsbtTransaction).tx,
158
- __UNSAFE_SIGN_NONSEGWIT: false,
196
+ tx: (this.data.globalMap.unsignedTx as PsbtTransaction).tx,
197
+ unsafeSignNonSegwit: false,
198
+ hasSignatures: false,
159
199
  };
160
200
 
161
201
  if (opts.version === 3) {
162
202
  this.setVersionTRUC();
163
203
  } else if (this.data.inputs.length === 0) this.setVersion(2);
204
+ }
164
205
 
165
- const dpew = <T>(obj: T, attr: string, enumerable: boolean, writable: boolean): void => {
166
- Object.defineProperty(obj, attr, {
167
- enumerable,
168
- writable,
169
- });
170
- };
206
+ /** @internal - Exposed for testing. Do not use in production code. */
207
+ get __CACHE(): PsbtCache {
208
+ return this.#cache;
209
+ }
171
210
 
172
- dpew(this, '__CACHE', false, true);
173
- dpew(this, 'opts', false, true);
211
+ /** @internal - Exposed for testing. Do not use in production code. */
212
+ get opts(): PsbtOpts {
213
+ return this.#opts;
174
214
  }
175
215
 
176
216
  get inputCount(): number {
@@ -178,7 +218,7 @@ export class Psbt {
178
218
  }
179
219
 
180
220
  get version(): number {
181
- return this.__CACHE.__TX.version;
221
+ return this.#cache.tx.version;
182
222
  }
183
223
 
184
224
  set version(version: number) {
@@ -186,7 +226,7 @@ export class Psbt {
186
226
  }
187
227
 
188
228
  get locktime(): number {
189
- return this.__CACHE.__TX.locktime;
229
+ return this.#cache.tx.locktime;
190
230
  }
191
231
 
192
232
  set locktime(locktime: number) {
@@ -194,21 +234,21 @@ export class Psbt {
194
234
  }
195
235
 
196
236
  get txInputs(): PsbtTxInput[] {
197
- return this.__CACHE.__TX.ins.map((input) => ({
198
- hash: cloneBuffer(input.hash),
237
+ return this.#cache.tx.ins.map((input) => ({
238
+ hash: clone(input.hash) as Bytes32,
199
239
  index: input.index,
200
240
  sequence: input.sequence,
201
241
  }));
202
242
  }
203
243
 
204
244
  get txOutputs(): PsbtTxOutput[] {
205
- return this.__CACHE.__TX.outs.map((output) => {
245
+ return this.#cache.tx.outs.map((output) => {
206
246
  let address;
207
247
  try {
208
- address = fromOutputScript(output.script, this.opts.network);
248
+ address = fromOutputScript(output.script, this.#opts.network);
209
249
  } catch (_) {}
210
250
  return {
211
- script: cloneBuffer(output.script),
251
+ script: clone(output.script) as Script,
212
252
  value: output.value,
213
253
  address,
214
254
  };
@@ -216,19 +256,28 @@ export class Psbt {
216
256
  }
217
257
 
218
258
  static fromBase64(data: string, opts: PsbtOptsOptional = {}): Psbt {
219
- const buffer = Buffer.from(data, 'base64');
259
+ const buffer = fromBase64(data);
220
260
  return this.fromBuffer(buffer, opts);
221
261
  }
222
262
 
223
263
  static fromHex(data: string, opts: PsbtOptsOptional = {}): Psbt {
224
- const buffer = Buffer.from(data, 'hex');
264
+ const buffer = fromHex(data);
225
265
  return this.fromBuffer(buffer, opts);
226
266
  }
227
267
 
228
- static fromBuffer(buffer: Buffer, opts: PsbtOptsOptional = {}): Psbt {
268
+ static fromBuffer(buffer: Uint8Array, opts: PsbtOptsOptional = {}): Psbt {
229
269
  const psbtBase = PsbtBase.fromBuffer(buffer, transactionFromBuffer);
230
270
  const psbt = new Psbt(opts, psbtBase);
231
- checkTxForDupeIns(psbt.__CACHE.__TX, psbt.__CACHE);
271
+ checkTxForDupeIns(psbt.#cache.tx, psbt.#cache);
272
+ // Check if restored PSBT has any signatures (partial or finalized)
273
+ psbt.#cache.hasSignatures = psbt.data.inputs.some(
274
+ (input) =>
275
+ input.partialSig?.length ||
276
+ input.tapKeySig ||
277
+ input.tapScriptSig?.length ||
278
+ input.finalScriptSig ||
279
+ input.finalScriptWitness,
280
+ );
232
281
  return psbt;
233
282
  }
234
283
 
@@ -239,21 +288,21 @@ export class Psbt {
239
288
 
240
289
  clone(): Psbt {
241
290
  // TODO: more efficient cloning
242
- const clonedOpts = JSON.parse(JSON.stringify(this.opts)) as PsbtOptsOptional;
243
- return Psbt.fromBuffer(this.data.toBuffer(), clonedOpts);
291
+ const clonedOpts = JSON.parse(JSON.stringify(this.#opts)) as PsbtOptsOptional;
292
+ return Psbt.fromBuffer(new Uint8Array(this.data.toBuffer()), clonedOpts);
244
293
  }
245
294
 
246
295
  setMaximumFeeRate(satoshiPerByte: number): void {
247
296
  check32Bit(satoshiPerByte); // 42.9 BTC per byte IS excessive... so throw
248
- this.opts.maximumFeeRate = satoshiPerByte;
297
+ this.#opts.maximumFeeRate = satoshiPerByte;
249
298
  }
250
299
 
251
300
  setVersion(version: number): this {
252
301
  check32Bit(version);
253
- checkInputsForPartialSig(this.data.inputs, 'setVersion');
254
- const c = this.__CACHE;
255
- c.__TX.version = version;
256
- c.__EXTRACTED_TX = undefined;
302
+ checkInputsForPartialSig(this.data.inputs, 'setVersion', this.#cache.hasSignatures);
303
+ const c = this.#cache;
304
+ c.tx.version = version;
305
+ c.extractedTx = undefined;
257
306
  return this;
258
307
  }
259
308
 
@@ -263,22 +312,22 @@ export class Psbt {
263
312
 
264
313
  setLocktime(locktime: number): this {
265
314
  check32Bit(locktime);
266
- checkInputsForPartialSig(this.data.inputs, 'setLocktime');
267
- const c = this.__CACHE;
268
- c.__TX.locktime = locktime;
269
- c.__EXTRACTED_TX = undefined;
315
+ checkInputsForPartialSig(this.data.inputs, 'setLocktime', this.#cache.hasSignatures);
316
+ const c = this.#cache;
317
+ c.tx.locktime = locktime;
318
+ c.extractedTx = undefined;
270
319
  return this;
271
320
  }
272
321
 
273
322
  setInputSequence(inputIndex: number, sequence: number): this {
274
323
  check32Bit(sequence);
275
- checkInputsForPartialSig(this.data.inputs, 'setInputSequence');
276
- const c = this.__CACHE;
277
- if (c.__TX.ins.length <= inputIndex) {
324
+ checkInputsForPartialSig(this.data.inputs, 'setInputSequence', this.#cache.hasSignatures);
325
+ const c = this.#cache;
326
+ if (c.tx.ins.length <= inputIndex) {
278
327
  throw new Error('Input index too high');
279
328
  }
280
- c.__TX.ins[inputIndex].sequence = sequence;
281
- c.__EXTRACTED_TX = undefined;
329
+ c.tx.ins[inputIndex]!.sequence = sequence;
330
+ c.extractedTx = undefined;
282
331
  return this;
283
332
  }
284
333
 
@@ -298,90 +347,118 @@ export class Psbt {
298
347
  checkTaprootInputFields(inputData, inputData, 'addInput');
299
348
 
300
349
  if (checkPartialSigs) {
301
- checkInputsForPartialSig(this.data.inputs, 'addInput');
350
+ checkInputsForPartialSig(this.data.inputs, 'addInput', this.#cache.hasSignatures);
302
351
  }
303
352
 
304
353
  if (inputData.witnessScript) checkInvalidP2WSH(inputData.witnessScript);
305
- const c = this.__CACHE;
306
- this.data.addInput(inputData);
307
- const txIn = c.__TX.ins[c.__TX.ins.length - 1];
354
+ // Convert witnessUtxo for bip174 v3 compatibility (value: bigint, script: Uint8Array)
355
+ const normalizedInputData = inputData.witnessUtxo
356
+ ? {
357
+ ...inputData,
358
+ witnessUtxo: {
359
+ script: inputData.witnessUtxo.script,
360
+ value:
361
+ typeof inputData.witnessUtxo.value === 'bigint'
362
+ ? inputData.witnessUtxo.value
363
+ : BigInt(inputData.witnessUtxo.value),
364
+ },
365
+ }
366
+ : inputData;
367
+ const c = this.#cache;
368
+ this.data.addInput(normalizedInputData);
369
+ const txIn = c.tx.ins[c.tx.ins.length - 1]!;
308
370
  checkTxInputCache(c, txIn);
309
371
 
310
372
  const inputIndex = this.data.inputs.length - 1;
311
- const input = this.data.inputs[inputIndex];
373
+ const input = this.data.inputs[inputIndex]!;
312
374
  if (input.nonWitnessUtxo) {
313
- addNonWitnessTxCache(this.__CACHE, input, inputIndex);
375
+ addNonWitnessTxCache(this.#cache, input, inputIndex);
314
376
  }
315
- c.__FEE = undefined;
316
- c.__FEE_RATE = undefined;
317
- c.__EXTRACTED_TX = undefined;
377
+ c.fee = undefined;
378
+ c.feeRate = undefined;
379
+ c.extractedTx = undefined;
380
+ c.prevOuts = undefined;
381
+ c.signingScripts = undefined;
382
+ c.values = undefined;
383
+ c.taprootHashCache = undefined;
318
384
  return this;
319
385
  }
320
386
 
321
- addOutputs(outputDatas: PsbtOutputExtended[]): this {
322
- outputDatas.forEach((outputData) => this.addOutput(outputData));
387
+ addOutputs(outputDatas: PsbtOutputExtended[], checkPartialSigs: boolean = true): this {
388
+ outputDatas.forEach((outputData) => this.addOutput(outputData, checkPartialSigs));
323
389
  return this;
324
390
  }
325
391
 
326
- addOutput(outputData: PsbtOutputExtended): this {
392
+ /**
393
+ * Add an output to the PSBT.
394
+ *
395
+ * **PERFORMANCE WARNING:** Passing an `address` string is ~10x slower than passing
396
+ * a `script` directly due to address parsing overhead (bech32 decode, etc.).
397
+ * For high-performance use cases with many outputs, pre-compute the script using
398
+ * `toOutputScript(address, network)` and pass `{ script, value }` instead.
399
+ *
400
+ * @param outputData - Output data with either `address` or `script`, and `value`
401
+ * @param checkPartialSigs - Whether to check for existing signatures (default: true)
402
+ */
403
+ addOutput(outputData: PsbtOutputExtended, checkPartialSigs: boolean = true): this {
327
404
  const hasAddress = 'address' in outputData;
328
405
  const hasScript = 'script' in outputData;
329
- if (
330
- arguments.length > 1 ||
331
- !outputData ||
332
- outputData.value === undefined ||
333
- (!hasAddress && !hasScript)
334
- ) {
406
+ if (!outputData || outputData.value === undefined || (!hasAddress && !hasScript)) {
335
407
  throw new Error(
336
408
  `Invalid arguments for Psbt.addOutput. ` +
337
409
  `Requires single object with at least [script or address] and [value]`,
338
410
  );
339
411
  }
340
- checkInputsForPartialSig(this.data.inputs, 'addOutput');
412
+ if (checkPartialSigs) {
413
+ checkInputsForPartialSig(this.data.inputs, 'addOutput', this.#cache.hasSignatures);
414
+ }
341
415
  if (hasAddress) {
342
416
  const { address } = outputData as PsbtOutputExtendedAddress;
343
- const { network } = this.opts;
344
- const script = toOutputScript(address, network);
417
+ const { network } = this.#opts;
418
+ const script = toOutputScript(address, network) as Script;
345
419
  outputData = Object.assign({}, outputData, { script });
346
420
  }
347
421
  checkTaprootOutputFields(outputData, outputData, 'addOutput');
348
422
 
349
- const c = this.__CACHE;
423
+ const c = this.#cache;
350
424
  this.data.addOutput(outputData);
351
- c.__FEE = undefined;
352
- c.__FEE_RATE = undefined;
353
- c.__EXTRACTED_TX = undefined;
425
+ c.fee = undefined;
426
+ c.feeRate = undefined;
427
+ c.extractedTx = undefined;
428
+ c.taprootHashCache = undefined;
354
429
  return this;
355
430
  }
356
431
 
357
432
  extractTransaction(disableFeeCheck?: boolean, disableOutputChecks?: boolean): Transaction {
358
433
  if (disableOutputChecks) {
359
- this.data.inputs = this.data.inputs.filter((i) => !i.partialSig);
434
+ (this.data as unknown as { inputs: PsbtInput[] }).inputs = this.data.inputs.filter(
435
+ (i) => !i.partialSig,
436
+ );
360
437
  }
361
438
 
362
439
  if (!this.data.inputs.every(isFinalized)) throw new Error('Not finalized');
363
- const c = this.__CACHE;
440
+ const c = this.#cache;
364
441
  if (!disableFeeCheck) {
365
- checkFees(this, c, this.opts);
442
+ checkFees(this, c, this.#opts);
366
443
  }
367
- if (c.__EXTRACTED_TX) return c.__EXTRACTED_TX;
368
- const tx = c.__TX.clone();
444
+ if (c.extractedTx) return c.extractedTx;
445
+ const tx = c.tx.clone();
369
446
  inputFinalizeGetAmts(this.data.inputs, tx, c, true, disableOutputChecks);
370
447
  return tx;
371
448
  }
372
449
 
373
450
  getFeeRate(disableOutputChecks: boolean = false): number {
374
451
  return getTxCacheValue(
375
- '__FEE_RATE',
452
+ 'feeRate',
376
453
  'fee rate',
377
454
  this.data.inputs,
378
- this.__CACHE,
455
+ this.#cache,
379
456
  disableOutputChecks,
380
457
  );
381
458
  }
382
459
 
383
460
  getFee(disableOutputChecks: boolean = false): number {
384
- return getTxCacheValue('__FEE', 'fee', this.data.inputs, this.__CACHE, disableOutputChecks);
461
+ return getTxCacheValue('fee', 'fee', this.data.inputs, this.#cache, disableOutputChecks);
385
462
  }
386
463
 
387
464
  finalizeAllInputs(): this {
@@ -397,14 +474,14 @@ export class Psbt {
397
474
  ): this {
398
475
  const input = checkForInput(this.data.inputs, inputIndex);
399
476
  if (isTaprootInput(input)) {
400
- return this._finalizeTaprootInput(
477
+ return this.#finalizeTaprootInput(
401
478
  inputIndex,
402
479
  input,
403
480
  undefined,
404
481
  finalScriptsFunc as FinalTaprootScriptsFunc,
405
482
  );
406
483
  }
407
- return this._finalizeInput(
484
+ return this.#finalizeInput(
408
485
  inputIndex,
409
486
  input,
410
487
  finalScriptsFunc as FinalScriptsFunc,
@@ -414,12 +491,12 @@ export class Psbt {
414
491
 
415
492
  finalizeTaprootInput(
416
493
  inputIndex: number,
417
- tapLeafHashToFinalize?: Buffer,
494
+ tapLeafHashToFinalize?: Bytes32,
418
495
  finalScriptsFunc: FinalTaprootScriptsFunc = tapScriptFinalizer,
419
496
  ): this {
420
497
  const input = checkForInput(this.data.inputs, inputIndex);
421
498
  if (isTaprootInput(input))
422
- return this._finalizeTaprootInput(
499
+ return this.#finalizeTaprootInput(
423
500
  inputIndex,
424
501
  input,
425
502
  tapLeafHashToFinalize,
@@ -430,7 +507,7 @@ export class Psbt {
430
507
 
431
508
  getInputType(inputIndex: number): AllScriptType {
432
509
  const input = checkForInput(this.data.inputs, inputIndex);
433
- const script = getScriptFromUtxo(inputIndex, input, this.__CACHE);
510
+ const script = getScriptFromUtxo(inputIndex, input, this.#cache);
434
511
  const result = getMeaningfulScript(
435
512
  script,
436
513
  inputIndex,
@@ -443,9 +520,9 @@ export class Psbt {
443
520
  return (type + mainType) as AllScriptType;
444
521
  }
445
522
 
446
- inputHasPubkey(inputIndex: number, pubkey: Buffer): boolean {
523
+ inputHasPubkey(inputIndex: number, pubkey: PublicKey): boolean {
447
524
  const input = checkForInput(this.data.inputs, inputIndex);
448
- return pubkeyInInput(pubkey, input, inputIndex, this.__CACHE);
525
+ return pubkeyInInput(pubkey, input, inputIndex, this.#cache);
449
526
  }
450
527
 
451
528
  inputHasHDKey(inputIndex: number, root: HDSigner): boolean {
@@ -454,9 +531,9 @@ export class Psbt {
454
531
  return !!input.bip32Derivation && input.bip32Derivation.some(derivationIsMine);
455
532
  }
456
533
 
457
- outputHasPubkey(outputIndex: number, pubkey: Buffer): boolean {
534
+ outputHasPubkey(outputIndex: number, pubkey: PublicKey): boolean {
458
535
  const output = checkForOutput(this.data.outputs, outputIndex);
459
- return pubkeyInOutput(pubkey, output, outputIndex, this.__CACHE);
536
+ return pubkeyInOutput(pubkey, output, outputIndex, this.#cache);
460
537
  }
461
538
 
462
539
  outputHasHDKey(outputIndex: number, root: HDSigner): boolean {
@@ -476,13 +553,13 @@ export class Psbt {
476
553
  validateSignaturesOfInput(
477
554
  inputIndex: number,
478
555
  validator: ValidateSigFunction,
479
- pubkey?: Buffer,
556
+ pubkey?: PublicKey,
480
557
  ): boolean {
481
- const input = this.data.inputs[inputIndex];
558
+ const input = this.data.inputs[inputIndex]!;
482
559
  if (isTaprootInput(input))
483
- return this.validateSignaturesOfTaprootInput(inputIndex, validator, pubkey);
560
+ return this.#validateSignaturesOfTaprootInput(inputIndex, validator, pubkey);
484
561
 
485
- return this._validateSignaturesOfInput(inputIndex, validator, pubkey);
562
+ return this.#validateSignaturesOfInput(inputIndex, validator, pubkey);
486
563
  }
487
564
 
488
565
  signAllInputsHD(hdKeyPair: HDSigner, sighashTypes: number[] = [Transaction.SIGHASH_ALL]): this {
@@ -545,7 +622,7 @@ export class Psbt {
545
622
  if (!hdKeyPair || !hdKeyPair.publicKey || !hdKeyPair.fingerprint) {
546
623
  throw new Error('Need HDSigner to sign input');
547
624
  }
548
- const signers = getSignersFromHD(inputIndex, this.data.inputs, hdKeyPair) as Signer[];
625
+ const signers = getSignersFromHD(inputIndex, this.data.inputs, hdKeyPair);
549
626
  signers.forEach((signer) => this.signInput(inputIndex, signer, sighashTypes));
550
627
  return this;
551
628
  }
@@ -561,7 +638,7 @@ export class Psbt {
561
638
  }
562
639
  const signers = getSignersFromHD(inputIndex, this.data.inputs, hdKeyPair);
563
640
  const promises = signers.map((signer) =>
564
- this.signInputAsync(inputIndex, signer as unknown as Signer, sighashTypes),
641
+ this.signInputAsync(inputIndex, signer, sighashTypes),
565
642
  );
566
643
  return Promise.all(promises)
567
644
  .then(() => {
@@ -631,7 +708,7 @@ export class Psbt {
631
708
 
632
709
  signInput(
633
710
  inputIndex: number,
634
- keyPair: Signer | SignerAlternative | BIP32Interface | ECPairInterface,
711
+ keyPair: Signer | SignerAlternative | HDSigner | BIP32Interface | ECPairInterface,
635
712
  sighashTypes?: number[],
636
713
  ): this {
637
714
  if (!keyPair || !keyPair.publicKey) {
@@ -640,16 +717,16 @@ export class Psbt {
640
717
 
641
718
  const input = checkForInput(this.data.inputs, inputIndex);
642
719
  if (isTaprootInput(input)) {
643
- return this._signTaprootInput(inputIndex, input, keyPair, undefined, sighashTypes);
720
+ return this.#signTaprootInput(inputIndex, input, keyPair, undefined, sighashTypes);
644
721
  }
645
722
 
646
- return this._signInput(inputIndex, keyPair, sighashTypes);
723
+ return this.#signInput(inputIndex, keyPair, sighashTypes);
647
724
  }
648
725
 
649
726
  signTaprootInput(
650
727
  inputIndex: number,
651
- keyPair: Signer | SignerAlternative | BIP32Interface | ECPairInterface,
652
- tapLeafHashToSign?: Buffer,
728
+ keyPair: Signer | SignerAlternative | HDSigner | BIP32Interface | ECPairInterface,
729
+ tapLeafHashToSign?: Uint8Array,
653
730
  sighashTypes?: number[],
654
731
  ): this {
655
732
  if (!keyPair || !keyPair.publicKey) {
@@ -658,7 +735,7 @@ export class Psbt {
658
735
 
659
736
  const input = checkForInput(this.data.inputs, inputIndex);
660
737
  if (isTaprootInput(input)) {
661
- return this._signTaprootInput(
738
+ return this.#signTaprootInput(
662
739
  inputIndex,
663
740
  input,
664
741
  keyPair,
@@ -672,7 +749,14 @@ export class Psbt {
672
749
 
673
750
  signInputAsync(
674
751
  inputIndex: number,
675
- keyPair: Signer | SignerAlternative | SignerAsync | BIP32Interface | ECPairInterface,
752
+ keyPair:
753
+ | Signer
754
+ | SignerAlternative
755
+ | SignerAsync
756
+ | HDSigner
757
+ | HDSignerAsync
758
+ | BIP32Interface
759
+ | ECPairInterface,
676
760
  sighashTypes?: number[],
677
761
  ): Promise<void> {
678
762
  return Promise.resolve().then(() => {
@@ -680,7 +764,7 @@ export class Psbt {
680
764
 
681
765
  const input = checkForInput(this.data.inputs, inputIndex);
682
766
  if (isTaprootInput(input))
683
- return this._signTaprootInputAsync(
767
+ return this.#signTaprootInputAsync(
684
768
  inputIndex,
685
769
  input,
686
770
  keyPair,
@@ -688,14 +772,21 @@ export class Psbt {
688
772
  sighashTypes,
689
773
  );
690
774
 
691
- return this._signInputAsync(inputIndex, keyPair, sighashTypes);
775
+ return this.#signInputAsync(inputIndex, keyPair, sighashTypes);
692
776
  });
693
777
  }
694
778
 
695
779
  signTaprootInputAsync(
696
780
  inputIndex: number,
697
- keyPair: Signer | SignerAlternative | SignerAsync | BIP32Interface | ECPairInterface,
698
- tapLeafHash?: Buffer,
781
+ keyPair:
782
+ | Signer
783
+ | SignerAlternative
784
+ | SignerAsync
785
+ | HDSigner
786
+ | HDSignerAsync
787
+ | BIP32Interface
788
+ | ECPairInterface,
789
+ tapLeafHash?: Uint8Array,
699
790
  sighashTypes?: number[],
700
791
  ): Promise<void> {
701
792
  return Promise.resolve().then(() => {
@@ -703,7 +794,7 @@ export class Psbt {
703
794
 
704
795
  const input = checkForInput(this.data.inputs, inputIndex);
705
796
  if (isTaprootInput(input))
706
- return this._signTaprootInputAsync(
797
+ return this.#signTaprootInputAsync(
707
798
  inputIndex,
708
799
  input,
709
800
  keyPair,
@@ -715,18 +806,18 @@ export class Psbt {
715
806
  });
716
807
  }
717
808
 
718
- toBuffer(): Buffer {
719
- checkCache(this.__CACHE);
720
- return this.data.toBuffer();
809
+ toBuffer(): Uint8Array {
810
+ checkCache(this.#cache);
811
+ return new Uint8Array(this.data.toBuffer());
721
812
  }
722
813
 
723
814
  toHex(): string {
724
- checkCache(this.__CACHE);
815
+ checkCache(this.#cache);
725
816
  return this.data.toHex();
726
817
  }
727
818
 
728
819
  toBase64(): string {
729
- checkCache(this.__CACHE);
820
+ checkCache(this.#cache);
730
821
  return this.data.toBase64();
731
822
  }
732
823
 
@@ -737,16 +828,29 @@ export class Psbt {
737
828
 
738
829
  updateInput(inputIndex: number, updateData: PsbtInputUpdate): this {
739
830
  if (updateData.witnessScript) checkInvalidP2WSH(updateData.witnessScript);
740
- checkTaprootInputFields(this.data.inputs[inputIndex], updateData, 'updateInput');
741
- this.data.updateInput(inputIndex, updateData);
831
+ checkTaprootInputFields(this.data.inputs[inputIndex]!, updateData, 'updateInput');
832
+ // Convert witnessUtxo for bip174 v3 compatibility (value: bigint, script: Uint8Array)
833
+ const normalizedUpdate = updateData.witnessUtxo
834
+ ? {
835
+ ...updateData,
836
+ witnessUtxo: {
837
+ script: updateData.witnessUtxo.script,
838
+ value:
839
+ typeof updateData.witnessUtxo.value === 'bigint'
840
+ ? updateData.witnessUtxo.value
841
+ : BigInt(updateData.witnessUtxo.value),
842
+ },
843
+ }
844
+ : updateData;
845
+ this.data.updateInput(inputIndex, normalizedUpdate);
742
846
  if (updateData.nonWitnessUtxo) {
743
- addNonWitnessTxCache(this.__CACHE, this.data.inputs[inputIndex], inputIndex);
847
+ addNonWitnessTxCache(this.#cache, this.data.inputs[inputIndex]!, inputIndex);
744
848
  }
745
849
  return this;
746
850
  }
747
851
 
748
852
  updateOutput(outputIndex: number, updateData: PsbtOutputUpdate): this {
749
- const outputData = this.data.outputs[outputIndex];
853
+ const outputData = this.data.outputs[outputIndex]!;
750
854
  checkTaprootOutputFields(outputData, updateData, 'updateOutput');
751
855
 
752
856
  this.data.updateOutput(outputIndex, updateData);
@@ -773,39 +877,46 @@ export class Psbt {
773
877
  return this;
774
878
  }
775
879
 
776
- public checkTaprootHashesForSig(
880
+ checkTaprootHashesForSig(
777
881
  inputIndex: number,
778
882
  input: PsbtInput,
779
- keyPair: Signer | SignerAlternative | SignerAsync | BIP32Interface | ECPairInterface,
780
- tapLeafHashToSign?: Buffer,
883
+ keyPair:
884
+ | Signer
885
+ | SignerAlternative
886
+ | SignerAsync
887
+ | HDSigner
888
+ | HDSignerAsync
889
+ | TaprootHashCheckSigner
890
+ | BIP32Interface
891
+ | ECPairInterface,
892
+ tapLeafHashToSign?: Uint8Array,
781
893
  allowedSighashTypes?: number[],
782
- ): { hash: Buffer; leafHash?: Buffer }[] {
783
- if (typeof keyPair.signSchnorr !== 'function')
894
+ ): { hash: Bytes32; leafHash?: Bytes32 }[] {
895
+ if (!('signSchnorr' in keyPair) || typeof keyPair.signSchnorr !== 'function')
784
896
  throw new Error(`Need Schnorr Signer to sign taproot input #${inputIndex}.`);
785
897
 
786
- const pubkey = Buffer.isBuffer(keyPair.publicKey)
787
- ? keyPair.publicKey
788
- : Buffer.from(keyPair.publicKey);
898
+ const pubkey =
899
+ keyPair.publicKey instanceof Uint8Array
900
+ ? keyPair.publicKey
901
+ : new Uint8Array(keyPair.publicKey);
789
902
 
790
903
  const hashesForSig = getTaprootHashesForSig(
791
904
  inputIndex,
792
905
  input,
793
906
  this.data.inputs,
794
907
  pubkey,
795
- this.__CACHE,
908
+ this.#cache,
796
909
  tapLeafHashToSign,
797
910
  allowedSighashTypes,
798
911
  );
799
912
 
800
913
  if (!hashesForSig || !hashesForSig.length)
801
- throw new Error(
802
- `Can not sign for input #${inputIndex} with the key ${pubkey.toString('hex')}`,
803
- );
914
+ throw new Error(`Can not sign for input #${inputIndex} with the key ${toHex(pubkey)}`);
804
915
 
805
916
  return hashesForSig;
806
917
  }
807
918
 
808
- private _finalizeInput(
919
+ #finalizeInput(
809
920
  inputIndex: number,
810
921
  input: PsbtInput,
811
922
  finalScriptsFunc: FinalScriptsFunc = getFinalScripts,
@@ -814,7 +925,7 @@ export class Psbt {
814
925
  const { script, isP2SH, isP2WSH, isSegwit } = getScriptFromInput(
815
926
  inputIndex,
816
927
  input,
817
- this.__CACHE,
928
+ this.#cache,
818
929
  );
819
930
  if (!script) throw new Error(`No script found for input #${inputIndex}`);
820
931
 
@@ -839,11 +950,11 @@ export class Psbt {
839
950
  return this;
840
951
  }
841
952
 
842
- private _finalizeTaprootInput(
953
+ #finalizeTaprootInput(
843
954
  inputIndex: number,
844
955
  input: PsbtInput,
845
- tapLeafHashToFinalize?: Buffer,
846
- finalScriptsFunc = tapScriptFinalizer,
956
+ tapLeafHashToFinalize?: Bytes32,
957
+ finalScriptsFunc: FinalTaprootScriptsFunc = tapScriptFinalizer,
847
958
  ): this {
848
959
  if (!input.witnessUtxo)
849
960
  throw new Error(`Cannot finalize input #${inputIndex}. Missing witness utxo.`);
@@ -851,8 +962,8 @@ export class Psbt {
851
962
  // Check key spend first. Increased privacy and reduced block space.
852
963
  if (input.tapKeySig) {
853
964
  const payment = payments.p2tr({
854
- output: input.witnessUtxo.script,
855
- signature: input.tapKeySig,
965
+ output: input.witnessUtxo.script as Script,
966
+ signature: input.tapKeySig as SchnorrSignature,
856
967
  });
857
968
  if (!payment.witness) throw new Error('Cannot finalize taproot key spend');
858
969
  const finalScriptWitness = witnessStackToScriptWitness(payment.witness);
@@ -863,7 +974,7 @@ export class Psbt {
863
974
  input,
864
975
  tapLeafHashToFinalize,
865
976
  );
866
- this.data.updateInput(inputIndex, { finalScriptWitness });
977
+ this.data.updateInput(inputIndex, { finalScriptWitness } as PsbtInputUpdate);
867
978
  }
868
979
 
869
980
  this.data.clearFinalizedInput(inputIndex);
@@ -871,10 +982,10 @@ export class Psbt {
871
982
  return this;
872
983
  }
873
984
 
874
- private _validateSignaturesOfInput(
985
+ #validateSignaturesOfInput(
875
986
  inputIndex: number,
876
987
  validator: ValidateSigFunction,
877
- pubkey?: Buffer,
988
+ pubkey?: PublicKey,
878
989
  ): boolean {
879
990
  const input = this.data.inputs[inputIndex];
880
991
  const partialSig = (input || {}).partialSig;
@@ -882,14 +993,16 @@ export class Psbt {
882
993
  throw new Error('No signatures to validate');
883
994
  if (typeof validator !== 'function')
884
995
  throw new Error('Need validator function to validate signatures');
885
- const mySigs = pubkey ? partialSig.filter((sig) => sig.pubkey.equals(pubkey)) : partialSig;
996
+ const mySigs = pubkey ? partialSig.filter((sig) => equals(sig.pubkey, pubkey)) : partialSig;
886
997
  if (mySigs.length < 1) throw new Error('No signatures for this pubkey');
887
998
  const results: boolean[] = [];
888
- let hashCache: Buffer | undefined;
889
- let scriptCache: Buffer | undefined;
999
+ let hashCache: Bytes32 | undefined;
1000
+ let scriptCache: Script | undefined;
890
1001
  let sighashCache: number | undefined;
891
1002
  for (const pSig of mySigs) {
892
- const sig = bscript.signature.decode(pSig.signature);
1003
+ const pSigSignature = pSig.signature;
1004
+ const pSigPubkey = pSig.pubkey as PublicKey;
1005
+ const sig = bscript.signature.decode(pSigSignature);
893
1006
  const { hash, script } =
894
1007
  sighashCache !== sig.hashType || !hashCache || !scriptCache
895
1008
  ? getHashForSig(
@@ -897,25 +1010,25 @@ export class Psbt {
897
1010
  Object.assign({}, input, {
898
1011
  sighashType: sig.hashType,
899
1012
  }),
900
- this.__CACHE,
1013
+ this.#cache,
901
1014
  true,
902
1015
  )
903
1016
  : { hash: hashCache, script: scriptCache };
904
1017
  sighashCache = sig.hashType;
905
1018
  hashCache = hash;
906
1019
  scriptCache = script;
907
- checkScriptForPubkey(pSig.pubkey, script, 'verify');
908
- results.push(validator(pSig.pubkey, hash, sig.signature));
1020
+ checkScriptForPubkey(pSigPubkey, script, 'verify');
1021
+ results.push(validator(pSigPubkey, hash, sig.signature));
909
1022
  }
910
1023
  return results.every((res) => res);
911
1024
  }
912
1025
 
913
- private validateSignaturesOfTaprootInput(
1026
+ #validateSignaturesOfTaprootInput(
914
1027
  inputIndex: number,
915
1028
  validator: ValidateSigFunction,
916
- pubkey?: Buffer,
1029
+ pubkey?: PublicKey,
917
1030
  ): boolean {
918
- const input = this.data.inputs[inputIndex];
1031
+ const input = this.data.inputs[inputIndex]!;
919
1032
  const tapKeySig = (input || {}).tapKeySig;
920
1033
  const tapScriptSig = (input || {}).tapScriptSig;
921
1034
  if (!input && !tapKeySig && !(tapScriptSig && !tapScriptSig.length))
@@ -923,10 +1036,10 @@ export class Psbt {
923
1036
  if (typeof validator !== 'function')
924
1037
  throw new Error('Need validator function to validate signatures');
925
1038
 
926
- pubkey = pubkey && toXOnly(pubkey);
927
- const allHashses = pubkey
928
- ? getTaprootHashesForSig(inputIndex, input, this.data.inputs, pubkey, this.__CACHE)
929
- : getAllTaprootHashesForSig(inputIndex, input, this.data.inputs, this.__CACHE);
1039
+ const xPubkey = pubkey ? toXOnly(pubkey) : undefined;
1040
+ const allHashses = xPubkey
1041
+ ? getTaprootHashesForSig(inputIndex, input, this.data.inputs, xPubkey, this.#cache)
1042
+ : getAllTaprootHashesForSig(inputIndex, input, this.data.inputs, this.#cache);
930
1043
 
931
1044
  if (!allHashses.length) throw new Error('No signatures for this pubkey');
932
1045
 
@@ -944,10 +1057,11 @@ export class Psbt {
944
1057
 
945
1058
  if (tapScriptSig) {
946
1059
  for (const tapSig of tapScriptSig) {
947
- const tapSigHash = allHashses.find((h) => tapSig.pubkey.equals(h.pubkey));
1060
+ const tapSigPubkey = tapSig.pubkey as PublicKey;
1061
+ const tapSigHash = allHashses.find((h) => equals(tapSigPubkey, h.pubkey));
948
1062
  if (tapSigHash) {
949
1063
  const isValidTapScriptSig = validator(
950
- tapSig.pubkey,
1064
+ tapSigPubkey,
951
1065
  tapSigHash.hash,
952
1066
  trimTaprootSig(tapSig.signature),
953
1067
  );
@@ -960,52 +1074,55 @@ export class Psbt {
960
1074
  return validationResultCount > 0;
961
1075
  }
962
1076
 
963
- private _signInput(
1077
+ #signInput(
964
1078
  inputIndex: number,
965
- keyPair: Signer | SignerAlternative | BIP32Interface | ECPairInterface,
1079
+ keyPair: Signer | SignerAlternative | HDSigner | BIP32Interface | ECPairInterface,
966
1080
  sighashTypes: number[] = [Transaction.SIGHASH_ALL],
967
1081
  ): this {
968
- //hookSigner(keyPair);
969
-
970
- const pubkey = Buffer.isBuffer(keyPair.publicKey)
971
- ? keyPair.publicKey
972
- : Buffer.from(keyPair.publicKey);
1082
+ const pubkey =
1083
+ keyPair.publicKey instanceof Uint8Array
1084
+ ? keyPair.publicKey
1085
+ : new Uint8Array(keyPair.publicKey);
973
1086
 
974
1087
  const { hash, sighashType } = getHashAndSighashType(
975
1088
  this.data.inputs,
976
1089
  inputIndex,
977
1090
  pubkey,
978
- this.__CACHE,
1091
+ this.#cache,
979
1092
  sighashTypes,
980
1093
  );
981
1094
 
982
- const sig = keyPair.sign(hash);
1095
+ const sig = keyPair.sign(hash) as Uint8Array;
983
1096
  const partialSig = [
984
1097
  {
985
1098
  pubkey,
986
1099
  signature: bscript.signature.encode(
987
- Buffer.isBuffer(sig) ? sig : Buffer.from(sig),
1100
+ sig instanceof Uint8Array ? sig : new Uint8Array(sig),
988
1101
  sighashType,
989
1102
  ),
990
1103
  },
991
1104
  ];
992
1105
 
993
1106
  this.data.updateInput(inputIndex, { partialSig });
1107
+ this.#cache.hasSignatures = true;
994
1108
  return this;
995
1109
  }
996
1110
 
997
- private _signTaprootInput(
1111
+ #signTaprootInput(
998
1112
  inputIndex: number,
999
1113
  input: PsbtInput,
1000
- keyPair: Signer | SignerAlternative | BIP32Interface | ECPairInterface,
1001
- tapLeafHashToSign?: Buffer,
1114
+ keyPair: Signer | SignerAlternative | HDSigner | BIP32Interface | ECPairInterface,
1115
+ tapLeafHashToSign?: Uint8Array,
1002
1116
  allowedSighashTypes: number[] = [Transaction.SIGHASH_DEFAULT],
1003
1117
  ): this {
1004
- //hookSigner(keyPair);
1118
+ const pubkey = (
1119
+ keyPair.publicKey instanceof Uint8Array
1120
+ ? keyPair.publicKey
1121
+ : new Uint8Array(keyPair.publicKey)
1122
+ ) as PublicKey;
1005
1123
 
1006
- const pubkey = Buffer.isBuffer(keyPair.publicKey)
1007
- ? keyPair.publicKey
1008
- : Buffer.from(keyPair.publicKey);
1124
+ if (!('signSchnorr' in keyPair) || typeof keyPair.signSchnorr !== 'function')
1125
+ throw new Error(`Need Schnorr Signer to sign taproot input #${inputIndex}.`);
1009
1126
 
1010
1127
  // checkTaprootHashesForSig validates signSchnorr exists
1011
1128
  const hashesForSig = this.checkTaprootHashesForSig(
@@ -1015,25 +1132,22 @@ export class Psbt {
1015
1132
  tapLeafHashToSign,
1016
1133
  allowedSighashTypes,
1017
1134
  );
1018
- const signSchnorr = (keyPair.signSchnorr as (h: Buffer) => Uint8Array).bind(keyPair);
1135
+ const signSchnorr = (keyPair.signSchnorr as (h: Uint8Array) => Uint8Array).bind(keyPair);
1019
1136
 
1020
- const toBuffer = (data: Uint8Array | Buffer): Buffer =>
1021
- Buffer.isBuffer(data) ? data : Buffer.from(data);
1022
-
1023
- const tapKeySig: TapKeySig = hashesForSig
1137
+ const tapKeySig = hashesForSig
1024
1138
  .filter((h) => !h.leafHash)
1025
1139
  .map((h) =>
1026
- serializeTaprootSignature(toBuffer(signSchnorr(h.hash)), input.sighashType),
1027
- )[0];
1140
+ serializeTaprootSignature(signSchnorr(h.hash), input.sighashType),
1141
+ )[0] as TapKeySig;
1028
1142
 
1029
- const tapScriptSig: TapScriptSig[] = hashesForSig
1143
+ const tapScriptSig = hashesForSig
1030
1144
  .filter((h) => !!h.leafHash)
1031
1145
  .map(
1032
1146
  (h) =>
1033
1147
  ({
1034
1148
  pubkey: toXOnly(pubkey),
1035
1149
  signature: serializeTaprootSignature(
1036
- toBuffer(signSchnorr(h.hash)),
1150
+ signSchnorr(h.hash),
1037
1151
  input.sighashType,
1038
1152
  ),
1039
1153
  leafHash: h.leafHash,
@@ -1042,36 +1156,44 @@ export class Psbt {
1042
1156
 
1043
1157
  if (tapKeySig) {
1044
1158
  this.data.updateInput(inputIndex, { tapKeySig });
1159
+ this.#cache.hasSignatures = true;
1045
1160
  }
1046
1161
 
1047
1162
  if (tapScriptSig.length) {
1048
1163
  this.data.updateInput(inputIndex, { tapScriptSig });
1164
+ this.#cache.hasSignatures = true;
1049
1165
  }
1050
1166
 
1051
1167
  return this;
1052
1168
  }
1053
1169
 
1054
- private _signInputAsync(
1170
+ #signInputAsync(
1055
1171
  inputIndex: number,
1056
- keyPair: Signer | SignerAlternative | SignerAsync | BIP32Interface | ECPairInterface,
1172
+ keyPair:
1173
+ | Signer
1174
+ | SignerAlternative
1175
+ | SignerAsync
1176
+ | HDSigner
1177
+ | HDSignerAsync
1178
+ | BIP32Interface
1179
+ | ECPairInterface,
1057
1180
  sighashTypes: number[] = [Transaction.SIGHASH_ALL],
1058
1181
  ): Promise<void> {
1059
- //hookSigner(keyPair);
1060
-
1061
- const pubkey = Buffer.isBuffer(keyPair.publicKey)
1062
- ? keyPair.publicKey
1063
- : Buffer.from(keyPair.publicKey);
1182
+ const pubkey =
1183
+ keyPair.publicKey instanceof Uint8Array
1184
+ ? keyPair.publicKey
1185
+ : new Uint8Array(keyPair.publicKey);
1064
1186
 
1065
1187
  const { hash, sighashType } = getHashAndSighashType(
1066
1188
  this.data.inputs,
1067
1189
  inputIndex,
1068
1190
  pubkey,
1069
- this.__CACHE,
1191
+ this.#cache,
1070
1192
  sighashTypes,
1071
1193
  );
1072
1194
 
1073
1195
  return Promise.resolve(keyPair.sign(hash)).then((signature) => {
1074
- const sig = Buffer.isBuffer(signature) ? signature : Buffer.from(signature);
1196
+ const sig = signature instanceof Uint8Array ? signature : new Uint8Array(signature);
1075
1197
  const partialSig = [
1076
1198
  {
1077
1199
  pubkey,
@@ -1080,21 +1202,32 @@ export class Psbt {
1080
1202
  ];
1081
1203
 
1082
1204
  this.data.updateInput(inputIndex, { partialSig });
1205
+ this.#cache.hasSignatures = true;
1083
1206
  });
1084
1207
  }
1085
1208
 
1086
- private async _signTaprootInputAsync(
1209
+ async #signTaprootInputAsync(
1087
1210
  inputIndex: number,
1088
1211
  input: PsbtInput,
1089
- keyPair: Signer | SignerAlternative | SignerAsync | BIP32Interface | ECPairInterface,
1090
- tapLeafHash?: Buffer,
1212
+ keyPair:
1213
+ | Signer
1214
+ | SignerAlternative
1215
+ | SignerAsync
1216
+ | HDSigner
1217
+ | HDSignerAsync
1218
+ | BIP32Interface
1219
+ | ECPairInterface,
1220
+ tapLeafHash?: Uint8Array,
1091
1221
  sighashTypes: number[] = [Transaction.SIGHASH_DEFAULT],
1092
1222
  ): Promise<void> {
1093
- //hookSigner(keyPair);
1223
+ const pubkey = (
1224
+ keyPair.publicKey instanceof Uint8Array
1225
+ ? keyPair.publicKey
1226
+ : new Uint8Array(keyPair.publicKey)
1227
+ ) as PublicKey;
1094
1228
 
1095
- const pubkey = Buffer.isBuffer(keyPair.publicKey)
1096
- ? keyPair.publicKey
1097
- : Buffer.from(keyPair.publicKey);
1229
+ if (!('signSchnorr' in keyPair) || typeof keyPair.signSchnorr !== 'function')
1230
+ throw new Error(`Need Schnorr Signer to sign taproot input #${inputIndex}.`);
1098
1231
 
1099
1232
  // checkTaprootHashesForSig validates signSchnorr exists
1100
1233
  const hashesForSig = this.checkTaprootHashesForSig(
@@ -1105,40 +1238,35 @@ export class Psbt {
1105
1238
  sighashTypes,
1106
1239
  );
1107
1240
  const signSchnorr = (
1108
- keyPair.signSchnorr as (hash: Buffer) => Uint8Array | Promise<Uint8Array>
1241
+ keyPair.signSchnorr as (hash: Uint8Array) => Uint8Array | Promise<Uint8Array>
1109
1242
  ).bind(keyPair);
1110
1243
 
1111
- const toBuffer = (data: Uint8Array | Buffer): Buffer =>
1112
- Buffer.isBuffer(data) ? data : Buffer.from(data);
1113
-
1114
- const signaturePromises: Promise<
1115
- { tapKeySig: Buffer } | { tapScriptSig: TapScriptSig[] }
1116
- >[] = [];
1244
+ type TapSignatureResult = { tapKeySig: Uint8Array } | { tapScriptSig: TapScriptSig[] };
1245
+ const signaturePromises: Promise<TapSignatureResult>[] = [];
1117
1246
 
1118
1247
  const tapKeyHash = hashesForSig.filter((h) => !h.leafHash)[0];
1119
1248
  if (tapKeyHash) {
1120
1249
  const tapKeySigPromise = Promise.resolve(signSchnorr(tapKeyHash.hash)).then((sig) => {
1121
1250
  return {
1122
- tapKeySig: serializeTaprootSignature(toBuffer(sig), input.sighashType),
1251
+ tapKeySig: serializeTaprootSignature(sig, input.sighashType),
1123
1252
  };
1124
1253
  });
1125
1254
  signaturePromises.push(tapKeySigPromise);
1126
1255
  }
1127
1256
 
1128
- const tapScriptHashes = hashesForSig.filter((h) => !!h.leafHash);
1257
+ const tapScriptHashes = hashesForSig.filter(
1258
+ (h): h is typeof h & { leafHash: Bytes32 } => !!h.leafHash,
1259
+ );
1129
1260
  if (tapScriptHashes.length) {
1130
1261
  const tapScriptSigPromises = tapScriptHashes.map(async (tsh) => {
1131
1262
  const signature = await signSchnorr(tsh.hash);
1132
1263
 
1133
- const tapScriptSig = [
1264
+ const tapScriptSig: TapScriptSig[] = [
1134
1265
  {
1135
1266
  pubkey: toXOnly(pubkey),
1136
- signature: serializeTaprootSignature(
1137
- toBuffer(signature),
1138
- input.sighashType,
1139
- ),
1267
+ signature: serializeTaprootSignature(signature, input.sighashType),
1140
1268
  leafHash: tsh.leafHash,
1141
- } as TapScriptSig,
1269
+ },
1142
1270
  ];
1143
1271
 
1144
1272
  return { tapScriptSig };
@@ -1148,124 +1276,18 @@ export class Psbt {
1148
1276
 
1149
1277
  const results = await Promise.all(signaturePromises);
1150
1278
  for (const v of results) {
1151
- this.data.updateInput(inputIndex, v);
1279
+ this.data.updateInput(inputIndex, v as PsbtInputUpdate);
1280
+ this.#cache.hasSignatures = true;
1152
1281
  }
1153
1282
  }
1154
1283
  }
1155
1284
 
1156
- interface PsbtCache {
1157
- __NON_WITNESS_UTXO_TX_CACHE: Transaction[];
1158
- __NON_WITNESS_UTXO_BUF_CACHE: Buffer[];
1159
- __TX_IN_CACHE: { [index: string]: number };
1160
- __TX: Transaction;
1161
- __FEE_RATE?: number;
1162
- __FEE?: number;
1163
- __EXTRACTED_TX?: Transaction;
1164
- __UNSAFE_SIGN_NONSEGWIT: boolean;
1165
- }
1166
-
1167
- export interface PsbtOptsOptional {
1168
- network?: Network;
1169
- maximumFeeRate?: number;
1170
- version?: 1 | 2 | 3;
1171
- }
1172
-
1173
- export interface PsbtOpts {
1174
- network: Network;
1175
- maximumFeeRate: number;
1176
- }
1177
-
1178
- export interface PsbtInputExtended extends PsbtInput, TransactionInput {
1179
- isPayToAnchor?: boolean;
1180
- }
1181
-
1182
- export type PsbtOutputExtended = PsbtOutputExtendedAddress | PsbtOutputExtendedScript;
1183
-
1184
- export interface PsbtOutputExtendedAddress extends PsbtOutput {
1185
- address: string;
1186
- value: number;
1187
- }
1188
-
1189
- export interface PsbtOutputExtendedScript extends PsbtOutput {
1190
- script: Buffer;
1191
- value: number;
1192
- }
1193
-
1194
- interface HDSignerBase {
1195
- /**
1196
- * DER format compressed publicKey buffer
1197
- */
1198
- publicKey: Buffer;
1199
- /**
1200
- * The first 4 bytes of the sha256-ripemd160 of the publicKey
1201
- */
1202
- fingerprint: Buffer;
1203
- }
1204
-
1205
- export interface HDSigner extends HDSignerBase {
1206
- /**
1207
- * The path string must match /^m(\/\d+'?)+$/
1208
- * ex. m/44'/0'/0'/1/23 levels with ' must be hard derivations
1209
- */
1210
- derivePath(path: string): HDSigner;
1211
-
1212
- /**
1213
- * Input hash (the "message digest") for the signature algorithm
1214
- * Return a 64 byte signature (32 byte r and 32 byte s in that order)
1215
- */
1216
- sign(hash: Buffer): Buffer;
1217
- }
1218
-
1219
- /**
1220
- * Same as above but with async sign method
1221
- */
1222
- export interface HDSignerAsync extends HDSignerBase {
1223
- derivePath(path: string): HDSignerAsync;
1224
-
1225
- sign(hash: Buffer): Promise<Buffer>;
1226
- }
1227
-
1228
- export interface SignerAlternative {
1229
- publicKey: Buffer;
1230
- lowR: boolean;
1231
-
1232
- sign(hash: Buffer, lowR?: boolean): Buffer;
1233
-
1234
- verify(hash: Buffer, signature: Buffer): boolean;
1235
-
1236
- signSchnorr(hash: Buffer): Buffer;
1237
-
1238
- verifySchnorr(hash: Buffer, signature: Buffer): boolean;
1239
- }
1240
-
1241
- export interface Signer {
1242
- publicKey: Buffer;
1243
- network?: Network;
1244
-
1245
- sign(hash: Buffer, lowR?: boolean): Buffer;
1246
-
1247
- signSchnorr?(hash: Buffer): Buffer;
1248
-
1249
- getPublicKey?(): Buffer;
1250
- }
1251
-
1252
- export interface SignerAsync {
1253
- publicKey: Buffer;
1254
- network?: Network;
1255
-
1256
- sign(hash: Buffer, lowR?: boolean): Promise<Buffer>;
1257
-
1258
- signSchnorr?(hash: Buffer): Promise<Buffer>;
1259
-
1260
- getPublicKey?(): Buffer;
1261
- }
1262
-
1263
1285
  /**
1264
1286
  * This function is needed to pass to the bip174 base class's fromBuffer.
1265
1287
  * It takes the "transaction buffer" portion of the psbt buffer and returns a
1266
1288
  * Transaction (From the bip174 library) interface.
1267
1289
  */
1268
- const transactionFromBuffer: TransactionFromBuffer = (buffer: Buffer): ITransaction =>
1290
+ const transactionFromBuffer: TransactionFromBuffer = (buffer: Uint8Array): ITransaction =>
1269
1291
  new PsbtTransaction(buffer);
1270
1292
 
1271
1293
  /**
@@ -1275,7 +1297,7 @@ const transactionFromBuffer: TransactionFromBuffer = (buffer: Buffer): ITransact
1275
1297
  class PsbtTransaction implements ITransaction {
1276
1298
  tx: Transaction;
1277
1299
 
1278
- constructor(buffer: Buffer = Buffer.from([2, 0, 0, 0, 0, 0, 0, 0, 0, 0])) {
1300
+ constructor(buffer: Uint8Array = new Uint8Array([2, 0, 0, 0, 0, 0, 0, 0, 0, 0])) {
1279
1301
  this.tx = Transaction.fromBuffer(buffer);
1280
1302
  checkTxEmpty(this.tx);
1281
1303
  Object.defineProperty(this, 'tx', {
@@ -1298,15 +1320,14 @@ class PsbtTransaction implements ITransaction {
1298
1320
  if (
1299
1321
  input.hash === undefined ||
1300
1322
  input.index === undefined ||
1301
- (!Buffer.isBuffer(input.hash) && typeof input.hash !== 'string') ||
1323
+ (!(input.hash instanceof Uint8Array) && typeof input.hash !== 'string') ||
1302
1324
  typeof input.index !== 'number'
1303
1325
  ) {
1304
1326
  throw new Error('Error adding input.');
1305
1327
  }
1306
- const hash =
1307
- typeof input.hash === 'string'
1308
- ? reverseBuffer(Buffer.from(input.hash, 'hex'))
1309
- : input.hash;
1328
+ const hash = (
1329
+ typeof input.hash === 'string' ? reverse(fromHex(input.hash)) : input.hash
1330
+ ) as Bytes32;
1310
1331
 
1311
1332
  this.tx.addInput(hash, input.index, input.sequence);
1312
1333
  }
@@ -1315,20 +1336,20 @@ class PsbtTransaction implements ITransaction {
1315
1336
  if (
1316
1337
  output.script === undefined ||
1317
1338
  output.value === undefined ||
1318
- !Buffer.isBuffer(output.script) ||
1319
- typeof output.value !== 'number'
1339
+ !(output.script instanceof Uint8Array) ||
1340
+ typeof output.value !== 'bigint'
1320
1341
  ) {
1321
1342
  throw new Error('Error adding output.');
1322
1343
  }
1323
1344
  this.tx.addOutput(output.script, output.value);
1324
1345
  }
1325
1346
 
1326
- toBuffer(): Buffer {
1347
+ toBuffer(): Uint8Array {
1327
1348
  return this.tx.toBuffer();
1328
1349
  }
1329
1350
  }
1330
1351
 
1331
- function canFinalize(input: PsbtInput, script: Buffer, scriptType: string): boolean {
1352
+ function canFinalize(input: PsbtInput, script: Uint8Array, scriptType: string): boolean {
1332
1353
  switch (scriptType) {
1333
1354
  case 'pubkey':
1334
1355
  case 'pubkeyhash':
@@ -1336,9 +1357,10 @@ function canFinalize(input: PsbtInput, script: Buffer, scriptType: string): bool
1336
1357
  return hasSigs(1, input.partialSig);
1337
1358
  case 'multisig': {
1338
1359
  const p2ms = payments.p2ms({
1339
- output: script,
1360
+ output: script as Script,
1340
1361
  });
1341
- return hasSigs(p2ms.m!, input.partialSig, p2ms.pubkeys);
1362
+ if (p2ms.m === undefined) throw new Error('Cannot determine m for multisig');
1363
+ return hasSigs(p2ms.m, input.partialSig, p2ms.pubkeys);
1342
1364
  }
1343
1365
  case 'nonstandard':
1344
1366
  return true;
@@ -1347,20 +1369,14 @@ function canFinalize(input: PsbtInput, script: Buffer, scriptType: string): bool
1347
1369
  }
1348
1370
  }
1349
1371
 
1350
- function checkCache(cache: PsbtCache): void {
1351
- if (cache.__UNSAFE_SIGN_NONSEGWIT) {
1352
- throw new Error('Not BIP174 compliant, can not export');
1353
- }
1354
- }
1355
-
1356
- function hasSigs(neededSigs: number, partialSig?: PartialSig[], pubkeys?: Buffer[]): boolean {
1372
+ function hasSigs(neededSigs: number, partialSig?: PartialSig[], pubkeys?: Uint8Array[]): boolean {
1357
1373
  if (!partialSig) return false;
1358
1374
  let sigs: PartialSig[];
1359
1375
  if (pubkeys) {
1360
1376
  sigs = pubkeys
1361
1377
  .map((pkey) => {
1362
1378
  const pubkey = compressPubkey(pkey);
1363
- return partialSig.find((pSig) => pSig.pubkey.equals(pubkey));
1379
+ return partialSig.find((pSig) => equals(pSig.pubkey, pubkey));
1364
1380
  })
1365
1381
  .filter((v): v is PartialSig => !!v);
1366
1382
  } else {
@@ -1370,32 +1386,25 @@ function hasSigs(neededSigs: number, partialSig?: PartialSig[], pubkeys?: Buffer
1370
1386
  return sigs.length === neededSigs;
1371
1387
  }
1372
1388
 
1373
- function isFinalized(input: PsbtInput): boolean {
1374
- return !!input.finalScriptSig || !!input.finalScriptWitness;
1375
- }
1376
-
1377
1389
  function bip32DerivationIsMine(root: HDSigner): (d: Bip32Derivation) => boolean {
1378
1390
  return (d: Bip32Derivation): boolean => {
1379
- const fingerprint = Buffer.isBuffer(root.fingerprint)
1380
- ? root.fingerprint
1381
- : Buffer.from(root.fingerprint);
1382
- if (!d.masterFingerprint.equals(fingerprint)) return false;
1391
+ const fingerprint =
1392
+ root.fingerprint instanceof Uint8Array
1393
+ ? root.fingerprint
1394
+ : new Uint8Array(root.fingerprint);
1395
+ if (!equals(d.masterFingerprint, fingerprint)) return false;
1383
1396
  const derivedPubkey = root.derivePath(d.path).publicKey;
1384
- const pubkey = Buffer.isBuffer(derivedPubkey) ? derivedPubkey : Buffer.from(derivedPubkey);
1385
- if (!pubkey.equals(d.pubkey)) return false;
1397
+ const pubkey =
1398
+ derivedPubkey instanceof Uint8Array ? derivedPubkey : new Uint8Array(derivedPubkey);
1399
+ if (!equals(pubkey, d.pubkey)) return false;
1386
1400
  return true;
1387
1401
  };
1388
1402
  }
1389
1403
 
1390
- function check32Bit(num: number): void {
1391
- if (typeof num !== 'number' || num !== Math.floor(num) || num > 0xffffffff || num < 0) {
1392
- throw new Error('Invalid 32 bit integer');
1393
- }
1394
- }
1395
-
1396
1404
  function checkFees(psbt: Psbt, cache: PsbtCache, opts: PsbtOpts): void {
1397
- const feeRate = cache.__FEE_RATE || psbt.getFeeRate();
1398
- const vsize = cache.__EXTRACTED_TX!.virtualSize();
1405
+ const feeRate = cache.feeRate || psbt.getFeeRate();
1406
+ if (!cache.extractedTx) throw new Error('Transaction not extracted');
1407
+ const vsize = cache.extractedTx.virtualSize();
1399
1408
  const satoshis = feeRate * vsize;
1400
1409
  if (feeRate >= opts.maximumFeeRate) {
1401
1410
  throw new Error(
@@ -1408,84 +1417,6 @@ function checkFees(psbt: Psbt, cache: PsbtCache, opts: PsbtOpts): void {
1408
1417
  }
1409
1418
  }
1410
1419
 
1411
- function checkInputsForPartialSig(inputs: PsbtInput[], action: string): void {
1412
- inputs.forEach((input) => {
1413
- const throws = isTaprootInput(input)
1414
- ? checkTaprootInputForSigs(input, action)
1415
- : checkInputForSig(input, action);
1416
- if (throws) throw new Error('Can not modify transaction, signatures exist.');
1417
- });
1418
- }
1419
-
1420
- function checkPartialSigSighashes(input: PsbtInput): void {
1421
- if (!input.sighashType || !input.partialSig) return;
1422
- const { partialSig, sighashType } = input;
1423
- partialSig.forEach((pSig) => {
1424
- const { hashType } = bscript.signature.decode(pSig.signature);
1425
- if (sighashType !== hashType) {
1426
- throw new Error('Signature sighash does not match input sighash type');
1427
- }
1428
- });
1429
- }
1430
-
1431
- function checkScriptForPubkey(pubkey: Buffer, script: Buffer, action: string): void {
1432
- if (!pubkeyInScript(pubkey, script)) {
1433
- throw new Error(`Can not ${action} for this input with the key ${pubkey.toString('hex')}`);
1434
- }
1435
- }
1436
-
1437
- function checkTxEmpty(tx: Transaction): void {
1438
- const isEmpty = tx.ins.every(
1439
- (input) =>
1440
- input.script &&
1441
- input.script.length === 0 &&
1442
- input.witness &&
1443
- input.witness.length === 0,
1444
- );
1445
- if (!isEmpty) {
1446
- throw new Error('Format Error: Transaction ScriptSigs are not empty');
1447
- }
1448
- }
1449
-
1450
- function checkTxForDupeIns(tx: Transaction, cache: PsbtCache): void {
1451
- tx.ins.forEach((input) => {
1452
- checkTxInputCache(cache, input);
1453
- });
1454
- }
1455
-
1456
- function checkTxInputCache(cache: PsbtCache, input: { hash: Buffer; index: number }): void {
1457
- const key = `${reverseBuffer(Buffer.from(input.hash)).toString('hex')}:${input.index}`;
1458
- if (cache.__TX_IN_CACHE[key]) throw new Error('Duplicate input detected.');
1459
- cache.__TX_IN_CACHE[key] = 1;
1460
- }
1461
-
1462
- function scriptCheckerFactory(
1463
- payment: (a: Payment, opts?: PaymentOpts) => Payment,
1464
- paymentScriptName: string,
1465
- ): (idx: number, scriptPubKey: Buffer, redeemScript: Buffer, ioType: 'input' | 'output') => void {
1466
- return (
1467
- inputIndex: number,
1468
- scriptPubKey: Buffer,
1469
- redeemScript: Buffer,
1470
- ioType: 'input' | 'output',
1471
- ): void => {
1472
- const redeemScriptOutput = payment({
1473
- redeem: { output: redeemScript },
1474
- } as P2SHPayment).output as Buffer;
1475
-
1476
- if (!scriptPubKey.equals(redeemScriptOutput)) {
1477
- throw new Error(
1478
- `${paymentScriptName} for ${ioType} #${inputIndex} doesn't match the scriptPubKey in the prevout`,
1479
- );
1480
- }
1481
- };
1482
- }
1483
-
1484
- const checkRedeemScript = scriptCheckerFactory(payments.p2sh, 'Redeem script');
1485
- const checkWitnessScript = scriptCheckerFactory(payments.p2wsh, 'Witness script');
1486
-
1487
- type TxCacheNumberKey = '__FEE_RATE' | '__FEE';
1488
-
1489
1420
  function getTxCacheValue(
1490
1421
  key: TxCacheNumberKey,
1491
1422
  name: string,
@@ -1494,70 +1425,45 @@ function getTxCacheValue(
1494
1425
  disableOutputChecks: boolean = false,
1495
1426
  ): number {
1496
1427
  if (!inputs.every(isFinalized)) throw new Error(`PSBT must be finalized to calculate ${name}`);
1497
- if (key === '__FEE_RATE' && c.__FEE_RATE) return c.__FEE_RATE;
1498
- if (key === '__FEE' && c.__FEE) return c.__FEE;
1428
+ if (key === 'feeRate' && c.feeRate) return c.feeRate;
1429
+ if (key === 'fee' && c.fee) return c.fee;
1499
1430
  let tx: Transaction;
1500
1431
  let mustFinalize = true;
1501
- if (c.__EXTRACTED_TX) {
1502
- tx = c.__EXTRACTED_TX;
1432
+ if (c.extractedTx) {
1433
+ tx = c.extractedTx;
1503
1434
  mustFinalize = false;
1504
1435
  } else {
1505
- tx = c.__TX.clone();
1436
+ tx = c.tx.clone();
1506
1437
  }
1507
1438
  inputFinalizeGetAmts(inputs, tx, c, mustFinalize, disableOutputChecks);
1508
- const value = key === '__FEE_RATE' ? c.__FEE_RATE : c.__FEE;
1439
+ const value = key === 'feeRate' ? c.feeRate : c.fee;
1509
1440
  if (value === undefined) throw new Error(`Failed to calculate ${name}`);
1510
1441
  return value;
1511
1442
  }
1512
1443
 
1513
- /**
1514
- * This function must do two things:
1515
- * 1. Check if the `input` can be finalized. If it can not be finalized, throw.
1516
- * ie. `Can not finalize input #${inputIndex}`
1517
- * 2. Create the finalScriptSig and finalScriptWitness Buffers.
1518
- */
1519
- type FinalScriptsFunc = (
1520
- inputIndex: number, // Which input is it?
1521
- input: PsbtInput, // The PSBT input contents
1522
- script: Buffer, // The "meaningful" locking script Buffer (redeemScript for P2SH etc.)
1523
- isSegwit: boolean, // Is it segwit?
1524
- isP2SH: boolean, // Is it P2SH?
1525
- isP2WSH: boolean, // Is it P2WSH?
1526
- canRunChecks: boolean,
1527
- ) => {
1528
- finalScriptSig: Buffer | undefined;
1529
- finalScriptWitness: Buffer | undefined;
1530
- };
1531
- type FinalTaprootScriptsFunc = (
1532
- inputIndex: number, // Which input is it?
1533
- input: PsbtInput, // The PSBT input contents
1534
- tapLeafHashToFinalize?: Buffer, // Only finalize this specific leaf
1535
- ) => {
1536
- finalScriptWitness: Buffer | undefined;
1537
- };
1538
-
1539
1444
  export function getFinalScripts(
1540
1445
  inputIndex: number,
1541
1446
  input: PsbtInput,
1542
- script: Buffer,
1447
+ script: Script,
1543
1448
  isSegwit: boolean,
1544
1449
  isP2SH: boolean,
1545
1450
  isP2WSH: boolean,
1546
1451
  canRunChecks: boolean = true,
1547
- solution?: Buffer[],
1452
+ solution?: Uint8Array[],
1548
1453
  ): {
1549
- finalScriptSig: Buffer | undefined;
1550
- finalScriptWitness: Buffer | undefined;
1454
+ finalScriptSig: Script | undefined;
1455
+ finalScriptWitness: Uint8Array | undefined;
1551
1456
  } {
1552
1457
  const scriptType = classifyScript(script);
1553
1458
  if (!canFinalize(input, script, scriptType) && canRunChecks) {
1554
1459
  throw new Error(`Can not finalize input #${inputIndex}`);
1555
1460
  }
1556
1461
 
1462
+ if (!input.partialSig) throw new Error('Input missing partial signatures');
1557
1463
  return prepareFinalScripts(
1558
1464
  script,
1559
1465
  scriptType,
1560
- input.partialSig!,
1466
+ input.partialSig,
1561
1467
  isSegwit,
1562
1468
  isP2SH,
1563
1469
  isP2WSH,
@@ -1566,19 +1472,19 @@ export function getFinalScripts(
1566
1472
  }
1567
1473
 
1568
1474
  export function prepareFinalScripts(
1569
- script: Buffer,
1475
+ script: Uint8Array,
1570
1476
  scriptType: string,
1571
1477
  partialSig: PartialSig[],
1572
1478
  isSegwit: boolean,
1573
1479
  isP2SH: boolean,
1574
1480
  isP2WSH: boolean,
1575
- solution?: Buffer[],
1481
+ solution?: Uint8Array[],
1576
1482
  ): {
1577
- finalScriptSig: Buffer | undefined;
1578
- finalScriptWitness: Buffer | undefined;
1483
+ finalScriptSig: Script | undefined;
1484
+ finalScriptWitness: Uint8Array | undefined;
1579
1485
  } {
1580
- let finalScriptSig: Buffer | undefined;
1581
- let finalScriptWitness: Buffer | undefined;
1486
+ let finalScriptSig: Script | undefined;
1487
+ let finalScriptWitness: Uint8Array | undefined;
1582
1488
 
1583
1489
  // Wow, the payments API is very handy
1584
1490
  const payment: payments.Payment = getPayment(script, scriptType, partialSig);
@@ -1586,26 +1492,27 @@ export function prepareFinalScripts(
1586
1492
  const p2sh = !isP2SH ? null : payments.p2sh({ redeem: p2wsh || payment } as P2SHPayment);
1587
1493
 
1588
1494
  if (isSegwit) {
1589
- if (p2wsh) {
1590
- finalScriptWitness = witnessStackToScriptWitness(p2wsh.witness!);
1591
- } else if (payment) {
1592
- finalScriptWitness = witnessStackToScriptWitness(payment.witness!);
1495
+ if (p2wsh && p2wsh.witness) {
1496
+ finalScriptWitness = witnessStackToScriptWitness(p2wsh.witness);
1497
+ } else if (payment && payment.witness) {
1498
+ finalScriptWitness = witnessStackToScriptWitness(payment.witness);
1593
1499
  } else {
1594
1500
  // nonstandard segwit script
1595
- finalScriptWitness = witnessStackToScriptWitness(solution ?? [Buffer.from([0x00])]);
1501
+ finalScriptWitness = witnessStackToScriptWitness(solution ?? [new Uint8Array([0x00])]);
1596
1502
  }
1597
1503
  if (p2sh) {
1598
- finalScriptSig = p2sh?.input;
1504
+ finalScriptSig = p2sh?.input as Script | undefined;
1599
1505
  }
1600
1506
  } else {
1601
1507
  if (p2sh) {
1602
- finalScriptSig = p2sh?.input;
1508
+ finalScriptSig = p2sh?.input as Script | undefined;
1603
1509
  } else {
1604
1510
  if (!payment) {
1605
- finalScriptSig =
1606
- Array.isArray(solution) && solution[0] ? solution[0] : Buffer.from([0x01]);
1511
+ finalScriptSig = (
1512
+ Array.isArray(solution) && solution[0] ? solution[0] : new Uint8Array([0x01])
1513
+ ) as Script;
1607
1514
  } else {
1608
- finalScriptSig = payment.input;
1515
+ finalScriptSig = payment.input as Script | undefined;
1609
1516
  }
1610
1517
  }
1611
1518
  }
@@ -1618,11 +1525,11 @@ export function prepareFinalScripts(
1618
1525
  function getHashAndSighashType(
1619
1526
  inputs: PsbtInput[],
1620
1527
  inputIndex: number,
1621
- pubkey: Buffer,
1528
+ pubkey: Uint8Array,
1622
1529
  cache: PsbtCache,
1623
1530
  sighashTypes: number[],
1624
1531
  ): {
1625
- hash: Buffer;
1532
+ hash: Bytes32;
1626
1533
  sighashType: number;
1627
1534
  } {
1628
1535
  const input = checkForInput(inputs, inputIndex);
@@ -1634,7 +1541,7 @@ function getHashAndSighashType(
1634
1541
  sighashTypes,
1635
1542
  );
1636
1543
 
1637
- checkScriptForPubkey(pubkey, script, 'sign');
1544
+ checkScriptForPubkey(pubkey as PublicKey, script, 'sign');
1638
1545
  return {
1639
1546
  hash,
1640
1547
  sighashType,
@@ -1648,34 +1555,37 @@ function getHashForSig(
1648
1555
  forValidate: boolean,
1649
1556
  sighashTypes?: number[],
1650
1557
  ): {
1651
- script: Buffer;
1652
- hash: Buffer;
1558
+ script: Script;
1559
+ hash: Bytes32;
1653
1560
  sighashType: number;
1654
1561
  } {
1655
- const unsignedTx = cache.__TX;
1562
+ const unsignedTx = cache.tx;
1656
1563
  const sighashType = input.sighashType || Transaction.SIGHASH_ALL;
1657
1564
  checkSighashTypeAllowed(sighashType, sighashTypes);
1658
1565
 
1659
- let hash: Buffer;
1566
+ let hash: Bytes32;
1660
1567
  let prevout: Output;
1661
1568
 
1662
1569
  if (input.nonWitnessUtxo) {
1663
1570
  const nonWitnessUtxoTx = nonWitnessUtxoTxFromCache(cache, input, inputIndex);
1664
1571
 
1665
- const prevoutHash = unsignedTx.ins[inputIndex].hash;
1572
+ const prevoutHash = unsignedTx.ins[inputIndex]!.hash;
1666
1573
  const utxoHash = nonWitnessUtxoTx.getHash();
1667
1574
 
1668
1575
  // If a non-witness UTXO is provided, its hash must match the hash specified in the prevout
1669
- if (!prevoutHash.equals(utxoHash)) {
1576
+ if (!equals(prevoutHash, utxoHash)) {
1670
1577
  throw new Error(
1671
1578
  `Non-witness UTXO hash for input #${inputIndex} doesn't match the hash specified in the prevout`,
1672
1579
  );
1673
1580
  }
1674
1581
 
1675
- const prevoutIndex = unsignedTx.ins[inputIndex].index;
1676
- prevout = nonWitnessUtxoTx.outs[prevoutIndex];
1582
+ const prevoutIndex = unsignedTx.ins[inputIndex]!.index;
1583
+ prevout = nonWitnessUtxoTx.outs[prevoutIndex]!;
1677
1584
  } else if (input.witnessUtxo) {
1678
- prevout = input.witnessUtxo;
1585
+ prevout = {
1586
+ script: input.witnessUtxo.script as Script,
1587
+ value: input.witnessUtxo.value as Satoshi,
1588
+ };
1679
1589
  } else {
1680
1590
  throw new Error('Need a Utxo input item for signing');
1681
1591
  }
@@ -1688,27 +1598,30 @@ function getHashForSig(
1688
1598
  input.witnessScript,
1689
1599
  );
1690
1600
 
1601
+ const script = meaningfulScript as Script;
1602
+
1691
1603
  if (['p2sh-p2wsh', 'p2wsh'].indexOf(type) >= 0) {
1604
+ hash = unsignedTx.hashForWitnessV0(inputIndex, script, prevout.value, sighashType);
1605
+ } else if (isP2WPKH(meaningfulScript)) {
1606
+ // P2WPKH uses the P2PKH template for prevoutScript when signing
1607
+ const p2pkhPayment = payments.p2pkh({
1608
+ hash: meaningfulScript.subarray(2) as Bytes20,
1609
+ });
1610
+ if (!p2pkhPayment.output) throw new Error('Unable to create signing script');
1692
1611
  hash = unsignedTx.hashForWitnessV0(
1693
1612
  inputIndex,
1694
- meaningfulScript,
1613
+ p2pkhPayment.output as Script,
1695
1614
  prevout.value,
1696
1615
  sighashType,
1697
1616
  );
1698
- } else if (isP2WPKH(meaningfulScript)) {
1699
- // P2WPKH uses the P2PKH template for prevoutScript when signing
1700
- const signingScript = payments.p2pkh({
1701
- hash: meaningfulScript.subarray(2),
1702
- }).output!;
1703
- hash = unsignedTx.hashForWitnessV0(inputIndex, signingScript, prevout.value, sighashType);
1704
1617
  } else {
1705
1618
  // non-segwit
1706
- if (input.nonWitnessUtxo === undefined && !cache.__UNSAFE_SIGN_NONSEGWIT)
1619
+ if (input.nonWitnessUtxo === undefined && !cache.unsafeSignNonSegwit)
1707
1620
  throw new Error(
1708
1621
  `Input #${inputIndex} has witnessUtxo but non-segwit script: ` +
1709
- meaningfulScript.toString('hex'),
1622
+ toHex(meaningfulScript),
1710
1623
  );
1711
- if (!forValidate && cache.__UNSAFE_SIGN_NONSEGWIT)
1624
+ if (!forValidate && cache.unsafeSignNonSegwit)
1712
1625
  console.warn(
1713
1626
  'Warning: Signing non-segwit inputs without the full parent transaction ' +
1714
1627
  'means there is a chance that a miner could feed you incorrect information ' +
@@ -1718,11 +1631,11 @@ function getHashForSig(
1718
1631
  'BIP174 compliant.\n*********************\nPROCEED WITH CAUTION!\n' +
1719
1632
  '*********************',
1720
1633
  );
1721
- hash = unsignedTx.hashForSignature(inputIndex, meaningfulScript, sighashType);
1634
+ hash = unsignedTx.hashForSignature(inputIndex, script, sighashType);
1722
1635
  }
1723
1636
 
1724
1637
  return {
1725
- script: meaningfulScript,
1638
+ script,
1726
1639
  sighashType,
1727
1640
  hash,
1728
1641
  };
@@ -1733,8 +1646,8 @@ function getAllTaprootHashesForSig(
1733
1646
  input: PsbtInput,
1734
1647
  inputs: PsbtInput[],
1735
1648
  cache: PsbtCache,
1736
- ): { pubkey: Buffer; hash: Buffer; leafHash?: Buffer }[] {
1737
- const allPublicKeys: Buffer[] = [];
1649
+ ): { pubkey: PublicKey; hash: Bytes32; leafHash?: Bytes32 }[] {
1650
+ const allPublicKeys: Uint8Array[] = [];
1738
1651
  if (input.tapInternalKey) {
1739
1652
  const key = getPrevoutTaprootKey(inputIndex, input, cache);
1740
1653
  if (key) {
@@ -1758,46 +1671,58 @@ function getPrevoutTaprootKey(
1758
1671
  inputIndex: number,
1759
1672
  input: PsbtInput,
1760
1673
  cache: PsbtCache,
1761
- ): Buffer | null {
1674
+ ): XOnlyPublicKey | null {
1762
1675
  const { script } = getScriptAndAmountFromUtxo(inputIndex, input, cache);
1763
- return isP2TR(script) ? Buffer.from(script.subarray(2, 34)) : null;
1676
+ return isP2TR(script) ? (script.subarray(2, 34) as XOnlyPublicKey) : null;
1764
1677
  }
1765
1678
 
1766
- function trimTaprootSig(signature: Buffer): Buffer {
1767
- return signature.length === 64 ? signature : Buffer.from(signature.subarray(0, 64));
1679
+ function trimTaprootSig(signature: Uint8Array): Uint8Array {
1680
+ return signature.length === 64 ? signature : signature.subarray(0, 64);
1768
1681
  }
1769
1682
 
1770
1683
  function getTaprootHashesForSig(
1771
1684
  inputIndex: number,
1772
1685
  input: PsbtInput,
1773
1686
  inputs: PsbtInput[],
1774
- pubkey: Buffer,
1687
+ pubkey: Uint8Array,
1775
1688
  cache: PsbtCache,
1776
- tapLeafHashToSign?: Buffer,
1689
+ tapLeafHashToSign?: Uint8Array,
1777
1690
  allowedSighashTypes?: number[],
1778
- ): { pubkey: Buffer; hash: Buffer; leafHash?: Buffer }[] {
1779
- const unsignedTx = cache.__TX;
1691
+ ): { pubkey: PublicKey; hash: Bytes32; leafHash?: Bytes32 }[] {
1692
+ const unsignedTx = cache.tx;
1780
1693
 
1781
1694
  const sighashType = input.sighashType || Transaction.SIGHASH_DEFAULT;
1782
1695
  checkSighashTypeAllowed(sighashType, allowedSighashTypes);
1783
1696
 
1784
- const prevOuts: Output[] = inputs.map((i, index) =>
1785
- getScriptAndAmountFromUtxo(index, i, cache),
1786
- );
1787
- const signingScripts = prevOuts.map((o) => o.script);
1788
- const values = prevOuts.map((o) => o.value);
1697
+ if (!cache.prevOuts) {
1698
+ const prevOuts = inputs.map((i, index) => getScriptAndAmountFromUtxo(index, i, cache));
1699
+ cache.prevOuts = prevOuts;
1700
+ cache.signingScripts = prevOuts.map((o) => o.script);
1701
+ cache.values = prevOuts.map((o) => o.value);
1702
+ }
1703
+ const signingScripts = cache.signingScripts as readonly Script[];
1704
+ const values = cache.values as readonly Satoshi[];
1705
+
1706
+ // Compute taproot hash cache once for all inputs (O(n) -> O(1) per input)
1707
+ if (!cache.taprootHashCache) {
1708
+ cache.taprootHashCache = unsignedTx.getTaprootHashCache(signingScripts, values);
1709
+ }
1710
+ const taprootCache = cache.taprootHashCache;
1789
1711
 
1790
- const hashes: { pubkey: Buffer; hash: Buffer; leafHash?: Buffer }[] = [];
1712
+ const hashes: { pubkey: PublicKey; hash: Bytes32; leafHash?: Bytes32 }[] = [];
1791
1713
  if (input.tapInternalKey && !tapLeafHashToSign) {
1792
- const outputKey = getPrevoutTaprootKey(inputIndex, input, cache) || Buffer.from([]);
1793
- if (toXOnly(pubkey).equals(outputKey)) {
1714
+ const outputKey = getPrevoutTaprootKey(inputIndex, input, cache) || new Uint8Array(0);
1715
+ if (equals(toXOnly(pubkey as PublicKey), outputKey)) {
1794
1716
  const tapKeyHash = unsignedTx.hashForWitnessV1(
1795
1717
  inputIndex,
1796
1718
  signingScripts,
1797
1719
  values,
1798
1720
  sighashType,
1721
+ undefined,
1722
+ undefined,
1723
+ taprootCache,
1799
1724
  );
1800
- hashes.push({ pubkey, hash: tapKeyHash });
1725
+ hashes.push({ pubkey: pubkey as PublicKey, hash: tapKeyHash });
1801
1726
  }
1802
1727
  }
1803
1728
 
@@ -1810,20 +1735,22 @@ function getTaprootHashesForSig(
1810
1735
  });
1811
1736
  return Object.assign({ hash }, tapLeaf);
1812
1737
  })
1813
- .filter((tapLeaf) => !tapLeafHashToSign || tapLeafHashToSign.equals(tapLeaf.hash))
1738
+ .filter((tapLeaf) => !tapLeafHashToSign || equals(tapLeafHashToSign, tapLeaf.hash))
1814
1739
  .map((tapLeaf) => {
1815
1740
  const tapScriptHash = unsignedTx.hashForWitnessV1(
1816
1741
  inputIndex,
1817
1742
  signingScripts,
1818
1743
  values,
1819
1744
  sighashType,
1820
- tapLeaf.hash,
1745
+ tapLeaf.hash as Bytes32,
1746
+ undefined,
1747
+ taprootCache,
1821
1748
  );
1822
1749
 
1823
1750
  return {
1824
- pubkey,
1751
+ pubkey: pubkey as PublicKey,
1825
1752
  hash: tapScriptHash,
1826
- leafHash: tapLeaf.hash,
1753
+ leafHash: tapLeaf.hash as Bytes32,
1827
1754
  };
1828
1755
  });
1829
1756
 
@@ -1841,49 +1768,39 @@ function checkSighashTypeAllowed(sighashType: number, sighashTypes?: number[]):
1841
1768
  }
1842
1769
 
1843
1770
  function getPayment(
1844
- script: Buffer,
1771
+ script: Uint8Array,
1845
1772
  scriptType: string,
1846
1773
  partialSig: PartialSig[],
1847
1774
  ): payments.Payment {
1848
- let payment: payments.Payment;
1775
+ const scriptBranded = script as Script;
1849
1776
  switch (scriptType) {
1850
1777
  case 'multisig': {
1851
1778
  const sigs = getSortedSigs(script, partialSig);
1852
- payment = payments.p2ms({
1853
- output: script,
1854
- signatures: sigs,
1779
+ return payments.p2ms({
1780
+ output: scriptBranded,
1781
+ signatures: sigs as Signature[],
1855
1782
  });
1856
- break;
1857
1783
  }
1858
1784
  case 'pubkey':
1859
- payment = payments.p2pk({
1860
- output: script,
1861
- signature: partialSig[0].signature,
1785
+ return payments.p2pk({
1786
+ output: scriptBranded,
1787
+ signature: partialSig[0]!.signature as Signature,
1862
1788
  });
1863
- break;
1864
1789
  case 'pubkeyhash':
1865
- payment = payments.p2pkh({
1866
- output: script,
1867
- pubkey: partialSig[0].pubkey,
1868
- signature: partialSig[0].signature,
1790
+ return payments.p2pkh({
1791
+ output: scriptBranded,
1792
+ pubkey: partialSig[0]!.pubkey as PublicKey,
1793
+ signature: partialSig[0]!.signature as Signature,
1869
1794
  });
1870
- break;
1871
1795
  case 'witnesspubkeyhash':
1872
- payment = payments.p2wpkh({
1873
- output: script,
1874
- pubkey: partialSig[0].pubkey,
1875
- signature: partialSig[0].signature,
1796
+ return payments.p2wpkh({
1797
+ output: scriptBranded,
1798
+ pubkey: partialSig[0]!.pubkey as PublicKey,
1799
+ signature: partialSig[0]!.signature as Signature,
1876
1800
  });
1877
- break;
1801
+ default:
1802
+ throw new Error(`Unknown script type: ${scriptType}`);
1878
1803
  }
1879
- return payment!;
1880
- }
1881
-
1882
- interface GetScriptReturn {
1883
- script: Buffer | null;
1884
- isSegwit: boolean;
1885
- isP2SH: boolean;
1886
- isP2WSH: boolean;
1887
1804
  }
1888
1805
 
1889
1806
  function getScriptFromInput(
@@ -1891,7 +1808,7 @@ function getScriptFromInput(
1891
1808
  input: PsbtInput,
1892
1809
  cache: PsbtCache,
1893
1810
  ): GetScriptReturn {
1894
- const unsignedTx = cache.__TX;
1811
+ const unsignedTx = cache.tx;
1895
1812
  const res: GetScriptReturn = {
1896
1813
  script: null,
1897
1814
  isSegwit: false,
@@ -1901,20 +1818,20 @@ function getScriptFromInput(
1901
1818
  res.isP2SH = !!input.redeemScript;
1902
1819
  res.isP2WSH = !!input.witnessScript;
1903
1820
  if (input.witnessScript) {
1904
- res.script = input.witnessScript;
1821
+ res.script = input.witnessScript as Script;
1905
1822
  } else if (input.redeemScript) {
1906
- res.script = input.redeemScript;
1823
+ res.script = input.redeemScript as Script;
1907
1824
  } else {
1908
1825
  if (input.nonWitnessUtxo) {
1909
1826
  const nonWitnessUtxoTx = nonWitnessUtxoTxFromCache(cache, input, inputIndex);
1910
- const prevoutIndex = unsignedTx.ins[inputIndex].index;
1911
- res.script = nonWitnessUtxoTx.outs[prevoutIndex].script;
1827
+ const prevoutIndex = unsignedTx.ins[inputIndex]!.index;
1828
+ res.script = nonWitnessUtxoTx.outs[prevoutIndex]!.script;
1912
1829
  } else if (input.witnessUtxo) {
1913
- res.script = input.witnessUtxo.script;
1830
+ res.script = input.witnessUtxo.script as Script;
1914
1831
  }
1915
1832
  }
1916
1833
 
1917
- if (input.witnessScript || isP2WPKH(res.script!)) {
1834
+ if (input.witnessScript || (res.script && isP2WPKH(res.script))) {
1918
1835
  res.isSegwit = true;
1919
1836
  } else {
1920
1837
  try {
@@ -1928,18 +1845,18 @@ function getScriptFromInput(
1928
1845
  return res;
1929
1846
  }
1930
1847
 
1931
- function getSignersFromHD(
1848
+ function getSignersFromHD<T extends HDSigner | HDSignerAsync>(
1932
1849
  inputIndex: number,
1933
1850
  inputs: PsbtInput[],
1934
- hdKeyPair: HDSigner | HDSignerAsync,
1935
- ): (HDSigner | HDSignerAsync)[] {
1851
+ hdKeyPair: T,
1852
+ ): T[] {
1936
1853
  const input = checkForInput(inputs, inputIndex);
1937
1854
  if (!input.bip32Derivation || input.bip32Derivation.length === 0) {
1938
1855
  throw new Error('Need bip32Derivation to sign with HD');
1939
1856
  }
1940
1857
  const myDerivations = input.bip32Derivation
1941
1858
  .map((bipDv) => {
1942
- if (bipDv.masterFingerprint.equals(hdKeyPair.fingerprint)) {
1859
+ if (equals(bipDv.masterFingerprint, hdKeyPair.fingerprint)) {
1943
1860
  return bipDv;
1944
1861
  } else {
1945
1862
  return;
@@ -1953,98 +1870,60 @@ function getSignersFromHD(
1953
1870
  }
1954
1871
 
1955
1872
  return myDerivations.map((bipDv) => {
1956
- const node = hdKeyPair.derivePath(bipDv.path);
1957
- if (!bipDv.pubkey.equals(node.publicKey)) {
1873
+ const node = hdKeyPair.derivePath(bipDv.path) as T;
1874
+ if (!equals(bipDv.pubkey, node.publicKey)) {
1958
1875
  throw new Error('pubkey did not match bip32Derivation');
1959
1876
  }
1960
1877
  return node;
1961
1878
  });
1962
1879
  }
1963
1880
 
1964
- function getSortedSigs(script: Buffer, partialSig: PartialSig[]): Buffer[] {
1965
- const p2ms = payments.p2ms({ output: script });
1881
+ function getSortedSigs(script: Uint8Array, partialSig: PartialSig[]): Uint8Array[] {
1882
+ const p2ms = payments.p2ms({ output: script as Script });
1883
+ if (!p2ms.pubkeys) throw new Error('Cannot extract pubkeys from multisig script');
1966
1884
  // for each pubkey in order of p2ms script
1967
- return p2ms
1968
- .pubkeys!.map((pk) => {
1969
- // filter partialSig array by pubkey being equal
1970
- return (
1971
- partialSig.filter((ps) => {
1972
- return ps.pubkey.equals(pk);
1973
- })[0] || {}
1974
- ).signature;
1975
- // Any pubkey without a match will return undefined
1976
- // this last filter removes all the undefined items in the array.
1977
- })
1978
- .filter((v) => !!v);
1979
- }
1980
-
1981
- function scriptWitnessToWitnessStack(buffer: Buffer): Buffer[] {
1982
- let offset = 0;
1983
-
1984
- function readSlice(n: number): Buffer {
1985
- offset += n;
1986
- return buffer.subarray(offset - n, offset);
1987
- }
1988
-
1989
- function readVarInt(): number {
1990
- const vi = varuintDecode(buffer, offset);
1991
- offset += varuintDecode.bytes;
1992
- return vi;
1993
- }
1994
-
1995
- function readVarSlice(): Buffer {
1996
- return readSlice(readVarInt());
1997
- }
1998
-
1999
- function readVector(): Buffer[] {
2000
- const count = readVarInt();
2001
- const vector: Buffer[] = [];
2002
- for (let i = 0; i < count; i++) vector.push(readVarSlice());
2003
- return vector;
1885
+ const result: Uint8Array[] = [];
1886
+ for (const pk of p2ms.pubkeys) {
1887
+ // filter partialSig array by pubkey being equal
1888
+ const matched = partialSig.filter((ps) => {
1889
+ return equals(ps.pubkey, pk);
1890
+ })[0];
1891
+ if (matched) {
1892
+ result.push(new Uint8Array(matched.signature));
1893
+ }
2004
1894
  }
2005
-
2006
- return readVector();
2007
- }
2008
-
2009
- function sighashTypeToString(sighashType: number): string {
2010
- let text = sighashType & Transaction.SIGHASH_ANYONECANPAY ? 'SIGHASH_ANYONECANPAY | ' : '';
2011
- const sigMod = sighashType & 0x1f;
2012
- switch (sigMod) {
2013
- case Transaction.SIGHASH_ALL:
2014
- text += 'SIGHASH_ALL';
2015
- break;
2016
- case Transaction.SIGHASH_SINGLE:
2017
- text += 'SIGHASH_SINGLE';
2018
- break;
2019
- case Transaction.SIGHASH_NONE:
2020
- text += 'SIGHASH_NONE';
2021
- break;
2022
- }
2023
- return text;
1895
+ return result;
2024
1896
  }
2025
1897
 
2026
1898
  function addNonWitnessTxCache(cache: PsbtCache, input: PsbtInput, inputIndex: number): void {
2027
- cache.__NON_WITNESS_UTXO_BUF_CACHE[inputIndex] = input.nonWitnessUtxo!;
2028
- cache.__NON_WITNESS_UTXO_TX_CACHE[inputIndex] = Transaction.fromBuffer(input.nonWitnessUtxo!);
1899
+ if (!input.nonWitnessUtxo) throw new Error('nonWitnessUtxo is required');
1900
+ // Prevent prototype pollution - ensure input is a valid object
1901
+ if (input === null || input === Object.prototype) {
1902
+ throw new Error('Invalid input object');
1903
+ }
1904
+ const nonWitnessUtxoBuf = input.nonWitnessUtxo;
1905
+ cache.nonWitnessUtxoBufCache[inputIndex] = nonWitnessUtxoBuf;
1906
+ cache.nonWitnessUtxoTxCache[inputIndex] = Transaction.fromBuffer(nonWitnessUtxoBuf);
2029
1907
 
2030
1908
  const self = cache;
2031
1909
  const selfIndex = inputIndex;
2032
1910
  delete input.nonWitnessUtxo;
2033
- Object.defineProperty(input, 'nonWitnessUtxo', {
1911
+ // Using Reflect.defineProperty to avoid prototype pollution concerns
1912
+ Reflect.defineProperty(input, 'nonWitnessUtxo', {
2034
1913
  enumerable: true,
2035
- get(): Buffer {
2036
- const buf = self.__NON_WITNESS_UTXO_BUF_CACHE[selfIndex];
2037
- const txCache = self.__NON_WITNESS_UTXO_TX_CACHE[selfIndex];
1914
+ get(): Uint8Array {
1915
+ const buf = self.nonWitnessUtxoBufCache[selfIndex];
1916
+ const txCache = self.nonWitnessUtxoTxCache[selfIndex];
2038
1917
  if (buf !== undefined) {
2039
1918
  return buf;
2040
1919
  } else {
2041
- const newBuf = txCache.toBuffer();
2042
- self.__NON_WITNESS_UTXO_BUF_CACHE[selfIndex] = newBuf;
1920
+ const newBuf = txCache!.toBuffer();
1921
+ self.nonWitnessUtxoBufCache[selfIndex] = newBuf;
2043
1922
  return newBuf;
2044
1923
  }
2045
1924
  },
2046
- set(data: Buffer): void {
2047
- self.__NON_WITNESS_UTXO_BUF_CACHE[selfIndex] = data;
1925
+ set(data: Uint8Array): void {
1926
+ self.nonWitnessUtxoBufCache[selfIndex] = data;
2048
1927
  },
2049
1928
  });
2050
1929
  }
@@ -2056,34 +1935,35 @@ function inputFinalizeGetAmts(
2056
1935
  mustFinalize: boolean,
2057
1936
  disableOutputChecks?: boolean,
2058
1937
  ): void {
2059
- let inputAmount = 0;
1938
+ let inputAmount = 0n;
2060
1939
  inputs.forEach((input, idx) => {
2061
- if (mustFinalize && input.finalScriptSig) tx.ins[idx].script = input.finalScriptSig;
1940
+ if (mustFinalize && input.finalScriptSig)
1941
+ tx.ins[idx]!.script = input.finalScriptSig as Script;
2062
1942
  if (mustFinalize && input.finalScriptWitness) {
2063
- tx.ins[idx].witness = scriptWitnessToWitnessStack(input.finalScriptWitness);
1943
+ tx.ins[idx]!.witness = scriptWitnessToWitnessStack(input.finalScriptWitness);
2064
1944
  }
2065
1945
  if (input.witnessUtxo) {
2066
1946
  inputAmount += input.witnessUtxo.value;
2067
1947
  } else if (input.nonWitnessUtxo) {
2068
1948
  const nwTx = nonWitnessUtxoTxFromCache(cache, input, idx);
2069
- const vout = tx.ins[idx].index;
2070
- const out = nwTx.outs[vout];
1949
+ const vout = tx.ins[idx]!.index;
1950
+ const out = nwTx.outs[vout]!;
2071
1951
  inputAmount += out.value;
2072
1952
  }
2073
1953
  });
2074
- const outputAmount = tx.outs.reduce((total, o) => total + o.value, 0);
1954
+ const outputAmount = tx.outs.reduce((total, o) => total + o.value, 0n);
2075
1955
  const fee = inputAmount - outputAmount;
2076
1956
  if (!disableOutputChecks) {
2077
- if (fee < 0) {
1957
+ if (fee < 0n) {
2078
1958
  throw new Error(
2079
1959
  `Outputs are spending more than Inputs ${inputAmount} < ${outputAmount}`,
2080
1960
  );
2081
1961
  }
2082
1962
  }
2083
1963
  const bytes = tx.virtualSize();
2084
- cache.__FEE = fee;
2085
- cache.__EXTRACTED_TX = tx;
2086
- cache.__FEE_RATE = Math.floor(fee / bytes);
1964
+ cache.fee = Number(fee);
1965
+ cache.extractedTx = tx;
1966
+ cache.feeRate = Math.floor(Number(fee) / bytes);
2087
1967
  }
2088
1968
 
2089
1969
  function nonWitnessUtxoTxFromCache(
@@ -2091,14 +1971,14 @@ function nonWitnessUtxoTxFromCache(
2091
1971
  input: PsbtInput,
2092
1972
  inputIndex: number,
2093
1973
  ): Transaction {
2094
- const c = cache.__NON_WITNESS_UTXO_TX_CACHE;
1974
+ const c = cache.nonWitnessUtxoTxCache;
2095
1975
  if (!c[inputIndex]) {
2096
1976
  addNonWitnessTxCache(cache, input, inputIndex);
2097
1977
  }
2098
- return c[inputIndex];
1978
+ return c[inputIndex]!;
2099
1979
  }
2100
1980
 
2101
- function getScriptFromUtxo(inputIndex: number, input: PsbtInput, cache: PsbtCache): Buffer {
1981
+ function getScriptFromUtxo(inputIndex: number, input: PsbtInput, cache: PsbtCache): Script {
2102
1982
  const { script } = getScriptAndAmountFromUtxo(inputIndex, input, cache);
2103
1983
  return script;
2104
1984
  }
@@ -2107,15 +1987,15 @@ function getScriptAndAmountFromUtxo(
2107
1987
  inputIndex: number,
2108
1988
  input: PsbtInput,
2109
1989
  cache: PsbtCache,
2110
- ): { script: Buffer; value: number } {
1990
+ ): { script: Script; value: Satoshi } {
2111
1991
  if (input.witnessUtxo !== undefined) {
2112
1992
  return {
2113
- script: input.witnessUtxo.script,
2114
- value: input.witnessUtxo.value,
1993
+ script: input.witnessUtxo.script as Script,
1994
+ value: input.witnessUtxo.value as Satoshi,
2115
1995
  };
2116
1996
  } else if (input.nonWitnessUtxo !== undefined) {
2117
1997
  const nonWitnessUtxoTx = nonWitnessUtxoTxFromCache(cache, input, inputIndex);
2118
- const o = nonWitnessUtxoTx.outs[cache.__TX.ins[inputIndex].index];
1998
+ const o = nonWitnessUtxoTx.outs[cache.tx.ins[inputIndex]!.index]!;
2119
1999
  return { script: o.script, value: o.value };
2120
2000
  } else {
2121
2001
  throw new Error("Can't find pubkey in input without Utxo data");
@@ -2123,7 +2003,7 @@ function getScriptAndAmountFromUtxo(
2123
2003
  }
2124
2004
 
2125
2005
  function pubkeyInInput(
2126
- pubkey: Buffer,
2006
+ pubkey: PublicKey,
2127
2007
  input: PsbtInput,
2128
2008
  inputIndex: number,
2129
2009
  cache: PsbtCache,
@@ -2140,12 +2020,12 @@ function pubkeyInInput(
2140
2020
  }
2141
2021
 
2142
2022
  function pubkeyInOutput(
2143
- pubkey: Buffer,
2023
+ pubkey: PublicKey,
2144
2024
  output: PsbtOutput,
2145
2025
  outputIndex: number,
2146
2026
  cache: PsbtCache,
2147
2027
  ): boolean {
2148
- const script = cache.__TX.outs[outputIndex].script;
2028
+ const script = cache.tx.outs[outputIndex]!.script;
2149
2029
  const { meaningfulScript } = getMeaningfulScript(
2150
2030
  script,
2151
2031
  outputIndex,
@@ -2156,122 +2036,23 @@ function pubkeyInOutput(
2156
2036
  return pubkeyInScript(pubkey, meaningfulScript);
2157
2037
  }
2158
2038
 
2159
- function redeemFromFinalScriptSig(finalScript: Buffer | undefined): Buffer | undefined {
2039
+ function redeemFromFinalScriptSig(finalScript: Uint8Array | undefined): Uint8Array | undefined {
2160
2040
  if (!finalScript) return;
2161
2041
  const decomp = bscript.decompile(finalScript);
2162
2042
  if (!decomp) return;
2163
- const lastItem = decomp[decomp.length - 1];
2164
- if (!Buffer.isBuffer(lastItem) || isPubkeyLike(lastItem) || isSigLike(lastItem)) return;
2043
+ const lastItem = decomp[decomp.length - 1]!;
2044
+ if (!(lastItem instanceof Uint8Array) || isPubkeyLike(lastItem) || isSigLike(lastItem)) return;
2165
2045
  const sDecomp = bscript.decompile(lastItem);
2166
2046
  if (!sDecomp) return;
2167
2047
  return lastItem;
2168
2048
  }
2169
2049
 
2170
- function redeemFromFinalWitnessScript(finalScript: Buffer | undefined): Buffer | undefined {
2050
+ function redeemFromFinalWitnessScript(finalScript: Uint8Array | undefined): Uint8Array | undefined {
2171
2051
  if (!finalScript) return;
2172
2052
  const decomp = scriptWitnessToWitnessStack(finalScript);
2173
- const lastItem = decomp[decomp.length - 1];
2053
+ const lastItem = decomp[decomp.length - 1]!;
2174
2054
  if (isPubkeyLike(lastItem)) return;
2175
2055
  const sDecomp = bscript.decompile(lastItem);
2176
2056
  if (!sDecomp) return;
2177
2057
  return lastItem;
2178
2058
  }
2179
-
2180
- function compressPubkey(pubkey: Buffer): Buffer {
2181
- if (pubkey.length === 65) {
2182
- const parity = pubkey[64] & 1;
2183
- const newKey = Buffer.from(pubkey.subarray(0, 33));
2184
- newKey[0] = 2 | parity;
2185
- return newKey;
2186
- }
2187
- return Buffer.from(pubkey);
2188
- }
2189
-
2190
- function isPubkeyLike(buf: Buffer): boolean {
2191
- return buf.length === 33 && bscript.isCanonicalPubKey(buf);
2192
- }
2193
-
2194
- function isSigLike(buf: Buffer): boolean {
2195
- return bscript.isCanonicalScriptSignature(buf);
2196
- }
2197
-
2198
- function getMeaningfulScript(
2199
- script: Buffer,
2200
- index: number,
2201
- ioType: 'input' | 'output',
2202
- redeemScript?: Buffer,
2203
- witnessScript?: Buffer,
2204
- ): {
2205
- meaningfulScript: Buffer;
2206
- type: 'p2sh' | 'p2wsh' | 'p2sh-p2wsh' | 'raw';
2207
- } {
2208
- const isP2SH = isP2SHScript(script);
2209
- const isP2SHP2WSH = isP2SH && redeemScript && isP2WSHScript(redeemScript);
2210
- const isP2WSH = isP2WSHScript(script);
2211
-
2212
- if (isP2SH && redeemScript === undefined)
2213
- throw new Error('scriptPubkey is P2SH but redeemScript missing');
2214
- if ((isP2WSH || isP2SHP2WSH) && witnessScript === undefined)
2215
- throw new Error('scriptPubkey or redeemScript is P2WSH but witnessScript missing');
2216
-
2217
- let meaningfulScript: Buffer;
2218
-
2219
- if (isP2SHP2WSH) {
2220
- meaningfulScript = witnessScript!;
2221
- checkRedeemScript(index, script, redeemScript, ioType);
2222
- checkWitnessScript(index, redeemScript, witnessScript!, ioType);
2223
- checkInvalidP2WSH(meaningfulScript);
2224
- } else if (isP2WSH) {
2225
- meaningfulScript = witnessScript!;
2226
- checkWitnessScript(index, script, witnessScript!, ioType);
2227
- checkInvalidP2WSH(meaningfulScript);
2228
- } else if (isP2SH) {
2229
- meaningfulScript = redeemScript!;
2230
- checkRedeemScript(index, script, redeemScript!, ioType);
2231
- } else {
2232
- meaningfulScript = script;
2233
- }
2234
- return {
2235
- meaningfulScript,
2236
- type: isP2SHP2WSH ? 'p2sh-p2wsh' : isP2SH ? 'p2sh' : isP2WSH ? 'p2wsh' : 'raw',
2237
- };
2238
- }
2239
-
2240
- function checkInvalidP2WSH(script: Buffer): void {
2241
- if (isP2WPKH(script) || isP2SHScript(script)) {
2242
- throw new Error('P2WPKH or P2SH can not be contained within P2WSH');
2243
- }
2244
- }
2245
-
2246
- type AllScriptType =
2247
- | 'witnesspubkeyhash'
2248
- | 'pubkeyhash'
2249
- | 'multisig'
2250
- | 'pubkey'
2251
- | 'nonstandard'
2252
- | 'p2sh-witnesspubkeyhash'
2253
- | 'p2sh-pubkeyhash'
2254
- | 'p2sh-multisig'
2255
- | 'p2sh-pubkey'
2256
- | 'p2sh-nonstandard'
2257
- | 'p2wsh-pubkeyhash'
2258
- | 'p2wsh-multisig'
2259
- | 'p2wsh-pubkey'
2260
- | 'p2wsh-nonstandard'
2261
- | 'p2sh-p2wsh-pubkeyhash'
2262
- | 'p2sh-p2wsh-multisig'
2263
- | 'p2sh-p2wsh-pubkey'
2264
- | 'p2sh-p2wsh-nonstandard';
2265
- type ScriptType = 'witnesspubkeyhash' | 'pubkeyhash' | 'multisig' | 'pubkey' | 'nonstandard';
2266
-
2267
- function classifyScript(script: Buffer): ScriptType {
2268
- if (isP2WPKH(script)) return 'witnesspubkeyhash';
2269
- if (isP2PKH(script)) return 'pubkeyhash';
2270
- if (isP2MS(script)) return 'multisig';
2271
- if (isP2PK(script)) return 'pubkey';
2272
- return 'nonstandard';
2273
- }
2274
-
2275
- function range(n: number): number[] {
2276
- return [...Array(n).keys()];
2277
- }