@btc-vision/transaction 1.0.59 → 1.0.61

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 (273) hide show
  1. package/.gitattributes +2 -2
  2. package/browser/_version.d.ts +1 -1
  3. package/browser/index.js +1 -1
  4. package/browser/transaction/builders/TapUnwarpTransaction.d.ts +40 -40
  5. package/browser/transaction/builders/UnwarpTransaction.d.ts +34 -34
  6. package/browser/utxo/UTXOManager.d.ts +7 -7
  7. package/build/Utils.d.ts +0 -0
  8. package/build/Utils.js +1 -0
  9. package/build/_version.d.ts +1 -1
  10. package/build/_version.js +1 -1
  11. package/build/consensus/metadata/RoswsellConsensus.d.ts +2 -0
  12. package/build/consensus/metadata/RoswsellConsensus.js +4 -0
  13. package/build/contracts/ContractMetadataManager.d.ts +0 -0
  14. package/build/contracts/ContractMetadataManager.js +1 -0
  15. package/build/generators/OPNetAddressGenerator.d.ts +0 -0
  16. package/build/generators/OPNetAddressGenerator.js +1 -0
  17. package/build/generators/builders/UnwrapGenerator.d.ts +8 -0
  18. package/build/generators/builders/UnwrapGenerator.js +79 -0
  19. package/build/keypair/interfaces/GeneratedWallet.d.ts +5 -0
  20. package/build/keypair/interfaces/GeneratedWallet.js +1 -0
  21. package/build/metadata/CommonContracts.d.ts +6 -0
  22. package/build/metadata/CommonContracts.js +5 -0
  23. package/build/metadata/ContractMetadataManager.d.ts +1 -0
  24. package/build/metadata/ContractMetadataManager.js +9 -0
  25. package/build/metadata/contracts/ContractBase.d.ts +9 -0
  26. package/build/metadata/contracts/ContractBase.js +13 -0
  27. package/build/metadata/contracts/ContractBaseMetadata.d.ts +9 -0
  28. package/build/metadata/contracts/ContractBaseMetadata.js +13 -0
  29. package/build/metadata/contracts/ContractMetadataManager.d.ts +0 -0
  30. package/build/metadata/contracts/ContractMetadataManager.js +1 -0
  31. package/build/network/NetworkConverter.d.ts +0 -0
  32. package/build/network/NetworkConverter.js +14 -0
  33. package/build/scripts/Regtest.d.ts +2 -0
  34. package/build/scripts/Regtest.js +15 -0
  35. package/build/scripts/test.d.ts +1 -0
  36. package/build/scripts/test.js +74 -0
  37. package/build/signer/Regtest.d.ts +2 -0
  38. package/build/signer/Regtest.js +15 -0
  39. package/build/tests/Regtest.d.ts +3 -0
  40. package/build/tests/Regtest.js +29 -0
  41. package/build/tests/adaptPSBT.d.ts +1 -0
  42. package/build/tests/adaptPSBT.js +44 -0
  43. package/build/tests/btc/send.d.ts +1 -0
  44. package/build/tests/btc/send.js +35 -0
  45. package/build/tests/btc/transfer.d.ts +1 -0
  46. package/build/tests/btc/transfer.js +35 -0
  47. package/build/tests/createPairReg.d.ts +1 -0
  48. package/build/tests/createPairReg.js +73 -0
  49. package/build/tests/deploy/deployMoto.d.ts +4 -0
  50. package/build/tests/deploy/deployMoto.js +89 -0
  51. package/build/tests/deploy/deployPool.d.ts +1 -0
  52. package/build/tests/deploy/deployPool.js +5 -0
  53. package/build/tests/deploy/deployStep1.d.ts +1 -0
  54. package/build/tests/deploy/deployStep1.js +5 -0
  55. package/build/tests/deploy/deployStep2.d.ts +1 -0
  56. package/build/tests/deploy/deployStep2.js +5 -0
  57. package/build/tests/deploy/deployStep3.d.ts +1 -0
  58. package/build/tests/deploy/deployStep3.js +5 -0
  59. package/build/tests/deploy.d.ts +1 -0
  60. package/build/tests/deploy.js +41 -0
  61. package/build/tests/deployMotoRegStep1.d.ts +1 -0
  62. package/build/tests/deployMotoRegStep1.js +85 -0
  63. package/build/tests/deployReg.d.ts +1 -0
  64. package/build/tests/deployReg.js +85 -0
  65. package/build/tests/factory/createPairReg.d.ts +1 -0
  66. package/build/tests/factory/createPairReg.js +13 -0
  67. package/build/tests/gen.d.ts +1 -0
  68. package/build/tests/gen.js +19 -0
  69. package/build/tests/interaction.d.ts +5 -0
  70. package/build/tests/interaction.js +62 -0
  71. package/build/tests/massWrapReg.d.ts +1 -0
  72. package/build/tests/massWrapReg.js +105 -0
  73. package/build/tests/mineReg.d.ts +1 -0
  74. package/build/tests/mineReg.js +19 -0
  75. package/build/tests/moto/airdropToken.d.ts +1 -0
  76. package/build/tests/moto/airdropToken.js +21 -0
  77. package/build/tests/moto/airdropTokens.d.ts +1 -0
  78. package/build/tests/moto/airdropTokens.js +60 -0
  79. package/build/tests/moto/allowance.d.ts +1 -0
  80. package/build/tests/moto/allowance.js +6 -0
  81. package/build/tests/moto/approve.d.ts +1 -0
  82. package/build/tests/moto/approve.js +10 -0
  83. package/build/tests/moto/approveWBTC.d.ts +1 -0
  84. package/build/tests/moto/approveWBTC.js +12 -0
  85. package/build/tests/moto/balanceOf.d.ts +1 -0
  86. package/build/tests/moto/balanceOf.js +12 -0
  87. package/build/tests/moto/transfer.d.ts +1 -0
  88. package/build/tests/moto/transfer.js +16 -0
  89. package/build/tests/motoswap/airdropToken.d.ts +11 -0
  90. package/build/tests/motoswap/airdropToken.js +36 -0
  91. package/build/tests/motoswap/deployMoto.d.ts +4 -0
  92. package/build/tests/motoswap/deployMoto.js +89 -0
  93. package/build/tests/motoswap/deployMotoRegStep1.d.ts +1 -0
  94. package/build/tests/motoswap/deployMotoRegStep1.js +91 -0
  95. package/build/tests/motoswap/deployMotoRegStep2.d.ts +1 -0
  96. package/build/tests/motoswap/deployMotoRegStep2.js +91 -0
  97. package/build/tests/motoswap/deployPool.d.ts +1 -0
  98. package/build/tests/motoswap/deployPool.js +5 -0
  99. package/build/tests/motoswap/deployStep1.d.ts +1 -0
  100. package/build/tests/motoswap/deployStep1.js +5 -0
  101. package/build/tests/motoswap/deployStep2.d.ts +1 -0
  102. package/build/tests/motoswap/deployStep2.js +5 -0
  103. package/build/tests/motoswap/deployStep3.d.ts +1 -0
  104. package/build/tests/motoswap/deployStep3.js +5 -0
  105. package/build/tests/motoswap/interaction.d.ts +3 -0
  106. package/build/tests/motoswap/interaction.js +63 -0
  107. package/build/tests/motoswap/routerAddLiquidity.d.ts +11 -0
  108. package/build/tests/motoswap/routerAddLiquidity.js +35 -0
  109. package/build/tests/motoswap-router/addLiquidity.d.ts +11 -0
  110. package/build/tests/motoswap-router/addLiquidity.js +36 -0
  111. package/build/tests/motoswap-router/deployMoto.d.ts +4 -0
  112. package/build/tests/motoswap-router/deployMoto.js +89 -0
  113. package/build/tests/motoswap-router/deployPool.d.ts +1 -0
  114. package/build/tests/motoswap-router/deployPool.js +5 -0
  115. package/build/tests/motoswap-router/deployStep1.d.ts +1 -0
  116. package/build/tests/motoswap-router/deployStep1.js +5 -0
  117. package/build/tests/motoswap-router/deployStep2.d.ts +1 -0
  118. package/build/tests/motoswap-router/deployStep2.js +5 -0
  119. package/build/tests/motoswap-router/deployStep3.d.ts +1 -0
  120. package/build/tests/motoswap-router/deployStep3.js +5 -0
  121. package/build/tests/motoswap-router/getAmountsOut.d.ts +5 -0
  122. package/build/tests/motoswap-router/getAmountsOut.js +34 -0
  123. package/build/tests/motoswap-router/routerAddLiquidity.d.ts +11 -0
  124. package/build/tests/motoswap-router/routerAddLiquidity.js +35 -0
  125. package/build/tests/motoswap-router/swap.d.ts +8 -0
  126. package/build/tests/motoswap-router/swap.js +24 -0
  127. package/build/tests/multisign.d.ts +1 -0
  128. package/build/tests/multisign.js +47 -0
  129. package/build/tests/multisign2.d.ts +1 -0
  130. package/build/tests/multisign2.js +27 -0
  131. package/build/tests/pool/DecodePoolAddress.d.ts +6 -0
  132. package/build/tests/pool/DecodePoolAddress.js +12 -0
  133. package/build/tests/pool/decodeReserves.d.ts +5 -0
  134. package/build/tests/pool/decodeReserves.js +13 -0
  135. package/build/tests/pool/reserves.d.ts +1 -0
  136. package/build/tests/pool/reserves.js +18 -0
  137. package/build/tests/shared/Utils.d.ts +2 -0
  138. package/build/tests/shared/Utils.js +14 -0
  139. package/build/tests/shared/interaction.d.ts +7 -0
  140. package/build/tests/shared/interaction.js +85 -0
  141. package/build/tests/shared/tokens.d.ts +6 -0
  142. package/build/tests/shared/tokens.js +5 -0
  143. package/build/tests/stakeReg.d.ts +1 -0
  144. package/build/tests/stakeReg.js +73 -0
  145. package/build/tests/stakedReg.d.ts +1 -0
  146. package/build/tests/stakedReg.js +28 -0
  147. package/build/tests/test.d.ts +1 -0
  148. package/build/tests/test.js +51 -0
  149. package/build/tests/test2.d.ts +1 -0
  150. package/build/tests/test2.js +73 -0
  151. package/build/tests/testReg.d.ts +1 -0
  152. package/build/tests/testReg.js +91 -0
  153. package/build/tests/tokens.d.ts +6 -0
  154. package/build/tests/tokens.js +5 -0
  155. package/build/tests/totalRewardReg.d.ts +1 -0
  156. package/build/tests/totalRewardReg.js +28 -0
  157. package/build/tests/transfer.d.ts +1 -0
  158. package/build/tests/transfer.js +74 -0
  159. package/build/tests/transferReg.d.ts +1 -0
  160. package/build/tests/transferReg.js +74 -0
  161. package/build/tests/unStakeReg.d.ts +1 -0
  162. package/build/tests/unStakeReg.js +72 -0
  163. package/build/tests/unwrapReg.d.ts +1 -0
  164. package/build/tests/unwrapReg.js +61 -0
  165. package/build/tests/unwrapReg2.d.ts +1 -0
  166. package/build/tests/unwrapReg2.js +56 -0
  167. package/build/tests/unwrapRegSegwit.d.ts +1 -0
  168. package/build/tests/unwrapRegSegwit.js +83 -0
  169. package/build/tests/wbtc/approve.d.ts +1 -0
  170. package/build/tests/wbtc/approve.js +6 -0
  171. package/build/tests/wbtc/approveWBTC.d.ts +1 -0
  172. package/build/tests/wbtc/approveWBTC.js +12 -0
  173. package/build/tests/wbtc/massWrapReg.d.ts +1 -0
  174. package/build/tests/wbtc/massWrapReg.js +105 -0
  175. package/build/tests/wbtc/transfer.d.ts +1 -0
  176. package/build/tests/wbtc/transfer.js +16 -0
  177. package/build/tests/wbtc/transferReg.d.ts +1 -0
  178. package/build/tests/wbtc/transferReg.js +16 -0
  179. package/build/tests/wbtc/unStakeReg.d.ts +1 -0
  180. package/build/tests/wbtc/unStakeReg.js +72 -0
  181. package/build/tests/wbtc/unwrapReg.d.ts +1 -0
  182. package/build/tests/wbtc/unwrapReg.js +60 -0
  183. package/build/tests/wbtc/unwrapRegSegwit.d.ts +1 -0
  184. package/build/tests/wbtc/unwrapRegSegwit.js +83 -0
  185. package/build/tests/wbtc/withdrawalRequestReg.d.ts +1 -0
  186. package/build/tests/wbtc/withdrawalRequestReg.js +71 -0
  187. package/build/tests/wbtc/wrapReg.d.ts +1 -0
  188. package/build/tests/wbtc/wrapReg.js +65 -0
  189. package/build/tests/wbtc/wrapTest.d.ts +1 -0
  190. package/build/tests/wbtc/wrapTest.js +66 -0
  191. package/build/tests/withdrawalRequestReg.d.ts +1 -0
  192. package/build/tests/withdrawalRequestReg.js +71 -0
  193. package/build/tests/wrap.d.ts +1 -0
  194. package/build/tests/wrap.js +65 -0
  195. package/build/tests/wrapReg.d.ts +1 -0
  196. package/build/tests/wrapReg.js +68 -0
  197. package/build/tests/wrapTest.d.ts +1 -0
  198. package/build/tests/wrapTest.js +66 -0
  199. package/build/tests/wrapTestg.d.ts +1 -0
  200. package/build/tests/wrapTestg.js +66 -0
  201. package/build/tests/writers/allowance.d.ts +3 -0
  202. package/build/tests/writers/allowance.js +10 -0
  203. package/build/tests/writers/approve.d.ts +4 -0
  204. package/build/tests/writers/approve.js +11 -0
  205. package/build/transaction/TransactionBuilder.d.ts +60 -0
  206. package/build/transaction/TransactionBuilder.js +244 -0
  207. package/build/transaction/TransactionFactory.js +3 -2
  208. package/build/transaction/browser/BrowserSigner.d.ts +11 -0
  209. package/build/transaction/browser/BrowserSigner.js +10 -0
  210. package/build/transaction/browser/extensions/Unisat.d.ts +54 -0
  211. package/build/transaction/browser/extensions/Unisat.js +11 -0
  212. package/build/transaction/builders/GenericTransaction.d.ts +11 -0
  213. package/build/transaction/builders/GenericTransaction.js +23 -0
  214. package/build/transaction/builders/TapUnwarpTransaction.d.ts +37 -0
  215. package/build/transaction/builders/TapUnwarpTransaction.js +201 -0
  216. package/build/transaction/builders/TransactionBuilder.js +1 -1
  217. package/build/transaction/builders/UnwarpSegwitTransaction.d.ts +34 -0
  218. package/build/transaction/builders/UnwarpSegwitTransaction.js +184 -0
  219. package/build/transaction/builders/UnwarpTransaction.d.ts +35 -0
  220. package/build/transaction/builders/UnwarpTransaction.js +199 -0
  221. package/build/transaction/interfaces/ITransactions.d.ts +32 -0
  222. package/build/transaction/interfaces/ITransactions.js +1 -0
  223. package/build/utxo/IUTXO.d.ts +0 -0
  224. package/build/utxo/IUTXO.js +1 -0
  225. package/build/utxo/OPNetUtils.d.ts +7 -0
  226. package/build/utxo/OPNetUtils.js +47 -0
  227. package/build/utxo/UTXOManager.d.ts +7 -0
  228. package/build/utxo/UTXOManager.js +47 -0
  229. package/build/wbtc/BroadcastResponse.d.ts +0 -0
  230. package/build/wbtc/BroadcastResponse.js +1 -0
  231. package/gulpfile.js +152 -152
  232. package/package.json +1 -1
  233. package/src/_version.ts +1 -1
  234. package/src/consensus/Consensus.ts +36 -36
  235. package/src/consensus/ConsensusConfig.ts +39 -39
  236. package/src/crypto/crypto-browser.js +75 -75
  237. package/src/generators/AddressGenerator.ts +24 -24
  238. package/src/generators/Features.ts +5 -5
  239. package/src/generators/Generator.ts +75 -75
  240. package/src/generators/builders/CalldataGenerator.ts +148 -148
  241. package/src/generators/builders/DeploymentGenerator.ts +66 -66
  242. package/src/index.ts +4 -4
  243. package/src/keypair/AddressVerificator.ts +40 -40
  244. package/src/keypair/EcKeyPair.ts +282 -282
  245. package/src/keypair/Wallet.ts +97 -97
  246. package/src/keypair/interfaces/IWallet.ts +19 -19
  247. package/src/metadata/ContractBaseMetadata.ts +23 -23
  248. package/src/network/NetworkInformation.ts +7 -7
  249. package/src/opnet.ts +84 -84
  250. package/src/transaction/TransactionFactory.ts +3 -2
  251. package/src/transaction/browser/BrowserSignerBase.ts +37 -37
  252. package/src/transaction/browser/Web3Provider.ts +46 -46
  253. package/src/transaction/browser/extensions/UnisatSigner.ts +218 -218
  254. package/src/transaction/browser/types/Unisat.ts +80 -80
  255. package/src/transaction/builders/FundingTransaction.ts +40 -40
  256. package/src/transaction/builders/InteractionTransaction.ts +38 -38
  257. package/src/transaction/builders/SharedInteractionTransaction.ts +368 -368
  258. package/src/transaction/builders/TransactionBuilder.ts +665 -665
  259. package/src/transaction/interfaces/Tap.ts +26 -26
  260. package/src/transaction/psbt/PSBTTypes.ts +3 -3
  261. package/src/transaction/shared/TweakedTransaction.ts +537 -537
  262. package/src/utxo/OPNetLimitedProvider.ts +244 -244
  263. package/src/utxo/interfaces/BroadcastResponse.ts +10 -10
  264. package/src/utxo/interfaces/IUTXO.ts +29 -29
  265. package/src/verification/TapscriptVerificator.ts +89 -89
  266. package/src/wbtc/Generate.ts +40 -40
  267. package/src/wbtc/UnwrapGeneration.ts +13 -13
  268. package/src/wbtc/WrappedGenerationParameters.ts +33 -33
  269. package/webpack.config.js +78 -78
  270. /package/build/generators/builders/{MultiSignGenerator.d.ts → MultisignGenerator.d.ts} +0 -0
  271. /package/build/generators/builders/{MultiSignGenerator.js → MultisignGenerator.js} +0 -0
  272. /package/build/generators/{Features.d.ts → features.d.ts} +0 -0
  273. /package/build/generators/{Features.js → features.js} +0 -0
