@btc-vision/transaction 1.0.106 → 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 (44) 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 +3 -3
  7. package/browser/transaction/builders/UnwrapSegwitTransaction.d.ts +1 -1
  8. package/browser/transaction/builders/UnwrapTransaction.d.ts +1 -1
  9. package/browser/transaction/processor/PsbtTransaction.d.ts +1 -1
  10. package/browser/transaction/shared/TweakedTransaction.d.ts +2 -1
  11. package/browser/utxo/interfaces/IUTXO.d.ts +1 -0
  12. package/build/_version.d.ts +1 -1
  13. package/build/_version.js +1 -1
  14. package/build/keypair/EcKeyPair.d.ts +4 -4
  15. package/build/transaction/builders/CustomScriptTransaction.js +1 -4
  16. package/build/transaction/builders/MultiSignTransaction.d.ts +1 -1
  17. package/build/transaction/builders/MultiSignTransaction.js +2 -2
  18. package/build/transaction/builders/SharedInteractionTransaction.d.ts +1 -0
  19. package/build/transaction/builders/SharedInteractionTransaction.js +43 -31
  20. package/build/transaction/builders/TransactionBuilder.d.ts +3 -3
  21. package/build/transaction/builders/TransactionBuilder.js +4 -4
  22. package/build/transaction/builders/UnwrapSegwitTransaction.d.ts +1 -1
  23. package/build/transaction/builders/UnwrapSegwitTransaction.js +2 -3
  24. package/build/transaction/builders/UnwrapTransaction.d.ts +1 -1
  25. package/build/transaction/builders/UnwrapTransaction.js +2 -2
  26. package/build/transaction/processor/PsbtTransaction.d.ts +1 -1
  27. package/build/transaction/processor/PsbtTransaction.js +2 -2
  28. package/build/transaction/shared/TweakedTransaction.d.ts +2 -1
  29. package/build/transaction/shared/TweakedTransaction.js +30 -10
  30. package/build/utxo/OPNetLimitedProvider.js +1 -1
  31. package/build/utxo/interfaces/IUTXO.d.ts +1 -0
  32. package/package.json +1 -1
  33. package/src/_version.ts +1 -1
  34. package/src/keypair/EcKeyPair.ts +4 -4
  35. package/src/transaction/builders/CustomScriptTransaction.ts +3 -7
  36. package/src/transaction/builders/MultiSignTransaction.ts +3 -2
  37. package/src/transaction/builders/SharedInteractionTransaction.ts +61 -34
  38. package/src/transaction/builders/TransactionBuilder.ts +17 -11
  39. package/src/transaction/builders/UnwrapSegwitTransaction.ts +5 -5
  40. package/src/transaction/builders/UnwrapTransaction.ts +6 -2
  41. package/src/transaction/processor/PsbtTransaction.ts +2 -2
  42. package/src/transaction/shared/TweakedTransaction.ts +38 -10
  43. package/src/utxo/OPNetLimitedProvider.ts +1 -1
  44. package/src/utxo/interfaces/IUTXO.ts +1 -0
@@ -185,44 +185,37 @@ export abstract class SharedInteractionTransaction<
185
185
  return;
186
186
  }
187
187
 
188
- for (let i = 0; i < transaction.data.inputs.length; i++) {
189
- const input: PsbtInput = transaction.data.inputs[i];
190
- let finalized: boolean = false;
191
- let signed: boolean = false;
188
+ const txs: PsbtInput[] = transaction.data.inputs;
189
+ for (let i = 0; i < txs.length; i += 20) {
190
+ const batch = txs.slice(i, i + 20);
192
191
 
193
- try {
194
- await this.signInput(transaction, input, i, this.scriptSigner);
195
- signed = true;
196
- } catch (e) {}
197
-
198
- try {
199
- await this.signInput(transaction, input, i);
200
- signed = true;
201
- } catch (e) {}
192
+ const promises: Promise<void>[] = [];
193
+ for (let y = 0; y < batch.length; y++) {
194
+ const offset = i * 20 + y;
195
+ const input = batch[y];
202
196
 
203
- try {
204
- transaction.finalizeInput(0, this.customFinalizer);
205
- finalized = true;
206
- } catch (e) {}
197
+ promises.push(this.signIndividualInputs(transaction, input, offset));
198
+ }
207
199
 
208
- try {
209
- transaction.finalizeInput(i);
210
- finalized = true;
211
- } catch (e) {}
200
+ await Promise.all(promises).catch((e: unknown) => {
201
+ throw e;
202
+ });
203
+ }
212
204
 
213
- if (signed || finalized) {
214
- this.log(
215
- `Signed input or finalized input #${i} out of ${transaction.data.inputs.length}! {Signed: ${signed}, Finalized: ${finalized}}`,
216
- );
205
+ try {
206
+ transaction.finalizeInput(0, this.customFinalizer);
217
207
 
218
- continue;
219
- }
208
+ this.log(`Finalized input 0!`);
209
+ } catch (e) {
210
+ console.log(`Failed to finalize input 0: ${(e as Error).stack}`);
211
+ }
220
212
 
221
- if (this.regenerated || this.ignoreSignatureErrors) {
222
- continue;
223
- }
213
+ for (let i = 0; i < txs.length; i++) {
214
+ try {
215
+ transaction.finalizeInput(i);
224
216
 
225
- throw new Error('Failed to sign input');
217
+ this.log(`Finalized input ${i}!`);
218
+ } catch {}
226
219
  }
227
220
  }
