@btc-vision/transaction 1.0.6 → 1.0.8
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/Deploy.md +186 -0
- package/README.md +5 -0
- package/Wrap.md +192 -0
- package/browser/_version.d.ts +1 -1
- package/browser/index.js +1 -1
- package/browser/index.js.LICENSE.txt +9 -0
- package/browser/opnet.d.ts +6 -1
- package/browser/tests/deploy.d.ts +1 -0
- package/browser/tests/wrap.d.ts +1 -0
- package/browser/tests/wrapTest.d.ts +1 -0
- package/browser/transaction/TransactionFactory.d.ts +15 -1
- package/browser/transaction/builders/DeploymentTransaction.d.ts +40 -0
- package/browser/transaction/builders/InteractionTransaction.d.ts +2 -35
- package/browser/transaction/builders/SharedInteractionTransaction.d.ts +46 -0
- package/browser/transaction/builders/TransactionBuilder.d.ts +8 -1
- package/browser/transaction/builders/WrapTransaction.d.ts +27 -0
- package/browser/transaction/interfaces/ITransactionParameters.d.ts +16 -12
- package/browser/utils/BitcoinUtils.d.ts +1 -0
- package/browser/utxo/OPNetLimitedProvider.d.ts +10 -0
- package/browser/wbtc/Generate.d.ts +13 -0
- package/browser/wbtc/WrappedGenerationParameters.d.ts +11 -0
- package/build/_version.d.ts +1 -1
- package/build/_version.js +1 -1
- package/build/bytecode/Compressor.js +4 -3
- package/build/generators/AddressGenerator.js +1 -1
- package/build/keypair/EcKeyPair.js +1 -1
- package/build/opnet.d.ts +6 -1
- package/build/opnet.js +6 -1
- package/build/signer/TweakedSigner.js +1 -1
- package/build/tests/deploy.d.ts +1 -0
- package/build/tests/deploy.js +60 -0
- package/build/tests/test.js +3 -3
- package/build/tests/transfer.js +2 -2
- package/build/tests/wrap.d.ts +1 -0
- package/build/tests/wrap.js +64 -0
- package/build/tests/wrapTest.d.ts +1 -0
- package/build/tests/wrapTest.js +64 -0
- package/build/tests/wrapTestg.d.ts +1 -0
- package/build/tests/wrapTestg.js +66 -0
- package/build/transaction/TransactionFactory.d.ts +15 -1
- package/build/transaction/TransactionFactory.js +68 -0
- package/build/transaction/builders/DeploymentTransaction.d.ts +40 -0
- package/build/transaction/builders/DeploymentTransaction.js +216 -0
- package/build/transaction/builders/FundingTransaction.js +4 -1
- package/build/transaction/builders/InteractionTransaction.d.ts +2 -35
- package/build/transaction/builders/InteractionTransaction.js +4 -207
- package/build/transaction/builders/SharedInteractionTransaction.d.ts +46 -0
- package/build/transaction/builders/SharedInteractionTransaction.js +213 -0
- package/build/transaction/builders/TransactionBuilder.d.ts +8 -1
- package/build/transaction/builders/TransactionBuilder.js +20 -12
- package/build/transaction/builders/WrapTransaction.d.ts +27 -0
- package/build/transaction/builders/WrapTransaction.js +132 -0
- package/build/transaction/interfaces/ITransactionParameters.d.ts +16 -12
- package/build/utils/BitcoinUtils.d.ts +1 -0
- package/build/utils/BitcoinUtils.js +7 -0
- package/build/utxo/OPNetLimitedProvider.d.ts +10 -0
- package/build/utxo/OPNetLimitedProvider.js +85 -0
- package/build/utxo/OPNetUtils.d.ts +7 -0
- package/build/utxo/OPNetUtils.js +47 -0
- package/build/verification/TapscriptVerificator.js +3 -3
- package/build/wbtc/Generate.d.ts +13 -0
- package/build/wbtc/Generate.js +1 -0
- package/build/wbtc/WrappedGenerationParameters.d.ts +11 -0
- package/build/wbtc/WrappedGenerationParameters.js +16 -0
- package/bytecode/contract.wasm +0 -0
- package/cjs/_version.d.ts +1 -1
- package/cjs/_version.js +1 -1
- package/cjs/bytecode/Compressor.js +1 -1
- package/cjs/generators/AddressGenerator.d.ts +7 -0
- package/cjs/generators/AddressGenerator.js +48 -0
- package/cjs/generators/Generator.d.ts +1 -2
- package/cjs/generators/Generator.js +1 -3
- package/cjs/generators/builders/DeploymentGenerator.d.ts +1 -0
- package/cjs/generators/builders/DeploymentGenerator.js +10 -7
- package/cjs/keypair/Wallet.d.ts +1 -0
- package/cjs/keypair/Wallet.js +6 -0
- package/cjs/opnet.d.ts +23 -0
- package/cjs/opnet.js +37 -0
- package/cjs/tests/Regtest.d.ts +3 -0
- package/cjs/tests/Regtest.js +32 -0
- package/cjs/tests/gen.d.ts +1 -0
- package/cjs/tests/gen.js +17 -0
- package/cjs/tests/test.d.ts +1 -0
- package/cjs/tests/test.js +53 -0
- package/cjs/tests/transfer.d.ts +1 -0
- package/cjs/tests/transfer.js +76 -0
- package/cjs/transaction/TransactionFactory.js +7 -4
- package/cjs/transaction/builders/FundingTransaction.js +1 -1
- package/cjs/transaction/builders/InteractionTransaction.d.ts +2 -0
- package/cjs/transaction/builders/InteractionTransaction.js +11 -2
- package/cjs/transaction/builders/TransactionBuilder.d.ts +3 -2
- package/cjs/transaction/builders/TransactionBuilder.js +22 -7
- package/cjs/transaction/interfaces/ITransactionParameters.d.ts +1 -0
- package/cjs/verification/TapscriptVerificator.d.ts +17 -0
- package/cjs/verification/TapscriptVerificator.js +70 -0
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/AddressGenerator.html +2 -2
- package/docs/classes/BitcoinUtils.html +7 -3
- package/docs/classes/CalldataGenerator.html +10 -10
- package/docs/classes/Compressor.html +4 -4
- package/docs/classes/ContractBaseMetadata.html +4 -4
- package/docs/classes/DeploymentGenerator.html +9 -9
- package/docs/classes/DeploymentTransaction.html +368 -0
- package/docs/classes/EcKeyPair.html +16 -16
- package/docs/classes/FundingTransaction.html +50 -47
- package/docs/classes/Generator.html +9 -9
- package/docs/classes/InteractionTransaction.html +89 -109
- package/docs/classes/OPNetLimitedProvider.html +197 -0
- package/docs/classes/SharedInteractionTransaction.html +392 -0
- package/docs/classes/TapscriptVerificator.html +2 -2
- package/docs/classes/TransactionBuilder.html +53 -50
- package/docs/classes/TransactionFactory.html +11 -4
- package/docs/classes/TweakedSigner.html +2 -2
- package/docs/classes/Wallet.html +10 -10
- package/docs/classes/WrapTransaction.html +404 -0
- package/docs/classes/WrappedGeneration.html +187 -0
- package/docs/classes/wBTC.html +7 -7
- package/docs/enums/TransactionSequence.html +177 -0
- package/docs/enums/TransactionType.html +2 -2
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +3 -1
- package/docs/interfaces/ContractAddressVerificationParams.html +2 -2
- package/docs/interfaces/DeploymentResult.html +177 -0
- package/docs/interfaces/FetchUTXOParams.html +2 -2
- package/docs/interfaces/GenerationConstraints.html +182 -0
- package/docs/interfaces/IDeploymentParameters.html +183 -0
- package/docs/interfaces/IFundingTransactionParameters.html +3 -3
- package/docs/interfaces/IInteractionParameters.html +4 -6
- package/docs/interfaces/ITransactionParameters.html +3 -3
- package/docs/interfaces/IWallet.html +4 -4
- package/docs/interfaces/IWrapParameters.html +186 -0
- package/docs/interfaces/NetworkInformation.html +2 -2
- package/docs/interfaces/PsbtInputExtended.html +1 -1
- package/docs/interfaces/PsbtOutputExtendedAddress.html +2 -2
- package/docs/interfaces/PsbtOutputExtendedScript.html +2 -2
- package/docs/interfaces/RawUTXOResponse.html +2 -2
- package/docs/interfaces/SharedInteractionParameters.html +183 -0
- package/docs/interfaces/TapLeafScript.html +2 -2
- package/docs/interfaces/TweakSettings.html +3 -3
- package/docs/interfaces/UTXO.html +2 -2
- package/docs/interfaces/UpdateInput.html +2 -2
- package/docs/interfaces/WrapResult.html +178 -0
- package/docs/interfaces/WrappedGenerationParameters.html +184 -0
- package/docs/modules.html +14 -4
- package/docs/types/PsbtOutputExtended.html +1 -1
- package/docs/variables/version.html +1 -1
- package/package.json +4 -5
- package/src/_version.ts +1 -1
- package/src/bytecode/Compressor.ts +27 -26
- package/src/generators/AddressGenerator.ts +1 -1
- package/src/keypair/EcKeyPair.ts +1 -1
- package/src/opnet.ts +8 -1
- package/src/signer/TweakedSigner.ts +1 -1
- package/src/tests/deploy.ts +81 -0
- package/src/tests/test.ts +3 -3
- package/src/tests/transfer.ts +2 -2
- package/src/tests/wrap.ts +89 -0
- package/src/tests/wrapTest.ts +88 -0
- package/src/transaction/TransactionFactory.ts +119 -1
- package/src/transaction/builders/DeploymentTransaction.ts +418 -0
- package/src/transaction/builders/FundingTransaction.ts +5 -1
- package/src/transaction/builders/InteractionTransaction.ts +5 -404
- package/src/transaction/builders/SharedInteractionTransaction.ts +432 -0
- package/src/transaction/builders/TransactionBuilder.ts +41 -16
- package/src/transaction/builders/WrapTransaction.ts +286 -0
- package/src/transaction/interfaces/ITransactionParameters.ts +20 -13
- package/src/utils/BitcoinUtils.ts +16 -0
- package/src/utxo/{UTXOManager.ts → OPNetLimitedProvider.ts} +53 -2
- package/src/verification/TapscriptVerificator.ts +3 -3
- package/src/wbtc/Generate.ts +30 -0
- package/src/wbtc/WrappedGenerationParameters.ts +33 -0
- package/tests/TransactionBuilder.test.ts +58 -58
- package/tsconfig.webpack.json +7 -1
- package/webpack.config.js +3 -1
- package/browser/873e754d6c7c6e9361f1.module.wasm +0 -0
- package/docs/classes/UTXOManager.html +0 -187
- package/docs/interfaces/ITransactionDataContractDeployment.html +0 -184
- package/docs/interfaces/ITransactionDataContractInteractionWrap.html +0 -186
|
@@ -1,219 +1,16 @@
|
|
|
1
|
-
import { address } from 'bitcoinjs-lib';
|
|
2
|
-
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
3
1
|
import { TransactionType } from '../enums/TransactionType.js';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
7
|
-
import { BitcoinUtils } from '../../utils/BitcoinUtils.js';
|
|
8
|
-
import { toXOnly } from 'bitcoinjs-lib/src/psbt/bip371.js';
|
|
9
|
-
import { TweakedSigner } from '../../signer/TweakedSigner.js';
|
|
10
|
-
export class InteractionTransaction extends TransactionBuilder {
|
|
2
|
+
import { SharedInteractionTransaction } from './SharedInteractionTransaction.js';
|
|
3
|
+
export class InteractionTransaction extends SharedInteractionTransaction {
|
|
11
4
|
type = TransactionType.INTERACTION;
|
|
12
|
-
randomBytes;
|
|
13
|
-
targetScriptRedeem = null;
|
|
14
|
-
leftOverFundsScriptRedeem = null;
|
|
15
5
|
compiledTargetScript;
|
|
16
6
|
scriptTree;
|
|
17
7
|
tapLeafScript = null;
|
|
18
|
-
|
|
19
|
-
calldata;
|
|
20
|
-
contractSecret = this.generateSecret();
|
|
21
|
-
tweakedSigner;
|
|
22
|
-
scriptSigner;
|
|
23
|
-
interactionPubKeys;
|
|
24
|
-
minimumSignatures;
|
|
8
|
+
contractSecret;
|
|
25
9
|
constructor(parameters) {
|
|
26
10
|
super(parameters);
|
|
27
|
-
|
|
28
|
-
throw new Error('Calldata is required');
|
|
29
|
-
}
|
|
30
|
-
this.calldata = Compressor.compress(parameters.calldata);
|
|
31
|
-
this.interactionPubKeys = parameters.pubKeys || [];
|
|
32
|
-
this.minimumSignatures = parameters.minimumSignatures || 0;
|
|
33
|
-
this.randomBytes = parameters.randomBytes || BitcoinUtils.rndBytes();
|
|
34
|
-
this.scriptSigner = this.generateKeyPairFromSeed();
|
|
35
|
-
this.calldataGenerator = new CalldataGenerator(this.internalPubKeyToXOnly(), this.scriptSignerXOnlyPubKey(), this.network);
|
|
11
|
+
this.contractSecret = this.generateSecret();
|
|
36
12
|
this.compiledTargetScript = this.calldataGenerator.compile(this.calldata, this.contractSecret, this.interactionPubKeys, this.minimumSignatures);
|
|
37
13
|
this.scriptTree = this.getScriptTree();
|
|
38
14
|
this.internalInit();
|
|
39
15
|
}
|
|
40
|
-
getContractSecret() {
|
|
41
|
-
return this.contractSecret;
|
|
42
|
-
}
|
|
43
|
-
getRndBytes() {
|
|
44
|
-
return this.randomBytes;
|
|
45
|
-
}
|
|
46
|
-
generateSecret() {
|
|
47
|
-
return address.fromBech32(this.to).data;
|
|
48
|
-
}
|
|
49
|
-
tweakSigner() {
|
|
50
|
-
this.tweakedSigner = this.getTweakedSigner();
|
|
51
|
-
}
|
|
52
|
-
scriptSignerXOnlyPubKey() {
|
|
53
|
-
return toXOnly(this.scriptSigner.publicKey);
|
|
54
|
-
}
|
|
55
|
-
generateKeyPairFromSeed() {
|
|
56
|
-
return EcKeyPair.fromSeedKeyPair(this.randomBytes, this.network);
|
|
57
|
-
}
|
|
58
|
-
addInputsFromUTXO() {
|
|
59
|
-
if (!this.tapLeafScript)
|
|
60
|
-
throw new Error('Tap leaf script is required');
|
|
61
|
-
for (let utxo of this.utxos) {
|
|
62
|
-
const input = {
|
|
63
|
-
hash: utxo.transactionId,
|
|
64
|
-
index: utxo.outputIndex,
|
|
65
|
-
witnessUtxo: {
|
|
66
|
-
value: Number(utxo.value),
|
|
67
|
-
script: this.getTapOutput(),
|
|
68
|
-
},
|
|
69
|
-
tapLeafScript: [this.tapLeafScript],
|
|
70
|
-
sequence: 0xfffffffd,
|
|
71
|
-
};
|
|
72
|
-
this.addInput(input);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
buildTransaction() {
|
|
76
|
-
const selectedRedeem = !!this.scriptSigner
|
|
77
|
-
? this.targetScriptRedeem
|
|
78
|
-
: this.leftOverFundsScriptRedeem;
|
|
79
|
-
if (!selectedRedeem) {
|
|
80
|
-
throw new Error('Left over funds script redeem is required');
|
|
81
|
-
}
|
|
82
|
-
if (!selectedRedeem.redeemVersion) {
|
|
83
|
-
throw new Error('Left over funds script redeem version is required');
|
|
84
|
-
}
|
|
85
|
-
if (!selectedRedeem.output) {
|
|
86
|
-
throw new Error('Left over funds script redeem output is required');
|
|
87
|
-
}
|
|
88
|
-
this.tapLeafScript = {
|
|
89
|
-
leafVersion: selectedRedeem.redeemVersion,
|
|
90
|
-
script: selectedRedeem.output,
|
|
91
|
-
controlBlock: this.getWitness(),
|
|
92
|
-
};
|
|
93
|
-
this.addInputsFromUTXO();
|
|
94
|
-
const amountSpent = this.getTransactionOPNetFee();
|
|
95
|
-
this.addOutput({
|
|
96
|
-
value: Number(amountSpent),
|
|
97
|
-
address: this.to,
|
|
98
|
-
});
|
|
99
|
-
this.addRefundOutput(amountSpent);
|
|
100
|
-
}
|
|
101
|
-
signInputs(transaction) {
|
|
102
|
-
if (!this.scriptSigner) {
|
|
103
|
-
super.signInputs(transaction);
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
transaction.signInput(0, this.scriptSigner);
|
|
107
|
-
transaction.signInput(0, this.getSignerKey());
|
|
108
|
-
transaction.finalizeInput(0, this.customFinalizer);
|
|
109
|
-
}
|
|
110
|
-
getSignerKey() {
|
|
111
|
-
if (this.tweakedSigner) {
|
|
112
|
-
return this.tweakedSigner;
|
|
113
|
-
}
|
|
114
|
-
return this.signer;
|
|
115
|
-
}
|
|
116
|
-
generateScriptAddress() {
|
|
117
|
-
return {
|
|
118
|
-
internalPubkey: this.internalPubKeyToXOnly(),
|
|
119
|
-
network: this.network,
|
|
120
|
-
scriptTree: this.scriptTree,
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
generateTapData() {
|
|
124
|
-
const selectedRedeem = !!this.scriptSigner
|
|
125
|
-
? this.targetScriptRedeem
|
|
126
|
-
: this.leftOverFundsScriptRedeem;
|
|
127
|
-
if (!selectedRedeem) {
|
|
128
|
-
throw new Error('Left over funds script redeem is required');
|
|
129
|
-
}
|
|
130
|
-
if (!this.scriptTree) {
|
|
131
|
-
throw new Error('Script tree is required');
|
|
132
|
-
}
|
|
133
|
-
return {
|
|
134
|
-
internalPubkey: this.internalPubKeyToXOnly(),
|
|
135
|
-
network: this.network,
|
|
136
|
-
scriptTree: this.scriptTree,
|
|
137
|
-
redeem: selectedRedeem,
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
getScriptSolution(input) {
|
|
141
|
-
if (!input.tapScriptSig) {
|
|
142
|
-
throw new Error('Tap script signature is required');
|
|
143
|
-
}
|
|
144
|
-
return [
|
|
145
|
-
this.contractSecret,
|
|
146
|
-
this.internalPubKeyToXOnly(),
|
|
147
|
-
input.tapScriptSig[0].signature,
|
|
148
|
-
input.tapScriptSig[1].signature,
|
|
149
|
-
];
|
|
150
|
-
}
|
|
151
|
-
getPubKeys() {
|
|
152
|
-
const pubkeys = [this.signer.publicKey];
|
|
153
|
-
if (this.scriptSigner) {
|
|
154
|
-
pubkeys.push(this.scriptSigner.publicKey);
|
|
155
|
-
}
|
|
156
|
-
return pubkeys;
|
|
157
|
-
}
|
|
158
|
-
customFinalizer = (_inputIndex, input) => {
|
|
159
|
-
if (!this.tapLeafScript) {
|
|
160
|
-
throw new Error('Tap leaf script is required');
|
|
161
|
-
}
|
|
162
|
-
if (!input.tapScriptSig) {
|
|
163
|
-
throw new Error('Tap script signature is required');
|
|
164
|
-
}
|
|
165
|
-
if (!this.contractSecret) {
|
|
166
|
-
throw new Error('Contract secret is required');
|
|
167
|
-
}
|
|
168
|
-
const scriptSolution = this.getScriptSolution(input);
|
|
169
|
-
const witness = scriptSolution
|
|
170
|
-
.concat(this.tapLeafScript.script)
|
|
171
|
-
.concat(this.tapLeafScript.controlBlock);
|
|
172
|
-
return {
|
|
173
|
-
finalScriptWitness: this.witnessStackToScriptWitness(witness),
|
|
174
|
-
};
|
|
175
|
-
};
|
|
176
|
-
getTweakerHash() {
|
|
177
|
-
return this.tapData?.hash;
|
|
178
|
-
}
|
|
179
|
-
getTweakedSigner(useTweakedHash = false) {
|
|
180
|
-
const settings = {
|
|
181
|
-
network: this.network,
|
|
182
|
-
};
|
|
183
|
-
if (useTweakedHash) {
|
|
184
|
-
settings.tweakHash = this.getTweakerHash();
|
|
185
|
-
}
|
|
186
|
-
return TweakedSigner.tweakSigner(this.signer, settings);
|
|
187
|
-
}
|
|
188
|
-
generateRedeemScripts() {
|
|
189
|
-
this.targetScriptRedeem = {
|
|
190
|
-
pubkeys: this.getPubKeys(),
|
|
191
|
-
output: this.compiledTargetScript,
|
|
192
|
-
redeemVersion: 192,
|
|
193
|
-
};
|
|
194
|
-
this.leftOverFundsScriptRedeem = {
|
|
195
|
-
pubkeys: this.getPubKeys(),
|
|
196
|
-
output: this.getLeafScript(),
|
|
197
|
-
redeemVersion: 192,
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
getLeafScript() {
|
|
201
|
-
return InteractionTransaction.LOCK_LEAF_SCRIPT;
|
|
202
|
-
}
|
|
203
|
-
getScriptTree() {
|
|
204
|
-
if (!this.calldata) {
|
|
205
|
-
throw new Error('Calldata is required');
|
|
206
|
-
}
|
|
207
|
-
this.generateRedeemScripts();
|
|
208
|
-
return [
|
|
209
|
-
{
|
|
210
|
-
output: this.compiledTargetScript,
|
|
211
|
-
version: 192,
|
|
212
|
-
},
|
|
213
|
-
{
|
|
214
|
-
output: this.getLeafScript(),
|
|
215
|
-
version: 192,
|
|
216
|
-
},
|
|
217
|
-
];
|
|
218
|
-
}
|
|
219
16
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { PsbtInput } from 'bip174/src/lib/interfaces.js';
|
|
3
|
+
import { Payment, Psbt, Signer } from 'bitcoinjs-lib';
|
|
4
|
+
import { Taptree } from 'bitcoinjs-lib/src/types.js';
|
|
5
|
+
import { ECPairInterface } from 'ecpair';
|
|
6
|
+
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
7
|
+
import { TransactionType } from '../enums/TransactionType.js';
|
|
8
|
+
import { TapLeafScript } from '../interfaces/Tap.js';
|
|
9
|
+
import { CalldataGenerator } from '../../generators/builders/CalldataGenerator.js';
|
|
10
|
+
import { SharedInteractionParameters } from '../interfaces/ITransactionParameters.js';
|
|
11
|
+
export declare abstract class SharedInteractionTransaction<T extends TransactionType> extends TransactionBuilder<T> {
|
|
12
|
+
readonly randomBytes: Buffer;
|
|
13
|
+
protected targetScriptRedeem: Payment | null;
|
|
14
|
+
protected leftOverFundsScriptRedeem: Payment | null;
|
|
15
|
+
protected abstract readonly compiledTargetScript: Buffer;
|
|
16
|
+
protected abstract readonly scriptTree: Taptree;
|
|
17
|
+
protected tapLeafScript: TapLeafScript | null;
|
|
18
|
+
protected readonly calldataGenerator: CalldataGenerator;
|
|
19
|
+
protected readonly calldata: Buffer;
|
|
20
|
+
protected abstract readonly contractSecret: Buffer;
|
|
21
|
+
protected tweakedSigner?: Signer;
|
|
22
|
+
protected readonly scriptSigner: Signer;
|
|
23
|
+
protected readonly interactionPubKeys: Buffer[];
|
|
24
|
+
protected readonly minimumSignatures: number;
|
|
25
|
+
protected constructor(parameters: SharedInteractionParameters);
|
|
26
|
+
getContractSecret(): Buffer;
|
|
27
|
+
getRndBytes(): Buffer;
|
|
28
|
+
protected generateSecret(): Buffer;
|
|
29
|
+
protected tweakSigner(): void;
|
|
30
|
+
protected scriptSignerXOnlyPubKey(): Buffer;
|
|
31
|
+
protected generateKeyPairFromSeed(): ECPairInterface;
|
|
32
|
+
protected addInputsFromUTXO(): void;
|
|
33
|
+
protected buildTransaction(): void;
|
|
34
|
+
protected signInputs(transaction: Psbt): void;
|
|
35
|
+
protected getSignerKey(): Signer;
|
|
36
|
+
protected generateScriptAddress(): Payment;
|
|
37
|
+
protected generateTapData(): Payment;
|
|
38
|
+
protected getScriptSolution(input: PsbtInput): Buffer[];
|
|
39
|
+
protected getScriptTree(): Taptree;
|
|
40
|
+
private getPubKeys;
|
|
41
|
+
private customFinalizer;
|
|
42
|
+
private getTweakerHash;
|
|
43
|
+
private getTweakedSigner;
|
|
44
|
+
private generateRedeemScripts;
|
|
45
|
+
private getLeafScript;
|
|
46
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { address } from 'bitcoinjs-lib';
|
|
2
|
+
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
3
|
+
import { CalldataGenerator } from '../../generators/builders/CalldataGenerator.js';
|
|
4
|
+
import { Compressor } from '../../bytecode/Compressor.js';
|
|
5
|
+
import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
6
|
+
import { BitcoinUtils } from '../../utils/BitcoinUtils.js';
|
|
7
|
+
import { toXOnly } from 'bitcoinjs-lib/src/psbt/bip371.js';
|
|
8
|
+
import { TweakedSigner } from '../../signer/TweakedSigner.js';
|
|
9
|
+
export class SharedInteractionTransaction extends TransactionBuilder {
|
|
10
|
+
randomBytes;
|
|
11
|
+
targetScriptRedeem = null;
|
|
12
|
+
leftOverFundsScriptRedeem = null;
|
|
13
|
+
tapLeafScript = null;
|
|
14
|
+
calldataGenerator;
|
|
15
|
+
calldata;
|
|
16
|
+
tweakedSigner;
|
|
17
|
+
scriptSigner;
|
|
18
|
+
interactionPubKeys = [];
|
|
19
|
+
minimumSignatures = 0;
|
|
20
|
+
constructor(parameters) {
|
|
21
|
+
super(parameters);
|
|
22
|
+
if (!parameters.calldata) {
|
|
23
|
+
throw new Error('Calldata is required');
|
|
24
|
+
}
|
|
25
|
+
this.calldata = Compressor.compress(parameters.calldata);
|
|
26
|
+
this.randomBytes = parameters.randomBytes || BitcoinUtils.rndBytes();
|
|
27
|
+
this.scriptSigner = this.generateKeyPairFromSeed();
|
|
28
|
+
this.calldataGenerator = new CalldataGenerator(this.internalPubKeyToXOnly(), this.scriptSignerXOnlyPubKey(), this.network);
|
|
29
|
+
}
|
|
30
|
+
getContractSecret() {
|
|
31
|
+
return this.contractSecret;
|
|
32
|
+
}
|
|
33
|
+
getRndBytes() {
|
|
34
|
+
return this.randomBytes;
|
|
35
|
+
}
|
|
36
|
+
generateSecret() {
|
|
37
|
+
if (!this.to)
|
|
38
|
+
throw new Error('To address is required');
|
|
39
|
+
return address.fromBech32(this.to).data;
|
|
40
|
+
}
|
|
41
|
+
tweakSigner() {
|
|
42
|
+
this.tweakedSigner = this.getTweakedSigner();
|
|
43
|
+
}
|
|
44
|
+
scriptSignerXOnlyPubKey() {
|
|
45
|
+
return toXOnly(this.scriptSigner.publicKey);
|
|
46
|
+
}
|
|
47
|
+
generateKeyPairFromSeed() {
|
|
48
|
+
return EcKeyPair.fromSeedKeyPair(this.randomBytes, this.network);
|
|
49
|
+
}
|
|
50
|
+
addInputsFromUTXO() {
|
|
51
|
+
if (!this.tapLeafScript)
|
|
52
|
+
throw new Error('Tap leaf script is required');
|
|
53
|
+
for (let utxo of this.utxos) {
|
|
54
|
+
const input = {
|
|
55
|
+
hash: utxo.transactionId,
|
|
56
|
+
index: utxo.outputIndex,
|
|
57
|
+
witnessUtxo: {
|
|
58
|
+
value: Number(utxo.value),
|
|
59
|
+
script: this.getTapOutput(),
|
|
60
|
+
},
|
|
61
|
+
tapLeafScript: [this.tapLeafScript],
|
|
62
|
+
sequence: this.sequence,
|
|
63
|
+
};
|
|
64
|
+
this.addInput(input);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
buildTransaction() {
|
|
68
|
+
if (!this.to)
|
|
69
|
+
throw new Error('To address is required');
|
|
70
|
+
const selectedRedeem = !!this.scriptSigner
|
|
71
|
+
? this.targetScriptRedeem
|
|
72
|
+
: this.leftOverFundsScriptRedeem;
|
|
73
|
+
if (!selectedRedeem) {
|
|
74
|
+
throw new Error('Left over funds script redeem is required');
|
|
75
|
+
}
|
|
76
|
+
if (!selectedRedeem.redeemVersion) {
|
|
77
|
+
throw new Error('Left over funds script redeem version is required');
|
|
78
|
+
}
|
|
79
|
+
if (!selectedRedeem.output) {
|
|
80
|
+
throw new Error('Left over funds script redeem output is required');
|
|
81
|
+
}
|
|
82
|
+
this.tapLeafScript = {
|
|
83
|
+
leafVersion: selectedRedeem.redeemVersion,
|
|
84
|
+
script: selectedRedeem.output,
|
|
85
|
+
controlBlock: this.getWitness(),
|
|
86
|
+
};
|
|
87
|
+
this.addInputsFromUTXO();
|
|
88
|
+
const amountSpent = this.getTransactionOPNetFee();
|
|
89
|
+
this.addOutput({
|
|
90
|
+
value: Number(amountSpent),
|
|
91
|
+
address: this.to,
|
|
92
|
+
});
|
|
93
|
+
this.addRefundOutput(amountSpent);
|
|
94
|
+
}
|
|
95
|
+
signInputs(transaction) {
|
|
96
|
+
if (!this.scriptSigner) {
|
|
97
|
+
super.signInputs(transaction);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
transaction.signInput(0, this.scriptSigner);
|
|
101
|
+
transaction.signInput(0, this.getSignerKey());
|
|
102
|
+
transaction.finalizeInput(0, this.customFinalizer);
|
|
103
|
+
}
|
|
104
|
+
getSignerKey() {
|
|
105
|
+
if (this.tweakedSigner) {
|
|
106
|
+
return this.tweakedSigner;
|
|
107
|
+
}
|
|
108
|
+
return this.signer;
|
|
109
|
+
}
|
|
110
|
+
generateScriptAddress() {
|
|
111
|
+
return {
|
|
112
|
+
internalPubkey: this.internalPubKeyToXOnly(),
|
|
113
|
+
network: this.network,
|
|
114
|
+
scriptTree: this.scriptTree,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
generateTapData() {
|
|
118
|
+
const selectedRedeem = !!this.scriptSigner
|
|
119
|
+
? this.targetScriptRedeem
|
|
120
|
+
: this.leftOverFundsScriptRedeem;
|
|
121
|
+
if (!selectedRedeem) {
|
|
122
|
+
throw new Error('Left over funds script redeem is required');
|
|
123
|
+
}
|
|
124
|
+
if (!this.scriptTree) {
|
|
125
|
+
throw new Error('Script tree is required');
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
internalPubkey: this.internalPubKeyToXOnly(),
|
|
129
|
+
network: this.network,
|
|
130
|
+
scriptTree: this.scriptTree,
|
|
131
|
+
redeem: selectedRedeem,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
getScriptSolution(input) {
|
|
135
|
+
if (!input.tapScriptSig) {
|
|
136
|
+
throw new Error('Tap script signature is required');
|
|
137
|
+
}
|
|
138
|
+
return [
|
|
139
|
+
this.contractSecret,
|
|
140
|
+
this.internalPubKeyToXOnly(),
|
|
141
|
+
input.tapScriptSig[0].signature,
|
|
142
|
+
input.tapScriptSig[1].signature,
|
|
143
|
+
];
|
|
144
|
+
}
|
|
145
|
+
getScriptTree() {
|
|
146
|
+
if (!this.calldata) {
|
|
147
|
+
throw new Error('Calldata is required');
|
|
148
|
+
}
|
|
149
|
+
this.generateRedeemScripts();
|
|
150
|
+
return [
|
|
151
|
+
{
|
|
152
|
+
output: this.compiledTargetScript,
|
|
153
|
+
version: 192,
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
output: this.getLeafScript(),
|
|
157
|
+
version: 192,
|
|
158
|
+
},
|
|
159
|
+
];
|
|
160
|
+
}
|
|
161
|
+
getPubKeys() {
|
|
162
|
+
const pubkeys = [this.signer.publicKey];
|
|
163
|
+
if (this.scriptSigner) {
|
|
164
|
+
pubkeys.push(this.scriptSigner.publicKey);
|
|
165
|
+
}
|
|
166
|
+
return pubkeys;
|
|
167
|
+
}
|
|
168
|
+
customFinalizer = (_inputIndex, input) => {
|
|
169
|
+
if (!this.tapLeafScript) {
|
|
170
|
+
throw new Error('Tap leaf script is required');
|
|
171
|
+
}
|
|
172
|
+
if (!input.tapScriptSig) {
|
|
173
|
+
throw new Error('Tap script signature is required');
|
|
174
|
+
}
|
|
175
|
+
if (!this.contractSecret) {
|
|
176
|
+
throw new Error('Contract secret is required');
|
|
177
|
+
}
|
|
178
|
+
const scriptSolution = this.getScriptSolution(input);
|
|
179
|
+
const witness = scriptSolution
|
|
180
|
+
.concat(this.tapLeafScript.script)
|
|
181
|
+
.concat(this.tapLeafScript.controlBlock);
|
|
182
|
+
return {
|
|
183
|
+
finalScriptWitness: this.witnessStackToScriptWitness(witness),
|
|
184
|
+
};
|
|
185
|
+
};
|
|
186
|
+
getTweakerHash() {
|
|
187
|
+
return this.tapData?.hash;
|
|
188
|
+
}
|
|
189
|
+
getTweakedSigner(useTweakedHash = false) {
|
|
190
|
+
const settings = {
|
|
191
|
+
network: this.network,
|
|
192
|
+
};
|
|
193
|
+
if (useTweakedHash) {
|
|
194
|
+
settings.tweakHash = this.getTweakerHash();
|
|
195
|
+
}
|
|
196
|
+
return TweakedSigner.tweakSigner(this.signer, settings);
|
|
197
|
+
}
|
|
198
|
+
generateRedeemScripts() {
|
|
199
|
+
this.targetScriptRedeem = {
|
|
200
|
+
pubkeys: this.getPubKeys(),
|
|
201
|
+
output: this.compiledTargetScript,
|
|
202
|
+
redeemVersion: 192,
|
|
203
|
+
};
|
|
204
|
+
this.leftOverFundsScriptRedeem = {
|
|
205
|
+
pubkeys: this.getPubKeys(),
|
|
206
|
+
output: this.getLeafScript(),
|
|
207
|
+
redeemVersion: 192,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
getLeafScript() {
|
|
211
|
+
return SharedInteractionTransaction.LOCK_LEAF_SCRIPT;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -5,13 +5,19 @@ import { TransactionType } from '../enums/TransactionType.js';
|
|
|
5
5
|
import { IFundingTransactionParameters, ITransactionParameters } from '../interfaces/ITransactionParameters.js';
|
|
6
6
|
import { Address } from '@btc-vision/bsi-binary';
|
|
7
7
|
import { UTXO } from '../../utxo/interfaces/IUTXO.js';
|
|
8
|
+
import { ECPairInterface } from 'ecpair';
|
|
8
9
|
import { Logger } from '@btc-vision/logger';
|
|
10
|
+
export declare enum TransactionSequence {
|
|
11
|
+
REPLACE_BY_FEE = 4294967293,
|
|
12
|
+
FINAL = 4294967295
|
|
13
|
+
}
|
|
9
14
|
export declare abstract class TransactionBuilder<T extends TransactionType> extends Logger {
|
|
10
15
|
static readonly LOCK_LEAF_SCRIPT: Buffer;
|
|
11
16
|
static readonly MINIMUM_DUST: bigint;
|
|
12
17
|
abstract readonly type: T;
|
|
13
18
|
readonly logColor: string;
|
|
14
19
|
transactionFee: bigint;
|
|
20
|
+
protected sequence: number;
|
|
15
21
|
protected readonly transaction: Psbt;
|
|
16
22
|
protected readonly inputs: PsbtInputExtended[];
|
|
17
23
|
protected readonly updateInputs: UpdateInput[];
|
|
@@ -26,10 +32,11 @@ export declare abstract class TransactionBuilder<T extends TransactionType> exte
|
|
|
26
32
|
protected readonly feeRate: number;
|
|
27
33
|
protected readonly priorityFee: bigint;
|
|
28
34
|
protected utxos: UTXO[];
|
|
29
|
-
protected to: Address;
|
|
35
|
+
protected to: Address | undefined;
|
|
30
36
|
protected from: Address;
|
|
31
37
|
private _maximumFeeRate;
|
|
32
38
|
protected constructor(parameters: ITransactionParameters);
|
|
39
|
+
static getFrom(from: string | undefined, keypair: ECPairInterface, network: Network): Address;
|
|
33
40
|
getFundingTransactionParameters(): IFundingTransactionParameters;
|
|
34
41
|
setDestinationAddress(address: Address): void;
|
|
35
42
|
setMaximumFeeRate(feeRate: number): void;
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { initEccLib, opcodes, payments, Psbt, script } from 'bitcoinjs-lib';
|
|
2
2
|
import { varuint } from 'bitcoinjs-lib/src/bufferutils.js';
|
|
3
3
|
import { toXOnly } from 'bitcoinjs-lib/src/psbt/bip371.js';
|
|
4
|
-
import * as ecc from '
|
|
4
|
+
import * as ecc from '@bitcoinerlab/secp256k1';
|
|
5
5
|
import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
6
6
|
import { Logger } from '@btc-vision/logger';
|
|
7
|
+
export var TransactionSequence;
|
|
8
|
+
(function (TransactionSequence) {
|
|
9
|
+
TransactionSequence[TransactionSequence["REPLACE_BY_FEE"] = 4294967293] = "REPLACE_BY_FEE";
|
|
10
|
+
TransactionSequence[TransactionSequence["FINAL"] = 4294967295] = "FINAL";
|
|
11
|
+
})(TransactionSequence || (TransactionSequence = {}));
|
|
7
12
|
export class TransactionBuilder extends Logger {
|
|
8
13
|
static LOCK_LEAF_SCRIPT = script.compile([
|
|
9
14
|
opcodes.OP_0,
|
|
@@ -11,6 +16,7 @@ export class TransactionBuilder extends Logger {
|
|
|
11
16
|
static MINIMUM_DUST = 330n;
|
|
12
17
|
logColor = '#785def';
|
|
13
18
|
transactionFee = 0n;
|
|
19
|
+
sequence = TransactionSequence.REPLACE_BY_FEE;
|
|
14
20
|
transaction;
|
|
15
21
|
inputs = [];
|
|
16
22
|
updateInputs = [];
|
|
@@ -35,10 +41,8 @@ export class TransactionBuilder extends Logger {
|
|
|
35
41
|
this.feeRate = parameters.feeRate;
|
|
36
42
|
this.priorityFee = parameters.priorityFee;
|
|
37
43
|
this.utxos = parameters.utxos;
|
|
38
|
-
this.to = parameters.to;
|
|
39
|
-
this.from =
|
|
40
|
-
parameters.from ||
|
|
41
|
-
EcKeyPair.getTaprootAddress(this.signer, this.network);
|
|
44
|
+
this.to = parameters.to || undefined;
|
|
45
|
+
this.from = TransactionBuilder.getFrom(parameters.from, this.signer, this.network);
|
|
42
46
|
this.totalInputAmount = this.calculateTotalUTXOAmount();
|
|
43
47
|
const totalVOut = this.calculateTotalVOutAmount();
|
|
44
48
|
if (totalVOut < this.totalInputAmount) {
|
|
@@ -51,6 +55,9 @@ export class TransactionBuilder extends Logger {
|
|
|
51
55
|
network: this.network,
|
|
52
56
|
});
|
|
53
57
|
}
|
|
58
|
+
static getFrom(from, keypair, network) {
|
|
59
|
+
return from || EcKeyPair.getTaprootAddress(keypair, network);
|
|
60
|
+
}
|
|
54
61
|
getFundingTransactionParameters() {
|
|
55
62
|
return {
|
|
56
63
|
utxos: this.utxos,
|
|
@@ -60,7 +67,7 @@ export class TransactionBuilder extends Logger {
|
|
|
60
67
|
feeRate: this.feeRate,
|
|
61
68
|
priorityFee: this.priorityFee,
|
|
62
69
|
from: this.from,
|
|
63
|
-
|
|
70
|
+
childTransactionRequiredValue: this.transactionFee,
|
|
64
71
|
};
|
|
65
72
|
}
|
|
66
73
|
setDestinationAddress(address) {
|
|
@@ -70,10 +77,10 @@ export class TransactionBuilder extends Logger {
|
|
|
70
77
|
this._maximumFeeRate = feeRate;
|
|
71
78
|
}
|
|
72
79
|
signTransaction() {
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
if (this.to) {
|
|
81
|
+
if (!EcKeyPair.verifyContractAddress(this.to, this.network)) {
|
|
82
|
+
throw new Error('Invalid contract address. The contract address must be a taproot address.');
|
|
83
|
+
}
|
|
77
84
|
}
|
|
78
85
|
if (this.signed)
|
|
79
86
|
throw new Error('Transaction is already signed');
|
|
@@ -97,8 +104,9 @@ export class TransactionBuilder extends Logger {
|
|
|
97
104
|
disableRBF() {
|
|
98
105
|
if (this.signed)
|
|
99
106
|
throw new Error('Transaction is already signed');
|
|
107
|
+
this.sequence = TransactionSequence.FINAL;
|
|
100
108
|
for (let input of this.inputs) {
|
|
101
|
-
input.sequence =
|
|
109
|
+
input.sequence = TransactionSequence.FINAL;
|
|
102
110
|
}
|
|
103
111
|
}
|
|
104
112
|
getTapAddress() {
|
|
@@ -156,7 +164,7 @@ export class TransactionBuilder extends Logger {
|
|
|
156
164
|
value: Number(utxo.value),
|
|
157
165
|
script: Buffer.from(utxo.scriptPubKey.hex, 'hex'),
|
|
158
166
|
},
|
|
159
|
-
sequence:
|
|
167
|
+
sequence: this.sequence,
|
|
160
168
|
};
|
|
161
169
|
this.addInput(input);
|
|
162
170
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Taptree } from 'bitcoinjs-lib/src/types.js';
|
|
3
|
+
import { TransactionType } from '../enums/TransactionType.js';
|
|
4
|
+
import { TapLeafScript } from '../interfaces/Tap.js';
|
|
5
|
+
import { IWrapParameters } from '../interfaces/ITransactionParameters.js';
|
|
6
|
+
import { SharedInteractionTransaction } from './SharedInteractionTransaction.js';
|
|
7
|
+
import { Address } from '@btc-vision/bsi-binary';
|
|
8
|
+
import { WrappedGeneration } from '../../wbtc/WrappedGenerationParameters.js';
|
|
9
|
+
export declare class WrapTransaction extends SharedInteractionTransaction<TransactionType.WBTC_WRAP> {
|
|
10
|
+
private static readonly WRAP_SELECTOR;
|
|
11
|
+
type: TransactionType.WBTC_WRAP;
|
|
12
|
+
readonly vault: Address;
|
|
13
|
+
readonly amount: bigint;
|
|
14
|
+
readonly receiver: Address;
|
|
15
|
+
protected readonly compiledTargetScript: Buffer;
|
|
16
|
+
protected readonly scriptTree: Taptree;
|
|
17
|
+
protected tapLeafScript: TapLeafScript | null;
|
|
18
|
+
protected readonly contractSecret: Buffer;
|
|
19
|
+
private readonly wbtc;
|
|
20
|
+
constructor(parameters: IWrapParameters);
|
|
21
|
+
private static generateMintCalldata;
|
|
22
|
+
verifyPublicKeysConstraints(generation: WrappedGeneration): boolean;
|
|
23
|
+
protected buildTransaction(): void;
|
|
24
|
+
private addVaultOutput;
|
|
25
|
+
private generateVaultAddress;
|
|
26
|
+
private generateChecksumSalt;
|
|
27
|
+
}
|