@btc-vision/transaction 1.0.21 → 1.0.23

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 (140) hide show
  1. package/browser/_version.d.ts +1 -1
  2. package/browser/index.js +1 -1
  3. package/browser/keypair/Wallet.d.ts +1 -0
  4. package/browser/opnet.d.ts +4 -0
  5. package/browser/transaction/TransactionFactory.d.ts +7 -1
  6. package/browser/transaction/builders/DeploymentTransaction.d.ts +2 -2
  7. package/browser/transaction/builders/SharedInteractionTransaction.d.ts +0 -3
  8. package/browser/transaction/builders/TransactionBuilder.d.ts +5 -30
  9. package/browser/transaction/builders/UnwarpTransaction.d.ts +19 -0
  10. package/browser/transaction/enums/TransactionType.d.ts +2 -1
  11. package/browser/transaction/interfaces/ITransactionParameters.d.ts +7 -5
  12. package/browser/transaction/processor/PsbtTransaction.d.ts +43 -0
  13. package/browser/transaction/psbt/PSBTTypes.d.ts +3 -0
  14. package/browser/transaction/shared/TweakedTransaction.d.ts +48 -0
  15. package/browser/utxo/OPNetLimitedProvider.d.ts +3 -0
  16. package/browser/utxo/interfaces/BroadcastResponse.d.ts +7 -0
  17. package/build/_version.d.ts +1 -1
  18. package/build/_version.js +1 -1
  19. package/build/keypair/Wallet.d.ts +1 -0
  20. package/build/keypair/Wallet.js +3 -0
  21. package/build/metadata/contracts/wBTC.js +1 -1
  22. package/build/opnet.d.ts +4 -0
  23. package/build/opnet.js +4 -0
  24. package/build/tests/adaptPSBT.d.ts +1 -0
  25. package/build/tests/adaptPSBT.js +59 -0
  26. package/build/tests/massWrapReg.d.ts +1 -0
  27. package/build/tests/massWrapReg.js +86 -0
  28. package/build/tests/unwrapReg.d.ts +1 -0
  29. package/build/tests/unwrapReg.js +46 -0
  30. package/build/transaction/TransactionFactory.d.ts +7 -1
  31. package/build/transaction/TransactionFactory.js +49 -0
  32. package/build/transaction/builders/DeploymentTransaction.d.ts +2 -2
  33. package/build/transaction/builders/DeploymentTransaction.js +1 -18
  34. package/build/transaction/builders/SharedInteractionTransaction.d.ts +0 -3
  35. package/build/transaction/builders/SharedInteractionTransaction.js +0 -22
  36. package/build/transaction/builders/TransactionBuilder.d.ts +5 -30
  37. package/build/transaction/builders/TransactionBuilder.js +15 -123
  38. package/build/transaction/builders/UnwarpTransaction.d.ts +19 -0
  39. package/build/transaction/builders/UnwarpTransaction.js +43 -0
  40. package/build/transaction/enums/TransactionType.d.ts +2 -1
  41. package/build/transaction/enums/TransactionType.js +1 -0
  42. package/build/transaction/interfaces/ITransactionParameters.d.ts +7 -5
  43. package/build/transaction/processor/PsbtTransaction.d.ts +43 -0
  44. package/build/transaction/processor/PsbtTransaction.js +131 -0
  45. package/build/transaction/psbt/PSBTTypes.d.ts +3 -0
  46. package/build/transaction/psbt/PSBTTypes.js +4 -0
  47. package/build/transaction/shared/TweakedTransaction.d.ts +48 -0
  48. package/build/transaction/shared/TweakedTransaction.js +150 -0
  49. package/build/utxo/OPNetLimitedProvider.d.ts +3 -0
  50. package/build/utxo/OPNetLimitedProvider.js +21 -5
  51. package/build/utxo/interfaces/BroadcastResponse.d.ts +7 -0
  52. package/build/utxo/interfaces/BroadcastResponse.js +1 -0
  53. package/build/wbtc/BroadcastResponse.d.ts +0 -0
  54. package/build/wbtc/BroadcastResponse.js +1 -0
  55. package/bytecode/wbtc.wasm +0 -0
  56. package/docs/assets/navigation.js +1 -1
  57. package/docs/assets/search.js +1 -1
  58. package/docs/classes/AddressGenerator.html +2 -2
  59. package/docs/classes/AddressVerificator.html +2 -2
  60. package/docs/classes/BitcoinUtils.html +4 -4
  61. package/docs/classes/CalldataGenerator.html +10 -10
  62. package/docs/classes/Compressor.html +4 -4
  63. package/docs/classes/ContractBaseMetadata.html +4 -4
  64. package/docs/classes/DeploymentGenerator.html +9 -9
  65. package/docs/classes/DeploymentTransaction.html +100 -81
  66. package/docs/classes/EcKeyPair.html +16 -16
  67. package/docs/classes/FundingTransaction.html +79 -58
  68. package/docs/classes/Generator.html +9 -9
  69. package/docs/classes/InteractionTransaction.html +89 -70
  70. package/docs/classes/OPNetLimitedProvider.html +15 -6
  71. package/docs/classes/PsbtTransaction.html +305 -0
  72. package/docs/classes/SharedInteractionTransaction.html +95 -76
  73. package/docs/classes/TapscriptVerificator.html +2 -2
  74. package/docs/classes/TransactionBuilder.html +102 -82
  75. package/docs/classes/TransactionFactory.html +7 -5
  76. package/docs/classes/TweakedSigner.html +2 -2
  77. package/docs/classes/TweakedTransaction.html +275 -0
  78. package/docs/classes/Wallet.html +15 -10
  79. package/docs/classes/WrapTransaction.html +102 -84
  80. package/docs/classes/WrappedGeneration.html +8 -8
  81. package/docs/classes/wBTC.html +7 -7
  82. package/docs/enums/PSBTTypes.html +175 -0
  83. package/docs/enums/TransactionSequence.html +2 -2
  84. package/docs/enums/TransactionType.html +3 -2
  85. package/docs/hierarchy.html +1 -1
  86. package/docs/interfaces/BroadcastResponse.html +179 -0
  87. package/docs/interfaces/ContractAddressVerificationParams.html +2 -2
  88. package/docs/interfaces/DeploymentResult.html +2 -2
  89. package/docs/interfaces/FetchUTXOParams.html +2 -2
  90. package/docs/interfaces/FetchUTXOParamsMultiAddress.html +2 -2
  91. package/docs/interfaces/GenerationConstraints.html +5 -5
  92. package/docs/interfaces/IDeploymentParameters.html +2 -2
  93. package/docs/interfaces/IFundingTransactionParameters.html +2 -2
  94. package/docs/interfaces/IInteractionParameters.html +2 -2
  95. package/docs/interfaces/ITransactionParameters.html +4 -4
  96. package/docs/interfaces/ITweakedTransactionData.html +177 -0
  97. package/docs/interfaces/IUnwrapParameters.html +186 -0
  98. package/docs/interfaces/IWBTCUTXODocument.html +180 -0
  99. package/docs/interfaces/IWallet.html +4 -4
  100. package/docs/interfaces/IWrapParameters.html +2 -2
  101. package/docs/interfaces/NetworkInformation.html +2 -2
  102. package/docs/interfaces/PsbtInputExtended.html +1 -1
  103. package/docs/interfaces/PsbtOutputExtendedAddress.html +2 -2
  104. package/docs/interfaces/PsbtOutputExtendedScript.html +2 -2
  105. package/docs/interfaces/PsbtTransactionData.html +179 -0
  106. package/docs/interfaces/RawUTXOResponse.html +2 -2
  107. package/docs/interfaces/SharedInteractionParameters.html +2 -2
  108. package/docs/interfaces/TapLeafScript.html +2 -2
  109. package/docs/interfaces/TweakSettings.html +3 -3
  110. package/docs/interfaces/UTXO.html +2 -2
  111. package/docs/interfaces/UnwrapResult.html +176 -0
  112. package/docs/interfaces/UpdateInput.html +2 -2
  113. package/docs/interfaces/VaultUTXOs.html +178 -0
  114. package/docs/interfaces/WrapResult.html +2 -2
  115. package/docs/interfaces/WrappedGenerationParameters.html +6 -6
  116. package/docs/modules.html +14 -3
  117. package/docs/types/FromBase64Params.html +174 -0
  118. package/docs/types/PsbtOutputExtended.html +1 -1
  119. package/docs/variables/version.html +1 -1
  120. package/package.json +1 -1
  121. package/src/_version.ts +1 -1
  122. package/src/generators/builders/CalldataGenerator.ts +1 -1
  123. package/src/keypair/Wallet.ts +10 -0
  124. package/src/metadata/contracts/wBTC.ts +1 -1
  125. package/src/opnet.ts +8 -0
  126. package/src/tests/adaptPSBT.ts +72 -0
  127. package/src/tests/massWrapReg.ts +111 -0
  128. package/src/tests/unwrapReg.ts +89 -0
  129. package/src/transaction/TransactionFactory.ts +77 -1
  130. package/src/transaction/builders/DeploymentTransaction.ts +6 -35
  131. package/src/transaction/builders/SharedInteractionTransaction.ts +2 -35
  132. package/src/transaction/builders/TransactionBuilder.ts +30 -246
  133. package/src/transaction/builders/UnwarpTransaction.ts +108 -0
  134. package/src/transaction/enums/TransactionType.ts +1 -0
  135. package/src/transaction/interfaces/ITransactionParameters.ts +10 -6
  136. package/src/transaction/processor/PsbtTransaction.ts +254 -0
  137. package/src/transaction/psbt/PSBTTypes.ts +3 -0
  138. package/src/transaction/shared/TweakedTransaction.ts +342 -0
  139. package/src/utxo/OPNetLimitedProvider.ts +47 -9
  140. package/src/utxo/interfaces/BroadcastResponse.ts +8 -0