228
221
 
@@ -310,9 +303,11 @@ export abstract class SharedInteractionTransaction<
310
303
  throw new Error('Tap leaf script is required');
311
304
  }
312
305
 
313
- if (!input.tapScriptSig) {
314
- throw new Error('Tap script signature is required');
315
- }
306
+ //console.log('finalizing input', input);
307
+
308
+ //if (!input.tapLeafScript) {
309
+ // throw new Error('Tap script signature is required');
310
+ //}
316
311
 
317
312
  if (!this.contractSecret) {
318
313
  throw new Error('Contract secret is required');
@@ -328,6 +323,38 @@ export abstract class SharedInteractionTransaction<
328
323
  };
329
324
  };
330
325
 
326
+ private async signIndividualInputs(
327
+ transaction: Psbt,
328
+ input: PsbtInput,
329
+ i: number,
330
+ ): Promise<void> {
331
+ let signed: boolean = false;
332
+
333
+ try {
334
+ await this.signInput(transaction, input, i, this.scriptSigner);
335
+ signed = true;
336
+ } catch {}
337
+
338
+ try {
339
+ await this.signInput(transaction, input, i);
340
+ signed = true;
341
+ } catch {}
342
+
343
+ if (signed) {
344
+ this.log(
345
+ `Signed input #${i} out of ${transaction.data.inputs.length}! {Signed: ${signed}}`,
346
+ );
347
+
348
+ return;
349
+ }
350
+
351
+ if (this.regenerated || this.ignoreSignatureErrors) {
352
+ return;
353
+ }
354
+
355
+ throw new Error('Failed to sign input');
356
+ }
357
+
331
358
  /**
332
359
  * Get the public keys
333
360
  * @private
@@ -47,6 +47,11 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
47
47
  * @description The estimated fees of the transaction
48
48
  */
49
49
  public estimatedFees: bigint = 0n;
50
+ /**
51
+ * @param {ITransactionParameters} parameters - The transaction parameters
52
+ */
53
+
54
+ public optionalOutputs: PsbtOutputExtended[] | undefined;
50
55
  /**
51
56
  * @description The transaction itself.
52
57
  */
@@ -102,12 +107,6 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
102
107
  */
103
108
  protected _maximumFeeRate: number = 100000000;
104
109
 
