@atomiqlabs/chain-evm 2.1.11 → 2.1.14
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/README.md +75 -0
- package/dist/chains/EVMOptions.d.ts +66 -0
- package/dist/chains/EVMOptions.js +2 -0
- package/dist/chains/alpen/AlpenInitializer.d.ts +3 -30
- package/dist/chains/alpen/AlpenInitializer.js +3 -3
- package/dist/chains/botanix/BotanixInitializer.d.ts +3 -30
- package/dist/chains/botanix/BotanixInitializer.js +3 -3
- package/dist/chains/citrea/CitreaBtcRelay.d.ts +5 -0
- package/dist/chains/citrea/CitreaBtcRelay.js +7 -2
- package/dist/chains/citrea/CitreaFees.d.ts +3 -5
- package/dist/chains/citrea/CitreaFees.js +3 -5
- package/dist/chains/citrea/CitreaInitializer.d.ts +3 -29
- package/dist/chains/citrea/CitreaInitializer.js +3 -3
- package/dist/chains/citrea/CitreaSpvVaultContract.d.ts +5 -0
- package/dist/chains/citrea/CitreaSpvVaultContract.js +7 -2
- package/dist/chains/citrea/CitreaSwapContract.d.ts +7 -2
- package/dist/chains/citrea/CitreaSwapContract.js +10 -5
- package/dist/chains/citrea/CitreaTokens.d.ts +5 -0
- package/dist/chains/citrea/CitreaTokens.js +5 -0
- package/dist/chains/goat/GoatInitializer.d.ts +3 -30
- package/dist/chains/goat/GoatInitializer.js +3 -3
- package/dist/evm/btcrelay/EVMBtcRelay.d.ts +41 -10
- package/dist/evm/btcrelay/EVMBtcRelay.js +50 -18
- package/dist/evm/btcrelay/headers/EVMBtcHeader.d.ts +53 -7
- package/dist/evm/btcrelay/headers/EVMBtcHeader.js +43 -5
- package/dist/evm/btcrelay/headers/EVMBtcStoredHeader.d.ts +53 -8
- package/dist/evm/btcrelay/headers/EVMBtcStoredHeader.js +41 -1
- package/dist/evm/chain/EVMChainInterface.d.ts +57 -2
- package/dist/evm/chain/EVMChainInterface.js +7 -7
- package/dist/evm/chain/EVMModule.d.ts +5 -0
- package/dist/evm/chain/EVMModule.js +6 -1
- package/dist/evm/chain/modules/EVMBlocks.d.ts +7 -0
- package/dist/evm/chain/modules/EVMBlocks.js +2 -0
- package/dist/evm/chain/modules/EVMEvents.js +19 -19
- package/dist/evm/chain/modules/EVMFees.d.ts +41 -5
- package/dist/evm/chain/modules/EVMFees.js +24 -5
- package/dist/evm/chain/modules/EVMTokens.d.ts +1 -1
- package/dist/evm/chain/modules/EVMTokens.js +1 -1
- package/dist/evm/chain/modules/EVMTransactions.d.ts +20 -2
- package/dist/evm/chain/modules/EVMTransactions.js +11 -8
- package/dist/evm/contract/EVMContractBase.d.ts +28 -10
- package/dist/evm/contract/EVMContractBase.js +9 -18
- package/dist/evm/contract/EVMContractModule.d.ts +5 -0
- package/dist/evm/contract/EVMContractModule.js +5 -0
- package/dist/evm/contract/modules/EVMContractEvents.d.ts +7 -1
- package/dist/evm/contract/modules/EVMContractEvents.js +23 -3
- package/dist/evm/events/EVMChainEvents.d.ts +8 -0
- package/dist/evm/events/EVMChainEvents.js +8 -0
- package/dist/evm/events/EVMChainEventsBrowser.d.ts +87 -19
- package/dist/evm/events/EVMChainEventsBrowser.js +53 -18
- package/dist/evm/providers/JsonRpcProviderWithRetries.d.ts +9 -0
- package/dist/evm/providers/JsonRpcProviderWithRetries.js +9 -0
- package/dist/evm/providers/ReconnectingWebSocketProvider.d.ts +5 -0
- package/dist/evm/providers/ReconnectingWebSocketProvider.js +5 -0
- package/dist/evm/providers/WebSocketProviderWithRetries.d.ts +9 -0
- package/dist/evm/providers/WebSocketProviderWithRetries.js +9 -0
- package/dist/evm/spv_swap/EVMSpvVaultContract.d.ts +46 -21
- package/dist/evm/spv_swap/EVMSpvVaultContract.js +62 -22
- package/dist/evm/spv_swap/EVMSpvVaultData.d.ts +57 -2
- package/dist/evm/spv_swap/EVMSpvVaultData.js +57 -2
- package/dist/evm/spv_swap/EVMSpvWithdrawalData.d.ts +12 -0
- package/dist/evm/spv_swap/EVMSpvWithdrawalData.js +12 -0
- package/dist/evm/swaps/EVMSwapContract.d.ts +58 -13
- package/dist/evm/swaps/EVMSwapContract.js +81 -54
- package/dist/evm/swaps/EVMSwapData.d.ts +27 -6
- package/dist/evm/swaps/EVMSwapData.js +26 -0
- package/dist/evm/swaps/EVMSwapModule.d.ts +5 -0
- package/dist/evm/swaps/EVMSwapModule.js +5 -0
- package/dist/evm/swaps/handlers/IHandler.d.ts +5 -0
- package/dist/evm/swaps/handlers/claim/ClaimHandlers.d.ts +15 -0
- package/dist/evm/swaps/handlers/claim/ClaimHandlers.js +5 -0
- package/dist/evm/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.d.ts +5 -0
- package/dist/evm/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.d.ts +10 -0
- package/dist/evm/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.d.ts +5 -0
- package/dist/evm/swaps/handlers/claim/btc/IBitcoinClaimHandler.d.ts +15 -0
- package/dist/evm/swaps/handlers/claim/btc/IBitcoinClaimHandler.js +7 -2
- package/dist/evm/swaps/modules/EVMLpVault.d.ts +5 -0
- package/dist/evm/swaps/modules/EVMLpVault.js +9 -4
- package/dist/evm/swaps/modules/EVMSwapClaim.d.ts +7 -2
- package/dist/evm/swaps/modules/EVMSwapClaim.js +11 -6
- package/dist/evm/swaps/modules/EVMSwapInit.d.ts +10 -0
- package/dist/evm/swaps/modules/EVMSwapInit.js +11 -6
- package/dist/evm/swaps/modules/EVMSwapRefund.d.ts +5 -0
- package/dist/evm/swaps/modules/EVMSwapRefund.js +9 -4
- package/dist/evm/wallet/EVMBrowserSigner.d.ts +22 -2
- package/dist/evm/wallet/EVMBrowserSigner.js +40 -2
- package/dist/evm/wallet/EVMPersistentSigner.d.ts +13 -2
- package/dist/evm/wallet/EVMPersistentSigner.js +13 -1
- package/dist/evm/wallet/EVMSigner.d.ts +30 -1
- package/dist/evm/wallet/EVMSigner.js +34 -1
- package/dist/index.d.ts +71 -0
- package/dist/index.js +70 -0
- package/dist/node/index.d.ts +10 -0
- package/dist/node/index.js +15 -0
- package/dist/utils/Utils.d.ts +50 -0
- package/dist/utils/Utils.js +45 -0
- package/node/index.d.ts +1 -0
- package/node/index.js +3 -0
- package/package.json +4 -3
- package/src/chains/EVMOptions.ts +70 -0
- package/src/chains/alpen/AlpenInitializer.ts +5 -27
- package/src/chains/botanix/BotanixChainType.ts +5 -5
- package/src/chains/botanix/BotanixInitializer.ts +5 -27
- package/src/chains/citrea/CitreaBtcRelay.ts +8 -3
- package/src/chains/citrea/CitreaFees.ts +3 -6
- package/src/chains/citrea/CitreaInitializer.ts +5 -27
- package/src/chains/citrea/CitreaSpvVaultContract.ts +7 -2
- package/src/chains/citrea/CitreaSwapContract.ts +11 -6
- package/src/chains/citrea/CitreaTokens.ts +6 -1
- package/src/chains/goat/GoatChainType.ts +5 -5
- package/src/chains/goat/GoatInitializer.ts +3 -25
- package/src/evm/btcrelay/EVMBtcRelay.ts +54 -22
- package/src/evm/btcrelay/headers/EVMBtcHeader.ts +60 -13
- package/src/evm/btcrelay/headers/EVMBtcStoredHeader.ts +55 -10
- package/src/evm/chain/EVMChainInterface.ts +66 -14
- package/src/evm/chain/EVMModule.ts +6 -1
- package/src/evm/chain/modules/EVMBlocks.ts +7 -0
- package/src/evm/chain/modules/EVMEvents.ts +19 -19
- package/src/evm/chain/modules/EVMFees.ts +41 -5
- package/src/evm/chain/modules/EVMTokens.ts +1 -1
- package/src/evm/chain/modules/EVMTransactions.ts +27 -8
- package/src/evm/contract/EVMContractBase.ts +29 -24
- package/src/evm/contract/EVMContractModule.ts +5 -0
- package/src/evm/contract/modules/EVMContractEvents.ts +27 -8
- package/src/evm/events/EVMChainEvents.ts +8 -0
- package/src/evm/events/EVMChainEventsBrowser.ts +103 -29
- package/src/evm/providers/JsonRpcProviderWithRetries.ts +10 -1
- package/src/evm/providers/ReconnectingWebSocketProvider.ts +6 -1
- package/src/evm/providers/WebSocketProviderWithRetries.ts +10 -1
- package/src/evm/spv_swap/EVMSpvVaultContract.ts +73 -31
- package/src/evm/spv_swap/EVMSpvVaultData.ts +57 -2
- package/src/evm/spv_swap/EVMSpvWithdrawalData.ts +12 -0
- package/src/evm/swaps/EVMSwapContract.ts +108 -63
- package/src/evm/swaps/EVMSwapData.ts +27 -1
- package/src/evm/swaps/EVMSwapModule.ts +5 -0
- package/src/evm/swaps/handlers/IHandler.ts +5 -0
- package/src/evm/swaps/handlers/claim/ClaimHandlers.ts +15 -0
- package/src/evm/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.ts +5 -0
- package/src/evm/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.ts +10 -0
- package/src/evm/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.ts +5 -0
- package/src/evm/swaps/handlers/claim/btc/IBitcoinClaimHandler.ts +17 -2
- package/src/evm/swaps/modules/EVMLpVault.ts +10 -5
- package/src/evm/swaps/modules/EVMSwapClaim.ts +12 -7
- package/src/evm/swaps/modules/EVMSwapInit.ts +17 -7
- package/src/evm/swaps/modules/EVMSwapRefund.ts +9 -4
- package/src/evm/wallet/EVMBrowserSigner.ts +44 -5
- package/src/evm/wallet/EVMPersistentSigner.ts +14 -2
- package/src/evm/wallet/EVMSigner.ts +37 -1
- package/src/index.ts +72 -0
- package/src/node/index.ts +10 -0
- package/src/utils/Utils.ts +50 -1
|
@@ -39,16 +39,28 @@ function decodeUtxo(utxo: string): {txHash: string, vout: bigint} {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Packs vault owner and vault id into compact `owner+vaultId` event key format.
|
|
44
|
+
*
|
|
45
|
+
* @category Swaps
|
|
46
|
+
*/
|
|
42
47
|
export function packOwnerAndVaultId(owner: string, vaultId: bigint): string {
|
|
43
48
|
if(owner.length!==42) throw new Error("Invalid owner address");
|
|
44
49
|
return owner.toLowerCase() + BigIntBufferUtils.toBuffer(vaultId, "be", 12).toString("hex");
|
|
45
50
|
}
|
|
46
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Unpacks compact `owner+vaultId` event key format into owner and vault id.
|
|
54
|
+
*
|
|
55
|
+
* @category Swaps
|
|
56
|
+
*/
|
|
47
57
|
export function unpackOwnerAndVaultId(data: string): [string, bigint] {
|
|
48
58
|
return [getAddress(data.substring(0, 42)), BigInt("0x"+data.substring(42, 66))];
|
|
49
59
|
}
|
|
50
60
|
|
|
51
61
|
/**
|
|
62
|
+
* EVM SPV vault (UTXO-controlled vault) contract representation.
|
|
63
|
+
*
|
|
52
64
|
* @category Swaps
|
|
53
65
|
*/
|
|
54
66
|
export class EVMSpvVaultContract<ChainId extends string>
|
|
@@ -61,7 +73,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
61
73
|
EVMSpvVaultData
|
|
62
74
|
>
|
|
63
75
|
{
|
|
64
|
-
|
|
76
|
+
private static readonly GasCosts = {
|
|
65
77
|
DEPOSIT_BASE: 15_000 + 21_000,
|
|
66
78
|
DEPOSIT_ERC20: 40_000,
|
|
67
79
|
|
|
@@ -79,12 +91,12 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
79
91
|
};
|
|
80
92
|
|
|
81
93
|
readonly chainId: ChainId;
|
|
94
|
+
public readonly claimTimeout: number = 180;
|
|
82
95
|
|
|
83
|
-
readonly btcRelay: EVMBtcRelay<any>;
|
|
84
|
-
readonly bitcoinRpc: BitcoinRpc<any>;
|
|
85
|
-
readonly claimTimeout: number = 180;
|
|
96
|
+
private readonly btcRelay: EVMBtcRelay<any>;
|
|
97
|
+
private readonly bitcoinRpc: BitcoinRpc<any>;
|
|
86
98
|
|
|
87
|
-
readonly logger = getLogger("EVMSpvVaultContract: ");
|
|
99
|
+
private readonly logger = getLogger("EVMSpvVaultContract: ");
|
|
88
100
|
|
|
89
101
|
constructor(
|
|
90
102
|
chainInterface: EVMChainInterface<ChainId>,
|
|
@@ -100,20 +112,20 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
100
112
|
}
|
|
101
113
|
|
|
102
114
|
//Transactions
|
|
103
|
-
|
|
115
|
+
private async Open(signer: string, vault: EVMSpvVaultData, feeRate: string): Promise<TransactionRequest> {
|
|
104
116
|
const {txHash, vout} = decodeUtxo(vault.getUtxo());
|
|
105
117
|
|
|
106
118
|
const tokens = vault.getTokenData();
|
|
107
119
|
if(tokens.length!==2) throw new Error("Must specify exactly 2 tokens for vault!");
|
|
108
120
|
|
|
109
|
-
const tx = await this.contract.open.populateTransaction(vault.vaultId, vault.
|
|
121
|
+
const tx = await this.contract.open.populateTransaction(vault.vaultId, vault._getVaultParamsStruct(), txHash, vout);
|
|
110
122
|
tx.from = signer;
|
|
111
123
|
EVMFees.applyFeeRate(tx, EVMSpvVaultContract.GasCosts.OPEN, feeRate);
|
|
112
124
|
|
|
113
125
|
return tx;
|
|
114
126
|
}
|
|
115
127
|
|
|
116
|
-
|
|
128
|
+
private async Deposit(signer: string, vault: EVMSpvVaultData, rawAmounts: bigint[], feeRate: string): Promise<TransactionRequest> {
|
|
117
129
|
let totalGas = EVMSpvVaultContract.GasCosts.DEPOSIT_BASE;
|
|
118
130
|
let value = 0n;
|
|
119
131
|
if(vault.token0.token.toLowerCase()===this.Chain.getNativeCurrencyAddress().toLowerCase()) {
|
|
@@ -129,7 +141,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
129
141
|
}
|
|
130
142
|
|
|
131
143
|
const tx = await this.contract.deposit.populateTransaction(
|
|
132
|
-
vault.owner, vault.vaultId, vault.
|
|
144
|
+
vault.owner, vault.vaultId, vault._getVaultParamsStruct(),
|
|
133
145
|
rawAmounts[0], rawAmounts[1] ?? 0n, { value }
|
|
134
146
|
);
|
|
135
147
|
tx.from = signer;
|
|
@@ -138,7 +150,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
138
150
|
return tx;
|
|
139
151
|
}
|
|
140
152
|
|
|
141
|
-
|
|
153
|
+
private async Front(
|
|
142
154
|
signer: string, vault: EVMSpvVaultData, data: EVMSpvWithdrawalData, withdrawalSequence: number, feeRate: string
|
|
143
155
|
): Promise<TransactionRequest> {
|
|
144
156
|
let value = 0n;
|
|
@@ -149,7 +161,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
149
161
|
value += (frontingAmount[1] ?? 0n) * vault.token1.multiplier;
|
|
150
162
|
|
|
151
163
|
const tx = await this.contract.front.populateTransaction(
|
|
152
|
-
vault.owner, vault.vaultId, vault.
|
|
164
|
+
vault.owner, vault.vaultId, vault._getVaultParamsStruct(),
|
|
153
165
|
withdrawalSequence, data.getTxHash(), data.serializeToStruct(),
|
|
154
166
|
{ value }
|
|
155
167
|
);
|
|
@@ -159,12 +171,12 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
159
171
|
return tx;
|
|
160
172
|
}
|
|
161
173
|
|
|
162
|
-
|
|
174
|
+
private async Claim(
|
|
163
175
|
signer: string, vault: EVMSpvVaultData, data: EVMSpvWithdrawalData,
|
|
164
176
|
blockheader: EVMBtcStoredHeader, merkle: Buffer[], position: number, feeRate: string
|
|
165
177
|
): Promise<TransactionRequest> {
|
|
166
178
|
const tx = await this.contract.claim.populateTransaction(
|
|
167
|
-
vault.owner, vault.vaultId, vault.
|
|
179
|
+
vault.owner, vault.vaultId, vault._getVaultParamsStruct(), "0x"+data.btcTx.hex,
|
|
168
180
|
blockheader.serializeToStruct(), merkle, position
|
|
169
181
|
)
|
|
170
182
|
|
|
@@ -191,7 +203,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
191
203
|
if(tokenData.length!==2) throw new Error("Must specify 2 tokens in tokenData!");
|
|
192
204
|
|
|
193
205
|
const vaultParams = {
|
|
194
|
-
btcRelayContract: this.btcRelay.
|
|
206
|
+
btcRelayContract: this.btcRelay._contractAddress,
|
|
195
207
|
token0: tokenData[0].token,
|
|
196
208
|
token1: tokenData[1].token,
|
|
197
209
|
token0Multiplier: tokenData[0].multiplier,
|
|
@@ -239,7 +251,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
239
251
|
promises.push(this.getFronterAddress(owner, vaultId, withdrawal).then(val => {
|
|
240
252
|
result[withdrawal.getTxId()] = val;
|
|
241
253
|
}));
|
|
242
|
-
if(promises.length>=this.Chain.
|
|
254
|
+
if(promises.length>=this.Chain._config.maxParallelCalls) {
|
|
243
255
|
await Promise.all(promises);
|
|
244
256
|
promises = [];
|
|
245
257
|
}
|
|
@@ -260,7 +272,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
260
272
|
|
|
261
273
|
const vaultParams = await this.vaultParamsCache.getOrComputeAsync(vaultState.spvVaultParametersCommitment, async () => {
|
|
262
274
|
const blockheight = Number(vaultState.openBlockheight);
|
|
263
|
-
const events = await this.
|
|
275
|
+
const events = await this._Events.getContractBlockEvents(
|
|
264
276
|
["Opened"],
|
|
265
277
|
[
|
|
266
278
|
"0x"+owner.substring(2).padStart(64, "0"),
|
|
@@ -277,7 +289,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
277
289
|
return foundEvent.args.params;
|
|
278
290
|
});
|
|
279
291
|
|
|
280
|
-
if(vaultParams.btcRelayContract.toLowerCase()!==this.btcRelay.
|
|
292
|
+
if(vaultParams.btcRelayContract.toLowerCase()!==this.btcRelay._contractAddress.toLowerCase()) return null;
|
|
281
293
|
|
|
282
294
|
return new EVMSpvVaultData(owner, vaultId, vaultState, vaultParams);
|
|
283
295
|
}
|
|
@@ -294,7 +306,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
294
306
|
result[owner] ??= {};
|
|
295
307
|
result[owner][vaultId.toString(10)] = val;
|
|
296
308
|
}));
|
|
297
|
-
if(promises.length>=this.Chain.
|
|
309
|
+
if(promises.length>=this.Chain._config.maxParallelCalls) {
|
|
298
310
|
await Promise.all(promises);
|
|
299
311
|
promises = [];
|
|
300
312
|
}
|
|
@@ -325,7 +337,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
325
337
|
result[owner] ??= {};
|
|
326
338
|
result[owner][vaultId.toString(10)] = val;
|
|
327
339
|
}));
|
|
328
|
-
if(promises.length>=this.Chain.
|
|
340
|
+
if(promises.length>=this.Chain._config.maxParallelCalls) {
|
|
329
341
|
await Promise.all(promises);
|
|
330
342
|
promises = [];
|
|
331
343
|
}
|
|
@@ -339,7 +351,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
339
351
|
*/
|
|
340
352
|
async getAllVaults(owner?: string): Promise<EVMSpvVaultData[]> {
|
|
341
353
|
const openedVaults = new Map<string, SpvVaultParametersStructOutput>();
|
|
342
|
-
await this.
|
|
354
|
+
await this._Events.findInContractEventsForward(
|
|
343
355
|
["Opened", "Closed"],
|
|
344
356
|
owner==null ? null : [
|
|
345
357
|
"0x"+owner.substring(2).padStart(64, "0")
|
|
@@ -358,6 +370,8 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
358
370
|
const vaults: EVMSpvVaultData[] = [];
|
|
359
371
|
let promises: Promise<void>[] = [];
|
|
360
372
|
for(let [identifier, vaultParams] of openedVaults.entries()) {
|
|
373
|
+
if(vaultParams.btcRelayContract.toLowerCase()!==this.btcRelay._contractAddress.toLowerCase()) continue;
|
|
374
|
+
|
|
361
375
|
const [owner, vaultIdStr] = identifier.split(":");
|
|
362
376
|
|
|
363
377
|
promises.push(this.contract.getVault(owner, BigInt(vaultIdStr)).then(vaultState => {
|
|
@@ -366,7 +380,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
366
380
|
}
|
|
367
381
|
}))
|
|
368
382
|
|
|
369
|
-
if(promises.length>=this.Chain.
|
|
383
|
+
if(promises.length>=this.Chain._config.maxParallelCalls) {
|
|
370
384
|
await Promise.all(promises);
|
|
371
385
|
promises = [];
|
|
372
386
|
}
|
|
@@ -442,14 +456,14 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
442
456
|
|
|
443
457
|
let result: SpvWithdrawalState | null;
|
|
444
458
|
if(scStartHeight==null) {
|
|
445
|
-
result = await this.
|
|
459
|
+
result = await this._Events.findInContractEvents(
|
|
446
460
|
events, keys,
|
|
447
461
|
async (event) => {
|
|
448
462
|
return this.parseWithdrawalEvent(event);
|
|
449
463
|
}
|
|
450
464
|
);
|
|
451
465
|
} else {
|
|
452
|
-
result = await this.
|
|
466
|
+
result = await this._Events.findInContractEventsForward(
|
|
453
467
|
events, keys,
|
|
454
468
|
async (event) => {
|
|
455
469
|
const result = this.parseWithdrawalEvent(event);
|
|
@@ -479,8 +493,8 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
479
493
|
|
|
480
494
|
const events: ["Fronted", "Claimed", "Closed"] = ["Fronted", "Claimed", "Closed"];
|
|
481
495
|
|
|
482
|
-
for(let i=0;i<withdrawalTxs.length;i+=this.Chain.
|
|
483
|
-
const checkWithdrawalTxs = withdrawalTxs.slice(i, i+this.Chain.
|
|
496
|
+
for(let i=0;i<withdrawalTxs.length;i+=this.Chain._config.maxLogTopics) {
|
|
497
|
+
const checkWithdrawalTxs = withdrawalTxs.slice(i, i+this.Chain._config.maxLogTopics);
|
|
484
498
|
const checkWithdrawalTxsMap = new Map(checkWithdrawalTxs.map(val => [val.withdrawal.getTxId() as string, val.withdrawal]));
|
|
485
499
|
|
|
486
500
|
let scStartHeight = null;
|
|
@@ -495,7 +509,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
495
509
|
const keys = [null, null, checkWithdrawalTxs.map(withdrawal => hexlify(Buffer.from(withdrawal.withdrawal.getTxId(), "hex").reverse()))];
|
|
496
510
|
|
|
497
511
|
if(scStartHeight==null) {
|
|
498
|
-
await this.
|
|
512
|
+
await this._Events.findInContractEvents(
|
|
499
513
|
events, keys,
|
|
500
514
|
async (event) => {
|
|
501
515
|
const _event = event as TypedEventLog<SpvVaultManager["filters"]["Fronted" | "Claimed" | "Closed"]>;
|
|
@@ -512,7 +526,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
512
526
|
}
|
|
513
527
|
);
|
|
514
528
|
} else {
|
|
515
|
-
await this.
|
|
529
|
+
await this._Events.findInContractEventsForward(
|
|
516
530
|
events, keys,
|
|
517
531
|
async (event) => {
|
|
518
532
|
const _event = event as TypedEventLog<SpvVaultManager["filters"]["Fronted" | "Claimed" | "Closed"]>;
|
|
@@ -558,7 +572,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
558
572
|
const {height: latestBlockheight} = await this.Chain.getFinalizedBlock();
|
|
559
573
|
const withdrawals: { [btcTxId: string]: SpvWithdrawalClaimedState | SpvWithdrawalFrontedState } = {};
|
|
560
574
|
|
|
561
|
-
await this.
|
|
575
|
+
await this._Events.findInContractEventsForward(
|
|
562
576
|
["Claimed", "Fronted"],
|
|
563
577
|
[null, recipient],
|
|
564
578
|
async (_event) => {
|
|
@@ -589,6 +603,12 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
589
603
|
fromOpReturnData(data: Buffer): { recipient: string; rawAmounts: bigint[]; executionHash?: string } {
|
|
590
604
|
return EVMSpvVaultContract.fromOpReturnData(data);
|
|
591
605
|
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Parses withdrawal params from OP_RETURN data.
|
|
609
|
+
*
|
|
610
|
+
* @param data Data as specified in the OP_RETURN output of the transaction
|
|
611
|
+
*/
|
|
592
612
|
static fromOpReturnData(data: Buffer): { recipient: string; rawAmounts: bigint[]; executionHash?: string } {
|
|
593
613
|
let rawAmount0: bigint = 0n;
|
|
594
614
|
let rawAmount1: bigint = 0n;
|
|
@@ -621,6 +641,14 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
621
641
|
toOpReturnData(recipient: string, rawAmounts: bigint[], executionHash?: string): Buffer {
|
|
622
642
|
return EVMSpvVaultContract.toOpReturnData(recipient, rawAmounts, executionHash);
|
|
623
643
|
}
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* Serializes withdrawal params to OP_RETURN data.
|
|
647
|
+
*
|
|
648
|
+
* @param recipient Recipient of the withdrawn tokens
|
|
649
|
+
* @param rawAmounts Raw amount of tokens to withdraw
|
|
650
|
+
* @param executionHash Optional execution hash of the actions to execute
|
|
651
|
+
*/
|
|
624
652
|
static toOpReturnData(recipient: string, rawAmounts: bigint[], executionHash?: string): Buffer {
|
|
625
653
|
if(!EVMAddresses.isValidAddress(recipient)) throw new Error("Invalid recipient specified");
|
|
626
654
|
if(rawAmounts.length < 1) throw new Error("At least 1 amount needs to be specified");
|
|
@@ -767,7 +795,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
767
795
|
}
|
|
768
796
|
|
|
769
797
|
const requiredApprovalTxns = await Promise.all(
|
|
770
|
-
Object.keys(requiredApprovals).map(token => this.Chain.Tokens.checkAndGetApproveTx(signer, token, requiredApprovals[token], this.
|
|
798
|
+
Object.keys(requiredApprovals).map(token => this.Chain.Tokens.checkAndGetApproveTx(signer, token, requiredApprovals[token], this._contractAddress, feeRate))
|
|
771
799
|
);
|
|
772
800
|
requiredApprovalTxns.forEach(tx => tx!=null && txs.push(tx));
|
|
773
801
|
|
|
@@ -811,7 +839,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
811
839
|
}
|
|
812
840
|
|
|
813
841
|
const requiredApprovalTxns = await Promise.all(
|
|
814
|
-
Object.keys(requiredApprovals).map(token => this.Chain.Tokens.checkAndGetApproveTx(signer, token, requiredApprovals[token], this.
|
|
842
|
+
Object.keys(requiredApprovals).map(token => this.Chain.Tokens.checkAndGetApproveTx(signer, token, requiredApprovals[token], this._contractAddress, feeRate))
|
|
815
843
|
);
|
|
816
844
|
requiredApprovalTxns.forEach(tx => tx!=null && txs.push(tx));
|
|
817
845
|
|
|
@@ -839,6 +867,13 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
839
867
|
return [tx];
|
|
840
868
|
}
|
|
841
869
|
|
|
870
|
+
/**
|
|
871
|
+
* Returns an estimated gas amount for a claim transaction.
|
|
872
|
+
*
|
|
873
|
+
* @param signer Signer address executing the claim
|
|
874
|
+
* @param vault Vault data used to determine transfer paths
|
|
875
|
+
* @param data Parsed withdrawal data
|
|
876
|
+
*/
|
|
842
877
|
getClaimGas(signer: string, vault?: EVMSpvVaultData, data?: EVMSpvWithdrawalData): number {
|
|
843
878
|
let totalGas = EVMSpvVaultContract.GasCosts.CLAIM_BASE;
|
|
844
879
|
|
|
@@ -861,6 +896,13 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
861
896
|
return totalGas;
|
|
862
897
|
}
|
|
863
898
|
|
|
899
|
+
/**
|
|
900
|
+
* Returns an estimated gas amount for a front-liquidity transaction.
|
|
901
|
+
*
|
|
902
|
+
* @param signer Signer address executing the front action
|
|
903
|
+
* @param vault Vault data used to determine transfer paths
|
|
904
|
+
* @param data Parsed withdrawal data
|
|
905
|
+
*/
|
|
864
906
|
getFrontGas(signer: string, vault: EVMSpvVaultData, data?: EVMSpvWithdrawalData): number {
|
|
865
907
|
let totalGas = EVMSpvVaultContract.GasCosts.FRONT_BASE;
|
|
866
908
|
|
|
@@ -889,7 +931,7 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
889
931
|
* @inheritDoc
|
|
890
932
|
*/
|
|
891
933
|
async getFrontFee(signer: string, vault?: EVMSpvVaultData, withdrawalData?: EVMSpvWithdrawalData, feeRate?: string): Promise<bigint> {
|
|
892
|
-
vault ??= EVMSpvVaultData.
|
|
934
|
+
vault ??= EVMSpvVaultData._randomVault();
|
|
893
935
|
feeRate ??= await this.Chain.Fees.getFeeRate();
|
|
894
936
|
let totalFee = EVMFees.getGasFee(this.getFrontGas(signer, vault, withdrawalData), feeRate);
|
|
895
937
|
if(withdrawalData==null || (withdrawalData.rawAmounts[0]!=null && withdrawalData.rawAmounts[0]>0n)) {
|
|
@@ -16,6 +16,11 @@ import {AbiCoder, keccak256} from "ethers";
|
|
|
16
16
|
import {EVMAddresses} from "../chain/modules/EVMAddresses";
|
|
17
17
|
import type {AddressLike, BigNumberish, BytesLike} from "ethers/lib.esm";
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Computes the vault parameter commitment hash used by the on-chain SPV vault state.
|
|
21
|
+
*
|
|
22
|
+
* @category Swaps
|
|
23
|
+
*/
|
|
19
24
|
export function getVaultParamsCommitment(vaultParams: SpvVaultParametersStruct) {
|
|
20
25
|
return keccak256(AbiCoder.defaultAbiCoder().encode(
|
|
21
26
|
["address", "address", "address", "uint192", "uint192", "uint256"],
|
|
@@ -23,12 +28,19 @@ export function getVaultParamsCommitment(vaultParams: SpvVaultParametersStruct)
|
|
|
23
28
|
));
|
|
24
29
|
}
|
|
25
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Decodes UTXO reference (`txid:vout`) from the on-chain SPV vault state struct.
|
|
33
|
+
*
|
|
34
|
+
* @category Swaps
|
|
35
|
+
*/
|
|
26
36
|
export function getVaultUtxoFromState(state: SpvVaultStateStruct): string {
|
|
27
37
|
const txHash = Buffer.from(hexlify(state.utxoTxHash).substring(2), "hex");
|
|
28
38
|
return txHash.reverse().toString("hex")+":"+BigInt(state.utxoVout).toString(10);
|
|
29
39
|
}
|
|
30
40
|
|
|
31
41
|
/**
|
|
42
|
+
* Represents the state of the EVM SPV vault (UTXO-controlled vault).
|
|
43
|
+
*
|
|
32
44
|
* @category Swaps
|
|
33
45
|
*/
|
|
34
46
|
export class EVMSpvVaultData extends SpvVaultData<EVMSpvWithdrawalData> {
|
|
@@ -102,6 +114,9 @@ export class EVMSpvVaultData extends SpvVaultData<EVMSpvWithdrawalData> {
|
|
|
102
114
|
}
|
|
103
115
|
}
|
|
104
116
|
|
|
117
|
+
/**
|
|
118
|
+
* @inheritDoc
|
|
119
|
+
*/
|
|
105
120
|
getBalances(): SpvVaultTokenBalance[] {
|
|
106
121
|
return [
|
|
107
122
|
{...this.token0, scaledAmount: this.token0.rawAmount * this.token0.multiplier},
|
|
@@ -109,34 +124,58 @@ export class EVMSpvVaultData extends SpvVaultData<EVMSpvWithdrawalData> {
|
|
|
109
124
|
];
|
|
110
125
|
}
|
|
111
126
|
|
|
127
|
+
/**
|
|
128
|
+
* @inheritDoc
|
|
129
|
+
*/
|
|
112
130
|
getConfirmations(): number {
|
|
113
131
|
return this.confirmations;
|
|
114
132
|
}
|
|
115
133
|
|
|
134
|
+
/**
|
|
135
|
+
* @inheritDoc
|
|
136
|
+
*/
|
|
116
137
|
getOwner(): string {
|
|
117
138
|
return this.owner;
|
|
118
139
|
}
|
|
119
140
|
|
|
141
|
+
/**
|
|
142
|
+
* @inheritDoc
|
|
143
|
+
*/
|
|
120
144
|
getTokenData(): SpvVaultTokenData[] {
|
|
121
145
|
return [this.token0, this.token1];
|
|
122
146
|
}
|
|
123
147
|
|
|
148
|
+
/**
|
|
149
|
+
* @inheritDoc
|
|
150
|
+
*/
|
|
124
151
|
getUtxo(): string {
|
|
125
152
|
return this.isOpened() ? this.utxo : this.initialUtxo!;
|
|
126
153
|
}
|
|
127
154
|
|
|
155
|
+
/**
|
|
156
|
+
* @inheritDoc
|
|
157
|
+
*/
|
|
128
158
|
getVaultId(): bigint {
|
|
129
159
|
return this.vaultId;
|
|
130
160
|
}
|
|
131
161
|
|
|
162
|
+
/**
|
|
163
|
+
* @inheritDoc
|
|
164
|
+
*/
|
|
132
165
|
getWithdrawalCount(): number {
|
|
133
166
|
return this.withdrawCount;
|
|
134
167
|
}
|
|
135
168
|
|
|
169
|
+
/**
|
|
170
|
+
* @inheritDoc
|
|
171
|
+
*/
|
|
136
172
|
isOpened(): boolean {
|
|
137
173
|
return this.utxo!=="0000000000000000000000000000000000000000000000000000000000000000:0";
|
|
138
174
|
}
|
|
139
175
|
|
|
176
|
+
/**
|
|
177
|
+
* @inheritDoc
|
|
178
|
+
*/
|
|
140
179
|
serialize(): any {
|
|
141
180
|
return {
|
|
142
181
|
type: "EVM",
|
|
@@ -161,6 +200,9 @@ export class EVMSpvVaultData extends SpvVaultData<EVMSpvWithdrawalData> {
|
|
|
161
200
|
}
|
|
162
201
|
}
|
|
163
202
|
|
|
203
|
+
/**
|
|
204
|
+
* @inheritDoc
|
|
205
|
+
*/
|
|
164
206
|
updateState(withdrawalTxOrEvent: SpvVaultClaimEvent | SpvVaultCloseEvent | SpvVaultOpenEvent | SpvVaultDepositEvent | EVMSpvWithdrawalData): void {
|
|
165
207
|
if(withdrawalTxOrEvent instanceof SpvVaultClaimEvent) {
|
|
166
208
|
if(withdrawalTxOrEvent.withdrawCount <= this.withdrawCount) return;
|
|
@@ -194,11 +236,19 @@ export class EVMSpvVaultData extends SpvVaultData<EVMSpvWithdrawalData> {
|
|
|
194
236
|
}
|
|
195
237
|
}
|
|
196
238
|
|
|
239
|
+
/**
|
|
240
|
+
* @inheritDoc
|
|
241
|
+
*/
|
|
197
242
|
getDepositCount(): number {
|
|
198
243
|
return this.depositCount;
|
|
199
244
|
}
|
|
200
245
|
|
|
201
|
-
|
|
246
|
+
/**
|
|
247
|
+
* Serializes this spv vault data to a struct object which can be passed to the ether.js functions
|
|
248
|
+
*
|
|
249
|
+
* @internal
|
|
250
|
+
*/
|
|
251
|
+
_getVaultParamsStruct(): SpvVaultParametersStruct {
|
|
202
252
|
return {
|
|
203
253
|
btcRelayContract: this.relayContract,
|
|
204
254
|
token0: this.token0.token,
|
|
@@ -209,7 +259,12 @@ export class EVMSpvVaultData extends SpvVaultData<EVMSpvWithdrawalData> {
|
|
|
209
259
|
}
|
|
210
260
|
}
|
|
211
261
|
|
|
212
|
-
|
|
262
|
+
/**
|
|
263
|
+
* Returns a dummy random vault that can be used for e.g. fee estimation
|
|
264
|
+
*
|
|
265
|
+
* @internal
|
|
266
|
+
*/
|
|
267
|
+
static _randomVault(): EVMSpvVaultData {
|
|
213
268
|
const spvVaultParams = {
|
|
214
269
|
btcRelayContract: EVMAddresses.randomAddress(),
|
|
215
270
|
token0: EVMAddresses.randomAddress(),
|
|
@@ -5,6 +5,9 @@ import {BitcoinVaultTransactionDataStruct} from "./SpvVaultContractTypechain";
|
|
|
5
5
|
import {AbiCoder, keccak256, ZeroHash} from "ethers";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
+
* Represents parsed withdrawal data used for claiming assets from the EVM SPV vault
|
|
9
|
+
* (UTXO-controlled vault).
|
|
10
|
+
*
|
|
8
11
|
* @category Swaps
|
|
9
12
|
*/
|
|
10
13
|
export class EVMSpvWithdrawalData extends SpvWithdrawalTransactionData {
|
|
@@ -43,10 +46,16 @@ export class EVMSpvWithdrawalData extends SpvWithdrawalTransactionData {
|
|
|
43
46
|
)).substring(2);
|
|
44
47
|
}
|
|
45
48
|
|
|
49
|
+
/**
|
|
50
|
+
* @inheritDoc
|
|
51
|
+
*/
|
|
46
52
|
getTxHash(): string {
|
|
47
53
|
return "0x"+Buffer.from(this.btcTx.txid, "hex").reverse().toString("hex");
|
|
48
54
|
}
|
|
49
55
|
|
|
56
|
+
/**
|
|
57
|
+
* @inheritDoc
|
|
58
|
+
*/
|
|
50
59
|
getFrontingAmount(): bigint[] {
|
|
51
60
|
return [this.rawAmounts[0] + this.getExecutionFee()[0], this.rawAmounts[1]];
|
|
52
61
|
}
|
|
@@ -61,6 +70,9 @@ export class EVMSpvWithdrawalData extends SpvWithdrawalTransactionData {
|
|
|
61
70
|
};
|
|
62
71
|
}
|
|
63
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Serializes the withdrawal data to the EVM contract struct representation.
|
|
75
|
+
*/
|
|
64
76
|
serializeToStruct(): BitcoinVaultTransactionDataStruct {
|
|
65
77
|
const callerFee = this.getCallerFee();
|
|
66
78
|
const frontingFee = this.getFrontingFee();
|