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

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