105
- /**
106
- * @param {ITransactionParameters} parameters - The transaction parameters
107
- */
108
-
109
- public optionalOutputs: PsbtOutputExtended[] | undefined;
110
-
111
110
  protected constructor(parameters: ITransactionParameters) {
112
111
  super(parameters);
113
112
 
@@ -259,7 +258,9 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
259
258
  * @description Generates the transaction minimal signatures
260
259
  * @public
261
260
  */
262
- public async generateTransactionMinimalSignatures(): Promise<void> {
261
+ public async generateTransactionMinimalSignatures(
262
+ checkPartialSigs: boolean = false,
263
+ ): Promise<void> {
263
264
  if (this.to && !EcKeyPair.verifyContractAddress(this.to, this.network)) {
264
265
  throw new Error(
265
266
  'Invalid contract address. The contract address must be a taproot address.',
@@ -273,7 +274,7 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
273
274
  const outputs: PsbtOutputExtended[] = this.getOutputs();
274
275
 
275
276
  this.transaction.setMaximumFeeRate(this._maximumFeeRate);
276
- this.transaction.addInputs(inputs);
277
+ this.transaction.addInputs(inputs, checkPartialSigs);
277
278
 
278
279
  for (let i = 0; i < this.updateInputs.length; i++) {
279
280
  this.transaction.updateInput(i, this.updateInputs[i]);
@@ -364,7 +365,7 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
364
365
  const fee: number = this.feeRate * size;
365
366
 
366
367
  this.estimatedFees = BigInt(Math.ceil(fee) + 1);
367
-
368
+
368
369
  return this.estimatedFees;
369
370
  } else {
370
371
  throw new Error(
@@ -501,6 +502,7 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
501
502
 
502
503
  return total;
503
504
  }
505
+
504
506
  /**
505
507
  * @description Adds optional outputs to transaction and returns their total value in satoshi to calculate refund transaction
506
508
  * @protected
@@ -655,17 +657,21 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
655
657
  /**
656
658
  * Builds the transaction.
657
659
  * @param {Psbt} transaction - The transaction to build
660
+ * @param checkPartialSigs
658
661
  * @protected
659
662
  * @returns {Promise<boolean>}
660
663
  * @throws {Error} - If something went wrong while building the transaction
661
664
  */
662
- protected async internalBuildTransaction(transaction: Psbt): Promise<boolean> {
665
+ protected async internalBuildTransaction(
666
+ transaction: Psbt,
667
+ checkPartialSigs: boolean = false,
668
+ ): Promise<boolean> {
663
669
  if (transaction.data.inputs.length === 0) {
664
670
  const inputs: PsbtInputExtended[] = this.getInputs();
665
671
  const outputs: PsbtOutputExtended[] = this.getOutputs();
666
672
 
667
673
  transaction.setMaximumFeeRate(this._maximumFeeRate);
668
- transaction.addInputs(inputs);
674
+ transaction.addInputs(inputs, checkPartialSigs);
669
675
 
670
676
  for (let i = 0; i < this.updateInputs.length; i++) {
671
677
  transaction.updateInput(i, this.updateInputs[i]);
@@ -196,13 +196,13 @@ export class UnwrapSegwitTransaction extends SharedInteractionTransaction<Transa
196
196
  * @returns {Promise<boolean>}
197
197
  * @throws {Error} - If something went wrong while building the transaction
198
198
  */
199
- protected async internalBuildTransaction(transaction: Psbt): Promise<boolean> {
199
+ protected async internalBuildTransaction(transaction: Psbt, checkPartialSigs: boolean = false): Promise<boolean> {
200
200
  if (transaction.data.inputs.length === 0) {
201
201
  const inputs: PsbtInputExtended[] = this.getInputs();
202
202
  const outputs: PsbtOutputExtended[] = this.getOutputs();
203
203
 
204
204
  transaction.setMaximumFeeRate(this._maximumFeeRate);
205
- transaction.addInputs(inputs);
205
+ transaction.addInputs(inputs, checkPartialSigs);
206
206
 
207
207
  for (let i = 0; i < this.updateInputs.length; i++) {
208
208
  transaction.updateInput(i, this.updateInputs[i]);
@@ -313,9 +313,9 @@ export class UnwrapSegwitTransaction extends SharedInteractionTransaction<Transa
313
313
  this.addVaultUTXO(utxo, p2wshOutput);
314
314
 
315
315
  if (firstSigner) {
316
- this.log(
317
- `Signing input ${inputIndex} with ${firstSigner.publicKey.toString('hex')}`,
318
- );
316
+ //this.log(
317
+ // `Signing input ${inputIndex} with ${firstSigner.publicKey.toString('hex')}`,
318
+ //);
319
319
 
320
320
  // we don't care if we fail to sign the input
321
321
  try {
@@ -381,17 +381,21 @@ export class UnwrapTransaction extends SharedInteractionTransaction<TransactionT
381
381
  /**
382
382
  * Builds the transaction.
383
383
  * @param {Psbt} transaction - The transaction to build
384
+ * @param checkPartialSigs
384
385
  * @protected
385
386
  * @returns {Promise<boolean>}
386
387
  * @throws {Error} - If something went wrong while building the transaction
387
388
  */
388
- protected async internalBuildTransaction(transaction: Psbt): Promise<boolean> {
389
+ protected async internalBuildTransaction(
390
+ transaction: Psbt,
391
+ checkPartialSigs: boolean = false,
392
+ ): Promise<boolean> {
389
393
  if (transaction.data.inputs.length === 0) {
390
394
  const inputs: PsbtInputExtended[] = this.getInputs();
391
395
  const outputs: PsbtOutputExtended[] = this.getOutputs();
392
396
 
393
397
  transaction.setMaximumFeeRate(this._maximumFeeRate);
394
- transaction.addInputs(inputs);
398
+ transaction.addInputs(inputs, checkPartialSigs);
395
399
 
396
400
  for (let i = 0; i < this.updateInputs.length; i++) {
397
401
  transaction.updateInput(i, this.updateInputs[i]);
@@ -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 {
@@ -132,7 +132,7 @@ export class OPNetLimitedProvider {
132
132
  minAmount: settings.minAmount,
133
133
  requestedAmount: settings.requestedAmount,
134
134
  optimized: settings.optimized,
135
- usePendingUTXO: false,
135
+ usePendingUTXO: settings.usePendingUTXO,
136
136
  };
137
137
 
138
138
  const promise = this.fetchUTXO(params).catch(() => {
@@ -20,6 +20,7 @@ export interface FetchUTXOParamsMultiAddress {
20
20
  readonly minAmount: bigint;
21
21
  readonly requestedAmount: bigint;
22
22
  readonly optimized?: boolean;
23
+ readonly usePendingUTXO?: boolean;
23
24
  }
24
25
 
25
26
  export interface RawUTXOResponse {