@btc-vision/transaction 1.0.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 (270) hide show
  1. package/.babelrc +7 -0
  2. package/.gitattributes +2 -0
  3. package/.github/workflows/node.js.yml +22 -0
  4. package/.idea/codeStyles/Project.xml +56 -0
  5. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  6. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  7. package/.idea/jsLibraryMappings.xml +6 -0
  8. package/.idea/modules.xml +8 -0
  9. package/.idea/prettier.xml +6 -0
  10. package/.idea/transaction.iml +16 -0
  11. package/.idea/vcs.xml +6 -0
  12. package/.prettierrc.json +12 -0
  13. package/CONTRIBUTING.md +71 -0
  14. package/LICENSE.md +16 -0
  15. package/README.md +213 -0
  16. package/browser/873e754d6c7c6e9361f1.module.wasm +0 -0
  17. package/browser/_version.d.ts +1 -0
  18. package/browser/bytecode/Compressor.d.ts +6 -0
  19. package/browser/crypto/crypto-browser.d.ts +40 -0
  20. package/browser/crypto/crypto.d.ts +2 -0
  21. package/browser/generators/Generator.d.ts +12 -0
  22. package/browser/generators/builders/CalldataGenerator.d.ts +8 -0
  23. package/browser/generators/builders/DeploymentGenerator.d.ts +7 -0
  24. package/browser/index.d.ts +3 -0
  25. package/browser/index.js +2 -0
  26. package/browser/index.js.LICENSE.txt +23 -0
  27. package/browser/keypair/EcKeyPair.d.ts +24 -0
  28. package/browser/keypair/Wallet.d.ts +16 -0
  29. package/browser/keypair/interfaces/IWallet.d.ts +5 -0
  30. package/browser/metadata/ContractBaseMetadata.d.ts +9 -0
  31. package/browser/metadata/ContractMetadataManager.d.ts +1 -0
  32. package/browser/metadata/contracts/wBTC.d.ts +12 -0
  33. package/browser/network/NetworkInformation.d.ts +6 -0
  34. package/browser/opnet.d.ts +22 -0
  35. package/browser/scripts/Regtest.d.ts +2 -0
  36. package/browser/scripts/test.d.ts +1 -0
  37. package/browser/signer/TweakedSigner.d.ts +9 -0
  38. package/browser/transaction/TransactionBuilder.d.ts +1 -0
  39. package/browser/transaction/TransactionFactory.d.ts +4 -0
  40. package/browser/transaction/builders/FundingTransaction.d.ts +11 -0
  41. package/browser/transaction/builders/InteractionTransaction.d.ts +47 -0
  42. package/browser/transaction/builders/TransactionBuilder.d.ts +64 -0
  43. package/browser/transaction/enums/TransactionType.d.ts +7 -0
  44. package/browser/transaction/interfaces/ITransactionParameters.d.ts +33 -0
  45. package/browser/transaction/interfaces/Tap.d.ts +22 -0
  46. package/browser/utils/BitcoinUtils.d.ts +5 -0
  47. package/browser/utxo/UTXOManager.d.ts +7 -0
  48. package/browser/utxo/interfaces/IUTXO.d.ts +19 -0
  49. package/build/Utils.d.ts +0 -0
  50. package/build/Utils.js +1 -0
  51. package/build/_version.d.ts +1 -0
  52. package/build/_version.js +1 -0
  53. package/build/bytecode/Compressor.d.ts +6 -0
  54. package/build/bytecode/Compressor.js +13 -0
  55. package/build/contracts/ContractMetadataManager.d.ts +0 -0
  56. package/build/contracts/ContractMetadataManager.js +1 -0
  57. package/build/crypto/crypto.d.ts +2 -0
  58. package/build/crypto/crypto.js +1 -0
  59. package/build/generators/Generator.d.ts +12 -0
  60. package/build/generators/Generator.js +25 -0
  61. package/build/generators/builders/CalldataGenerator.d.ts +8 -0
  62. package/build/generators/builders/CalldataGenerator.js +79 -0
  63. package/build/generators/builders/DeploymentGenerator.d.ts +7 -0
  64. package/build/generators/builders/DeploymentGenerator.js +38 -0
  65. package/build/index.d.ts +3 -0
  66. package/build/index.js +3 -0
  67. package/build/keypair/EcKeyPair.d.ts +24 -0
  68. package/build/keypair/EcKeyPair.js +107 -0
  69. package/build/keypair/Wallet.d.ts +16 -0
  70. package/build/keypair/Wallet.js +30 -0
  71. package/build/keypair/interfaces/GeneratedWallet.d.ts +5 -0
  72. package/build/keypair/interfaces/GeneratedWallet.js +1 -0
  73. package/build/keypair/interfaces/IWallet.d.ts +5 -0
  74. package/build/keypair/interfaces/IWallet.js +1 -0
  75. package/build/metadata/ContractBaseMetadata.d.ts +9 -0
  76. package/build/metadata/ContractBaseMetadata.js +13 -0
  77. package/build/metadata/ContractMetadataManager.d.ts +1 -0
  78. package/build/metadata/ContractMetadataManager.js +9 -0
  79. package/build/metadata/contracts/ContractBase.d.ts +9 -0
  80. package/build/metadata/contracts/ContractBase.js +13 -0
  81. package/build/metadata/contracts/ContractBaseMetadata.d.ts +9 -0
  82. package/build/metadata/contracts/ContractBaseMetadata.js +13 -0
  83. package/build/metadata/contracts/ContractMetadataManager.d.ts +0 -0
  84. package/build/metadata/contracts/ContractMetadataManager.js +1 -0
  85. package/build/metadata/contracts/wBTC.d.ts +12 -0
  86. package/build/metadata/contracts/wBTC.js +26 -0
  87. package/build/network/NetworkConverter.d.ts +0 -0
  88. package/build/network/NetworkConverter.js +14 -0
  89. package/build/network/NetworkInformation.d.ts +6 -0
  90. package/build/network/NetworkInformation.js +1 -0
  91. package/build/opnet.d.ts +22 -0
  92. package/build/opnet.js +22 -0
  93. package/build/scripts/Regtest.d.ts +2 -0
  94. package/build/scripts/Regtest.js +15 -0
  95. package/build/scripts/test.d.ts +1 -0
  96. package/build/scripts/test.js +74 -0
  97. package/build/signer/Regtest.d.ts +2 -0
  98. package/build/signer/Regtest.js +15 -0
  99. package/build/signer/TweakedSigner.d.ts +9 -0
  100. package/build/signer/TweakedSigner.js +22 -0
  101. package/build/transaction/TransactionBuilder.d.ts +60 -0
  102. package/build/transaction/TransactionBuilder.js +244 -0
  103. package/build/transaction/TransactionFactory.d.ts +4 -0
  104. package/build/transaction/TransactionFactory.js +32 -0
  105. package/build/transaction/builders/FundingTransaction.d.ts +11 -0
  106. package/build/transaction/builders/FundingTransaction.js +23 -0
  107. package/build/transaction/builders/GenericTransaction.d.ts +11 -0
  108. package/build/transaction/builders/GenericTransaction.js +23 -0
  109. package/build/transaction/builders/InteractionTransaction.d.ts +47 -0
  110. package/build/transaction/builders/InteractionTransaction.js +219 -0
  111. package/build/transaction/builders/TransactionBuilder.d.ts +64 -0
  112. package/build/transaction/builders/TransactionBuilder.js +288 -0
  113. package/build/transaction/enums/TransactionType.d.ts +7 -0
  114. package/build/transaction/enums/TransactionType.js +8 -0
  115. package/build/transaction/interfaces/ITransactionParameters.d.ts +33 -0
  116. package/build/transaction/interfaces/ITransactionParameters.js +1 -0
  117. package/build/transaction/interfaces/ITransactions.d.ts +32 -0
  118. package/build/transaction/interfaces/ITransactions.js +1 -0
  119. package/build/transaction/interfaces/Tap.d.ts +22 -0
  120. package/build/transaction/interfaces/Tap.js +1 -0
  121. package/build/utils/BitcoinUtils.d.ts +5 -0
  122. package/build/utils/BitcoinUtils.js +9 -0
  123. package/build/utxo/IUTXO.d.ts +0 -0
  124. package/build/utxo/IUTXO.js +1 -0
  125. package/build/utxo/UTXOManager.d.ts +7 -0
  126. package/build/utxo/UTXOManager.js +47 -0
  127. package/build/utxo/interfaces/IUTXO.d.ts +19 -0
  128. package/build/utxo/interfaces/IUTXO.js +1 -0
  129. package/cjs/_version.d.ts +1 -0
  130. package/cjs/_version.js +4 -0
  131. package/cjs/bytecode/Compressor.d.ts +6 -0
  132. package/cjs/bytecode/Compressor.js +20 -0
  133. package/cjs/crypto/crypto.d.ts +2 -0
  134. package/cjs/crypto/crypto.js +8 -0
  135. package/cjs/generators/Generator.d.ts +13 -0
  136. package/cjs/generators/Generator.js +31 -0
  137. package/cjs/generators/builders/CalldataGenerator.d.ts +8 -0
  138. package/cjs/generators/builders/CalldataGenerator.js +83 -0
  139. package/cjs/generators/builders/DeploymentGenerator.d.ts +7 -0
  140. package/cjs/generators/builders/DeploymentGenerator.js +42 -0
  141. package/cjs/index.d.ts +3 -0
  142. package/cjs/index.js +32 -0
  143. package/cjs/keypair/EcKeyPair.d.ts +24 -0
  144. package/cjs/keypair/EcKeyPair.js +137 -0
  145. package/cjs/keypair/Wallet.d.ts +16 -0
  146. package/cjs/keypair/Wallet.js +34 -0
  147. package/cjs/keypair/interfaces/IWallet.d.ts +5 -0
  148. package/cjs/keypair/interfaces/IWallet.js +2 -0
  149. package/cjs/metadata/ContractBaseMetadata.d.ts +9 -0
  150. package/cjs/metadata/ContractBaseMetadata.js +17 -0
  151. package/cjs/metadata/ContractMetadataManager.d.ts +0 -0
  152. package/cjs/metadata/ContractMetadataManager.js +1 -0
  153. package/cjs/metadata/contracts/wBTC.d.ts +12 -0
  154. package/cjs/metadata/contracts/wBTC.js +30 -0
  155. package/cjs/network/NetworkInformation.d.ts +6 -0
  156. package/cjs/network/NetworkInformation.js +2 -0
  157. package/cjs/opnet.d.ts +1 -0
  158. package/cjs/opnet.js +5 -0
  159. package/cjs/scripts/Regtest.d.ts +2 -0
  160. package/cjs/scripts/Regtest.js +18 -0
  161. package/cjs/scripts/test.d.ts +1 -0
  162. package/cjs/scripts/test.js +44 -0
  163. package/cjs/signer/TweakedSigner.d.ts +9 -0
  164. package/cjs/signer/TweakedSigner.js +49 -0
  165. package/cjs/transaction/TransactionBuilder.d.ts +0 -0
  166. package/cjs/transaction/TransactionBuilder.js +1 -0
  167. package/cjs/transaction/TransactionFactory.d.ts +4 -0
  168. package/cjs/transaction/TransactionFactory.js +33 -0
  169. package/cjs/transaction/builders/FundingTransaction.d.ts +11 -0
  170. package/cjs/transaction/builders/FundingTransaction.js +27 -0
  171. package/cjs/transaction/builders/InteractionTransaction.d.ts +45 -0
  172. package/cjs/transaction/builders/InteractionTransaction.js +214 -0
  173. package/cjs/transaction/builders/TransactionBuilder.d.ts +64 -0
  174. package/cjs/transaction/builders/TransactionBuilder.js +304 -0
  175. package/cjs/transaction/enums/TransactionType.d.ts +7 -0
  176. package/cjs/transaction/enums/TransactionType.js +11 -0
  177. package/cjs/transaction/interfaces/ITransactionParameters.d.ts +32 -0
  178. package/cjs/transaction/interfaces/ITransactionParameters.js +2 -0
  179. package/cjs/transaction/interfaces/Tap.d.ts +22 -0
  180. package/cjs/transaction/interfaces/Tap.js +2 -0
  181. package/cjs/utils/BitcoinUtils.d.ts +5 -0
  182. package/cjs/utils/BitcoinUtils.js +13 -0
  183. package/cjs/utxo/UTXOManager.d.ts +7 -0
  184. package/cjs/utxo/UTXOManager.js +51 -0
  185. package/cjs/utxo/interfaces/IUTXO.d.ts +19 -0
  186. package/cjs/utxo/interfaces/IUTXO.js +2 -0
  187. package/docs/.nojekyll +1 -0
  188. package/docs/assets/highlight.css +92 -0
  189. package/docs/assets/icons.js +15 -0
  190. package/docs/assets/icons.svg +1 -0
  191. package/docs/assets/main.js +59 -0
  192. package/docs/assets/material-style.css +247 -0
  193. package/docs/assets/navigation.js +1 -0
  194. package/docs/assets/search.js +1 -0
  195. package/docs/assets/style.css +1412 -0
  196. package/docs/classes/BitcoinUtils.html +183 -0
  197. package/docs/classes/CalldataGenerator.html +211 -0
  198. package/docs/classes/Compressor.html +185 -0
  199. package/docs/classes/ContractBaseMetadata.html +182 -0
  200. package/docs/classes/DeploymentGenerator.html +200 -0
  201. package/docs/classes/EcKeyPair.html +280 -0
  202. package/docs/classes/FundingTransaction.html +293 -0
  203. package/docs/classes/Generator.html +199 -0
  204. package/docs/classes/InteractionTransaction.html +365 -0
  205. package/docs/classes/TransactionBuilder.html +303 -0
  206. package/docs/classes/TransactionFactory.html +180 -0
  207. package/docs/classes/TweakedSigner.html +181 -0
  208. package/docs/classes/UTXOManager.html +187 -0
  209. package/docs/classes/Wallet.html +191 -0
  210. package/docs/classes/wBTC.html +189 -0
  211. package/docs/enums/TransactionType.html +179 -0
  212. package/docs/hierarchy.html +174 -0
  213. package/docs/index.html +237 -0
  214. package/docs/interfaces/FetchUTXOParams.html +178 -0
  215. package/docs/interfaces/IFundingTransactionParameters.html +182 -0
  216. package/docs/interfaces/IInteractionParameters.html +185 -0
  217. package/docs/interfaces/ITransactionDataContractDeployment.html +184 -0
  218. package/docs/interfaces/ITransactionDataContractInteractionWrap.html +186 -0
  219. package/docs/interfaces/ITransactionParameters.html +181 -0
  220. package/docs/interfaces/IWallet.html +181 -0
  221. package/docs/interfaces/NetworkInformation.html +176 -0
  222. package/docs/interfaces/PsbtInputExtended.html +194 -0
  223. package/docs/interfaces/PsbtOutputExtendedAddress.html +183 -0
  224. package/docs/interfaces/PsbtOutputExtendedScript.html +183 -0
  225. package/docs/interfaces/RawUTXOResponse.html +178 -0
  226. package/docs/interfaces/TapLeafScript.html +177 -0
  227. package/docs/interfaces/TweakSettings.html +179 -0
  228. package/docs/interfaces/UTXO.html +178 -0
  229. package/docs/interfaces/UpdateInput.html +175 -0
  230. package/docs/modules.html +208 -0
  231. package/docs/types/PsbtOutputExtended.html +174 -0
  232. package/docs/variables/version.html +174 -0
  233. package/gulpfile.js +152 -0
  234. package/jest.config.ts +52 -0
  235. package/package.json +116 -0
  236. package/src/_version.ts +1 -0
  237. package/src/bytecode/Compressor.ts +27 -0
  238. package/src/crypto/crypto-browser.js +71 -0
  239. package/src/crypto/crypto.ts +1 -0
  240. package/src/generators/Generator.ts +75 -0
  241. package/src/generators/builders/CalldataGenerator.ts +143 -0
  242. package/src/generators/builders/DeploymentGenerator.ts +63 -0
  243. package/src/index.ts +4 -0
  244. package/src/keypair/EcKeyPair.ts +265 -0
  245. package/src/keypair/Wallet.ts +75 -0
  246. package/src/keypair/interfaces/IWallet.ts +19 -0
  247. package/src/metadata/ContractBaseMetadata.ts +23 -0
  248. package/src/metadata/contracts/wBTC.ts +44 -0
  249. package/src/network/NetworkInformation.ts +7 -0
  250. package/src/opnet.ts +42 -0
  251. package/src/scripts/Regtest.ts +19 -0
  252. package/src/scripts/test.ts +98 -0
  253. package/src/signer/TweakedSigner.ts +57 -0
  254. package/src/transaction/TransactionFactory.ts +57 -0
  255. package/src/transaction/builders/FundingTransaction.ts +36 -0
  256. package/src/transaction/builders/InteractionTransaction.ts +439 -0
  257. package/src/transaction/builders/TransactionBuilder.ts +603 -0
  258. package/src/transaction/enums/TransactionType.ts +7 -0
  259. package/src/transaction/interfaces/ITransactionParameters.ts +41 -0
  260. package/src/transaction/interfaces/Tap.ts +26 -0
  261. package/src/utils/BitcoinUtils.ts +24 -0
  262. package/src/utxo/UTXOManager.ts +67 -0
  263. package/src/utxo/interfaces/IUTXO.ts +22 -0
  264. package/tests/TransactionBuilder.test.ts +58 -0
  265. package/tests/contracts/wbtc.wasm +0 -0
  266. package/tsconfig.base.json +43 -0
  267. package/tsconfig.cjs.json +9 -0
  268. package/tsconfig.json +8 -0
  269. package/tsconfig.webpack.json +11 -0
  270. package/webpack.config.js +77 -0
