@btc-vision/transaction 1.0.105 → 1.0.107

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 (52) hide show
  1. package/browser/_version.d.ts +1 -1
  2. package/browser/index.js +1 -1
  3. package/browser/keypair/EcKeyPair.d.ts +4 -4
  4. package/browser/transaction/builders/MultiSignTransaction.d.ts +1 -1
  5. package/browser/transaction/builders/SharedInteractionTransaction.d.ts +1 -0
  6. package/browser/transaction/builders/TransactionBuilder.d.ts +4 -2
  7. package/browser/transaction/builders/UnwrapSegwitTransaction.d.ts +1 -1
  8. package/browser/transaction/builders/UnwrapTransaction.d.ts +1 -1
  9. package/browser/transaction/interfaces/ITransactionParameters.d.ts +9 -8
  10. package/browser/transaction/processor/PsbtTransaction.d.ts +1 -1
  11. package/browser/transaction/shared/TweakedTransaction.d.ts +2 -1
  12. package/browser/utxo/OPNetLimitedProvider.d.ts +11 -1
  13. package/browser/utxo/interfaces/IUTXO.d.ts +3 -1
  14. package/build/_version.d.ts +1 -1
  15. package/build/_version.js +1 -1
  16. package/build/keypair/EcKeyPair.d.ts +4 -4
  17. package/build/transaction/TransactionFactory.js +2 -1
  18. package/build/transaction/builders/CustomScriptTransaction.js +1 -4
  19. package/build/transaction/builders/MultiSignTransaction.d.ts +1 -1
  20. package/build/transaction/builders/MultiSignTransaction.js +2 -2
  21. package/build/transaction/builders/SharedInteractionTransaction.d.ts +1 -0
  22. package/build/transaction/builders/SharedInteractionTransaction.js +43 -31
  23. package/build/transaction/builders/TransactionBuilder.d.ts +4 -2
  24. package/build/transaction/builders/TransactionBuilder.js +17 -5
  25. package/build/transaction/builders/UnwrapSegwitTransaction.d.ts +1 -1
  26. package/build/transaction/builders/UnwrapSegwitTransaction.js +2 -3
  27. package/build/transaction/builders/UnwrapTransaction.d.ts +1 -1
  28. package/build/transaction/builders/UnwrapTransaction.js +2 -2
  29. package/build/transaction/interfaces/ITransactionParameters.d.ts +9 -8
  30. package/build/transaction/processor/PsbtTransaction.d.ts +1 -1
  31. package/build/transaction/processor/PsbtTransaction.js +2 -2
  32. package/build/transaction/shared/TweakedTransaction.d.ts +2 -1
  33. package/build/transaction/shared/TweakedTransaction.js +30 -10
  34. package/build/utxo/OPNetLimitedProvider.d.ts +11 -1
  35. package/build/utxo/OPNetLimitedProvider.js +49 -2
  36. package/build/utxo/interfaces/IUTXO.d.ts +3 -1
  37. package/eslint.config.js +0 -1
  38. package/package.json +2 -2
  39. package/src/_version.ts +1 -1
  40. package/src/keypair/EcKeyPair.ts +4 -4
  41. package/src/transaction/TransactionFactory.ts +3 -3
  42. package/src/transaction/builders/CustomScriptTransaction.ts +3 -7
  43. package/src/transaction/builders/MultiSignTransaction.ts +3 -2
  44. package/src/transaction/builders/SharedInteractionTransaction.ts +61 -34
  45. package/src/transaction/builders/TransactionBuilder.ts +38 -11
  46. package/src/transaction/builders/UnwrapSegwitTransaction.ts +5 -5
  47. package/src/transaction/builders/UnwrapTransaction.ts +6 -2
  48. package/src/transaction/interfaces/ITransactionParameters.ts +11 -9
  49. package/src/transaction/processor/PsbtTransaction.ts +2 -2
  50. package/src/transaction/shared/TweakedTransaction.ts +38 -10
  51. package/src/utxo/OPNetLimitedProvider.ts +86 -4
  52. package/src/utxo/interfaces/IUTXO.ts +3 -1
@@ -4,15 +4,17 @@ import { WrappedGeneration } from '../../wbtc/WrappedGenerationParameters.js';
4
4
  import { ITweakedTransactionData } from '../shared/TweakedTransaction.js';
5
5
  import { VaultUTXOs } from '../processor/PsbtTransaction.js';
6
6
  import { ChainId } from '../../network/ChainId.js';
