@btc-vision/transaction 1.7.19 → 1.7.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.
- package/.babelrc +10 -1
- package/LICENSE +190 -21
- package/README.md +1 -1
- package/browser/_version.d.ts +1 -1
- package/browser/bip39.js +204 -0
- package/browser/bitcoin-utils.js +3172 -0
- package/browser/btc-vision-bip32.js +805 -0
- package/browser/btc-vision-bitcoin.js +4179 -0
- package/browser/btc-vision-logger.js +273 -0
- package/browser/btc-vision-post-quantum.js +542 -0
- package/browser/chain/ChainData.d.ts +1 -1
- package/browser/crypto/crypto.d.ts +1 -1
- package/browser/generators/AddressGenerator.d.ts +1 -1
- package/browser/generators/Generator.d.ts +1 -1
- package/browser/generators/MLDSAData.d.ts +1 -1
- package/browser/generators/builders/CalldataGenerator.d.ts +1 -1
- package/browser/generators/builders/CustomGenerator.d.ts +1 -1
- package/browser/generators/builders/DeploymentGenerator.d.ts +1 -1
- package/browser/generators/builders/HashCommitmentGenerator.d.ts +49 -0
- package/browser/generators/builders/LegacyCalldataGenerator.d.ts +1 -1
- package/browser/generators/builders/P2WDAGenerator.d.ts +1 -1
- package/browser/index.js +10775 -2
- package/browser/keypair/Address.d.ts +5 -3
- package/browser/keypair/AddressVerificator.d.ts +2 -2
- package/browser/keypair/EcKeyPair.d.ts +2 -2
- package/browser/keypair/MessageSigner.d.ts +2 -2
- package/browser/keypair/Wallet.d.ts +2 -2
- package/browser/metadata/ContractBaseMetadata.d.ts +1 -1
- package/browser/mnemonic/Mnemonic.d.ts +2 -2
- package/browser/noble-curves.js +3316 -0
- package/browser/noble-hashes.js +1608 -0
- package/browser/opnet.d.ts +15 -2
- package/browser/p2wda/P2WDADetector.d.ts +2 -2
- package/browser/polyfills.js +4590 -0
- package/browser/scure-base.js +410 -0
- package/browser/signer/AddressRotation.d.ts +12 -0
- package/browser/signer/SignerUtils.d.ts +1 -1
- package/browser/signer/TweakedSigner.d.ts +1 -1
- package/browser/transaction/TransactionFactory.d.ts +15 -1
- package/browser/transaction/browser/BrowserSignerBase.d.ts +1 -1
- package/browser/transaction/browser/Web3Provider.d.ts +1 -1
- package/browser/transaction/browser/extensions/UnisatSigner.d.ts +1 -1
- package/browser/transaction/browser/extensions/XverseSigner.d.ts +1 -1
- package/browser/transaction/builders/CancelTransaction.d.ts +1 -1
- package/browser/transaction/builders/ConsolidatedInteractionTransaction.d.ts +44 -0
- package/browser/transaction/builders/CustomScriptTransaction.d.ts +1 -1
- package/browser/transaction/builders/DeploymentTransaction.d.ts +1 -1
- package/browser/transaction/builders/FundingTransaction.d.ts +1 -1
- package/browser/transaction/builders/InteractionTransaction.d.ts +1 -1
- package/browser/transaction/builders/InteractionTransactionP2WDA.d.ts +2 -2
- package/browser/transaction/builders/MultiSignTransaction.d.ts +1 -1
- package/browser/transaction/builders/SharedInteractionTransaction.d.ts +1 -1
- package/browser/transaction/builders/TransactionBuilder.d.ts +1 -1
- package/browser/transaction/enums/TransactionType.d.ts +3 -1
- package/browser/transaction/interfaces/IConsolidatedTransactionParameters.d.ts +31 -0
- package/browser/transaction/interfaces/ITransactionParameters.d.ts +3 -1
- package/browser/transaction/interfaces/Tap.d.ts +1 -1
- package/browser/transaction/mineable/TimelockGenerator.d.ts +1 -1
- package/browser/transaction/offline/OfflineTransactionManager.d.ts +69 -0
- package/browser/transaction/offline/TransactionReconstructor.d.ts +28 -0
- package/browser/transaction/offline/TransactionSerializer.d.ts +50 -0
- package/browser/transaction/offline/TransactionStateCapture.d.ts +52 -0
- package/browser/transaction/offline/interfaces/ISerializableState.d.ts +62 -0
- package/browser/transaction/offline/interfaces/ITypeSpecificData.d.ts +62 -0
- package/browser/transaction/processor/PsbtTransaction.d.ts +1 -1
- package/browser/transaction/shared/P2TR_MS.d.ts +1 -1
- package/browser/transaction/shared/TweakedTransaction.d.ts +15 -4
- package/browser/utxo/OPNetLimitedProvider.d.ts +1 -1
- package/browser/utxo/interfaces/IUTXO.d.ts +2 -0
- package/browser/valibot.js +4948 -0
- package/browser/vendors.js +12913 -0
- package/browser/verification/TapscriptVerificator.d.ts +1 -1
- package/build/_version.d.ts +1 -1
- package/build/_version.js +1 -1
- package/build/generators/builders/HashCommitmentGenerator.d.ts +49 -0
- package/build/generators/builders/HashCommitmentGenerator.js +229 -0
- package/build/keypair/Address.d.ts +3 -1
- package/build/keypair/Address.js +87 -54
- package/build/opnet.d.ts +14 -1
- package/build/opnet.js +11 -1
- package/build/signer/AddressRotation.d.ts +12 -0
- package/build/signer/AddressRotation.js +16 -0
- package/build/transaction/TransactionFactory.d.ts +14 -0
- package/build/transaction/TransactionFactory.js +36 -0
- package/build/transaction/builders/ConsolidatedInteractionTransaction.d.ts +44 -0
- package/build/transaction/builders/ConsolidatedInteractionTransaction.js +259 -0
- package/build/transaction/builders/TransactionBuilder.js +2 -0
- package/build/transaction/enums/TransactionType.d.ts +3 -1
- package/build/transaction/enums/TransactionType.js +2 -0
- package/build/transaction/interfaces/IConsolidatedTransactionParameters.d.ts +31 -0
- package/build/transaction/interfaces/IConsolidatedTransactionParameters.js +1 -0
- package/build/transaction/interfaces/ITransactionParameters.d.ts +2 -0
- package/build/transaction/offline/OfflineTransactionManager.d.ts +69 -0
- package/build/transaction/offline/OfflineTransactionManager.js +255 -0
- package/build/transaction/offline/TransactionReconstructor.d.ts +28 -0
- package/build/transaction/offline/TransactionReconstructor.js +243 -0
- package/build/transaction/offline/TransactionSerializer.d.ts +50 -0
- package/build/transaction/offline/TransactionSerializer.js +700 -0
- package/build/transaction/offline/TransactionStateCapture.d.ts +52 -0
- package/build/transaction/offline/TransactionStateCapture.js +275 -0
- package/build/transaction/offline/interfaces/ISerializableState.d.ts +62 -0
- package/build/transaction/offline/interfaces/ISerializableState.js +2 -0
- package/build/transaction/offline/interfaces/ITypeSpecificData.d.ts +62 -0
- package/build/transaction/offline/interfaces/ITypeSpecificData.js +19 -0
- package/build/transaction/shared/TweakedTransaction.d.ts +12 -1
- package/build/transaction/shared/TweakedTransaction.js +75 -8
- package/build/utxo/interfaces/IUTXO.d.ts +2 -0
- package/documentation/README.md +5 -0
- package/documentation/offline-transaction-signing.md +650 -0
- package/documentation/transaction-building.md +603 -0
- package/package.json +62 -4
- package/src/_version.ts +1 -1
- package/src/generators/builders/HashCommitmentGenerator.ts +495 -0
- package/src/keypair/Address.ts +123 -70
- package/src/opnet.ts +16 -1
- package/src/signer/AddressRotation.ts +72 -0
- package/src/transaction/TransactionFactory.ts +87 -0
- package/src/transaction/builders/CancelTransaction.ts +4 -2
- package/src/transaction/builders/ConsolidatedInteractionTransaction.ts +561 -0
- package/src/transaction/builders/CustomScriptTransaction.ts +4 -2
- package/src/transaction/builders/MultiSignTransaction.ts +4 -2
- package/src/transaction/builders/TransactionBuilder.ts +8 -2
- package/src/transaction/enums/TransactionType.ts +2 -0
- package/src/transaction/interfaces/IConsolidatedTransactionParameters.ts +78 -0
- package/src/transaction/interfaces/ITransactionParameters.ts +8 -0
- package/src/transaction/offline/OfflineTransactionManager.ts +630 -0
- package/src/transaction/offline/TransactionReconstructor.ts +402 -0
- package/src/transaction/offline/TransactionSerializer.ts +920 -0
- package/src/transaction/offline/TransactionStateCapture.ts +469 -0
- package/src/transaction/offline/interfaces/ISerializableState.ts +141 -0
- package/src/transaction/offline/interfaces/ITypeSpecificData.ts +172 -0
- package/src/transaction/shared/TweakedTransaction.ts +156 -9
- package/src/utxo/interfaces/IUTXO.ts +8 -0
- package/test/address-rotation.test.ts +553 -0
- package/test/offline-transaction.test.ts +2065 -0
- package/vite.config.browser.ts +92 -0
- package/webpack.config.js +143 -2
- package/browser/crypto/crypto-browser.d.ts +0 -11
- package/browser/index.js.LICENSE.txt +0 -29
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
import { Network, networks, PsbtOutputExtended, Signer, Stack } from '@btc-vision/bitcoin';
|
|
2
|
+
import { ECPairInterface } from 'ecpair';
|
|
3
|
+
import { QuantumBIP32Interface } from '@btc-vision/bip32';
|
|
4
|
+
import { UTXO } from '../../utxo/interfaces/IUTXO.js';
|
|
5
|
+
import { AddressRotationConfig, SignerMap } from '../../signer/AddressRotation.js';
|
|
6
|
+
import { ChallengeSolution } from '../../epoch/ChallengeSolution.js';
|
|
7
|
+
import { TransactionType } from '../enums/TransactionType.js';
|
|
8
|
+
import { TransactionBuilder } from '../builders/TransactionBuilder.js';
|
|
9
|
+
import { FundingTransaction } from '../builders/FundingTransaction.js';
|
|
10
|
+
import { DeploymentTransaction } from '../builders/DeploymentTransaction.js';
|
|
11
|
+
import { InteractionTransaction } from '../builders/InteractionTransaction.js';
|
|
12
|
+
import { MultiSignTransaction } from '../builders/MultiSignTransaction.js';
|
|
13
|
+
import { CustomScriptTransaction } from '../builders/CustomScriptTransaction.js';
|
|
14
|
+
import { CancelTransaction } from '../builders/CancelTransaction.js';
|
|
15
|
+
import { ISerializableTransactionState, SerializedOutput, SerializedUTXO, } from './interfaces/ISerializableState.js';
|
|
16
|
+
import {
|
|
17
|
+
CancelSpecificData,
|
|
18
|
+
CustomScriptSpecificData,
|
|
19
|
+
DeploymentSpecificData,
|
|
20
|
+
FundingSpecificData,
|
|
21
|
+
InteractionSpecificData,
|
|
22
|
+
isCancelSpecificData,
|
|
23
|
+
isCustomScriptSpecificData,
|
|
24
|
+
isDeploymentSpecificData,
|
|
25
|
+
isFundingSpecificData,
|
|
26
|
+
isInteractionSpecificData,
|
|
27
|
+
isMultiSigSpecificData,
|
|
28
|
+
MultiSigSpecificData,
|
|
29
|
+
} from './interfaces/ITypeSpecificData.js';
|
|
30
|
+
import {
|
|
31
|
+
IDeploymentParameters,
|
|
32
|
+
IFundingTransactionParameters,
|
|
33
|
+
IInteractionParameters,
|
|
34
|
+
ITransactionParameters,
|
|
35
|
+
} from '../interfaces/ITransactionParameters.js';
|
|
36
|
+
import { SupportedTransactionVersion } from '../shared/TweakedTransaction.js';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Options for reconstructing a transaction from serialized state
|
|
40
|
+
*/
|
|
41
|
+
export interface ReconstructionOptions {
|
|
42
|
+
/** Primary signer (used for normal mode or as default in rotation mode) */
|
|
43
|
+
signer: Signer | ECPairInterface;
|
|
44
|
+
|
|
45
|
+
/** Optional: Override fee rate for fee bumping */
|
|
46
|
+
newFeeRate?: number;
|
|
47
|
+
|
|
48
|
+
/** Optional: Override priority fee */
|
|
49
|
+
newPriorityFee?: bigint;
|
|
50
|
+
|
|
51
|
+
/** Optional: Override gas sat fee */
|
|
52
|
+
newGasSatFee?: bigint;
|
|
53
|
+
|
|
54
|
+
/** Signer map for address rotation mode (keyed by address) */
|
|
55
|
+
signerMap?: SignerMap;
|
|
56
|
+
|
|
57
|
+
/** MLDSA signer (for quantum-resistant features) */
|
|
58
|
+
mldsaSigner?: QuantumBIP32Interface | null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Reconstructs transaction builders from serialized state.
|
|
63
|
+
* Supports fee bumping by allowing parameter overrides during reconstruction.
|
|
64
|
+
*/
|
|
65
|
+
export class TransactionReconstructor {
|
|
66
|
+
/**
|
|
67
|
+
* Reconstruct and optionally rebuild transaction with new parameters
|
|
68
|
+
* @param state - Serialized transaction state
|
|
69
|
+
* @param options - Signer(s) and optional fee overrides
|
|
70
|
+
* @returns Reconstructed transaction builder ready for signing
|
|
71
|
+
*/
|
|
72
|
+
public static reconstruct(
|
|
73
|
+
state: ISerializableTransactionState,
|
|
74
|
+
options: ReconstructionOptions,
|
|
75
|
+
): TransactionBuilder<TransactionType> {
|
|
76
|
+
const network = this.nameToNetwork(state.baseParams.networkName);
|
|
77
|
+
const utxos = this.deserializeUTXOs(state.utxos);
|
|
78
|
+
const optionalInputs = this.deserializeUTXOs(state.optionalInputs);
|
|
79
|
+
const optionalOutputs = this.deserializeOutputs(state.optionalOutputs);
|
|
80
|
+
|
|
81
|
+
// Build address rotation config
|
|
82
|
+
const addressRotation = this.buildAddressRotationConfig(
|
|
83
|
+
state.addressRotationEnabled,
|
|
84
|
+
options.signerMap,
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
// Apply fee overrides
|
|
88
|
+
const feeRate = options.newFeeRate ?? state.baseParams.feeRate;
|
|
89
|
+
const priorityFee = options.newPriorityFee ?? BigInt(state.baseParams.priorityFee);
|
|
90
|
+
const gasSatFee = options.newGasSatFee ?? BigInt(state.baseParams.gasSatFee);
|
|
91
|
+
|
|
92
|
+
// Build base params
|
|
93
|
+
const baseParams: ITransactionParameters = {
|
|
94
|
+
signer: options.signer,
|
|
95
|
+
mldsaSigner: options.mldsaSigner ?? null,
|
|
96
|
+
network,
|
|
97
|
+
chainId: state.header.chainId,
|
|
98
|
+
utxos,
|
|
99
|
+
optionalInputs,
|
|
100
|
+
optionalOutputs,
|
|
101
|
+
from: state.baseParams.from,
|
|
102
|
+
to: state.baseParams.to,
|
|
103
|
+
feeRate,
|
|
104
|
+
priorityFee,
|
|
105
|
+
gasSatFee,
|
|
106
|
+
txVersion: state.baseParams.txVersion as SupportedTransactionVersion,
|
|
107
|
+
note: state.baseParams.note ? Buffer.from(state.baseParams.note, 'hex') : undefined,
|
|
108
|
+
anchor: state.baseParams.anchor,
|
|
109
|
+
debugFees: state.baseParams.debugFees,
|
|
110
|
+
addressRotation,
|
|
111
|
+
estimatedFees: state.precomputedData.estimatedFees
|
|
112
|
+
? BigInt(state.precomputedData.estimatedFees)
|
|
113
|
+
: undefined,
|
|
114
|
+
compiledTargetScript: state.precomputedData.compiledTargetScript
|
|
115
|
+
? Buffer.from(state.precomputedData.compiledTargetScript, 'hex')
|
|
116
|
+
: undefined,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Dispatch based on transaction type
|
|
120
|
+
const typeData = state.typeSpecificData;
|
|
121
|
+
|
|
122
|
+
if (isFundingSpecificData(typeData)) {
|
|
123
|
+
return this.reconstructFunding(baseParams, typeData);
|
|
124
|
+
} else if (isDeploymentSpecificData(typeData)) {
|
|
125
|
+
return this.reconstructDeployment(baseParams, typeData, state);
|
|
126
|
+
} else if (isInteractionSpecificData(typeData)) {
|
|
127
|
+
return this.reconstructInteraction(baseParams, typeData, state);
|
|
128
|
+
} else if (isMultiSigSpecificData(typeData)) {
|
|
129
|
+
return this.reconstructMultiSig(baseParams, typeData);
|
|
130
|
+
} else if (isCustomScriptSpecificData(typeData)) {
|
|
131
|
+
return this.reconstructCustomScript(baseParams, typeData, state);
|
|
132
|
+
} else if (isCancelSpecificData(typeData)) {
|
|
133
|
+
return this.reconstructCancel(baseParams, typeData);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
throw new Error(`Unsupported transaction type: ${state.header.transactionType}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Reconstruct a FundingTransaction
|
|
141
|
+
*/
|
|
142
|
+
private static reconstructFunding(
|
|
143
|
+
baseParams: ITransactionParameters,
|
|
144
|
+
data: FundingSpecificData,
|
|
145
|
+
): FundingTransaction {
|
|
146
|
+
const params: IFundingTransactionParameters = {
|
|
147
|
+
...baseParams,
|
|
148
|
+
amount: BigInt(data.amount),
|
|
149
|
+
splitInputsInto: data.splitInputsInto,
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
return new FundingTransaction(params);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Reconstruct a DeploymentTransaction
|
|
157
|
+
*/
|
|
158
|
+
private static reconstructDeployment(
|
|
159
|
+
baseParams: ITransactionParameters,
|
|
160
|
+
data: DeploymentSpecificData,
|
|
161
|
+
state: ISerializableTransactionState,
|
|
162
|
+
): DeploymentTransaction {
|
|
163
|
+
const challenge = new ChallengeSolution(data.challenge);
|
|
164
|
+
|
|
165
|
+
const params: IDeploymentParameters = {
|
|
166
|
+
...baseParams,
|
|
167
|
+
bytecode: Buffer.from(data.bytecode, 'hex'),
|
|
168
|
+
calldata: data.calldata ? Buffer.from(data.calldata, 'hex') : undefined,
|
|
169
|
+
challenge,
|
|
170
|
+
randomBytes: state.precomputedData.randomBytes
|
|
171
|
+
? Buffer.from(state.precomputedData.randomBytes, 'hex')
|
|
172
|
+
: undefined,
|
|
173
|
+
revealMLDSAPublicKey: data.revealMLDSAPublicKey,
|
|
174
|
+
linkMLDSAPublicKeyToAddress: data.linkMLDSAPublicKeyToAddress,
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
return new DeploymentTransaction(params);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Reconstruct an InteractionTransaction
|
|
182
|
+
*/
|
|
183
|
+
private static reconstructInteraction(
|
|
184
|
+
baseParams: ITransactionParameters,
|
|
185
|
+
data: InteractionSpecificData,
|
|
186
|
+
state: ISerializableTransactionState,
|
|
187
|
+
): InteractionTransaction {
|
|
188
|
+
const challenge = new ChallengeSolution(data.challenge);
|
|
189
|
+
|
|
190
|
+
if (!baseParams.to) {
|
|
191
|
+
throw new Error('InteractionTransaction requires a "to" address');
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const params: IInteractionParameters = {
|
|
195
|
+
...baseParams,
|
|
196
|
+
to: baseParams.to,
|
|
197
|
+
calldata: Buffer.from(data.calldata, 'hex'),
|
|
198
|
+
contract: data.contract,
|
|
199
|
+
challenge,
|
|
200
|
+
randomBytes: state.precomputedData.randomBytes
|
|
201
|
+
? Buffer.from(state.precomputedData.randomBytes, 'hex')
|
|
202
|
+
: undefined,
|
|
203
|
+
loadedStorage: data.loadedStorage,
|
|
204
|
+
isCancellation: data.isCancellation,
|
|
205
|
+
disableAutoRefund: data.disableAutoRefund,
|
|
206
|
+
revealMLDSAPublicKey: data.revealMLDSAPublicKey,
|
|
207
|
+
linkMLDSAPublicKeyToAddress: data.linkMLDSAPublicKeyToAddress,
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
return new InteractionTransaction(params);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Reconstruct a MultiSignTransaction
|
|
215
|
+
*/
|
|
216
|
+
private static reconstructMultiSig(
|
|
217
|
+
baseParams: ITransactionParameters,
|
|
218
|
+
data: MultiSigSpecificData,
|
|
219
|
+
): MultiSignTransaction {
|
|
220
|
+
const pubkeys = data.pubkeys.map((pk) => Buffer.from(pk, 'hex'));
|
|
221
|
+
|
|
222
|
+
// If there's an existing PSBT, use fromBase64 to preserve partial signatures
|
|
223
|
+
if (data.existingPsbtBase64) {
|
|
224
|
+
return MultiSignTransaction.fromBase64({
|
|
225
|
+
mldsaSigner: baseParams.mldsaSigner,
|
|
226
|
+
network: baseParams.network,
|
|
227
|
+
chainId: baseParams.chainId,
|
|
228
|
+
utxos: baseParams.utxos,
|
|
229
|
+
optionalInputs: baseParams.optionalInputs,
|
|
230
|
+
optionalOutputs: baseParams.optionalOutputs,
|
|
231
|
+
feeRate: baseParams.feeRate,
|
|
232
|
+
pubkeys,
|
|
233
|
+
minimumSignatures: data.minimumSignatures,
|
|
234
|
+
receiver: data.receiver,
|
|
235
|
+
requestedAmount: BigInt(data.requestedAmount),
|
|
236
|
+
refundVault: data.refundVault,
|
|
237
|
+
psbt: data.existingPsbtBase64,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// No existing PSBT - create fresh transaction
|
|
242
|
+
const params = {
|
|
243
|
+
mldsaSigner: baseParams.mldsaSigner,
|
|
244
|
+
network: baseParams.network,
|
|
245
|
+
chainId: baseParams.chainId,
|
|
246
|
+
utxos: baseParams.utxos,
|
|
247
|
+
optionalInputs: baseParams.optionalInputs,
|
|
248
|
+
optionalOutputs: baseParams.optionalOutputs,
|
|
249
|
+
feeRate: baseParams.feeRate,
|
|
250
|
+
pubkeys,
|
|
251
|
+
minimumSignatures: data.minimumSignatures,
|
|
252
|
+
receiver: data.receiver,
|
|
253
|
+
requestedAmount: BigInt(data.requestedAmount),
|
|
254
|
+
refundVault: data.refundVault,
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
return new MultiSignTransaction(params);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Reconstruct a CustomScriptTransaction
|
|
262
|
+
*/
|
|
263
|
+
private static reconstructCustomScript(
|
|
264
|
+
baseParams: ITransactionParameters,
|
|
265
|
+
data: CustomScriptSpecificData,
|
|
266
|
+
state: ISerializableTransactionState,
|
|
267
|
+
): CustomScriptTransaction {
|
|
268
|
+
// Convert serialized elements to (Buffer | Stack)[]
|
|
269
|
+
const scriptElements: (Buffer | Stack)[] = data.scriptElements.map((el) => {
|
|
270
|
+
if (el.elementType === 'buffer') {
|
|
271
|
+
return Buffer.from(el.value as string, 'hex');
|
|
272
|
+
}
|
|
273
|
+
// Opcodes stored as numbers - wrap in array for Stack type
|
|
274
|
+
return [el.value as number] as Stack;
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
const witnesses = data.witnesses.map((w) => Buffer.from(w, 'hex'));
|
|
278
|
+
const annex = data.annex ? Buffer.from(data.annex, 'hex') : undefined;
|
|
279
|
+
|
|
280
|
+
if (!baseParams.to) {
|
|
281
|
+
throw new Error('CustomScriptTransaction requires a "to" address');
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const params = {
|
|
285
|
+
...baseParams,
|
|
286
|
+
to: baseParams.to,
|
|
287
|
+
script: scriptElements,
|
|
288
|
+
witnesses,
|
|
289
|
+
annex,
|
|
290
|
+
randomBytes: state.precomputedData.randomBytes
|
|
291
|
+
? Buffer.from(state.precomputedData.randomBytes, 'hex')
|
|
292
|
+
: undefined,
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
return new CustomScriptTransaction(params);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Reconstruct a CancelTransaction
|
|
300
|
+
*/
|
|
301
|
+
private static reconstructCancel(
|
|
302
|
+
baseParams: ITransactionParameters,
|
|
303
|
+
data: CancelSpecificData,
|
|
304
|
+
): CancelTransaction {
|
|
305
|
+
const params = {
|
|
306
|
+
...baseParams,
|
|
307
|
+
compiledTargetScript: Buffer.from(data.compiledTargetScript, 'hex'),
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
return new CancelTransaction(params);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Build address rotation config from options
|
|
315
|
+
*/
|
|
316
|
+
private static buildAddressRotationConfig(
|
|
317
|
+
enabled: boolean,
|
|
318
|
+
signerMap?: SignerMap,
|
|
319
|
+
): AddressRotationConfig | undefined {
|
|
320
|
+
if (!enabled) {
|
|
321
|
+
return undefined;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (!signerMap || signerMap.size === 0) {
|
|
325
|
+
throw new Error(
|
|
326
|
+
'Address rotation enabled but no signerMap provided in reconstruction options',
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return {
|
|
331
|
+
enabled: true,
|
|
332
|
+
signerMap,
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Deserialize UTXOs from serialized format
|
|
338
|
+
*/
|
|
339
|
+
private static deserializeUTXOs(serialized: SerializedUTXO[]): UTXO[] {
|
|
340
|
+
return serialized.map((s) => ({
|
|
341
|
+
transactionId: s.transactionId,
|
|
342
|
+
outputIndex: s.outputIndex,
|
|
343
|
+
value: BigInt(s.value),
|
|
344
|
+
scriptPubKey: {
|
|
345
|
+
hex: s.scriptPubKeyHex,
|
|
346
|
+
address: s.scriptPubKeyAddress,
|
|
347
|
+
},
|
|
348
|
+
redeemScript: s.redeemScript ? Buffer.from(s.redeemScript, 'hex') : undefined,
|
|
349
|
+
witnessScript: s.witnessScript ? Buffer.from(s.witnessScript, 'hex') : undefined,
|
|
350
|
+
nonWitnessUtxo: s.nonWitnessUtxo ? Buffer.from(s.nonWitnessUtxo, 'hex') : undefined,
|
|
351
|
+
}));
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Deserialize outputs from serialized format
|
|
356
|
+
*/
|
|
357
|
+
private static deserializeOutputs(serialized: SerializedOutput[]): PsbtOutputExtended[] {
|
|
358
|
+
return serialized.map((s): PsbtOutputExtended => {
|
|
359
|
+
const tapInternalKey = s.tapInternalKey
|
|
360
|
+
? Buffer.from(s.tapInternalKey, 'hex')
|
|
361
|
+
: undefined;
|
|
362
|
+
|
|
363
|
+
// PsbtOutputExtended is a union type - either has address OR script, not both
|
|
364
|
+
if (s.address) {
|
|
365
|
+
return {
|
|
366
|
+
value: s.value,
|
|
367
|
+
address: s.address,
|
|
368
|
+
tapInternalKey,
|
|
369
|
+
};
|
|
370
|
+
} else if (s.script) {
|
|
371
|
+
return {
|
|
372
|
+
value: s.value,
|
|
373
|
+
script: Buffer.from(s.script, 'hex'),
|
|
374
|
+
tapInternalKey,
|
|
375
|
+
};
|
|
376
|
+
} else {
|
|
377
|
+
// Fallback - shouldn't happen with valid data
|
|
378
|
+
return {
|
|
379
|
+
value: s.value,
|
|
380
|
+
address: '',
|
|
381
|
+
tapInternalKey,
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Convert network name to Network object
|
|
389
|
+
*/
|
|
390
|
+
private static nameToNetwork(name: 'mainnet' | 'testnet' | 'regtest'): Network {
|
|
391
|
+
switch (name) {
|
|
392
|
+
case 'mainnet':
|
|
393
|
+
return networks.bitcoin;
|
|
394
|
+
case 'testnet':
|
|
395
|
+
return networks.testnet;
|
|
396
|
+
case 'regtest':
|
|
397
|
+
return networks.regtest;
|
|
398
|
+
default:
|
|
399
|
+
throw new Error(`Unknown network: ${name}`);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|