@btc-vision/transaction 1.0.7 → 1.0.9
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 +7 -0
- package/Wrap.md +192 -0
- package/browser/_version.d.ts +1 -1
- package/browser/index.js +1 -1
- 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/opnet.d.ts +6 -1
- package/build/opnet.js +6 -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 +19 -11
- 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 +8 -1
- 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/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 +5 -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 +1 -1
- package/src/_version.ts +1 -1
- package/src/opnet.ts +8 -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 +40 -15
- package/src/transaction/builders/WrapTransaction.ts +286 -0
- package/src/transaction/interfaces/ITransactionParameters.ts +20 -13
- package/src/utils/BitcoinUtils.ts +17 -1
- 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/docs/classes/UTXOManager.html +0 -187
- package/docs/interfaces/ITransactionDataContractDeployment.html +0 -184
- package/docs/interfaces/ITransactionDataContractInteractionWrap.html +0 -186
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import { Taptree } from 'bitcoinjs-lib/src/types.js';
|
|
2
|
+
import { TransactionType } from '../enums/TransactionType.js';
|
|
3
|
+
import { PsbtOutputExtendedAddress, TapLeafScript } from '../interfaces/Tap.js';
|
|
4
|
+
import { IWrapParameters } from '../interfaces/ITransactionParameters.js';
|
|
5
|
+
import { SharedInteractionTransaction } from './SharedInteractionTransaction.js';
|
|
6
|
+
import { wBTC } from '../../metadata/contracts/wBTC.js';
|
|
7
|
+
import { ABICoder, Address, BinaryWriter, Selector } from '@btc-vision/bsi-binary';
|
|
8
|
+
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
9
|
+
import { ECPairInterface } from 'ecpair';
|
|
10
|
+
import { WrappedGeneration } from '../../wbtc/WrappedGenerationParameters.js';
|
|
11
|
+
import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
12
|
+
import { BitcoinUtils } from '../../utils/BitcoinUtils.js';
|
|
13
|
+
|
|
14
|
+
const abiCoder: ABICoder = new ABICoder();
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Wrapped Bitcoin transaction wrap interaction
|
|
18
|
+
* @class InteractionTransaction
|
|
19
|
+
*/
|
|
20
|
+
export class WrapTransaction extends SharedInteractionTransaction<TransactionType.WBTC_WRAP> {
|
|
21
|
+
private static readonly WRAP_SELECTOR: Selector = Number(
|
|
22
|
+
'0x' + abiCoder.encodeSelector('mint'),
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
public type: TransactionType.WBTC_WRAP = TransactionType.WBTC_WRAP;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The vault address
|
|
29
|
+
* @private
|
|
30
|
+
* @readonly
|
|
31
|
+
*/
|
|
32
|
+
public readonly vault: Address;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The amount to wrap
|
|
36
|
+
* @private
|
|
37
|
+
*/
|
|
38
|
+
public readonly amount: bigint;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The receiver of the wrapped tokens
|
|
42
|
+
* @private
|
|
43
|
+
*/
|
|
44
|
+
public readonly receiver: Address;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The compiled target script
|
|
48
|
+
* @protected
|
|
49
|
+
*/
|
|
50
|
+
protected readonly compiledTargetScript: Buffer;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Tap tree for the interaction
|
|
54
|
+
* @protected
|
|
55
|
+
*/
|
|
56
|
+
protected readonly scriptTree: Taptree;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Tap leaf script
|
|
60
|
+
* @protected
|
|
61
|
+
*/
|
|
62
|
+
protected tapLeafScript: TapLeafScript | null = null;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Contract secret for the interaction
|
|
66
|
+
* @protected
|
|
67
|
+
*/
|
|
68
|
+
protected readonly contractSecret: Buffer;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The wBTC contract
|
|
72
|
+
* @private
|
|
73
|
+
*/
|
|
74
|
+
private readonly wbtc: wBTC;
|
|
75
|
+
|
|
76
|
+
public constructor(parameters: IWrapParameters) {
|
|
77
|
+
if (parameters.amount < TransactionBuilder.MINIMUM_DUST) {
|
|
78
|
+
throw new Error('Amount is below dust limit');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const receiver: Address =
|
|
82
|
+
parameters.receiver ||
|
|
83
|
+
TransactionBuilder.getFrom(
|
|
84
|
+
parameters.from,
|
|
85
|
+
parameters.signer as ECPairInterface,
|
|
86
|
+
parameters.network,
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
parameters.calldata = WrapTransaction.generateMintCalldata(parameters.amount, receiver);
|
|
90
|
+
|
|
91
|
+
super(parameters);
|
|
92
|
+
|
|
93
|
+
this.wbtc = new wBTC(parameters.network);
|
|
94
|
+
this.vault = parameters.generationParameters.vault;
|
|
95
|
+
|
|
96
|
+
this.to = this.wbtc.getAddress();
|
|
97
|
+
this.receiver = receiver;
|
|
98
|
+
this.amount = parameters.amount;
|
|
99
|
+
|
|
100
|
+
this.contractSecret = this.generateSecret();
|
|
101
|
+
|
|
102
|
+
if (!this.verifyPublicKeysConstraints(parameters.generationParameters)) {
|
|
103
|
+
throw new Error(
|
|
104
|
+
'Oops. Your wrapping request have been decline! It failed security checks!',
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
this.compiledTargetScript = this.calldataGenerator.compile(
|
|
109
|
+
this.calldata,
|
|
110
|
+
this.contractSecret,
|
|
111
|
+
this.interactionPubKeys,
|
|
112
|
+
this.minimumSignatures,
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
this.scriptTree = this.getScriptTree();
|
|
116
|
+
this.internalInit();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Generate a valid wBTC calldata
|
|
121
|
+
* @param {bigint} amount - The amount to wrap
|
|
122
|
+
* @param {Address} to - The address to send the wrapped tokens to
|
|
123
|
+
* @private
|
|
124
|
+
* @returns {Buffer} - The calldata
|
|
125
|
+
*/
|
|
126
|
+
private static generateMintCalldata(amount: bigint, to: Address): Buffer {
|
|
127
|
+
if (!amount) throw new Error('Amount is required');
|
|
128
|
+
if (!to) throw new Error('To address is required');
|
|
129
|
+
|
|
130
|
+
const bufWriter: BinaryWriter = new BinaryWriter();
|
|
131
|
+
bufWriter.writeSelector(WrapTransaction.WRAP_SELECTOR);
|
|
132
|
+
bufWriter.writeAddress(to);
|
|
133
|
+
bufWriter.writeU256(amount);
|
|
134
|
+
|
|
135
|
+
return Buffer.from(bufWriter.getBuffer());
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Verify the data integrity received by the client.
|
|
140
|
+
* @param {WrappedGeneration} generation - The generation parameters
|
|
141
|
+
* @returns {boolean} - True if the data is valid
|
|
142
|
+
* @throws {Error} - If the data is invalid
|
|
143
|
+
*/
|
|
144
|
+
public verifyPublicKeysConstraints(generation: WrappedGeneration): boolean {
|
|
145
|
+
if (generation.constraints.minimum < 2) {
|
|
146
|
+
throw new Error('Minimum signatures must be at least 2');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (
|
|
150
|
+
generation.keys.length < generation.constraints.transactionMinimum ||
|
|
151
|
+
generation.keys.length < generation.constraints.minimum
|
|
152
|
+
) {
|
|
153
|
+
throw new Error('Not enough pub keys');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (generation.keys.length > 255) {
|
|
157
|
+
throw new Error('Too many pub keys');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const generatedVault: string = this.generateVaultAddress(
|
|
161
|
+
generation.pubKeys,
|
|
162
|
+
generation.constraints.minimum,
|
|
163
|
+
);
|
|
164
|
+
if (generatedVault !== generation.vault) {
|
|
165
|
+
throw new Error(
|
|
166
|
+
`Invalid vault address. Expected: ${generatedVault} Got: ${generation.vault}`,
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const passChecksum: Buffer = this.generateChecksumSalt(
|
|
171
|
+
generation,
|
|
172
|
+
this.amount,
|
|
173
|
+
generation.vault,
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
const checksum: string = BitcoinUtils.opnetHash(passChecksum);
|
|
177
|
+
if (checksum !== generation.signature) {
|
|
178
|
+
throw new Error(`Invalid checksum. Expected: ${checksum} Got: ${generation.signature}`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Build the transaction
|
|
186
|
+
* @protected
|
|
187
|
+
*
|
|
188
|
+
* @throws {Error} If the leftover funds script redeem is required
|
|
189
|
+
* @throws {Error} If the leftover funds script redeem version is required
|
|
190
|
+
* @throws {Error} If the leftover funds script redeem output is required
|
|
191
|
+
* @throws {Error} If the to address is required
|
|
192
|
+
*/
|
|
193
|
+
protected override buildTransaction(): void {
|
|
194
|
+
if (!this.to) throw new Error('To address is required');
|
|
195
|
+
|
|
196
|
+
const selectedRedeem = !!this.scriptSigner
|
|
197
|
+
? this.targetScriptRedeem
|
|
198
|
+
: this.leftOverFundsScriptRedeem;
|
|
199
|
+
|
|
200
|
+
if (!selectedRedeem) {
|
|
201
|
+
throw new Error('Left over funds script redeem is required');
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (!selectedRedeem.redeemVersion) {
|
|
205
|
+
throw new Error('Left over funds script redeem version is required');
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (!selectedRedeem.output) {
|
|
209
|
+
throw new Error('Left over funds script redeem output is required');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
this.tapLeafScript = {
|
|
213
|
+
leafVersion: selectedRedeem.redeemVersion,
|
|
214
|
+
script: selectedRedeem.output,
|
|
215
|
+
controlBlock: this.getWitness(),
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
this.addInputsFromUTXO();
|
|
219
|
+
|
|
220
|
+
const amountSpent: bigint = this.getTransactionOPNetFee();
|
|
221
|
+
this.addOutput({
|
|
222
|
+
value: Number(amountSpent),
|
|
223
|
+
address: this.to,
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
this.addVaultOutput();
|
|
227
|
+
this.addRefundOutput(amountSpent + this.amount);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Add the vault output
|
|
232
|
+
* @private
|
|
233
|
+
* @throws {Error} If no vault address is provided
|
|
234
|
+
* @throws {Error} If the amount is not a number
|
|
235
|
+
*/
|
|
236
|
+
private addVaultOutput(): void {
|
|
237
|
+
if (!this.vault) {
|
|
238
|
+
throw new Error(`No vault address provided`);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const amountOutput: PsbtOutputExtendedAddress = {
|
|
242
|
+
address: this.vault,
|
|
243
|
+
value: Number(this.amount),
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
this.addOutput(amountOutput);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Generate a vault address
|
|
251
|
+
* @param {Buffer[]} keys
|
|
252
|
+
* @param {number} minimumSignatureRequired
|
|
253
|
+
* @private
|
|
254
|
+
* @returns {string}
|
|
255
|
+
*/
|
|
256
|
+
private generateVaultAddress(keys: Buffer[], minimumSignatureRequired: number): string {
|
|
257
|
+
return EcKeyPair.generateMultiSigAddress(keys, minimumSignatureRequired, this.network);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Generate a wrapped checksum hash
|
|
262
|
+
* @param {WrappedGeneration} param
|
|
263
|
+
* @param {bigint} amount
|
|
264
|
+
* @param {string} vault
|
|
265
|
+
* @private
|
|
266
|
+
* @returns {Buffer}
|
|
267
|
+
*/
|
|
268
|
+
private generateChecksumSalt(param: WrappedGeneration, amount: bigint, vault: string): Buffer {
|
|
269
|
+
const version: string = param.constraints.version;
|
|
270
|
+
const timestamp: number = param.constraints.timestamp;
|
|
271
|
+
|
|
272
|
+
const params: Buffer = Buffer.alloc(12 + version.length);
|
|
273
|
+
params.writeBigInt64BE(BigInt(timestamp), 0);
|
|
274
|
+
params.writeInt16BE(param.constraints.minimum, 8);
|
|
275
|
+
params.writeInt16BE(param.constraints.transactionMinimum, 10);
|
|
276
|
+
params.write(version, 12, version.length, 'utf-8');
|
|
277
|
+
|
|
278
|
+
return Buffer.concat([
|
|
279
|
+
...param.pubKeys,
|
|
280
|
+
...param.entities.map((entity: string) => Buffer.from(entity, 'utf-8')),
|
|
281
|
+
params,
|
|
282
|
+
Buffer.from(amount.toString(), 'utf-8'),
|
|
283
|
+
Buffer.from(vault, 'utf-8'),
|
|
284
|
+
]);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
@@ -2,10 +2,11 @@ import { Signer } from 'bitcoinjs-lib';
|
|
|
2
2
|
import { UTXO } from '../../utxo/interfaces/IUTXO.js';
|
|
3
3
|
import { Network } from 'bitcoinjs-lib/src/networks.js';
|
|
4
4
|
import { Address } from '@btc-vision/bsi-binary';
|
|
5
|
+
import { WrappedGeneration } from '../../wbtc/WrappedGenerationParameters.js';
|
|
5
6
|
|
|
6
7
|
export interface ITransactionParameters {
|
|
7
8
|
readonly from?: Address;
|
|
8
|
-
readonly to
|
|
9
|
+
readonly to?: Address | undefined;
|
|
9
10
|
utxos: UTXO[];
|
|
10
11
|
|
|
11
12
|
readonly signer: Signer;
|
|
@@ -15,27 +16,33 @@ export interface ITransactionParameters {
|
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export interface IFundingTransactionParameters extends ITransactionParameters {
|
|
18
|
-
|
|
19
|
+
childTransactionRequiredValue: bigint;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
export interface
|
|
22
|
-
|
|
22
|
+
export interface SharedInteractionParameters extends ITransactionParameters {
|
|
23
|
+
calldata?: Buffer | undefined;
|
|
23
24
|
|
|
24
|
-
readonly pubKeys?: Buffer[];
|
|
25
|
-
readonly minimumSignatures?: number;
|
|
26
|
-
|
|
27
25
|
readonly randomBytes?: Buffer;
|
|
28
26
|
}
|
|
29
27
|
|
|
30
|
-
export interface
|
|
28
|
+
export interface IInteractionParameters extends SharedInteractionParameters {
|
|
29
|
+
readonly calldata: Buffer;
|
|
30
|
+
|
|
31
|
+
readonly to: Address;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface IWrapParameters extends SharedInteractionParameters {
|
|
35
|
+
readonly to?: undefined;
|
|
36
|
+
|
|
31
37
|
readonly amount: bigint;
|
|
32
|
-
readonly
|
|
33
|
-
|
|
38
|
+
readonly receiver?: Address;
|
|
39
|
+
|
|
40
|
+
readonly generationParameters: WrappedGeneration;
|
|
34
41
|
}
|
|
35
42
|
|
|
36
|
-
export interface
|
|
43
|
+
export interface IDeploymentParameters extends ITransactionParameters {
|
|
37
44
|
readonly bytecode: Buffer;
|
|
38
|
-
readonly salt: Buffer; // sha256
|
|
39
45
|
|
|
40
|
-
readonly
|
|
46
|
+
readonly to?: undefined;
|
|
47
|
+
readonly randomBytes?: Buffer;
|
|
41
48
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createHash, getRandomValues } from 'crypto';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Utility class for Bitcoin related functions
|
|
3
5
|
*/
|
|
@@ -17,8 +19,22 @@ export class BitcoinUtils {
|
|
|
17
19
|
* @returns {Buffer} The random bytes
|
|
18
20
|
*/
|
|
19
21
|
public static rndBytes(): Buffer {
|
|
20
|
-
const buf =
|
|
22
|
+
const buf = getRandomValues(new Uint8Array(64));
|
|
21
23
|
|
|
22
24
|
return Buffer.from(buf);
|
|
23
25
|
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Hashes the given data
|
|
29
|
+
* @param {Buffer} data - The data to hash
|
|
30
|
+
* @returns {string} The hashed data
|
|
31
|
+
*/
|
|
32
|
+
public static opnetHash(data: Buffer): string {
|
|
33
|
+
const hashed = createHash('sha512');
|
|
34
|
+
hashed.update(data);
|
|
35
|
+
|
|
36
|
+
const hash = hashed.digest();
|
|
37
|
+
|
|
38
|
+
return `0x${hash.toString('hex')}`;
|
|
39
|
+
}
|
|
24
40
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { FetchUTXOParams, RawUTXOResponse, UTXO } from './interfaces/IUTXO.js';
|
|
2
|
+
import { WrappedGeneration } from '../wbtc/WrappedGenerationParameters.js';
|
|
3
|
+
import { WrappedGenerationParameters } from '../wbtc/Generate.js';
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* Allows to fetch UTXO data from any OPNET node
|
|
5
7
|
*/
|
|
6
|
-
export class
|
|
8
|
+
export class OPNetLimitedProvider {
|
|
7
9
|
private readonly utxoPath: string = 'address/utxos';
|
|
10
|
+
private readonly rpc: string = 'json-rpc';
|
|
8
11
|
|
|
9
12
|
constructor(private readonly opnetAPIUrl: string) {}
|
|
10
13
|
|
|
@@ -57,11 +60,59 @@ export class UTXOManager {
|
|
|
57
60
|
scriptPubKey: utxo.scriptPubKey,
|
|
58
61
|
});
|
|
59
62
|
|
|
60
|
-
if (currentAmount
|
|
63
|
+
if (currentAmount > amountRequested) {
|
|
61
64
|
break;
|
|
62
65
|
}
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
return finalUTXOs;
|
|
66
69
|
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Fetches the wrap parameters from the OPNET node
|
|
73
|
+
* @param {bigint} amount - The amount to wrap
|
|
74
|
+
* @returns {Promise<WrappedGeneration | undefined>} - The wrap parameters fetched
|
|
75
|
+
* @throws {Error} - If wrap parameters could not be fetched
|
|
76
|
+
*/
|
|
77
|
+
public async fetchWrapParameters(amount: bigint): Promise<WrappedGeneration | undefined> {
|
|
78
|
+
const params = {
|
|
79
|
+
method: 'POST',
|
|
80
|
+
headers: {
|
|
81
|
+
'Content-Type': 'application/json',
|
|
82
|
+
},
|
|
83
|
+
body: JSON.stringify({
|
|
84
|
+
jsonrpc: '2.0',
|
|
85
|
+
method: 'btc_generate',
|
|
86
|
+
params: [0, amount.toString()],
|
|
87
|
+
id: 1,
|
|
88
|
+
}),
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const url: string = `${this.opnetAPIUrl}/api/v1/${this.rpc}`;
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
const resp: Response = await fetch(url, params);
|
|
95
|
+
if (!resp.ok) {
|
|
96
|
+
throw new Error(`Failed to fetch wrap parameters: ${resp.statusText}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const fetchedData = await resp.json();
|
|
100
|
+
if (!fetchedData) {
|
|
101
|
+
throw new Error('No wrap parameters found');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const result = fetchedData.result;
|
|
105
|
+
if (!result) {
|
|
106
|
+
throw new Error('No wrap parameters found');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if ('error' in result) {
|
|
110
|
+
throw new Error('Something went wrong while fetching wrap parameters');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return new WrappedGeneration(result as WrappedGenerationParameters);
|
|
114
|
+
} catch (e) {
|
|
115
|
+
console.error(`Failed to fetch wrap parameters: ${(e as Error).stack}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
67
118
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { crypto as bitCrypto, Network, networks, Payment, payments } from 'bitcoinjs-lib';
|
|
2
2
|
import { toXOnly } from 'bitcoinjs-lib/src/psbt/bip371.js';
|
|
3
3
|
import { Taptree } from 'bitcoinjs-lib/src/types.js';
|
|
4
4
|
import { DeploymentGenerator } from '../generators/builders/DeploymentGenerator.js';
|
|
@@ -50,10 +50,10 @@ export class TapscriptVerificator {
|
|
|
50
50
|
bytecode: Buffer,
|
|
51
51
|
saltHash: Buffer,
|
|
52
52
|
): Buffer {
|
|
53
|
-
const sha256OfBytecode: Buffer =
|
|
53
|
+
const sha256OfBytecode: Buffer = bitCrypto.hash256(bytecode);
|
|
54
54
|
const buf: Buffer = Buffer.concat([deployerPubKey, saltHash, sha256OfBytecode]);
|
|
55
55
|
|
|
56
|
-
return
|
|
56
|
+
return bitCrypto.hash256(buf);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
public static generateContractVirtualAddress(
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface GenerationConstraints {
|
|
2
|
+
/** Timestamp of the generation */
|
|
3
|
+
readonly timestamp: number;
|
|
4
|
+
|
|
5
|
+
/** Protocol version used for generation */
|
|
6
|
+
readonly version: string;
|
|
7
|
+
|
|
8
|
+
/** Minimum different trusted validators */
|
|
9
|
+
readonly minimum: number;
|
|
10
|
+
|
|
11
|
+
/** Minimum different trusted validator in a new generated transaction */
|
|
12
|
+
readonly transactionMinimum: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface WrappedGenerationParameters {
|
|
16
|
+
/** Public trusted keys */
|
|
17
|
+
readonly keys: string[];
|
|
18
|
+
|
|
19
|
+
/** Vault address (p2ms) */
|
|
20
|
+
readonly vault: string;
|
|
21
|
+
|
|
22
|
+
/** Public trusted entities */
|
|
23
|
+
readonly entities: string[];
|
|
24
|
+
|
|
25
|
+
/** OPNet Signature that verify the trusted keys and entities */
|
|
26
|
+
readonly signature: string;
|
|
27
|
+
|
|
28
|
+
/** Generation constraints */
|
|
29
|
+
readonly constraints: GenerationConstraints;
|
|
30
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { GenerationConstraints, WrappedGenerationParameters } from './Generate.js';
|
|
2
|
+
|
|
3
|
+
export class WrappedGeneration implements WrappedGenerationParameters {
|
|
4
|
+
/** Generation constraints */
|
|
5
|
+
public readonly constraints: GenerationConstraints;
|
|
6
|
+
|
|
7
|
+
/** Public trusted entities */
|
|
8
|
+
public readonly entities: string[];
|
|
9
|
+
|
|
10
|
+
/** Public trusted keys */
|
|
11
|
+
public readonly keys: string[];
|
|
12
|
+
|
|
13
|
+
/** OPNet Signature that verify the trusted keys and entities */
|
|
14
|
+
public readonly signature: string;
|
|
15
|
+
|
|
16
|
+
/** Vault address (p2ms) */
|
|
17
|
+
public readonly vault: string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Public keys of the trusted entities
|
|
21
|
+
*/
|
|
22
|
+
public readonly pubKeys: Buffer[];
|
|
23
|
+
|
|
24
|
+
constructor(params: WrappedGenerationParameters) {
|
|
25
|
+
this.constraints = params.constraints;
|
|
26
|
+
this.entities = params.entities;
|
|
27
|
+
this.keys = params.keys;
|
|
28
|
+
this.signature = params.signature;
|
|
29
|
+
this.vault = params.vault;
|
|
30
|
+
|
|
31
|
+
this.pubKeys = this.keys.map((key: string) => Buffer.from(key, 'base64'));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
import 'jest';
|
|
2
|
-
import { Regtest } from '../src/tests/Regtest.js';
|
|
3
|
-
import { Logger } from '@btc-vision/logger';
|
|
4
|
-
import { networks } from 'bitcoinjs-lib';
|
|
5
|
-
import {
|
|
6
|
-
FetchUTXOParams,
|
|
7
|
-
IInteractionParameters,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Wallet,
|
|
12
|
-
wBTC,
|
|
13
|
-
} from '../src/index.js';
|
|
14
|
-
|
|
15
|
-
const logger: Logger = new Logger();
|
|
16
|
-
const network: networks.Network = networks.regtest;
|
|
17
|
-
|
|
18
|
-
describe('Transaction Builder', () => {
|
|
19
|
-
const wBtc: wBTC = new wBTC(network);
|
|
20
|
-
|
|
21
|
-
const wallet: Wallet = new Wallet(Regtest.wallet, network);
|
|
22
|
-
logger.log(`Loaded wallet: ${wallet.p2tr} - ${wallet.p2wpkh}`);
|
|
23
|
-
|
|
24
|
-
const utxoManager:
|
|
25
|
-
const factory: TransactionFactory = new TransactionFactory();
|
|
26
|
-
|
|
27
|
-
/** @test {TransactionBuilder#build} */
|
|
28
|
-
test('should be able to build a transaction', async () => {
|
|
29
|
-
const utxoSetting: FetchUTXOParams = {
|
|
30
|
-
address: wallet.p2wpkh,
|
|
31
|
-
minAmount: 10000n,
|
|
32
|
-
requestedAmount: 100000n,
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const utxos: UTXO[] = await utxoManager.fetchUTXO(utxoSetting);
|
|
36
|
-
console.log(`UTXOs:`, utxos);
|
|
37
|
-
|
|
38
|
-
if (!utxos) {
|
|
39
|
-
throw new Error('No UTXOs found');
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
logger.log(`UTXOs fetched. Count: ${utxos.length}`);
|
|
43
|
-
|
|
44
|
-
const interactionParameters: IInteractionParameters = {
|
|
45
|
-
from: wallet.p2wpkh,
|
|
46
|
-
to: wBtc.getAddress(),
|
|
47
|
-
utxos: utxos,
|
|
48
|
-
signer: wallet.keypair,
|
|
49
|
-
network: network,
|
|
50
|
-
feeRate: 150,
|
|
51
|
-
priorityFee: 500n,
|
|
52
|
-
calldata: Buffer.from('test'),
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const finalTx = factory.signInteraction(interactionParameters);
|
|
56
|
-
console.log(`Transaction:`, finalTx);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
1
|
+
import 'jest';
|
|
2
|
+
import { Regtest } from '../src/tests/Regtest.js';
|
|
3
|
+
import { Logger } from '@btc-vision/logger';
|
|
4
|
+
import { networks } from 'bitcoinjs-lib';
|
|
5
|
+
import {
|
|
6
|
+
FetchUTXOParams,
|
|
7
|
+
IInteractionParameters,
|
|
8
|
+
OPNetLimitedProvider,
|
|
9
|
+
TransactionFactory,
|
|
10
|
+
UTXO,
|
|
11
|
+
Wallet,
|
|
12
|
+
wBTC,
|
|
13
|
+
} from '../src/index.js';
|
|
14
|
+
|
|
15
|
+
const logger: Logger = new Logger();
|
|
16
|
+
const network: networks.Network = networks.regtest;
|
|
17
|
+
|
|
18
|
+
describe('Transaction Builder', () => {
|
|
19
|
+
const wBtc: wBTC = new wBTC(network);
|
|
20
|
+
|
|
21
|
+
const wallet: Wallet = new Wallet(Regtest.wallet, network);
|
|
22
|
+
logger.log(`Loaded wallet: ${wallet.p2tr} - ${wallet.p2wpkh}`);
|
|
23
|
+
|
|
24
|
+
const utxoManager: OPNetLimitedProvider = new OPNetLimitedProvider('http://localhost:9001');
|
|
25
|
+
const factory: TransactionFactory = new TransactionFactory();
|
|
26
|
+
|
|
27
|
+
/** @test {TransactionBuilder#build} */
|
|
28
|
+
test('should be able to build a transaction', async () => {
|
|
29
|
+
const utxoSetting: FetchUTXOParams = {
|
|
30
|
+
address: wallet.p2wpkh,
|
|
31
|
+
minAmount: 10000n,
|
|
32
|
+
requestedAmount: 100000n,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const utxos: UTXO[] = await utxoManager.fetchUTXO(utxoSetting);
|
|
36
|
+
console.log(`UTXOs:`, utxos);
|
|
37
|
+
|
|
38
|
+
if (!utxos) {
|
|
39
|
+
throw new Error('No UTXOs found');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
logger.log(`UTXOs fetched. Count: ${utxos.length}`);
|
|
43
|
+
|
|
44
|
+
const interactionParameters: IInteractionParameters = {
|
|
45
|
+
from: wallet.p2wpkh,
|
|
46
|
+
to: wBtc.getAddress(),
|
|
47
|
+
utxos: utxos,
|
|
48
|
+
signer: wallet.keypair,
|
|
49
|
+
network: network,
|
|
50
|
+
feeRate: 150,
|
|
51
|
+
priorityFee: 500n,
|
|
52
|
+
calldata: Buffer.from('test'),
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const finalTx = factory.signInteraction(interactionParameters);
|
|
56
|
+
console.log(`Transaction:`, finalTx);
|
|
57
|
+
});
|
|
58
|
+
});
|