7
-
7
+ import { PsbtOutputExtended } from './Tap.js';
8
8
  export interface ITransactionParameters extends ITweakedTransactionData {
9
9
  readonly from?: Address;
10
- readonly to?: Address | undefined;
10
+ readonly to?: Address;
11
11
  utxos: UTXO[];
12
12
 
13
- nonWitnessUtxo?: Buffer | undefined;
13
+ nonWitnessUtxo?: Buffer;
14
14
  estimatedFees?: bigint;
15
15
 
16
+ optionalOutputs?: PsbtOutputExtended[];
17
+
16
18
  chainId?: ChainId;
17
19
 
18
20
  readonly feeRate: number;
@@ -26,19 +28,20 @@ export interface IFundingTransactionParameters extends ITransactionParameters {
26
28
  }
27
29
 
28
30
  export interface SharedInteractionParameters extends ITransactionParameters {
29
- calldata?: Buffer | undefined;
31
+ calldata?: Buffer;
30
32
  disableAutoRefund?: boolean;
31
33
 
32
34
  readonly randomBytes?: Buffer;
33
35
  }
34
36
 
35
- export interface IInteractionParameters extends SharedInteractionParameters {
37
+ export interface IInteractionParameters
38
+ extends Omit<SharedInteractionParameters, 'optionalOutputs'> {
36
39
  readonly calldata: Buffer;
37
40
 
38
41
  readonly to: Address;
39
42
  }
40
43
 
41
- export interface IWrapParameters extends SharedInteractionParameters {
44
+ export interface IWrapParameters extends Omit<SharedInteractionParameters, 'optionalOutputs'> {
42
45
  readonly to?: Address;
43
46
 
44
47
  readonly from: Address;
@@ -48,14 +51,13 @@ export interface IWrapParameters extends SharedInteractionParameters {
48
51
  readonly generationParameters: WrappedGeneration;
49
52
  }
50
53
 
51
- export interface IUnwrapParameters extends SharedInteractionParameters {
54
+ export interface IUnwrapParameters extends Omit<SharedInteractionParameters, 'optionalOutputs'> {
52
55
  readonly unwrapUTXOs: VaultUTXOs[];
53
56
  readonly amount: bigint;
54
57
  }
55
58
 
56
- export interface IDeploymentParameters extends ITransactionParameters {
59
+ export interface IDeploymentParameters extends Omit<ITransactionParameters, 'to'> {
57
60
  readonly bytecode: Buffer;
58
61
 
59
- readonly to?: undefined;
60
62
  readonly randomBytes?: Buffer;
61
63
  }
@@ -119,8 +119,8 @@ export class PsbtTransaction extends TweakedTransaction {
119
119
  * @description Add an input to the transaction
120
120
  * @param input
121
121
  */
122
- public addInput(input: PsbtInputExtended): void {
123
- this.transaction.addInput(input);
122
+ public addInput(input: PsbtInputExtended, checkPartialSigs: boolean = false): void {
123
+ this.transaction.addInput(input, checkPartialSigs);
124
124
  }
125
125
 
126
126
  /**
@@ -7,8 +7,8 @@ import { PsbtInput } from 'bip174/src/lib/interfaces.js';
7
7
  import { UTXO } from '../../utxo/interfaces/IUTXO.js';
8
8
  import { PsbtInputExtended, TapLeafScript } from '../interfaces/Tap.js';
9
9
  import { AddressVerificator } from '../../keypair/AddressVerificator.js';
10
- import { varuint } from 'bitcoinjs-lib/src/bufferutils.js';
11
10
  import { ChainId } from '../../network/ChainId.js';
11
+ import { varuint } from 'bitcoinjs-lib/src/bufferutils.js';
12
12
 
13
13
  export interface ITweakedTransactionData {
14
14
  readonly signer: Signer;
@@ -109,17 +109,17 @@ export abstract class TweakedTransaction extends Logger {
109
109
  * Read witnesses
110
110
  * @protected
111
111
  */
112
- public static readScriptWitnessToWitnessStack(buffer: Buffer): Buffer[] {
112
+ public static readScriptWitnessToWitnessStack(Buffer: Buffer): Buffer[] {
113
113
  let offset = 0;
114
114
 
115
115
  function readSlice(n: number): Buffer {
116
- const slice = buffer.subarray(offset, offset + n);
116
+ const slice = Buffer.subarray(offset, offset + n);
117
117
  offset += n;
118
118
  return slice;
119
119
  }
120
120
 
121
121
  function readVarInt(): number {
122
- const varint = varuint.decode(buffer, offset);
122
+ const varint = varuint.decode(Buffer, offset);
123
123
  offset += varuint.decode.bytes;
124
124
  return varint;
125
125
  }
@@ -421,6 +421,20 @@ export abstract class TweakedTransaction extends Logger {
421
421
  }
422
422
  }
423
423
 
424
+ protected splitArray<T>(arr: T[], chunkSize: number): T[][] {
425
+ if (chunkSize <= 0) {
426
+ throw new Error('Chunk size must be greater than 0.');
427
+ }
428
+
429
+ const result: T[][] = [];
430
+
431
+ for (let i = 0; i < arr.length; i += chunkSize) {
432
+ result.push(arr.slice(i, i + chunkSize));
433
+ }
434
+
435
+ return result;
436
+ }
437
+
424
438
  /**
425
439
  * Signs all the inputs of the transaction.
426
440
  * @param {Psbt} transaction - The transaction to sign
@@ -428,14 +442,28 @@ export abstract class TweakedTransaction extends Logger {
428
442
  * @returns {Promise<void>}
429
443
  */
430
444
  protected async signInputs(transaction: Psbt): Promise<void> {
431
- for (let i = 0; i < transaction.data.inputs.length; i++) {
432
- const input: PsbtInput = transaction.data.inputs[i];
445
+ const txs: PsbtInput[] = transaction.data.inputs;
446
+
447
+ const batchSize: number = 20;
448
+ const batches = this.splitArray(txs, batchSize);
449
+
450
+ for (let i = 0; i < batches.length; i++) {
451
+ const batch = batches[i];
452
+ const promises: Promise<void>[] = [];
453
+ const offset = i * batchSize;
454
+
455
+ for (let j = 0; j < batch.length; j++) {
456
+ const index = offset + j;
457
+ const input = batch[j];
433
458
 
434
- try {
435
- await this.signInput(transaction, input, i);
436
- } catch (e) {
437
- this.log(`Failed to sign input ${i}: ${(e as Error).stack}`);
459
+ try {
460
+ promises.push(this.signInput(transaction, input, index));
461
+ } catch (e) {
462
+ this.log(`Failed to sign input ${index}: ${(e as Error).stack}`);
463
+ }
438
464
  }
465
+
466
+ await Promise.all(promises);
439
467
  }
440
468
 
441
469
  try {
@@ -1,5 +1,7 @@
1
1
  import { Address } from '@btc-vision/bsi-binary';
2
+ import { Network } from 'bitcoinjs-lib';
2
3
  import { currentConsensusConfig } from '../consensus/ConsensusConfig.js';
4
+ import { IFundingTransactionParameters, TransactionFactory, Wallet } from '../opnet.js';
3
5
  import { UnwrappedGenerationParameters, WrappedGenerationParameters } from '../wbtc/Generate.js';
4
6
  import { UnwrapGeneration } from '../wbtc/UnwrapGeneration.js';
5
7
  import { WrappedGeneration } from '../wbtc/WrappedGenerationParameters.js';
@@ -11,6 +13,12 @@ import {
11
13
  UTXO,
12
14
  } from './interfaces/IUTXO.js';
13
15
 
16
+ export interface WalletUTXOs {
17
+ readonly confirmed: RawUTXOResponse[];
18
+ readonly pending: RawUTXOResponse[];
19
+ readonly spentTransactions: RawUTXOResponse[];
20
+ }
21
+
14
22
  /**
15
23
  * Allows to fetch UTXO data from any OPNET node
16
24
  */
@@ -18,7 +26,7 @@ export class OPNetLimitedProvider {
18
26
  private readonly utxoPath: string = 'address/utxos';
19
27
  private readonly rpc: string = 'json-rpc';
20
28
 
21
- constructor(private readonly opnetAPIUrl: string) {}
29
+ public constructor(private readonly opnetAPIUrl: string) {}
22
30
 
23
31
  /**
24
32
  * Fetches UTXO data from the OPNET node
@@ -27,6 +35,14 @@ export class OPNetLimitedProvider {
27
35
  * @throws {Error} - If UTXOs could not be fetched
28
36
  */
29
37
  public async fetchUTXO(settings: FetchUTXOParams): Promise<UTXO[]> {
38
+ if (settings.usePendingUTXO === undefined) {
39
+ settings.usePendingUTXO = true;
40
+ }
41
+
42
+ if (settings.optimized === undefined) {
43
+ settings.optimized = true;
44
+ }
45
+
30
46
  const params = {
31
47
  method: 'GET',
32
48
  headers: {
@@ -41,12 +57,31 @@ export class OPNetLimitedProvider {
41
57
  throw new Error(`Failed to fetch UTXO data: ${resp.statusText}`);
42
58
  }
43
59
 
44
- const fetchedData: RawUTXOResponse[] = (await resp.json()) as RawUTXOResponse[];
45
- if (fetchedData.length === 0) {
60
+ const fetchedData: WalletUTXOs = (await resp.json()) as WalletUTXOs;
61
+ const allUtxos = settings.usePendingUTXO
62
+ ? [...fetchedData.confirmed, ...fetchedData.pending]
63
+ : fetchedData.confirmed;
64
+
65
+ const unspentUTXOs: RawUTXOResponse[] = [];
66
+ for (const utxo of allUtxos) {
67
+ if (
68
+ fetchedData.spentTransactions.some(
69
+ (spent) =>
70
+ spent.transactionId === utxo.transactionId &&
71
+ spent.outputIndex === utxo.outputIndex,
72
+ )
73
+ ) {
74
+ continue;
75
+ }
76
+
77
+ unspentUTXOs.push(utxo);
78
+ }
79
+
80
+ if (unspentUTXOs.length === 0) {
46
81
  throw new Error('No UTXO found');
47
82
  }
48
83
 
49
- const meetCriteria: RawUTXOResponse[] = fetchedData.filter((utxo: RawUTXOResponse) => {
84
+ const meetCriteria: RawUTXOResponse[] = unspentUTXOs.filter((utxo: RawUTXOResponse) => {
50
85
  return BigInt(utxo.value) >= settings.minAmount;
51
86
  });
52
87
 
@@ -97,6 +132,7 @@ export class OPNetLimitedProvider {
97
132
  minAmount: settings.minAmount,
98
133
  requestedAmount: settings.requestedAmount,
99
134
  optimized: settings.optimized,
135
+ usePendingUTXO: settings.usePendingUTXO,
100
136
  };
101
137
 
102
138
  const promise = this.fetchUTXO(params).catch(() => {
@@ -145,6 +181,52 @@ export class OPNetLimitedProvider {
145
181
  return result as BroadcastResponse;
146
182
  }
147
183
 
184
+ /**
185
+ * Splits UTXOs into smaller UTXOs
186
+ * @param {Wallet} wallet - The wallet to split UTXOs
187
+ * @param {Network} network - The network to split UTXOs
188
+ * @param {number} splitInputsInto - The number of UTXOs to split into
189
+ * @param {bigint} amountPerUTXO - The amount per UTXO
190
+ * @returns {Promise<BroadcastResponse | { error: string }>} - The response from the OPNET node or an error
191
+ */
192
+ public async splitUTXOs(
193
+ wallet: Wallet,
194
+ network: Network,
195
+ splitInputsInto: number,
196
+ amountPerUTXO: bigint,
197
+ ): Promise<BroadcastResponse | { error: string }> {
198
+ const utxoSetting: FetchUTXOParamsMultiAddress = {
199
+ addresses: [wallet.p2wpkh, wallet.p2tr],
200
+ minAmount: 330n,
201
+ requestedAmount: 1_000_000_000_000_000n,
202
+ };
203
+
204
+ const utxos: UTXO[] = await this.fetchUTXOMultiAddr(utxoSetting);
205
+ if (!utxos || !utxos.length) return { error: 'No UTXOs found' };
206
+
207
+ const amount = BigInt(splitInputsInto) * amountPerUTXO;
208
+
209
+ const fundingTransactionParameters: IFundingTransactionParameters = {
210
+ amount: amount,
211
+ feeRate: 500,
212
+ from: wallet.p2tr,
213
+ utxos: utxos,
214
+ signer: wallet.keypair,
215
+ network,
216
+ to: wallet.p2tr,
217
+ splitInputsInto,
218
+ priorityFee: 330n,
219
+ };
220
+
221
+ const transactionFactory = new TransactionFactory();
222
+ const fundingTx = await transactionFactory.createBTCTransfer(fundingTransactionParameters);
223
+
224
+ const broadcastResponse = await this.broadcastTransaction(fundingTx.tx, false);
225
+ if (!broadcastResponse) return { error: 'Could not broadcast transaction' };
226
+
227
+ return broadcastResponse;
228
+ }
229
+
148
230
  /**
149
231
  * Fetches to the OPNET node
150
232
  * @param {string} method
@@ -11,7 +11,8 @@ export interface FetchUTXOParams {
11
11
  readonly address: string;
12
12
  readonly minAmount: bigint;
13
13
  readonly requestedAmount: bigint;
14
- readonly optimized?: boolean;
14
+ optimized?: boolean;
15
+ usePendingUTXO?: boolean;
15
16
  }
16
17
 
17
18
  export interface FetchUTXOParamsMultiAddress {
@@ -19,6 +20,7 @@ export interface FetchUTXOParamsMultiAddress {
19
20
  readonly minAmount: bigint;
20
21
  readonly requestedAmount: bigint;
21
22
  readonly optimized?: boolean;
23
+ readonly usePendingUTXO?: boolean;
22
24
  }
23
25
 
24
26
  export interface RawUTXOResponse {