@@ -0,0 +1,603 @@
1
+ import { initEccLib, Network, opcodes, Payment, payments, Psbt, script, Signer, Transaction } from 'bitcoinjs-lib';
2
+ import { varuint } from 'bitcoinjs-lib/src/bufferutils.js';
3
+ import { toXOnly } from 'bitcoinjs-lib/src/psbt/bip371.js';
4
+ import * as ecc from 'tiny-secp256k1';
5
+ import { PsbtInputExtended, PsbtOutputExtended, UpdateInput } from '../interfaces/Tap.js';
6
+ import { TransactionType } from '../enums/TransactionType.js';
7
+ import { IFundingTransactionParameters, ITransactionParameters } from '../interfaces/ITransactionParameters.js';
8
+ import { EcKeyPair } from '../../keypair/EcKeyPair.js';
9
+ import { Address } from '@btc-vision/bsi-binary';
10
+ import { UTXO } from '../../utxo/interfaces/IUTXO.js';
11
+ import { ECPairInterface } from 'ecpair';
12
+
13
+ /**
14
+ * Allows to build a transaction like you would on Ethereum.
15
+ * @description The transaction builder class
16
+ * @abstract
17
+ * @class TransactionBuilder
18
+ */
19
+ export abstract class TransactionBuilder<T extends TransactionType> {
20
+ protected static readonly LOCK_LEAF_SCRIPT: Buffer = script.compile([opcodes.OP_0]);
21
+ protected static readonly MINIMUM_DUST: bigint = 330n;
22
+
23
+ public abstract readonly type: T;
24
+ public readonly logColor: string = '#785def';
25
+
26
+ /**
27
+ * @description Cost in satoshis of the transaction fee
28
+ */
29
+ public transactionFee: bigint = 0n;
30
+ /**
31
+ * @description The transaction itself.
32
+ */
33
+ protected readonly transaction: Psbt;
34
+ /**
35
+ * @description The inputs of the transaction
36
+ */
37
+ protected readonly inputs: PsbtInputExtended[] = [];
38
+ /**
39
+ * @description Inputs to update later on.
40
+ */
41
+ protected readonly updateInputs: UpdateInput[] = [];
42
+ /**
43
+ * @description The outputs of the transaction
44
+ */
45
+ protected readonly outputs: PsbtOutputExtended[] = [];
46
+ /**
47
+ * @description Output that will be used to pay the fees
48
+ */
49
+ protected feeOutput: PsbtOutputExtended | null = null;
50
+ /**
51
+ * @description Was the transaction signed?
52
+ */
53
+ protected signed: boolean = false;
54
+ /**
55
+ * @description The tap data of the transaction
56
+ */
57
+ protected tapData: Payment | null = null;
58
+ /**
59
+ * @description The script data of the transaction
60
+ */
61
+ protected scriptData: Payment | null = null;
62
+ /**
63
+ * @description The total amount of satoshis in the inputs
64
+ */
65
+ protected totalInputAmount: bigint;
66
+ /**
67
+ * @description The signer of the transaction
68
+ */
69
+ protected readonly signer: Signer;
70
+ /**
71
+ * @description The network where the transaction will be broadcasted
72
+ */
73
+ protected readonly network: Network;
74
+ /**
75
+ * @description The fee rate of the transaction
76
+ */
77
+ protected readonly feeRate: number;
78
+ /**
79
+ * @description The opnet priority fee of the transaction
80
+ */
81
+ protected readonly priorityFee: bigint;
82
+ /**
83
+ * @description The utxos used in the transaction
84
+ */
85
+ protected utxos: UTXO[];
86
+
87
+ /**
88
+ * @description The address where the transaction is sent to
89
+ * @protected
90
+ */
91
+ protected to: Address;
92
+
93
+ /**
94
+ * @description The address where the transaction is sent from
95
+ * @protected
96
+ */
97
+ protected from: Address;
98
+
99
+ /**
100
+ * @description The maximum fee rate of the transaction
101
+ */
102
+ private _maximumFeeRate: number = 100000000;
103
+
104
+ /**
105
+ * @param {ITransactionParameters} parameters - The transaction parameters
106
+ */
107
+ protected constructor(parameters: ITransactionParameters) {
108
+ this.signer = parameters.signer;
109
+ this.network = parameters.network;
110
+ this.feeRate = parameters.feeRate;
111
+ this.priorityFee = parameters.priorityFee;
112
+ this.utxos = parameters.utxos;
113
+ this.to = parameters.to;
114
+ this.from =
115
+ parameters.from ||
116
+ EcKeyPair.getTaprootAddress(this.signer as ECPairInterface, this.network);
117
+
118
+ this.totalInputAmount = this.calculateTotalUTXOAmount();
119
+ const totalVOut: bigint = this.calculateTotalVOutAmount();
120
+
121
+ if (totalVOut < this.totalInputAmount) {
122
+ throw new Error(`Vout value is less than the value to send`);
123
+ }
124
+
125
+ if (this.totalInputAmount < TransactionBuilder.MINIMUM_DUST) {
126
+ throw new Error(`Value is less than the minimum dust`);
127
+ }
128
+
129
+ this.transaction = new Psbt({
130
+ network: this.network,
131
+ });
132
+ }
133
+
134
+ public getFundingTransactionParameters(): IFundingTransactionParameters {
135
+ return {
136
+ utxos: this.utxos,
137
+ to: this.getScriptAddress(),
138
+ signer: this.signer,
139
+ network: this.network,
140
+ feeRate: this.feeRate,
141
+ priorityFee: this.priorityFee,
142
+ from: this.from,
143
+ childTransactionRequiredFees: this.transactionFee,
144
+ };
145
+ }
146
+
147
+ /**
148
+ * Set the destination address of the transaction
149
+ * @param {Address} address - The address to set
150
+ */
151
+ public setDestinationAddress(address: Address): void {
152
+ this.to = address; // this.getScriptAddress()
153
+ }
154
+
155
+ /**
156
+ * Set the maximum fee rate of the transaction in satoshis per byte
157
+ * @param {number} feeRate - The fee rate to set
158
+ * @public
159
+ */
160
+ public setMaximumFeeRate(feeRate: number): void {
161
+ this._maximumFeeRate = feeRate;
162
+ }
163
+
164
+ /**
165
+ * @description Signs the transaction
166
+ * @public
167
+ * @returns {Transaction} - The signed transaction in hex format
168
+ * @throws {Error} - If something went wrong
169
+ */
170
+ public signTransaction(): Transaction {
171
+ if (!this.to) throw new Error('Transaction must have a recipient');
172
+
173
+ if (!EcKeyPair.verifyContractAddress(this.to, this.network)) {
174
+ throw new Error(
175
+ 'Invalid contract address. The contract address must be a taproot address.',
176
+ );
177
+ }
178
+
179
+ if (this.signed) throw new Error('Transaction is already signed');
180
+ this.signed = true;
181
+
182
+ this.buildTransaction();
183
+
184
+ const builtTx = this.internalBuildTransaction(this.transaction);
185
+ if (builtTx) {
186
+ return this.transaction.extractTransaction(false);
187
+ }
188
+
189
+ throw new Error('Could not sign transaction');
190
+ }
191
+
192
+ /**
193
+ * @description Returns the transaction
194
+ * @returns {Transaction}
195
+ */
196
+ public getTransaction(): Transaction {
197
+ return this.transaction.extractTransaction(false);
198
+ }
199
+
200
+ /**
201
+ * @description Returns the script address
202
+ * @returns {string}
203
+ */
204
+ public getScriptAddress(): string {
205
+ if (!this.scriptData || !this.scriptData.address) {
206
+ throw new Error('Tap data is required');
207
+ }
208
+
209
+ return this.scriptData.address;
210
+ }
211
+
212
+ /**
213
+ * @description Disables replace by fee on the transaction
214
+ */
215
+ public disableRBF(): void {
216
+ if (this.signed) throw new Error('Transaction is already signed');
217
+
218
+ for (let input of this.inputs) {
219
+ input.sequence = 0xffffffff;
220
+ }
221
+ }
222
+
223
+ /**
224
+ * @description Returns the tap address
225
+ * @returns {string}
226
+ * @throws {Error} - If tap data is not set
227
+ */
228
+ public getTapAddress(): string {
229
+ if (!this.tapData || !this.tapData.address) {
230
+ throw new Error('Tap data is required');
231
+ }
232
+
233
+ return this.tapData.address;
234
+ }
235
+
236
+ /**
237
+ * Add an input to the transaction.
238
+ * @param {PsbtInputExtended} input - The input to add
239
+ * @public
240
+ * @returns {void}
241
+ */
242
+ public addInput(input: PsbtInputExtended): void {
243
+ this.inputs.push(input);
244
+ }
245
+
246
+ /**
247
+ * Add an output to the transaction.
248
+ * @param {PsbtOutputExtended} output - The output to add
249
+ * @public
250
+ * @returns {void}
251
+ */
252
+ public addOutput(output: PsbtOutputExtended): void {
253
+ if (output.value < TransactionBuilder.MINIMUM_DUST) {
254
+ throw new Error(
255
+ `Output value is less than the minimum dust ${output.value} < ${TransactionBuilder.MINIMUM_DUST}`,
256
+ );
257
+ }
258
+
259
+ this.outputs.push(output);
260
+ }
261
+
262
+ /**
263
+ * @description Adds the refund output to the transaction
264
+ * @param {bigint} amountSpent - The amount spent
265
+ * @protected
266
+ * @returns {void}
267
+ */
268
+ protected addRefundOutput(amountSpent: bigint): void {
269
+ /** Add the refund output */
270
+ const sendBackAmount: bigint = this.totalInputAmount - amountSpent;
271
+ if (sendBackAmount >= TransactionBuilder.MINIMUM_DUST) {
272
+ this.setFeeOutput({
273
+ value: Number(sendBackAmount),
274
+ address: this.from,
275
+ });
276
+
277
+ return;
278
+ }
279
+
280
+ console.warn(
281
+ `Amount to send back is less than the minimum dust, will be consumed in fees instead.`,
282
+ );
283
+ }
284
+
285
+ /**
286
+ * @description Returns the transaction opnet fee
287
+ * @protected
288
+ * @returns {bigint}
289
+ */
290
+ protected getTransactionOPNetFee(): bigint {
291
+ if (this.priorityFee > TransactionBuilder.MINIMUM_DUST) {
292
+ return this.priorityFee;
293
+ }
294
+
295
+ return TransactionBuilder.MINIMUM_DUST;
296
+ }
297
+
298
+ /**
299
+ * @description Returns the total amount of satoshis in the inputs
300
+ * @protected
301
+ * @returns {bigint}
302
+ */
303
+ protected calculateTotalUTXOAmount(): bigint {
304
+ let total: bigint = 0n;
305
+ for (let utxo of this.utxos) {
306
+ total += utxo.value;
307
+ }
308
+
309
+ return total;
310
+ }
311
+
312
+ /**
313
+ * @description Returns the total amount of satoshis in the outputs
314
+ * @protected
315
+ * @returns {bigint}
316
+ */
317
+ protected calculateTotalVOutAmount(): bigint {
318
+ let total: bigint = 0n;
319
+ for (let utxo of this.utxos) {
320
+ total += utxo.value;
321
+ }
322
+
323
+ return total;
324
+ }
325
+
326
+ /**
327
+ * @description Adds the inputs from the utxos
328
+ * @protected
329
+ * @returns {void}
330
+ */
331
+ protected addInputsFromUTXO(): void {
332
+ for (let utxo of this.utxos) {
333
+ const input: PsbtInputExtended = {
334
+ hash: utxo.transactionId,
335
+ index: utxo.outputIndex,
336
+ witnessUtxo: {
337
+ value: Number(utxo.value),
338
+ script: Buffer.from(utxo.scriptPubKey.hex, 'hex'),
339
+ },
340
+ sequence: 0xfffffffd,
341
+ };
342
+
343
+ this.addInput(input);
344
+ }
345
+ }
346
+
347
+ /**
348
+ * @description Converts the witness stack to a script witness
349
+ * @param {Buffer[]} witness - The witness stack
350
+ * @protected
351
+ * @returns {Buffer}
352
+ */
353
+ protected witnessStackToScriptWitness(witness: Buffer[]): Buffer {
354
+ let buffer = Buffer.allocUnsafe(0);
355
+
356
+ function writeSlice(slice: Buffer) {
357
+ buffer = Buffer.concat([buffer, Buffer.from(slice)]);
358
+ }
359
+
360
+ function writeVarInt(i: number) {
361
+ const currentLen = buffer.length;
362
+ const varintLen = varuint.encodingLength(i);
363
+
364
+ buffer = Buffer.concat([buffer, Buffer.allocUnsafe(varintLen)]);
365
+ varuint.encode(i, buffer, currentLen);
366
+ }
367
+
368
+ function writeVarSlice(slice: Buffer) {
369
+ writeVarInt(slice.length);
370
+ writeSlice(slice);
371
+ }
372
+
373
+ function writeVector(vector: Buffer[]) {
374
+ writeVarInt(vector.length);
375
+ vector.forEach(writeVarSlice);
376
+ }
377
+
378
+ writeVector(witness);
379
+
380
+ return buffer;
381
+ }
382
+
383
+ /**
384
+ * Internal init.
385
+ * @protected
386
+ */
387
+ protected internalInit(): void {
388
+ this.verifyUTXOValidity();
389
+
390
+ this.scriptData = payments.p2tr(this.generateScriptAddress());
391
+ this.tapData = payments.p2tr(this.generateTapData());
392
+ }
393
+
394
+ /**
395
+ * Builds the transaction.
396
+ * @protected
397
+ * @returns {void}
398
+ */
399
+ protected abstract buildTransaction(): void;
400
+
401
+ /**
402
+ * Generates the script address.
403
+ * @protected
404
+ * @returns {Payment}
405
+ */
406
+ protected generateScriptAddress(): Payment {
407
+ return {
408
+ internalPubkey: this.internalPubKeyToXOnly(),
409
+ network: this.network,
410
+ };
411
+ }
412
+
413
+ protected generateTapData(): Payment {
414
+ return {
415
+ internalPubkey: this.internalPubKeyToXOnly(),
416
+ network: this.network,
417
+ };
418
+ }
419
+
420
+ /**
421
+ * Add an input update
422
+ * @param {UpdateInput} input - The input to update
423
+ * @protected
424
+ * @returns {void}
425
+ */
426
+ protected updateInput(input: UpdateInput): void {
427
+ this.updateInputs.push(input);
428
+ }
429
+
430
+ /**
431
+ * Returns the witness of the tap transaction.
432
+ * @protected
433
+ * @returns {Buffer}
434
+ */
435
+ protected getWitness(): Buffer {
436
+ if (!this.tapData || !this.tapData.witness) {
437
+ throw new Error('Witness is required');
438
+ }
439
+
440
+ if (this.tapData.witness.length === 0) {
441
+ throw new Error('Witness is empty');
442
+ }
443
+
444
+ return this.tapData.witness[this.tapData.witness.length - 1];
445
+ }
446
+
447
+ /**
448
+ * Returns the tap output.
449
+ * @protected
450
+ * @returns {Buffer}
451
+ */
452
+ protected getTapOutput(): Buffer {
453
+ if (!this.tapData || !this.tapData.output) {
454
+ throw new Error('Tap data is required');
455
+ }
456
+
457
+ return this.tapData.output;
458
+ }
459
+
460
+ /**
461
+ * Returns the inputs of the transaction.
462
+ * @protected
463
+ * @returns {PsbtInputExtended[]}
464
+ */
465
+ protected getInputs(): PsbtInputExtended[] {
466
+ return this.inputs;
467
+ }
468
+
469
+ /**
470
+ * Returns the outputs of the transaction.
471
+ * @protected
472
+ * @returns {PsbtOutputExtended[]}
473
+ */
474
+ protected getOutputs(): PsbtOutputExtended[] {
475
+ const outputs: PsbtOutputExtended[] = [...this.outputs];
476
+ if (this.feeOutput) outputs.push(this.feeOutput);
477
+
478
+ return outputs;
479
+ }
480
+
481
+ /**
482
+ * Verifies that the utxos are valid.
483
+ * @protected
484
+ */
485
+ protected verifyUTXOValidity(): void {
486
+ for (let utxo of this.utxos) {
487
+ if (!utxo.scriptPubKey) {
488
+ throw new Error('Address is required');
489
+ }
490
+ }
491
+ }
492
+
493
+ /**
494
+ * Set transaction fee output.
495
+ * @param {PsbtOutputExtended} output - The output to set the fees
496
+ * @protected
497
+ * @returns {void}
498
+ */
499
+ protected setFeeOutput(output: PsbtOutputExtended): void {
500
+ const initialValue = output.value;
501
+
502
+ this.feeOutput = output;
503
+
504
+ const fee = this.estimateTransactionFees();
505
+ if (fee > BigInt(initialValue)) {
506
+ throw new Error('Insufficient funds');
507
+ }
508
+
509
+ this.feeOutput.value = initialValue - Number(fee);
510
+
511
+ if (this.feeOutput.value < TransactionBuilder.MINIMUM_DUST) {
512
+ this.feeOutput = null;
513
+ }
514
+ }
515
+
516
+ /**
517
+ * Returns the signer key.
518
+ * @protected
519
+ * @returns {Signer}
520
+ */
521
+ protected abstract getSignerKey(): Signer;
522
+
523
+ /**
524
+ * Converts the public key to x-only.
525
+ * @protected
526
+ * @returns {Buffer}
527
+ */
528
+ protected internalPubKeyToXOnly(): Buffer {
529
+ return toXOnly(this.signer.publicKey);
530
+ }
531
+
532
+ /**
533
+ * Signs all the inputs of the transaction.
534
+ * @param {Psbt} transaction - The transaction to sign
535
+ * @protected
536
+ * @returns {void}
537
+ */
538
+ protected signInputs(transaction: Psbt): void {
539
+ transaction.signAllInputs(this.getSignerKey());
540
+ transaction.finalizeAllInputs();
541
+ }
542
+
543
+ /**
544
+ * Builds the transaction.
545
+ * @param {Psbt} transaction - The transaction to build
546
+ * @protected
547
+ * @returns {boolean}
548
+ * @throws {Error} - If something went wrong while building the transaction
549
+ */
550
+ private internalBuildTransaction(transaction: Psbt): boolean {
551
+ const inputs: PsbtInputExtended[] = this.getInputs();
552
+ const outputs: PsbtOutputExtended[] = this.getOutputs();
553
+
554
+ transaction.setMaximumFeeRate(this._maximumFeeRate);
555
+ transaction.addInputs(inputs);
556
+
557
+ for (let i = 0; i < this.updateInputs.length; i++) {
558
+ transaction.updateInput(i, this.updateInputs[i]);
559
+ }
560
+
561
+ transaction.addOutputs(outputs);
562
+
563
+ try {
564
+ this.signInputs(transaction);
565
+ this.transactionFee = BigInt(transaction.getFee());
566
+
567
+ return true;
568
+ } catch (e) {
569
+ const err: Error = e as Error;
570
+
571
+ console.error(
572
+ `[internalBuildTransaction] Something went wrong while getting building the transaction: ${err.stack}`,
573
+ );
574
+ }
575
+
576
+ return false;
577
+ }
578
+
579
+ /**
580
+ * Estimates the transaction fees.
581
+ * @private
582
+ */
583
+ private estimateTransactionFees(): bigint {
584
+ const fakeTx = new Psbt({
585
+ network: this.network,
586
+ });
587
+
588
+ const builtTx = this.internalBuildTransaction(fakeTx);
589
+ if (builtTx) {
590
+ const tx = fakeTx.extractTransaction(false);
591
+ const size = tx.virtualSize();
592
+ const fee: number = this.feeRate * size + 1;
593
+
594
+ return BigInt(Math.ceil(fee));
595
+ } else {
596
+ throw new Error(
597
+ `Could not build transaction to estimate fee. Something went wrong while building the transaction.`,
598
+ );
599
+ }
600
+ }
601
+ }
602
+
603
+ initEccLib(ecc);
@@ -0,0 +1,7 @@
1
+ export enum TransactionType {
2
+ GENERIC = 0,
3
+ FUNDING = 1,
4
+ DEPLOYMENT = 2,
5
+ INTERACTION = 3,
6
+ WBTC_WRAP = 4,
7
+ }
@@ -0,0 +1,41 @@
1
+ import { Signer } from 'bitcoinjs-lib';
2
+ import { UTXO } from '../../utxo/interfaces/IUTXO.js';
3
+ import { Network } from 'bitcoinjs-lib/src/networks.js';
4
+ import { Address } from '@btc-vision/bsi-binary';
5
+
6
+ export interface ITransactionParameters {
7
+ readonly from?: Address;
8
+ readonly to: Address;
9
+ utxos: UTXO[];
10
+
11
+ readonly signer: Signer;
12
+ readonly network: Network;
13
+ readonly feeRate: number;
14
+ readonly priorityFee: bigint;
15
+ }
16
+
17
+ export interface IFundingTransactionParameters extends ITransactionParameters {
18
+ readonly childTransactionRequiredFees: bigint;
19
+ }
20
+
21
+ export interface IInteractionParameters extends ITransactionParameters {
22
+ readonly calldata: Buffer;
23
+
24
+ readonly pubKeys?: Buffer[];
25
+ readonly minimumSignatures?: number;
26
+
27
+ readonly randomBytes?: Buffer;
28
+ }
29
+
30
+ export interface ITransactionDataContractInteractionWrap extends IInteractionParameters {
31
+ readonly amount: bigint;
32
+ readonly minimumSignatures: number;
33
+ readonly pubKeys: Buffer[];
34
+ }
35
+
36
+ export interface ITransactionDataContractDeployment extends ITransactionParameters {
37
+ readonly bytecode: Buffer;
38
+ readonly salt: Buffer; // sha256
39
+
40
+ readonly customSigner: Signer;
41
+ }
@@ -0,0 +1,26 @@
1
+ import { PsbtInput, PsbtOutput } from 'bip174/src/lib/interfaces.js';
2
+ import { TransactionInput } from 'bitcoinjs-lib/src/psbt.js';
3
+
4
+ export interface TapLeafScript {
5
+ readonly leafVersion: number;
6
+ readonly controlBlock: Buffer;
7
+ readonly script: Buffer;
8
+ }
9
+
10
+ export interface UpdateInput {
11
+ tapLeafScript: TapLeafScript[];
12
+ }
13
+
14
+ export interface PsbtInputExtended extends PsbtInput, TransactionInput {}
15
+
16
+ export interface PsbtOutputExtendedAddress extends PsbtOutput {
17
+ address: string;
18
+ value: number;
19
+ }
20
+
21
+ export interface PsbtOutputExtendedScript extends PsbtOutput {
22
+ script: Buffer;
23
+ value: number;
24
+ }
25
+
26
+ export type PsbtOutputExtended = PsbtOutputExtendedAddress | PsbtOutputExtendedScript;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Utility class for Bitcoin related functions
3
+ */
4
+ export class BitcoinUtils {
5
+ /**
6
+ * Converts satoshi to BTC
7
+ * @param {number} btc - The amount in BTC
8
+ * @returns {BigInt} The amount in satoshi
9
+ */
10
+ public static btcToSatoshi(btc: number): BigInt {
11
+ return BigInt(btc * 100000000);
12
+ }
13
+
14
+ /**
15
+ * Generates random bytes.
16
+ * @public
17
+ * @returns {Buffer} The random bytes
18
+ */
19
+ public static rndBytes(): Buffer {
20
+ const buf = crypto.getRandomValues(new Uint8Array(64));
21
+
22
+ return Buffer.from(buf);
23
+ }
24
+ }