@@ -1,537 +1,537 @@
1
- import { Logger } from '@btc-vision/logger';
2
- import { Network, Payment, payments, Psbt, Signer, Transaction } from 'bitcoinjs-lib';
3
- import { TweakedSigner, TweakSettings } from '../../signer/TweakedSigner.js';
4
- import { ECPairInterface } from 'ecpair';
5
- import { toXOnly } from 'bitcoinjs-lib/src/psbt/bip371.js';
6
- import { PsbtInput } from 'bip174/src/lib/interfaces.js';
7
- import { UTXO } from '../../utxo/interfaces/IUTXO.js';
8
- import { PsbtInputExtended, TapLeafScript } from '../interfaces/Tap.js';
9
- import { AddressVerificator } from '../../keypair/AddressVerificator.js';
10
- import { varuint } from 'bitcoinjs-lib/src/bufferutils.js';
11
-
12
- export interface ITweakedTransactionData {
13
- readonly signer: Signer;
14
- readonly network: Network;
15
- readonly nonWitnessUtxo?: Buffer;
16
- }
17
-
18
- /**
19
- * The transaction sequence
20
- */
21
- export enum TransactionSequence {
22
- REPLACE_BY_FEE = 0xfffffffd,
23
- FINAL = 0xffffffff,
24
- }
25
-
26
- /**
27
- * @description PSBT Transaction processor.
28
- * */
29
- export abstract class TweakedTransaction extends Logger {
30
- public readonly logColor: string = '#00ffe1';
31
- public finalized: boolean = false;
32
- /**
33
- * @description Was the transaction signed?
34
- */
35
- protected signer: Signer;
36
- /**
37
- * @description Tweaked signer
38
- */
39
- protected tweakedSigner?: Signer;
40
- /**
41
- * @description The network of the transaction
42
- */
43
- protected network: Network;
44
- /**
45
- * @description Was the transaction signed?
46
- */
47
- protected signed: boolean = false;
48
- /**
49
- * @description The transaction
50
- * @protected
51
- */
52
- protected abstract readonly transaction: Psbt;
53
- /**
54
- * @description The sighash types of the transaction
55
- * @protected
56
- */
57
- protected sighashTypes: number[] | undefined;
58
- /**
59
- * @description The script data of the transaction
60
- */
61
- protected scriptData: Payment | null = null;
62
- /**
63
- * @description The tap data of the transaction
64
- */
65
- protected tapData: Payment | null = null;
66
- /**
67
- * @description The inputs of the transaction
68
- */
69
- protected readonly inputs: PsbtInputExtended[] = [];
70
- /**
71
- * @description The sequence of the transaction
72
- * @protected
73
- */
74
- protected sequence: number = TransactionSequence.REPLACE_BY_FEE;
75
- /**
76
- * The tap leaf script
77
- * @protected
78
- */
79
- protected tapLeafScript: TapLeafScript | null = null;
80
- /**
81
- * Add a non-witness utxo to the transaction
82
- * @protected
83
- */
84
- protected nonWitnessUtxo?: Buffer;
85
-
86
- /**
87
- * Is the transaction being generated inside a browser?
88
- * @protected
89
- */
90
- protected readonly isBrowser: boolean = false;
91
-
92
- protected regenerated: boolean = false;
93
- protected ignoreSignatureErrors: boolean = false;
94
-
95
- protected constructor(data: ITweakedTransactionData) {
96
- super();
97
-
98
- this.signer = data.signer;
99
- this.network = data.network;
100
-
101
- this.nonWitnessUtxo = data.nonWitnessUtxo;
102
-
103
- this.isBrowser = typeof window !== 'undefined';
104
- }
105
-
106
- /**
107
- * Read witnesses
108
- * @protected
109
- */
110
- public static readScriptWitnessToWitnessStack(buffer: Buffer): Buffer[] {
111
- let offset = 0;
112
-
113
- function readSlice(n: number): Buffer {
114
- const slice = buffer.subarray(offset, offset + n);
115
- offset += n;
116
- return slice;
117
- }
118
-
119
- function readVarInt(): number {
120
- const varint = varuint.decode(buffer, offset);
121
- offset += varuint.decode.bytes;
122
- return varint;
123
- }
124
-
125
- function readVarSlice(): Buffer {
126
- const len = readVarInt();
127
- return readSlice(len);
128
- }
129
-
130
- function readVector(): Buffer[] {
131
- const count = readVarInt();
132
- const vector = [];
133
- for (let i = 0; i < count; i++) {
134
- vector.push(readVarSlice());
135
- }
136
- return vector;
137
- }
138
-
139
- return readVector();
140
- }
141
-
142
- /**
143
- * Pre-estimate the transaction fees for a Taproot transaction
144
- * @param {bigint} feeRate - The fee rate in satoshis per virtual byte
145
- * @param {bigint} numInputs - The number of inputs
146
- * @param {bigint} numOutputs - The number of outputs
147
- * @param {bigint} numWitnessElements - The number of witness elements (e.g., number of control blocks and witnesses)
148
- * @param {bigint} witnessElementSize - The average size of each witness element in bytes
149
- * @param {bigint} emptyWitness - The amount of empty witnesses
150
- * @param {bigint} [taprootControlWitnessSize=139n] - The size of the control block witness in bytes
151
- * @param {bigint} [taprootScriptSize=32n] - The size of the taproot script in bytes
152
- * @returns {bigint} - The estimated transaction fees
153
- */
154
- public static preEstimateTaprootTransactionFees(
155
- feeRate: bigint, // satoshis per virtual byte
156
- numInputs: bigint,
157
- numOutputs: bigint,
158
- numWitnessElements: bigint,
159
- witnessElementSize: bigint,
160
- emptyWitness: bigint,
161
- taprootControlWitnessSize: bigint = 32n,
162
- taprootScriptSize: bigint = 139n,
163
- ): bigint {
164
- const txHeaderSize = 10n;
165
- const inputBaseSize = 41n;
166
- const outputSize = 68n;
167
- const taprootWitnessBaseSize = 1n; // Base witness size per input (without signatures and control blocks)
168
-
169
- // Base transaction size (excluding witness data)
170
- const baseTxSize = txHeaderSize + inputBaseSize * numInputs + outputSize * numOutputs;
171
-
172
- // Witness data size for Taproot
173
- const witnessSize =
174
- numInputs * taprootWitnessBaseSize +
175
- numWitnessElements * witnessElementSize +
176
- taprootControlWitnessSize * numInputs +
177
- taprootScriptSize * numInputs +
178
- emptyWitness;
179
-
180
- // Total weight and virtual size
181
- const weight = baseTxSize * 3n + (baseTxSize + witnessSize);
182
- const vSize = weight / 4n;
183
-
184
- return vSize * feeRate;
185
- }
186
-
187
- protected static signInput(
188
- transaction: Psbt,
189
- input: PsbtInput,
190
- i: number,
191
- signer: Signer,
192
- sighashTypes: number[],
193
- ): void {
194
- if (sighashTypes && sighashTypes[0]) input.sighashType = sighashTypes[0];
195
-
196
- transaction.signInput(i, signer, sighashTypes.length ? sighashTypes : undefined);
197
- }
198
-
199
- /**
200
- * Calculate the sign hash number
201
- * @description Calculates the sign hash
202
- * @protected
203
- * @returns {number}
204
- */
205
- protected static calculateSignHash(sighashTypes: number[]): number {
206
- if (!sighashTypes) {
207
- throw new Error('Sighash types are required');
208
- }
209
-
210
- let signHash: number = 0;
211
- for (let sighashType of sighashTypes) {
212
- signHash |= sighashType;
213
- }
214
-
215
- return signHash || 0;
216
- }
217
-
218
- public ignoreSignatureError(): void {
219
- this.ignoreSignatureErrors = true;
220
- }
221
-
222
- /**
223
- * @description Returns the script address
224
- * @returns {string}
225
- */
226
- public getScriptAddress(): string {
227
- if (!this.scriptData || !this.scriptData.address) {
228
- throw new Error('Tap data is required');
229
- }
230
-
231
- return this.scriptData.address;
232
- }
233
-
234
- /**
235
- * @description Returns the transaction
236
- * @returns {Transaction}
237
- */
238
- public getTransaction(): Transaction {
239
- return this.transaction.extractTransaction(false);
240
- }
241
-
242
- /**
243
- * @description Returns the tap address
244
- * @returns {string}
245
- * @throws {Error} - If tap data is not set
246
- */
247
- public getTapAddress(): string {
248
- if (!this.tapData || !this.tapData.address) {
249
- throw new Error('Tap data is required');
250
- }
251
-
252
- return this.tapData.address;
253
- }
254
-
255
- /**
256
- * @description Disables replace by fee on the transaction
257
- */
258
- public disableRBF(): void {
259
- if (this.signed) throw new Error('Transaction is already signed');
260
-
261
- this.sequence = TransactionSequence.FINAL;
262
-
263
- for (let input of this.inputs) {
264
- input.sequence = TransactionSequence.FINAL;
265
- }
266
- }
267
-
268
- /**
269
- * Get the tweaked hash
270
- * @private
271
- *
272
- * @returns {Buffer | undefined} The tweaked hash
273
- */
274
- public getTweakerHash(): Buffer | undefined {
275
- return this.tapData?.hash;
276
- }
277
-
278
- /**
279
- * Pre-estimate the transaction fees
280
- * @param {bigint} feeRate - The fee rate
281
- * @param {bigint} numInputs - The number of inputs
282
- * @param {bigint} numOutputs - The number of outputs
283
- * @param {bigint} numSignatures - The number of signatures
284
- * @param {bigint} numPubkeys - The number of public keys
285
- * @returns {bigint} - The estimated transaction fees
286
- */
287
- public preEstimateTransactionFees(
288
- feeRate: bigint, // satoshis per byte
289
- numInputs: bigint,
290
- numOutputs: bigint,
291
- numSignatures: bigint,
292
- numPubkeys: bigint,
293
- ): bigint {
294
- const txHeaderSize = 10n;
295
- const inputBaseSize = 41n;
296
- const outputSize = 68n;
297
- const signatureSize = 144n;
298
- const pubkeySize = 34n;
299
-
300
- // Base transaction size (excluding witness data)
301
- const baseTxSize = txHeaderSize + inputBaseSize * numInputs + outputSize * numOutputs;
302
-
303
- // Witness data size
304
- const redeemScriptSize = 1n + numPubkeys * (1n + pubkeySize) + 1n + numSignatures;
305
- const witnessSize =
306
- numSignatures * signatureSize + numPubkeys * pubkeySize + redeemScriptSize;
307
-
308
- // Total weight and virtual size
309
- const weight = baseTxSize * 3n + (baseTxSize + witnessSize);
310
- const vSize = weight / 4n;
311
-
312
- return vSize * feeRate;
313
- }
314
-
315
- protected generateTapData(): Payment {
316
- return {
317
- internalPubkey: this.internalPubKeyToXOnly(),
318
- network: this.network,
319
- };
320
- }
321
-
322
- /**
323
- * Generates the script address.
324
- * @protected
325
- * @returns {Payment}
326
- */
327
- protected generateScriptAddress(): Payment {
328
- return {
329
- internalPubkey: this.internalPubKeyToXOnly(),
330
- network: this.network,
331
- };
332
- }
333
-
334
- /**
335
- * Returns the signer key.
336
- * @protected
337
- * @returns {Signer}
338
- */
339
- protected getSignerKey(): Signer {
340
- return this.signer;
341
- }
342
-
343
- /**
344
- * Signs an input of the transaction.
345
- * @param {Psbt} transaction - The transaction to sign
346
- * @param {PsbtInput} input - The input to sign
347
- * @param {number} i - The index of the input
348
- * @param {Signer} [signer] - The signer to use
349
- * @protected
350
- */
351
- protected async signInput(
352
- transaction: Psbt,
353
- input: PsbtInput,
354
- i: number,
355
- signer?: Signer,
356
- ): Promise<void> {
357
- const signHash =
358
- this.sighashTypes && this.sighashTypes.length
359
- ? [TweakedTransaction.calculateSignHash(this.sighashTypes)]
360
- : undefined;
361
-
362
- signer = signer || this.getSignerKey();
363
-
364
- let testedTap: boolean = false;
365
- if (input.tapInternalKey) {
366
- if (!this.tweakedSigner) this.tweakSigner();
367
-
368
- let tweakedSigner: Signer | undefined;
369
- if (signer !== this.signer) {
370
- tweakedSigner = this.getTweakedSigner(true, signer);
371
- } else {
372
- tweakedSigner = this.tweakedSigner;
373
- }
374
-
375
- if (tweakedSigner) {
376
- testedTap = true;
377
-
378
- try {
379
- if ('signTaprootInput' in signer) {
380
- // @ts-ignore
381
- return await signer.signTaprootInput(transaction, i, signHash);
382
- } else {
383
- transaction.signTaprootInput(i, tweakedSigner, undefined, signHash);
384
- }
385
-
386
- return;
387
- } catch (e) {}
388
- }
389
- }
390
-
391
- try {
392
- if ('signInput' in signer) {
393
- // @ts-ignore
394
- return await signer.signInput(transaction, i, signHash);
395
- } else {
396
- transaction.signInput(i, signer, signHash);
397
- }
398
- } catch (e) {
399
- if (!testedTap) {
400
- // and we try again taproot...
401
-
402
- if ('signTaprootInput' in signer) {
403
- // @ts-ignore
404
- return await signer.signTaprootInput(transaction, i, signHash);
405
- } else if (this.tweakedSigner) {
406
- transaction.signTaprootInput(i, this.tweakedSigner, undefined, signHash);
407
- } else {
408
- throw e;
409
- }
410
- }
411
- }
412
- }
413
-
414
- /**
415
- * Signs all the inputs of the transaction.
416
- * @param {Psbt} transaction - The transaction to sign
417
- * @protected
418
- * @returns {Promise<void>}
419
- */
420
- protected async signInputs(transaction: Psbt): Promise<void> {
421
- for (let i = 0; i < transaction.data.inputs.length; i++) {
422
- let input: PsbtInput = transaction.data.inputs[i];
423
-
424
- try {
425
- await this.signInput(transaction, input, i);
426
- } catch (e) {
427
- this.log(`Failed to sign input ${i}: ${(e as Error).stack}`);
428
- }
429
- }
430
-
431
- try {
432
- transaction.finalizeAllInputs();
433
-
434
- this.finalized = true;
435
- } catch (e) {
436
- this.finalized = false;
437
- }
438
- }
439
-
440
- /**
441
- * Converts the public key to x-only.
442
- * @protected
443
- * @returns {Buffer}
444
- */
445
- protected internalPubKeyToXOnly(): Buffer {
446
- return toXOnly(this.signer.publicKey);
447
- }
448
-
449
- /**
450
- * Internal init.
451
- * @protected
452
- */
453
- protected internalInit(): void {
454
- this.scriptData = payments.p2tr(this.generateScriptAddress());
455
- this.tapData = payments.p2tr(this.generateTapData());
456
- }
457
-
458
- /**
459
- * Tweak the signer for the interaction
460
- * @protected
461
- */
462
- protected tweakSigner(): void {
463
- if (this.tweakedSigner) return;
464
-
465
- // tweaked p2tr signer.
466
- this.tweakedSigner = this.getTweakedSigner(true);
467
- }
468
-
469
- /**
470
- * Get the tweaked signer
471
- * @private
472
- * @returns {Signer} The tweaked signer
473
- */
474
- protected getTweakedSigner(
475
- useTweakedHash: boolean = false,
476
- signer: Signer = this.signer,
477
- ): Signer | undefined {
478
- const settings: TweakSettings = {
479
- network: this.network,
480
- };
481
-
482
- if (useTweakedHash) {
483
- settings.tweakHash = this.getTweakerHash();
484
- }
485
-
486
- if (!('privateKey' in signer)) {
487
- return;
488
- }
489
-
490
- return TweakedSigner.tweakSigner(signer as unknown as ECPairInterface, settings) as Signer;
491
- }
492
-
493
- /**
494
- * Generate the PSBT input extended
495
- * @param {UTXO} utxo The UTXO
496
- * @param {number} i The index of the input
497
- * @protected
498
- * @returns {PsbtInputExtended} The PSBT input extended
499
- */
500
- protected generatePsbtInputExtended(utxo: UTXO, i: number): PsbtInputExtended {
501
- const input: PsbtInputExtended = {
502
- hash: utxo.transactionId,
503
- index: utxo.outputIndex,
504
- witnessUtxo: {
505
- value: Number(utxo.value),
506
- script: Buffer.from(utxo.scriptPubKey.hex, 'hex'),
507
- },
508
- sequence: this.sequence,
509
- };
510
-
511
- if (this.sighashTypes) {
512
- const inputSign = TweakedTransaction.calculateSignHash(this.sighashTypes);
513
- if (inputSign) input.sighashType = inputSign;
514
- }
515
-
516
- if (this.tapLeafScript) {
517
- input.tapLeafScript = [this.tapLeafScript];
518
- }
519
-
520
- if (i === 0 && this.nonWitnessUtxo) {
521
- input.nonWitnessUtxo = this.nonWitnessUtxo;
522
- this.log(`Using non-witness utxo for input ${i}`);
523
- }
524
-
525
- // automatically detect p2tr inputs.
526
- if (
527
- utxo.scriptPubKey.address &&
528
- AddressVerificator.isValidP2TRAddress(utxo.scriptPubKey.address, this.network)
529
- ) {
530
- this.tweakSigner();
531
-
532
- input.tapInternalKey = this.internalPubKeyToXOnly();
533
- }
534
-
535
- return input;
536
- }
537
- }
1
+ import { Logger } from '@btc-vision/logger';
2
+ import { Network, Payment, payments, Psbt, Signer, Transaction } from 'bitcoinjs-lib';
3
+ import { TweakedSigner, TweakSettings } from '../../signer/TweakedSigner.js';
4
+ import { ECPairInterface } from 'ecpair';
5
+ import { toXOnly } from 'bitcoinjs-lib/src/psbt/bip371.js';
6
+ import { PsbtInput } from 'bip174/src/lib/interfaces.js';
7
+ import { UTXO } from '../../utxo/interfaces/IUTXO.js';
8
+ import { PsbtInputExtended, TapLeafScript } from '../interfaces/Tap.js';
9
+ import { AddressVerificator } from '../../keypair/AddressVerificator.js';
10
+ import { varuint } from 'bitcoinjs-lib/src/bufferutils.js';
11
+
12
+ export interface ITweakedTransactionData {
13
+ readonly signer: Signer;
14
+ readonly network: Network;
15
+ readonly nonWitnessUtxo?: Buffer;
16
+ }
17
+
18
+ /**
19
+ * The transaction sequence
20
+ */
21
+ export enum TransactionSequence {
22
+ REPLACE_BY_FEE = 0xfffffffd,
23
+ FINAL = 0xffffffff,
24
+ }
25
+
26
+ /**
27
+ * @description PSBT Transaction processor.
28
+ * */
29
+ export abstract class TweakedTransaction extends Logger {
30
+ public readonly logColor: string = '#00ffe1';
31
+ public finalized: boolean = false;
32
+ /**
33
+ * @description Was the transaction signed?
34
+ */
35
+ protected signer: Signer;
36
+ /**
37
+ * @description Tweaked signer
38
+ */
39
+ protected tweakedSigner?: Signer;
40
+ /**
41
+ * @description The network of the transaction
42
+ */
43
+ protected network: Network;
44
+ /**
45
+ * @description Was the transaction signed?
46
+ */
47
+ protected signed: boolean = false;
48
+ /**
49
+ * @description The transaction
50
+ * @protected
51
+ */
52
+ protected abstract readonly transaction: Psbt;
53
+ /**
54
+ * @description The sighash types of the transaction
55
+ * @protected
56
+ */
57
+ protected sighashTypes: number[] | undefined;
58
+ /**
59
+ * @description The script data of the transaction
60
+ */
61
+ protected scriptData: Payment | null = null;
62
+ /**
63
+ * @description The tap data of the transaction
64
+ */
65
+ protected tapData: Payment | null = null;
66
+ /**
67
+ * @description The inputs of the transaction
68
+ */
69
+ protected readonly inputs: PsbtInputExtended[] = [];
70
+ /**
71
+ * @description The sequence of the transaction
72
+ * @protected
73
+ */
74
+ protected sequence: number = TransactionSequence.REPLACE_BY_FEE;
75
+ /**
76
+ * The tap leaf script
77
+ * @protected
78
+ */
79
+ protected tapLeafScript: TapLeafScript | null = null;
80
+ /**
81
+ * Add a non-witness utxo to the transaction
82
+ * @protected
83
+ */
84
+ protected nonWitnessUtxo?: Buffer;
85
+
86
+ /**
87
+ * Is the transaction being generated inside a browser?
88
+ * @protected
89
+ */
90
+ protected readonly isBrowser: boolean = false;
91
+
92
+ protected regenerated: boolean = false;
93
+ protected ignoreSignatureErrors: boolean = false;
94
+
95
+ protected constructor(data: ITweakedTransactionData) {
96
+ super();
97
+
98
+ this.signer = data.signer;
99
+ this.network = data.network;
100
+
101
+ this.nonWitnessUtxo = data.nonWitnessUtxo;
102
+
103
+ this.isBrowser = typeof window !== 'undefined';
104
+ }
105
+
106
+ /**
107
+ * Read witnesses
108
+ * @protected
109
+ */
110
+ public static readScriptWitnessToWitnessStack(buffer: Buffer): Buffer[] {
111
+ let offset = 0;
112
+
113
+ function readSlice(n: number): Buffer {
114
+ const slice = buffer.subarray(offset, offset + n);
115
+ offset += n;
116
+ return slice;
117
+ }
118
+
119
+ function readVarInt(): number {
120
+ const varint = varuint.decode(buffer, offset);
121
+ offset += varuint.decode.bytes;
122
+ return varint;
123
+ }
124
+
125
+ function readVarSlice(): Buffer {
126
+ const len = readVarInt();
127
+ return readSlice(len);
128
+ }
129
+
130
+ function readVector(): Buffer[] {
131
+ const count = readVarInt();
132
+ const vector = [];
133
+ for (let i = 0; i < count; i++) {
134
+ vector.push(readVarSlice());
135
+ }
136
+ return vector;
137
+ }
138
+
139
+ return readVector();
140
+ }
141
+
142
+ /**
143
+ * Pre-estimate the transaction fees for a Taproot transaction
144
+ * @param {bigint} feeRate - The fee rate in satoshis per virtual byte
145
+ * @param {bigint} numInputs - The number of inputs
146
+ * @param {bigint} numOutputs - The number of outputs
147
+ * @param {bigint} numWitnessElements - The number of witness elements (e.g., number of control blocks and witnesses)
148
+ * @param {bigint} witnessElementSize - The average size of each witness element in bytes
149
+ * @param {bigint} emptyWitness - The amount of empty witnesses
150
+ * @param {bigint} [taprootControlWitnessSize=139n] - The size of the control block witness in bytes
151
+ * @param {bigint} [taprootScriptSize=32n] - The size of the taproot script in bytes
152
+ * @returns {bigint} - The estimated transaction fees
153
+ */
154
+ public static preEstimateTaprootTransactionFees(
155
+ feeRate: bigint, // satoshis per virtual byte
156
+ numInputs: bigint,
157
+ numOutputs: bigint,
158
+ numWitnessElements: bigint,
159
+ witnessElementSize: bigint,
160
+ emptyWitness: bigint,
161
+ taprootControlWitnessSize: bigint = 32n,
162
+ taprootScriptSize: bigint = 139n,
163
+ ): bigint {
164
+ const txHeaderSize = 10n;
165
+ const inputBaseSize = 41n;
166
+ const outputSize = 68n;
167
+ const taprootWitnessBaseSize = 1n; // Base witness size per input (without signatures and control blocks)
168
+
169
+ // Base transaction size (excluding witness data)
170
+ const baseTxSize = txHeaderSize + inputBaseSize * numInputs + outputSize * numOutputs;
171
+
172
+ // Witness data size for Taproot
173
+ const witnessSize =
174
+ numInputs * taprootWitnessBaseSize +
175
+ numWitnessElements * witnessElementSize +
176
+ taprootControlWitnessSize * numInputs +
177
+ taprootScriptSize * numInputs +
178
+ emptyWitness;
179
+
180
+ // Total weight and virtual size
181
+ const weight = baseTxSize * 3n + (baseTxSize + witnessSize);
182
+ const vSize = weight / 4n;
183
+
184
+ return vSize * feeRate;
185
+ }
186
+
187
+ protected static signInput(
188
+ transaction: Psbt,
189
+ input: PsbtInput,
190
+ i: number,
191
+ signer: Signer,
192
+ sighashTypes: number[],
193
+ ): void {
194
+ if (sighashTypes && sighashTypes[0]) input.sighashType = sighashTypes[0];
195
+
196
+ transaction.signInput(i, signer, sighashTypes.length ? sighashTypes : undefined);
197
+ }
198
+
199
+ /**
200
+ * Calculate the sign hash number
201
+ * @description Calculates the sign hash
202
+ * @protected
203
+ * @returns {number}
204
+ */
205
+ protected static calculateSignHash(sighashTypes: number[]): number {
206
+ if (!sighashTypes) {
207
+ throw new Error('Sighash types are required');
208
+ }
209
+
210
+ let signHash: number = 0;
211
+ for (let sighashType of sighashTypes) {
212
+ signHash |= sighashType;
213
+ }
214
+
215
+ return signHash || 0;
216
+ }
217
+
218
+ public ignoreSignatureError(): void {
219
+ this.ignoreSignatureErrors = true;
220
+ }
221
+
222
+ /**
223
+ * @description Returns the script address
224
+ * @returns {string}
225
+ */
226
+ public getScriptAddress(): string {
227
+ if (!this.scriptData || !this.scriptData.address) {
228
+ throw new Error('Tap data is required');
229
+ }
230
+
231
+ return this.scriptData.address;
232
+ }
233
+
234
+ /**
235
+ * @description Returns the transaction
236
+ * @returns {Transaction}
237
+ */
238
+ public getTransaction(): Transaction {
239
+ return this.transaction.extractTransaction(false);
240
+ }
241
+
242
+ /**
243
+ * @description Returns the tap address
244
+ * @returns {string}
245
+ * @throws {Error} - If tap data is not set
246
+ */
247
+ public getTapAddress(): string {
248
+ if (!this.tapData || !this.tapData.address) {
249
+ throw new Error('Tap data is required');
250
+ }
251
+
252
+ return this.tapData.address;
253
+ }
254
+
255
+ /**
256
+ * @description Disables replace by fee on the transaction
257
+ */
258
+ public disableRBF(): void {
259
+ if (this.signed) throw new Error('Transaction is already signed');
260
+
261
+ this.sequence = TransactionSequence.FINAL;
262
+
263
+ for (let input of this.inputs) {
264
+ input.sequence = TransactionSequence.FINAL;
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Get the tweaked hash
270
+ * @private
271
+ *
272
+ * @returns {Buffer | undefined} The tweaked hash
273
+ */
274
+ public getTweakerHash(): Buffer | undefined {
275
+ return this.tapData?.hash;
276
+ }
277
+
278
+ /**
279
+ * Pre-estimate the transaction fees
280
+ * @param {bigint} feeRate - The fee rate
281
+ * @param {bigint} numInputs - The number of inputs
282
+ * @param {bigint} numOutputs - The number of outputs
283
+ * @param {bigint} numSignatures - The number of signatures
284
+ * @param {bigint} numPubkeys - The number of public keys
285
+ * @returns {bigint} - The estimated transaction fees
286
+ */
287
+ public preEstimateTransactionFees(
288
+ feeRate: bigint, // satoshis per byte
289
+ numInputs: bigint,
290
+ numOutputs: bigint,
291
+ numSignatures: bigint,
292
+ numPubkeys: bigint,
293
+ ): bigint {
294
+ const txHeaderSize = 10n;
295
+ const inputBaseSize = 41n;
296
+ const outputSize = 68n;
297
+ const signatureSize = 144n;
298
+ const pubkeySize = 34n;
299
+
300
+ // Base transaction size (excluding witness data)
301
+ const baseTxSize = txHeaderSize + inputBaseSize * numInputs + outputSize * numOutputs;
302
+
303
+ // Witness data size
304
+ const redeemScriptSize = 1n + numPubkeys * (1n + pubkeySize) + 1n + numSignatures;
305
+ const witnessSize =
306
+ numSignatures * signatureSize + numPubkeys * pubkeySize + redeemScriptSize;
307
+
308
+ // Total weight and virtual size
309
+ const weight = baseTxSize * 3n + (baseTxSize + witnessSize);
310
+ const vSize = weight / 4n;
311
+
312
+ return vSize * feeRate;
313
+ }
314
+
315
+ protected generateTapData(): Payment {
316
+ return {
317
+ internalPubkey: this.internalPubKeyToXOnly(),
318
+ network: this.network,
319
+ };
320
+ }
321
+
322
+ /**
323
+ * Generates the script address.
324
+ * @protected
325
+ * @returns {Payment}
326
+ */
327
+ protected generateScriptAddress(): Payment {
328
+ return {
329
+ internalPubkey: this.internalPubKeyToXOnly(),
330
+ network: this.network,
331
+ };
332
+ }
333
+
334
+ /**
335
+ * Returns the signer key.
336
+ * @protected
337
+ * @returns {Signer}
338
+ */
339
+ protected getSignerKey(): Signer {
340
+ return this.signer;
341
+ }
342
+
343
+ /**
344
+ * Signs an input of the transaction.
345
+ * @param {Psbt} transaction - The transaction to sign
346
+ * @param {PsbtInput} input - The input to sign
347
+ * @param {number} i - The index of the input
348
+ * @param {Signer} [signer] - The signer to use
349
+ * @protected
350
+ */
351
+ protected async signInput(
352
+ transaction: Psbt,
353
+ input: PsbtInput,
354
+ i: number,
355
+ signer?: Signer,
356
+ ): Promise<void> {
357
+ const signHash =
358
+ this.sighashTypes && this.sighashTypes.length
359
+ ? [TweakedTransaction.calculateSignHash(this.sighashTypes)]
360
+ : undefined;
361
+
362
+ signer = signer || this.getSignerKey();
363
+
364
+ let testedTap: boolean = false;
365
+ if (input.tapInternalKey) {
366
+ if (!this.tweakedSigner) this.tweakSigner();
367
+
368
+ let tweakedSigner: Signer | undefined;
369
+ if (signer !== this.signer) {
370
+ tweakedSigner = this.getTweakedSigner(true, signer);
371
+ } else {
372
+ tweakedSigner = this.tweakedSigner;
373
+ }
374
+
375
+ if (tweakedSigner) {
376
+ testedTap = true;
377
+
378
+ try {
379
+ if ('signTaprootInput' in signer) {
380
+ // @ts-ignore
381
+ return await signer.signTaprootInput(transaction, i, signHash);
382
+ } else {
383
+ transaction.signTaprootInput(i, tweakedSigner, undefined, signHash);
384
+ }
385
+
386
+ return;
387
+ } catch (e) {}
388
+ }
389
+ }
390
+
391
+ try {
392
+ if ('signInput' in signer) {
393
+ // @ts-ignore
394
+ return await signer.signInput(transaction, i, signHash);
395
+ } else {
396
+ transaction.signInput(i, signer, signHash);
397
+ }
398
+ } catch (e) {
399
+ if (!testedTap) {
400
+ // and we try again taproot...
401
+
402
+ if ('signTaprootInput' in signer) {
403
+ // @ts-ignore
404
+ return await signer.signTaprootInput(transaction, i, signHash);
405
+ } else if (this.tweakedSigner) {
406
+ transaction.signTaprootInput(i, this.tweakedSigner, undefined, signHash);
407
+ } else {
408
+ throw e;
409
+ }
410
+ }
411
+ }
412
+ }
413
+
414
+ /**
415
+ * Signs all the inputs of the transaction.
416
+ * @param {Psbt} transaction - The transaction to sign
417
+ * @protected
418
+ * @returns {Promise<void>}
419
+ */
420
+ protected async signInputs(transaction: Psbt): Promise<void> {
421
+ for (let i = 0; i < transaction.data.inputs.length; i++) {
422
+ let input: PsbtInput = transaction.data.inputs[i];
423
+
424
+ try {
425
+ await this.signInput(transaction, input, i);
426
+ } catch (e) {
427
+ this.log(`Failed to sign input ${i}: ${(e as Error).stack}`);
428
+ }
429
+ }
430
+
431
+ try {
432
+ transaction.finalizeAllInputs();
433
+
434
+ this.finalized = true;
435
+ } catch (e) {
436
+ this.finalized = false;
437
+ }
438
+ }
439
+
440
+ /**
441
+ * Converts the public key to x-only.
442
+ * @protected
443
+ * @returns {Buffer}
444
+ */
445
+ protected internalPubKeyToXOnly(): Buffer {
446
+ return toXOnly(this.signer.publicKey);
447
+ }
448
+
449
+ /**
450
+ * Internal init.
451
+ * @protected
452
+ */
453
+ protected internalInit(): void {
454
+ this.scriptData = payments.p2tr(this.generateScriptAddress());
455
+ this.tapData = payments.p2tr(this.generateTapData());
456
+ }
457
+
458
+ /**
459
+ * Tweak the signer for the interaction
460
+ * @protected
461
+ */
462
+ protected tweakSigner(): void {
463
+ if (this.tweakedSigner) return;
464
+
465
+ // tweaked p2tr signer.
466
+ this.tweakedSigner = this.getTweakedSigner(true);
467
+ }
468
+
469
+ /**
470
+ * Get the tweaked signer
471
+ * @private
472
+ * @returns {Signer} The tweaked signer
473
+ */
474
+ protected getTweakedSigner(
475
+ useTweakedHash: boolean = false,
476
+ signer: Signer = this.signer,
477
+ ): Signer | undefined {
478
+ const settings: TweakSettings = {
479
+ network: this.network,
480
+ };
481
+
482
+ if (useTweakedHash) {
483
+ settings.tweakHash = this.getTweakerHash();
484
+ }
485
+
486
+ if (!('privateKey' in signer)) {
487
+ return;
488
+ }
489
+
490
+ return TweakedSigner.tweakSigner(signer as unknown as ECPairInterface, settings) as Signer;
491
+ }
492
+
493
+ /**
494
+ * Generate the PSBT input extended
495
+ * @param {UTXO} utxo The UTXO
496
+ * @param {number} i The index of the input
497
+ * @protected
498
+ * @returns {PsbtInputExtended} The PSBT input extended
499
+ */
500
+ protected generatePsbtInputExtended(utxo: UTXO, i: number): PsbtInputExtended {
501
+ const input: PsbtInputExtended = {
502
+ hash: utxo.transactionId,
503
+ index: utxo.outputIndex,
504
+ witnessUtxo: {
505
+ value: Number(utxo.value),
506
+ script: Buffer.from(utxo.scriptPubKey.hex, 'hex'),
507
+ },
508
+ sequence: this.sequence,
509
+ };
510
+
511
+ if (this.sighashTypes) {
512
+ const inputSign = TweakedTransaction.calculateSignHash(this.sighashTypes);
513
+ if (inputSign) input.sighashType = inputSign;
514
+ }
515
+
516
+ if (this.tapLeafScript) {
517
+ input.tapLeafScript = [this.tapLeafScript];
518
+ }
519
+
520
+ if (i === 0 && this.nonWitnessUtxo) {
521
+ input.nonWitnessUtxo = this.nonWitnessUtxo;
522
+ this.log(`Using non-witness utxo for input ${i}`);
523
+ }
524
+
525
+ // automatically detect p2tr inputs.
526
+ if (
527
+ utxo.scriptPubKey.address &&
528
+ AddressVerificator.isValidP2TRAddress(utxo.scriptPubKey.address, this.network)
529
+ ) {
530
+ this.tweakSigner();
531
+
532
+ input.tapInternalKey = this.internalPubKeyToXOnly();
533
+ }
534
+
535
+ return input;
536
+ }
537
+ }