@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.
- package/browser/_version.d.ts +1 -1
- package/browser/index.js +1 -1
- package/browser/keypair/EcKeyPair.d.ts +4 -4
- package/browser/transaction/builders/MultiSignTransaction.d.ts +1 -1
- package/browser/transaction/builders/SharedInteractionTransaction.d.ts +1 -0
- package/browser/transaction/builders/TransactionBuilder.d.ts +4 -2
- package/browser/transaction/builders/UnwrapSegwitTransaction.d.ts +1 -1
- package/browser/transaction/builders/UnwrapTransaction.d.ts +1 -1
- package/browser/transaction/interfaces/ITransactionParameters.d.ts +9 -8
- package/browser/transaction/processor/PsbtTransaction.d.ts +1 -1
- package/browser/transaction/shared/TweakedTransaction.d.ts +2 -1
- package/browser/utxo/OPNetLimitedProvider.d.ts +11 -1
- package/browser/utxo/interfaces/IUTXO.d.ts +3 -1
- package/build/_version.d.ts +1 -1
- package/build/_version.js +1 -1
- package/build/keypair/EcKeyPair.d.ts +4 -4
- package/build/transaction/TransactionFactory.js +2 -1
- package/build/transaction/builders/CustomScriptTransaction.js +1 -4
- package/build/transaction/builders/MultiSignTransaction.d.ts +1 -1
- package/build/transaction/builders/MultiSignTransaction.js +2 -2
- package/build/transaction/builders/SharedInteractionTransaction.d.ts +1 -0
- package/build/transaction/builders/SharedInteractionTransaction.js +43 -31
- package/build/transaction/builders/TransactionBuilder.d.ts +4 -2
- package/build/transaction/builders/TransactionBuilder.js +17 -5
- package/build/transaction/builders/UnwrapSegwitTransaction.d.ts +1 -1
- package/build/transaction/builders/UnwrapSegwitTransaction.js +2 -3
- package/build/transaction/builders/UnwrapTransaction.d.ts +1 -1
- package/build/transaction/builders/UnwrapTransaction.js +2 -2
- package/build/transaction/interfaces/ITransactionParameters.d.ts +9 -8
- package/build/transaction/processor/PsbtTransaction.d.ts +1 -1
- package/build/transaction/processor/PsbtTransaction.js +2 -2
- package/build/transaction/shared/TweakedTransaction.d.ts +2 -1
- package/build/transaction/shared/TweakedTransaction.js +30 -10
- package/build/utxo/OPNetLimitedProvider.d.ts +11 -1
- package/build/utxo/OPNetLimitedProvider.js +49 -2
- package/build/utxo/interfaces/IUTXO.d.ts +3 -1
- package/eslint.config.js +0 -1
- package/package.json +2 -2
- package/src/_version.ts +1 -1
- package/src/keypair/EcKeyPair.ts +4 -4
- package/src/transaction/TransactionFactory.ts +3 -3
- package/src/transaction/builders/CustomScriptTransaction.ts +3 -7
- package/src/transaction/builders/MultiSignTransaction.ts +3 -2
- package/src/transaction/builders/SharedInteractionTransaction.ts +61 -34
- package/src/transaction/builders/TransactionBuilder.ts +38 -11
- package/src/transaction/builders/UnwrapSegwitTransaction.ts +5 -5
- package/src/transaction/builders/UnwrapTransaction.ts +6 -2
- package/src/transaction/interfaces/ITransactionParameters.ts +11 -9
- package/src/transaction/processor/PsbtTransaction.ts +2 -2
- package/src/transaction/shared/TweakedTransaction.ts +38 -10
- package/src/utxo/OPNetLimitedProvider.ts +86 -4
- 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
|
|
10
|
+
readonly to?: Address;
|
|
11
11
|
utxos: UTXO[];
|
|
12
12
|
|
|
13
|
-
nonWitnessUtxo?: Buffer
|
|
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
|
|
31
|
+
calldata?: Buffer;
|
|
30
32
|
disableAutoRefund?: boolean;
|
|
31
33
|
|
|
32
34
|
readonly randomBytes?: Buffer;
|
|
33
35
|
}
|
|
34
36
|
|
|
35
|
-
export interface IInteractionParameters
|
|
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(
|
|
112
|
+
public static readScriptWitnessToWitnessStack(Buffer: Buffer): Buffer[] {
|
|
113
113
|
let offset = 0;
|
|
114
114
|
|
|
115
115
|
function readSlice(n: number): Buffer {
|
|
116
|
-
const slice =
|
|
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(
|
|
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
|
-
|
|
432
|
-
|
|
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
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
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:
|
|
45
|
-
|
|
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[] =
|
|
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
|
-
|
|
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 {
|