@@ -0,0 +1,254 @@
1
+ import { Network, payments, Psbt, Signer, Transaction } from 'bitcoinjs-lib';
2
+ import { ITweakedTransactionData, TweakedTransaction } from '../shared/TweakedTransaction.js';
3
+ import { PsbtInputExtended, PsbtOutputExtended } from '../interfaces/Tap.js';
4
+ import { Address } from '@btc-vision/bsi-binary';
5
+
6
+ export interface PsbtTransactionData extends ITweakedTransactionData {
7
+ readonly psbt: Psbt;
8
+ readonly signer: Signer;
9
+ readonly network: Network;
10
+ readonly amountRequested: bigint;
11
+ }
12
+
13
+ export interface IWBTCUTXODocument {
14
+ readonly vault: Address;
15
+ readonly blockId: bigint;
16
+
17
+ readonly hash: string;
18
+ readonly value: bigint;
19
+ readonly outputIndex: number;
20
+
21
+ readonly output: string;
22
+ }
23
+
24
+ export interface VaultUTXOs {
25
+ readonly vault: Address;
26
+ readonly publicKeys: Address[];
27
+ readonly minimum: number;
28
+ readonly utxos: IWBTCUTXODocument[];
29
+ }
30
+
31
+ export type FromBase64Params = Omit<PsbtTransactionData, 'psbt'>;
32
+
33
+ /**
34
+ * @description PSBT Transaction processor.
35
+ * */
36
+ export class PsbtTransaction extends TweakedTransaction {
37
+ public readonly logColor: string = '#00ffe1';
38
+
39
+ /**
40
+ * @description The transaction
41
+ * @protected
42
+ */
43
+ protected readonly transaction: Psbt;
44
+
45
+ /**
46
+ * @description Sign hash types
47
+ * @protected
48
+ */
49
+ protected readonly sighashTypes: number[] = [
50
+ Transaction.SIGHASH_ALL,
51
+ Transaction.SIGHASH_ANYONECANPAY,
52
+ ];
53
+
54
+ protected readonly amountRequested: bigint;
55
+
56
+ constructor(data: PsbtTransactionData) {
57
+ super(data);
58
+
59
+ if (!data.amountRequested) {
60
+ throw new Error('Amount requested is required');
61
+ }
62
+
63
+ this.signer = data.signer;
64
+ this.network = data.network;
65
+ this.amountRequested = data.amountRequested;
66
+
67
+ this.transaction = data.psbt;
68
+
69
+ this.tweakSigner();
70
+ this.internalInit();
71
+ }
72
+
73
+ public static fromBase64(data: string, params: FromBase64Params): PsbtTransaction {
74
+ const psbt = Psbt.fromBase64(data, {
75
+ network: params.network,
76
+ });
77
+
78
+ return new PsbtTransaction({
79
+ ...params,
80
+ psbt,
81
+ });
82
+ }
83
+
84
+ /**
85
+ * @description Add an input to the transaction
86
+ * @param input
87
+ */
88
+ public addInput(input: PsbtInputExtended): void {
89
+ this.transaction.addInput(input);
90
+ }
91
+
92
+ /**
93
+ * @description Add an output to the transaction
94
+ * @param output
95
+ */
96
+ public addOutput(output: PsbtOutputExtended): void {
97
+ this.transaction.addOutput(output);
98
+ }
99
+
100
+ /**
101
+ * @description Merge vault UTXOs into the transaction
102
+ * @param {VaultUTXOs[]} input The vault UTXOs
103
+ * @param {Signer} [firstSigner] The first signer
104
+ * @public
105
+ */
106
+ public mergeVaults(input: VaultUTXOs[], firstSigner?: Signer): void {
107
+ const firstVault = input[0];
108
+ if (!firstVault) {
109
+ throw new Error('No vaults provided');
110
+ }
111
+
112
+ const outputLeftAmount = this.calculateOuputLeftAmountFromVaults(input);
113
+ if (outputLeftAmount < 0) {
114
+ throw new Error(
115
+ `Output left amount is negative ${outputLeftAmount} for vault ${firstVault.vault}`,
116
+ );
117
+ }
118
+
119
+ this.addOutput({
120
+ address: firstVault.vault,
121
+ value: Number(outputLeftAmount),
122
+ });
123
+
124
+ for (const vault of input) {
125
+ this.addVaultInputs(vault, firstSigner);
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Attempt to sign all inputs
131
+ */
132
+ public attemptSignAllInputs(): boolean {
133
+ let signed = false;
134
+ for (let i = 0; i < this.transaction.data.inputs.length; i++) {
135
+ const input = this.transaction.data.inputs[i];
136
+ if (!input.partialSig) {
137
+ continue;
138
+ }
139
+
140
+ try {
141
+ this.signInput(this.transaction, input, i, this.signer);
142
+ signed = true;
143
+ } catch (e) {}
144
+ }
145
+
146
+ return signed;
147
+ }
148
+
149
+ public attemptFinalizeInputs(): boolean {
150
+ try {
151
+ this.transaction.finalizeAllInputs();
152
+ return true;
153
+ } catch (e) {
154
+ return false;
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Generate a multi-signature redeem script
160
+ * @param {string[]} publicKeys The public keys
161
+ * @param {number} minimum The minimum number of signatures
162
+ * @protected
163
+ * @returns {Buffer} The redeem script
164
+ */
165
+ protected generateMultiSignRedeemScript(publicKeys: string[], minimum: number): Buffer {
166
+ const redeemBuffer = payments.p2ms({
167
+ m: minimum,
168
+ pubkeys: publicKeys.map((key) => Buffer.from(key, 'base64')),
169
+ network: this.network,
170
+ }).output;
171
+
172
+ if (!redeemBuffer) {
173
+ throw new Error('Failed to generate redeem script');
174
+ }
175
+
176
+ return redeemBuffer;
177
+ }
178
+
179
+ /**
180
+ * @description Calculate the amount left to refund to the first vault.
181
+ * @param {VaultUTXOs[]} vaults The vaults
182
+ * @private
183
+ * @returns {bigint} The amount left
184
+ */
185
+ private calculateOuputLeftAmountFromVaults(vaults: VaultUTXOs[]): bigint {
186
+ let total = BigInt(0);
187
+ for (const vault of vaults) {
188
+ for (const utxo of vault.utxos) {
189
+ total += BigInt(utxo.value);
190
+ }
191
+ }
192
+
193
+ return total - this.amountRequested;
194
+ }
195
+
196
+ /**
197
+ * @description Add vault inputs to the transaction
198
+ * @param {VaultUTXOs} vault The vault UTXOs
199
+ * @param {Signer} [firstSigner] The first signer
200
+ * @private
201
+ */
202
+ private addVaultInputs(vault: VaultUTXOs, firstSigner: Signer = this.signer): void {
203
+ const vaultRedeem = this.generateMultiSignRedeemScript(vault.publicKeys, vault.minimum);
204
+ for (const utxo of vault.utxos) {
205
+ const inputIndex = this.transaction.inputCount;
206
+ this.addVaultUTXO(utxo, vaultRedeem);
207
+
208
+ if (firstSigner) {
209
+ this.log(
210
+ `Signing input ${inputIndex} with ${firstSigner.publicKey.toString('hex')}`,
211
+ );
212
+
213
+ // we don't care if we fail to sign the input
214
+ try {
215
+ this.signInput(
216
+ this.transaction,
217
+ this.transaction.data.inputs[inputIndex],
218
+ inputIndex,
219
+ firstSigner,
220
+ );
221
+ } catch (e) {
222
+ this.warn(
223
+ `Failed to sign input ${inputIndex} with ${firstSigner.publicKey.toString('hex')}`,
224
+ );
225
+ }
226
+ }
227
+ }
228
+ }
229
+
230
+ /**
231
+ * @description Add a vault UTXO to the transaction
232
+ * @param {IWBTCUTXODocument} utxo The UTXO to add
233
+ * @param {Buffer} redeem The redeem script
234
+ * @private
235
+ */
236
+ private addVaultUTXO(utxo: IWBTCUTXODocument, redeem: Buffer): void {
237
+ const input: PsbtInputExtended = {
238
+ hash: Buffer.from(utxo.hash, 'hex'),
239
+ index: utxo.outputIndex,
240
+ witnessUtxo: {
241
+ script: Buffer.from(utxo.output, 'base64'),
242
+ value: Number(utxo.value),
243
+ },
244
+ witnessScript: redeem,
245
+ partialSig: [],
246
+ };
247
+
248
+ if (this.sighashTypes) {
249
+ input.sighashType = this.calculateSignHash();
250
+ }
251
+
252
+ this.addInput(input);
253
+ }
254
+ }
@@ -0,0 +1,3 @@
1
+ export enum PSBTTypes {
2
+ UNWRAP = 0,
3
+ }
@@ -0,0 +1,342 @@
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
+
11
+ export interface ITweakedTransactionData {
12
+ readonly signer: Signer;
13
+ readonly network: Network;
14
+ readonly nonWitnessUtxo?: Buffer;
15
+ }
16
+
17
+ /**
18
+ * The transaction sequence
19
+ */
20
+ export enum TransactionSequence {
21
+ REPLACE_BY_FEE = 0xfffffffd,
22
+ FINAL = 0xffffffff,
23
+ }
24
+
25
+ /**
26
+ * @description PSBT Transaction processor.
27
+ * */
28
+ export abstract class TweakedTransaction extends Logger {
29
+ public readonly logColor: string = '#00ffe1';
30
+
31
+ /**
32
+ * @description Was the transaction signed?
33
+ */
34
+ protected signer: Signer;
35
+
36
+ /**
37
+ * @description Tweaked signer
38
+ */
39
+ protected tweakedSigner?: Signer;
40
+
41
+ /**
42
+ * @description The network of the transaction
43
+ */
44
+ protected network: Network;
45
+
46
+ /**
47
+ * @description Was the transaction signed?
48
+ */
49
+ protected signed: boolean = false;
50
+
51
+ /**
52
+ * @description The transaction
53
+ * @protected
54
+ */
55
+ protected abstract readonly transaction: Psbt;
56
+ /**
57
+ * @description The sighash types of the transaction
58
+ * @protected
59
+ */
60
+ protected readonly sighashTypes: number[] | undefined;
61
+
62
+ /**
63
+ * @description The script data of the transaction
64
+ */
65
+ protected scriptData: Payment | null = null;
66
+
67
+ /**
68
+ * @description The tap data of the transaction
69
+ */
70
+ protected tapData: Payment | null = null;
71
+
72
+ /**
73
+ * @description The inputs of the transaction
74
+ */
75
+ protected readonly inputs: PsbtInputExtended[] = [];
76
+
77
+ /**
78
+ * @description The sequence of the transaction
79
+ * @protected
80
+ */
81
+ protected sequence: number = TransactionSequence.REPLACE_BY_FEE;
82
+
83
+ /**
84
+ * The tap leaf script
85
+ * @protected
86
+ */
87
+ protected tapLeafScript: TapLeafScript | null = null;
88
+
89
+ /**
90
+ * Add a non-witness utxo to the transaction
91
+ * @protected
92
+ */
93
+ protected nonWitnessUtxo?: Buffer;
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
+
104
+ /**
105
+ * @description Returns the script address
106
+ * @returns {string}
107
+ */
108
+ public getScriptAddress(): string {
109
+ if (!this.scriptData || !this.scriptData.address) {
110
+ throw new Error('Tap data is required');
111
+ }
112
+
113
+ return this.scriptData.address;
114
+ }
115
+
116
+ /**
117
+ * @description Returns the transaction
118
+ * @returns {Transaction}
119
+ */
120
+ public getTransaction(): Transaction {
121
+ return this.transaction.extractTransaction(false);
122
+ }
123
+
124
+ /**
125
+ * @description Returns the tap address
126
+ * @returns {string}
127
+ * @throws {Error} - If tap data is not set
128
+ */
129
+ public getTapAddress(): string {
130
+ if (!this.tapData || !this.tapData.address) {
131
+ throw new Error('Tap data is required');
132
+ }
133
+
134
+ return this.tapData.address;
135
+ }
136
+
137
+ /**
138
+ * Get the transaction PSBT as a base64 string.
139
+ * @public
140
+ * @returns {string} - The transaction as a base64 string
141
+ */
142
+ public toBase64(): string {
143
+ return this.transaction.toBase64();
144
+ }
145
+
146
+ /**
147
+ * @description Disables replace by fee on the transaction
148
+ */
149
+ public disableRBF(): void {
150
+ if (this.signed) throw new Error('Transaction is already signed');
151
+
152
+ this.sequence = TransactionSequence.FINAL;
153
+
154
+ for (let input of this.inputs) {
155
+ input.sequence = TransactionSequence.FINAL;
156
+ }
157
+ }
158
+
159
+ protected generateTapData(): Payment {
160
+ return {
161
+ internalPubkey: this.internalPubKeyToXOnly(),
162
+ network: this.network,
163
+ };
164
+ }
165
+
166
+ /**
167
+ * Generates the script address.
168
+ * @protected
169
+ * @returns {Payment}
170
+ */
171
+ protected generateScriptAddress(): Payment {
172
+ return {
173
+ internalPubkey: this.internalPubKeyToXOnly(),
174
+ network: this.network,
175
+ };
176
+ }
177
+
178
+ /**
179
+ * Returns the signer key.
180
+ * @protected
181
+ * @returns {Signer}
182
+ */
183
+ protected getSignerKey(): Signer {
184
+ return this.signer;
185
+ }
186
+
187
+ /**
188
+ * Signs an input of the transaction.
189
+ * @param {Psbt} transaction - The transaction to sign
190
+ * @param {PsbtInput} input - The input to sign
191
+ * @param {number} i - The index of the input
192
+ * @param {Signer} [signer] - The signer to use
193
+ * @protected
194
+ */
195
+ protected signInput(transaction: Psbt, input: PsbtInput, i: number, signer?: Signer): void {
196
+ const signHash = this.sighashTypes ? [this.calculateSignHash()] : undefined;
197
+
198
+ if (input.tapInternalKey) {
199
+ if (!this.tweakedSigner) throw new Error('Tweaked signer is required');
200
+ transaction.signTaprootInput(i, this.tweakedSigner, undefined, signHash);
201
+ } else {
202
+ transaction.signInput(i, signer || this.getSignerKey(), signHash);
203
+ }
204
+ }
205
+
206
+ /**
207
+ * Signs all the inputs of the transaction.
208
+ * @param {Psbt} transaction - The transaction to sign
209
+ * @protected
210
+ * @returns {void}
211
+ */
212
+ protected signInputs(transaction: Psbt): void {
213
+ for (let i = 0; i < transaction.data.inputs.length; i++) {
214
+ let input: PsbtInput = transaction.data.inputs[i];
215
+
216
+ this.signInput(transaction, input, i);
217
+ }
218
+
219
+ transaction.finalizeAllInputs();
220
+ }
221
+
222
+ /**
223
+ * Calculate the sign hash number
224
+ * @description Calculates the sign hash
225
+ * @protected
226
+ * @returns {number}
227
+ */
228
+ protected calculateSignHash(): number {
229
+ if (!this.sighashTypes) {
230
+ throw new Error('Sighash types are required');
231
+ }
232
+
233
+ let signHash: number = 0;
234
+ for (let sighashType of this.sighashTypes) {
235
+ signHash |= sighashType;
236
+ }
237
+
238
+ return signHash;
239
+ }
240
+
241
+ /**
242
+ * Converts the public key to x-only.
243
+ * @protected
244
+ * @returns {Buffer}
245
+ */
246
+ protected internalPubKeyToXOnly(): Buffer {
247
+ return toXOnly(this.signer.publicKey);
248
+ }
249
+
250
+ /**
251
+ * Internal init.
252
+ * @protected
253
+ */
254
+ protected internalInit(): void {
255
+ this.scriptData = payments.p2tr(this.generateScriptAddress());
256
+ this.tapData = payments.p2tr(this.generateTapData());
257
+ }
258
+
259
+ /**
260
+ * Tweak the signer for the interaction
261
+ * @protected
262
+ */
263
+ protected tweakSigner(): void {
264
+ if (this.tweakedSigner) return;
265
+
266
+ // tweaked p2tr signer.
267
+ this.tweakedSigner = this.getTweakedSigner(true);
268
+ }
269
+
270
+ /**
271
+ * Get the tweaked signer
272
+ * @param {boolean} useTweakedHash Whether to use the tweaked hash
273
+ * @private
274
+ *
275
+ * @returns {Signer} The tweaked signer
276
+ */
277
+ protected getTweakedSigner(useTweakedHash: boolean = false): Signer {
278
+ const settings: TweakSettings = {
279
+ network: this.network,
280
+ };
281
+
282
+ if (useTweakedHash) {
283
+ settings.tweakHash = this.getTweakerHash();
284
+ }
285
+
286
+ return TweakedSigner.tweakSigner(this.signer as ECPairInterface, settings);
287
+ }
288
+
289
+ /**
290
+ * Get the tweaked hash
291
+ * @private
292
+ *
293
+ * @returns {Buffer | undefined} The tweaked hash
294
+ */
295
+ protected getTweakerHash(): Buffer | undefined {
296
+ return this.tapData?.hash;
297
+ }
298
+
299
+ /**
300
+ * Generate the PSBT input extended
301
+ * @param {UTXO} utxo The UTXO
302
+ * @param {number} i The index of the input
303
+ * @protected
304
+ * @returns {PsbtInputExtended} The PSBT input extended
305
+ */
306
+ protected generatePsbtInputExtended(utxo: UTXO, i: number): PsbtInputExtended {
307
+ const input: PsbtInputExtended = {
308
+ hash: utxo.transactionId,
309
+ index: utxo.outputIndex,
310
+ witnessUtxo: {
311
+ value: Number(utxo.value),
312
+ script: Buffer.from(utxo.scriptPubKey.hex, 'hex'),
313
+ },
314
+ sequence: this.sequence,
315
+ };
316
+
317
+ if (this.sighashTypes) {
318
+ input.sighashType = this.calculateSignHash();
319
+ }
320
+
321
+ if (this.tapLeafScript) {
322
+ input.tapLeafScript = [this.tapLeafScript];
323
+ }
324
+
325
+ if (i === 0 && this.nonWitnessUtxo) {
326
+ input.nonWitnessUtxo = this.nonWitnessUtxo;
327
+ this.log(`Using non-witness utxo for input ${i}`);
328
+ }
329
+
330
+ // automatically detect p2tr inputs.
331
+ if (
332
+ utxo.scriptPubKey.address &&
333
+ AddressVerificator.isValidP2TRAddress(utxo.scriptPubKey.address, this.network)
334
+ ) {
335
+ this.tweakSigner();
336
+
337
+ input.tapInternalKey = this.internalPubKeyToXOnly();
338
+ }
339
+
340
+ return input;
341
+ }
342
+ }
@@ -1,6 +1,7 @@
1
1
  import { FetchUTXOParams, FetchUTXOParamsMultiAddress, RawUTXOResponse, UTXO } from './interfaces/IUTXO.js';
2
2
  import { WrappedGeneration } from '../wbtc/WrappedGenerationParameters.js';
3
3
  import { WrappedGenerationParameters } from '../wbtc/Generate.js';
4
+ import { BroadcastResponse } from './interfaces/BroadcastResponse.js';
4
5
 
5
6
  /**
6
7
  * Allows to fetch UTXO data from any OPNET node
@@ -117,12 +118,32 @@ export class OPNetLimitedProvider {
117
118
  }
118
119
 
119
120
  /**
120
- * Fetches the wrap parameters from the OPNET node
121
- * @param {bigint} amount - The amount to wrap
122
- * @returns {Promise<WrappedGeneration | undefined>} - The wrap parameters fetched
123
- * @throws {Error} - If wrap parameters could not be fetched
121
+ * Broadcasts a transaction to the OPNET node
122
+ * @param {string} transaction - The transaction to broadcast
123
+ * @param {boolean} psbt - Whether the transaction is a PSBT
124
+ * @returns {Promise<BroadcastResponse>} - The response from the OPNET node
124
125
  */
125
- public async fetchWrapParameters(amount: bigint): Promise<WrappedGeneration | undefined> {
126
+ public async broadcastTransaction(
127
+ transaction: string,
128
+ psbt: boolean,
129
+ ): Promise<BroadcastResponse | undefined> {
130
+ const params = [transaction, psbt];
131
+ const result = await this.rpcMethod('btc_sendRawTransaction', params);
132
+
133
+ if (!result) {
134
+ return;
135
+ }
136
+
137
+ return result as BroadcastResponse;
138
+ }
139
+
140
+ /**
141
+ * Fetches to the OPNET node
142
+ * @param {string} method
143
+ * @param {unknown[]} paramsMethod
144
+ * @returns {Promise<unknown>}
145
+ */
146
+ public async rpcMethod(method: string, paramsMethod: unknown[]): Promise<unknown> {
126
147
  const params = {
127
148
  method: 'POST',
128
149
  headers: {
@@ -130,8 +151,8 @@ export class OPNetLimitedProvider {
130
151
  },
131
152
  body: JSON.stringify({
132
153
  jsonrpc: '2.0',
133
- method: 'btc_generate',
134
- params: [0, amount.toString()],
154
+ method: method,
155
+ params: paramsMethod,
135
156
  id: 1,
136
157
  }),
137
158
  };
@@ -146,7 +167,7 @@ export class OPNetLimitedProvider {
146
167
 
147
168
  const fetchedData = await resp.json();
148
169
  if (!fetchedData) {
149
- throw new Error('No wrap parameters found');
170
+ throw new Error('No data fetched');
150
171
  }
151
172
 
152
173
  const result = fetchedData.result;
@@ -158,9 +179,26 @@ export class OPNetLimitedProvider {
158
179
  throw new Error('Something went wrong while fetching wrap parameters');
159
180
  }
160
181
 
161
- return new WrappedGeneration(result as WrappedGenerationParameters);
182
+ return result;
162
183
  } catch (e) {
163
184
  console.error(`Failed to fetch wrap parameters: ${(e as Error).stack}`);
164
185
  }
165
186
  }
187
+
188
+ /**
189
+ * Fetches the wrap parameters from the OPNET node
190
+ * @param {bigint} amount - The amount to wrap
191
+ * @returns {Promise<WrappedGeneration | undefined>} - The wrap parameters fetched
192
+ * @throws {Error} - If wrap parameters could not be fetched
193
+ */
194
+ public async fetchWrapParameters(amount: bigint): Promise<WrappedGeneration | undefined> {
195
+ const params = [0, amount.toString()];
196
+ const result = await this.rpcMethod('btc_generate', params);
197
+
198
+ if (!result) {
199
+ return;
200
+ }
201
+
202
+ return new WrappedGeneration(result as WrappedGenerationParameters);
203
+ }
166
204
  }
@@ -0,0 +1,8 @@
1
+ export interface BroadcastResponse {
2
+ success: boolean;
3
+ result?: string;
4
+ error?: string;
5
+ peers?: number;
6
+
7
+ identifier: bigint;
8
+ }