@atomiqlabs/chain-starknet 8.0.13 → 8.1.10

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.
Files changed (119) hide show
  1. package/dist/index.d.ts +18 -18
  2. package/dist/index.js +42 -42
  3. package/dist/starknet/StarknetChainType.d.ts +19 -19
  4. package/dist/starknet/StarknetChainType.js +2 -2
  5. package/dist/starknet/StarknetInitializer.d.ts +66 -63
  6. package/dist/starknet/StarknetInitializer.js +101 -101
  7. package/dist/starknet/btcrelay/BtcRelayAbi.d.ts +250 -250
  8. package/dist/starknet/btcrelay/BtcRelayAbi.js +341 -341
  9. package/dist/starknet/btcrelay/StarknetBtcRelay.d.ts +196 -196
  10. package/dist/starknet/btcrelay/StarknetBtcRelay.js +419 -411
  11. package/dist/starknet/btcrelay/headers/StarknetBtcHeader.d.ts +70 -70
  12. package/dist/starknet/btcrelay/headers/StarknetBtcHeader.js +115 -115
  13. package/dist/starknet/btcrelay/headers/StarknetBtcStoredHeader.d.ts +91 -91
  14. package/dist/starknet/btcrelay/headers/StarknetBtcStoredHeader.js +155 -155
  15. package/dist/starknet/chain/StarknetAction.d.ts +19 -19
  16. package/dist/starknet/chain/StarknetAction.js +74 -74
  17. package/dist/starknet/chain/StarknetChainInterface.d.ts +142 -143
  18. package/dist/starknet/chain/StarknetChainInterface.js +198 -199
  19. package/dist/starknet/chain/StarknetModule.d.ts +8 -8
  20. package/dist/starknet/chain/StarknetModule.js +12 -12
  21. package/dist/starknet/chain/modules/ERC20Abi.d.ts +755 -755
  22. package/dist/starknet/chain/modules/ERC20Abi.js +1032 -1032
  23. package/dist/starknet/chain/modules/StarknetAccounts.d.ts +6 -6
  24. package/dist/starknet/chain/modules/StarknetAccounts.js +26 -26
  25. package/dist/starknet/chain/modules/StarknetAddresses.d.ts +10 -10
  26. package/dist/starknet/chain/modules/StarknetAddresses.js +27 -27
  27. package/dist/starknet/chain/modules/StarknetBlocks.d.ts +27 -27
  28. package/dist/starknet/chain/modules/StarknetBlocks.js +82 -82
  29. package/dist/starknet/chain/modules/StarknetEvents.d.ts +47 -47
  30. package/dist/starknet/chain/modules/StarknetEvents.js +90 -90
  31. package/dist/starknet/chain/modules/StarknetFees.d.ts +118 -104
  32. package/dist/starknet/chain/modules/StarknetFees.js +150 -146
  33. package/dist/starknet/chain/modules/StarknetSignatures.d.ts +29 -29
  34. package/dist/starknet/chain/modules/StarknetSignatures.js +72 -72
  35. package/dist/starknet/chain/modules/StarknetTokens.d.ts +66 -66
  36. package/dist/starknet/chain/modules/StarknetTokens.js +99 -99
  37. package/dist/starknet/chain/modules/StarknetTransactions.d.ts +122 -115
  38. package/dist/starknet/chain/modules/StarknetTransactions.js +633 -612
  39. package/dist/starknet/contract/StarknetContractBase.d.ts +14 -13
  40. package/dist/starknet/contract/StarknetContractBase.js +21 -20
  41. package/dist/starknet/contract/StarknetContractModule.d.ts +8 -8
  42. package/dist/starknet/contract/StarknetContractModule.js +11 -11
  43. package/dist/starknet/contract/modules/StarknetContractEvents.d.ts +56 -57
  44. package/dist/starknet/contract/modules/StarknetContractEvents.js +111 -111
  45. package/dist/starknet/events/StarknetChainEvents.d.ts +21 -21
  46. package/dist/starknet/events/StarknetChainEvents.js +61 -61
  47. package/dist/starknet/events/StarknetChainEventsBrowser.d.ts +178 -190
  48. package/dist/starknet/events/StarknetChainEventsBrowser.js +523 -582
  49. package/dist/starknet/provider/RpcProviderWithRetries.d.ts +49 -53
  50. package/dist/starknet/provider/RpcProviderWithRetries.js +94 -94
  51. package/dist/starknet/provider/WebSocketChannelWithRetries.d.ts +21 -21
  52. package/dist/starknet/provider/WebSocketChannelWithRetries.js +46 -46
  53. package/dist/starknet/spv_swap/SpvVaultContractAbi.d.ts +488 -488
  54. package/dist/starknet/spv_swap/SpvVaultContractAbi.js +656 -656
  55. package/dist/starknet/spv_swap/StarknetSpvVaultContract.d.ts +225 -219
  56. package/dist/starknet/spv_swap/StarknetSpvVaultContract.js +663 -621
  57. package/dist/starknet/spv_swap/StarknetSpvVaultData.d.ts +108 -108
  58. package/dist/starknet/spv_swap/StarknetSpvVaultData.js +190 -190
  59. package/dist/starknet/spv_swap/StarknetSpvWithdrawalData.d.ts +56 -56
  60. package/dist/starknet/spv_swap/StarknetSpvWithdrawalData.js +103 -103
  61. package/dist/starknet/swaps/EscrowManagerAbi.d.ts +431 -431
  62. package/dist/starknet/swaps/EscrowManagerAbi.js +583 -583
  63. package/dist/starknet/swaps/StarknetSwapContract.d.ts +309 -278
  64. package/dist/starknet/swaps/StarknetSwapContract.js +755 -579
  65. package/dist/starknet/swaps/StarknetSwapData.d.ts +234 -234
  66. package/dist/starknet/swaps/StarknetSwapData.js +474 -474
  67. package/dist/starknet/swaps/StarknetSwapModule.d.ts +10 -10
  68. package/dist/starknet/swaps/StarknetSwapModule.js +12 -12
  69. package/dist/starknet/swaps/handlers/IHandler.d.ts +13 -13
  70. package/dist/starknet/swaps/handlers/IHandler.js +2 -2
  71. package/dist/starknet/swaps/handlers/claim/ClaimHandlers.d.ts +13 -13
  72. package/dist/starknet/swaps/handlers/claim/ClaimHandlers.js +13 -13
  73. package/dist/starknet/swaps/handlers/claim/HashlockClaimHandler.d.ts +21 -21
  74. package/dist/starknet/swaps/handlers/claim/HashlockClaimHandler.js +44 -44
  75. package/dist/starknet/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.d.ts +24 -24
  76. package/dist/starknet/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.js +48 -48
  77. package/dist/starknet/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.d.ts +25 -25
  78. package/dist/starknet/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.js +40 -40
  79. package/dist/starknet/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.d.ts +20 -20
  80. package/dist/starknet/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.js +30 -30
  81. package/dist/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.d.ts +42 -45
  82. package/dist/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.js +50 -54
  83. package/dist/starknet/swaps/handlers/refund/TimelockRefundHandler.d.ts +17 -17
  84. package/dist/starknet/swaps/handlers/refund/TimelockRefundHandler.js +27 -27
  85. package/dist/starknet/swaps/modules/StarknetLpVault.d.ts +67 -67
  86. package/dist/starknet/swaps/modules/StarknetLpVault.js +122 -122
  87. package/dist/starknet/swaps/modules/StarknetSwapClaim.d.ts +52 -52
  88. package/dist/starknet/swaps/modules/StarknetSwapClaim.js +99 -99
  89. package/dist/starknet/swaps/modules/StarknetSwapInit.d.ts +94 -94
  90. package/dist/starknet/swaps/modules/StarknetSwapInit.js +239 -239
  91. package/dist/starknet/swaps/modules/StarknetSwapRefund.d.ts +60 -60
  92. package/dist/starknet/swaps/modules/StarknetSwapRefund.js +126 -126
  93. package/dist/starknet/wallet/StarknetBrowserSigner.d.ts +11 -11
  94. package/dist/starknet/wallet/StarknetBrowserSigner.js +17 -17
  95. package/dist/starknet/wallet/StarknetPersistentSigner.d.ts +76 -76
  96. package/dist/starknet/wallet/StarknetPersistentSigner.js +291 -291
  97. package/dist/starknet/wallet/StarknetSigner.d.ts +72 -72
  98. package/dist/starknet/wallet/StarknetSigner.js +114 -114
  99. package/dist/starknet/wallet/accounts/StarknetKeypairWallet.d.ts +18 -18
  100. package/dist/starknet/wallet/accounts/StarknetKeypairWallet.js +45 -45
  101. package/dist/utils/Utils.d.ts +77 -77
  102. package/dist/utils/Utils.js +304 -303
  103. package/package.json +2 -2
  104. package/src/starknet/StarknetInitializer.ts +6 -3
  105. package/src/starknet/btcrelay/StarknetBtcRelay.ts +19 -6
  106. package/src/starknet/btcrelay/headers/StarknetBtcHeader.ts +7 -7
  107. package/src/starknet/btcrelay/headers/StarknetBtcStoredHeader.ts +6 -6
  108. package/src/starknet/chain/StarknetAction.ts +1 -0
  109. package/src/starknet/chain/StarknetChainInterface.ts +0 -2
  110. package/src/starknet/chain/modules/StarknetFees.ts +15 -2
  111. package/src/starknet/chain/modules/StarknetTransactions.ts +24 -0
  112. package/src/starknet/contract/StarknetContractBase.ts +7 -4
  113. package/src/starknet/contract/StarknetContractModule.ts +1 -1
  114. package/src/starknet/contract/modules/StarknetContractEvents.ts +7 -7
  115. package/src/starknet/events/StarknetChainEventsBrowser.ts +2 -64
  116. package/src/starknet/provider/RpcProviderWithRetries.ts +1 -1
  117. package/src/starknet/spv_swap/StarknetSpvVaultContract.ts +84 -18
  118. package/src/starknet/swaps/StarknetSwapContract.ts +242 -6
  119. package/src/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.ts +0 -4
@@ -1,621 +1,663 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.StarknetSpvVaultContract = void 0;
4
- const base_1 = require("@atomiqlabs/base");
5
- const buffer_1 = require("buffer");
6
- const StarknetContractBase_1 = require("../contract/StarknetContractBase");
7
- const StarknetBtcRelay_1 = require("../btcrelay/StarknetBtcRelay");
8
- const starknet_1 = require("starknet");
9
- const StarknetAction_1 = require("../chain/StarknetAction");
10
- const SpvVaultContractAbi_1 = require("./SpvVaultContractAbi");
11
- const StarknetSpvVaultData_1 = require("./StarknetSpvVaultData");
12
- const StarknetSpvWithdrawalData_1 = require("./StarknetSpvWithdrawalData");
13
- const Utils_1 = require("../../utils/Utils");
14
- const StarknetAddresses_1 = require("../chain/modules/StarknetAddresses");
15
- const StarknetFees_1 = require("../chain/modules/StarknetFees");
16
- const spvVaultContractAddreses = {
17
- [starknet_1.constants.StarknetChainId.SN_SEPOLIA]: "0x02d581ea838cd5ca46ba08660eddd064d50a0392f618e95310432147928d572e",
18
- [starknet_1.constants.StarknetChainId.SN_MAIN]: "0x01932042992647771f3d0aa6ee526e65359c891fe05a285faaf4d3ffa373e132"
19
- };
20
- const STARK_PRIME_MOD = 2n ** 251n + 17n * 2n ** 192n + 1n;
21
- function decodeUtxo(utxo) {
22
- const [txId, vout] = utxo.split(":");
23
- return {
24
- txHash: BigInt("0x" + buffer_1.Buffer.from(txId, "hex").reverse().toString("hex")),
25
- vout: BigInt(vout)
26
- };
27
- }
28
- /**
29
- * Starknet SPV vault (UTXO-controlled vault) contract representation
30
- *
31
- * @category Swaps
32
- */
33
- class StarknetSpvVaultContract extends StarknetContractBase_1.StarknetContractBase {
34
- constructor(chainInterface, btcRelay, bitcoinRpc, contractAddress = spvVaultContractAddreses[chainInterface.starknetChainId]) {
35
- super(chainInterface, contractAddress, SpvVaultContractAbi_1.SpvVaultContractAbi);
36
- this.chainId = "STARKNET";
37
- this.claimTimeout = 180;
38
- this.maxClaimsPerTx = 10;
39
- this.logger = (0, Utils_1.getLogger)("StarknetSpvVaultContract: ");
40
- this.btcRelay = btcRelay;
41
- this.bitcoinRpc = bitcoinRpc;
42
- }
43
- /**
44
- * Returns a {@link StarknetAction} that opens up the spv vault with the passed data
45
- *
46
- * @param signer A starknet signer's address
47
- * @param vault Vault data and configuration
48
- */
49
- Open(signer, vault) {
50
- const { txHash, vout } = decodeUtxo(vault.getUtxo());
51
- const tokens = vault.getTokenData();
52
- if (tokens.length !== 2)
53
- throw new Error("Must specify exactly 2 tokens for vault!");
54
- return new StarknetAction_1.StarknetAction(signer, this.Chain, this.contract.populateTransaction.open(vault.getVaultId(), this.btcRelay.contract.address, starknet_1.cairo.tuple(starknet_1.cairo.uint256(txHash), vout), vault.getConfirmations(), tokens[0].token, tokens[1].token, tokens[0].multiplier, tokens[1].multiplier), StarknetSpvVaultContract.GasCosts.OPEN);
55
- }
56
- /**
57
- * Returns a {@link StarknetAction} that deposits assets to the spv vault, amounts have to be already scaled!
58
- * This also doesn't add the approval call!
59
- *
60
- * @param signer A starknet signer's address
61
- * @param vault Vault data and configuration
62
- * @param rawAmounts An array of amounts to deposit, since the vault supports 2 tokens, up to 2 amounts are allowed
63
- */
64
- Deposit(signer, vault, rawAmounts) {
65
- return new StarknetAction_1.StarknetAction(signer, this.Chain, this.contract.populateTransaction.deposit(vault.getOwner(), vault.getVaultId(), rawAmounts[0], rawAmounts[1] ?? 0n), StarknetSpvVaultContract.GasCosts.DEPOSIT);
66
- }
67
- /**
68
- * Returns a {@link StarknetAction} that fronts the vault withdrawal. This doesn't add the approval call!
69
- *
70
- * @param signer A starknet signer's address
71
- * @param vault Vault data and configuration
72
- * @param data Vault withdrawal transaction data to front
73
- * @param withdrawalSequence Which withdrawal in sequence is this, used to prevent race conditions when 2 parties
74
- * were to front at the same time
75
- */
76
- Front(signer, vault, data, withdrawalSequence) {
77
- return new StarknetAction_1.StarknetAction(signer, this.Chain, this.contract.populateTransaction.front(vault.getOwner(), vault.getVaultId(), BigInt(withdrawalSequence), data.getTxHash(), data.serializeToStruct()), StarknetSpvVaultContract.GasCosts.FRONT);
78
- }
79
- /**
80
- * Returns a {@link StarknetAction} that submits the withdrawal data and executes the vault withdrawal
81
- *
82
- * @param signer A starknet signer's address
83
- * @param vault Vault data and configuration
84
- * @param data Vault withdrawal transaction data to execute and claim assets based on it
85
- * @param blockheader A stored and committed bitcoin blockheader where the bitcoin transaction got confirmed
86
- * @param merkle Merkle proof for the bitcoin transaction
87
- * @param position Position of the bitcoin transaction in the block - used for the merkle proof verification
88
- */
89
- Claim(signer, vault, data, blockheader, merkle, position) {
90
- return new StarknetAction_1.StarknetAction(signer, this.Chain, {
91
- contractAddress: this.contract.address,
92
- entrypoint: "claim",
93
- calldata: [
94
- vault.getOwner(),
95
- vault.getVaultId(),
96
- ...(0, Utils_1.bufferToByteArray)(buffer_1.Buffer.from(data.btcTx.hex, "hex")),
97
- ...blockheader.serialize(),
98
- merkle.length,
99
- ...merkle.map(Utils_1.bufferToU32Array).flat(),
100
- position,
101
- ].map(val => (0, Utils_1.toHex)(val, 0))
102
- }, StarknetSpvVaultContract.GasCosts.CLAIM);
103
- }
104
- /**
105
- * @inheritDoc
106
- */
107
- async checkWithdrawalTx(tx) {
108
- const result = await this.Chain.provider.callContract({
109
- contractAddress: this.contract.address,
110
- entrypoint: "parse_bitcoin_tx",
111
- calldata: (0, Utils_1.bufferToByteArray)(buffer_1.Buffer.from(tx.btcTx.hex, "hex"))
112
- });
113
- if (result == null)
114
- throw new Error("Failed to parse transaction!");
115
- }
116
- /**
117
- * @inheritDoc
118
- */
119
- createVaultData(owner, vaultId, utxo, confirmations, tokenData) {
120
- if (tokenData.length !== 2)
121
- throw new Error("Must specify 2 tokens in tokenData!");
122
- return Promise.resolve(new StarknetSpvVaultData_1.StarknetSpvVaultData({
123
- owner,
124
- vaultId,
125
- struct: {
126
- relay_contract: this.btcRelay.contract.address,
127
- token_0: tokenData[0].token,
128
- token_1: tokenData[1].token,
129
- token_0_multiplier: tokenData[0].multiplier,
130
- token_1_multiplier: tokenData[1].multiplier,
131
- utxo: starknet_1.cairo.tuple(starknet_1.cairo.uint256(0), 0),
132
- confirmations: confirmations,
133
- withdraw_count: 0,
134
- deposit_count: 0,
135
- token_0_amount: 0n,
136
- token_1_amount: 0n
137
- },
138
- initialUtxo: utxo
139
- }));
140
- }
141
- //Getters
142
- /**
143
- * @inheritDoc
144
- */
145
- async getVaultData(owner, vaultId) {
146
- const struct = await this.contract.get_vault(owner, vaultId);
147
- if ((0, Utils_1.toHex)(struct.relay_contract) !== (0, Utils_1.toHex)(this.btcRelay.contract.address))
148
- return null;
149
- return new StarknetSpvVaultData_1.StarknetSpvVaultData({
150
- owner, vaultId, struct
151
- });
152
- }
153
- /**
154
- * @inheritDoc
155
- */
156
- async getMultipleVaultData(vaults) {
157
- const result = {};
158
- let promises = [];
159
- //TODO: We can upgrade this to use multicall
160
- for (let { owner, vaultId } of vaults) {
161
- promises.push(this.getVaultData(owner, vaultId).then(val => {
162
- result[owner] ?? (result[owner] = {});
163
- result[owner][vaultId.toString(10)] = val;
164
- }));
165
- if (promises.length >= this.Chain.config.maxParallelCalls) {
166
- await Promise.all(promises);
167
- promises = [];
168
- }
169
- }
170
- await Promise.all(promises);
171
- return result;
172
- }
173
- /**
174
- * @inheritDoc
175
- */
176
- async getVaultLatestUtxo(owner, vaultId) {
177
- const vault = await this.getVaultData(owner, vaultId);
178
- if (vault == null)
179
- return null;
180
- if (!vault.isOpened())
181
- return null;
182
- return vault.getUtxo();
183
- }
184
- /**
185
- * @inheritDoc
186
- */
187
- async getVaultLatestUtxos(vaults) {
188
- const result = {};
189
- let promises = [];
190
- //TODO: We can upgrade this to use multicall
191
- for (let { owner, vaultId } of vaults) {
192
- promises.push(this.getVaultLatestUtxo(owner, vaultId).then(val => {
193
- result[owner] ?? (result[owner] = {});
194
- result[owner][vaultId.toString(10)] = val;
195
- }));
196
- if (promises.length >= this.Chain.config.maxParallelCalls) {
197
- await Promise.all(promises);
198
- promises = [];
199
- }
200
- }
201
- await Promise.all(promises);
202
- return result;
203
- }
204
- /**
205
- * @inheritDoc
206
- */
207
- async getAllVaults(owner) {
208
- const openedVaults = new Set();
209
- await this.Events.findInContractEventsForward(["spv_swap_vault::events::Opened", "spv_swap_vault::events::Closed"], owner == null ? null : [null, owner], (event) => {
210
- const owner = (0, Utils_1.toHex)(event.params.owner);
211
- const vaultId = (0, Utils_1.toBigInt)(event.params.vault_id);
212
- const vaultIdentifier = owner + ":" + vaultId.toString(10);
213
- if (event.name === "spv_swap_vault::events::Opened") {
214
- openedVaults.add(vaultIdentifier);
215
- }
216
- else {
217
- openedVaults.delete(vaultIdentifier);
218
- }
219
- return Promise.resolve(null);
220
- });
221
- const vaults = [];
222
- for (let identifier of openedVaults.keys()) {
223
- const [owner, vaultIdStr] = identifier.split(":");
224
- const vaultData = await this.getVaultData(owner, BigInt(vaultIdStr));
225
- if (vaultData != null)
226
- vaults.push(vaultData);
227
- }
228
- return vaults;
229
- }
230
- /**
231
- * @inheritDoc
232
- */
233
- async getFronterAddress(owner, vaultId, withdrawal) {
234
- const fronterAddress = await this.contract.get_fronter_address_by_id(owner, vaultId, "0x" + withdrawal.getFrontingId());
235
- if ((0, Utils_1.toHex)(fronterAddress, 64) === "0x0000000000000000000000000000000000000000000000000000000000000000")
236
- return null;
237
- return fronterAddress;
238
- }
239
- /**
240
- * @inheritDoc
241
- */
242
- async getFronterAddresses(withdrawals) {
243
- const result = {};
244
- let promises = [];
245
- //TODO: We can upgrade this to use multicall
246
- for (let { owner, vaultId, withdrawal } of withdrawals) {
247
- promises.push(this.getFronterAddress(owner, vaultId, withdrawal).then(val => {
248
- result[withdrawal.getTxId()] = val;
249
- }));
250
- if (promises.length >= this.Chain.config.maxParallelCalls) {
251
- await Promise.all(promises);
252
- promises = [];
253
- }
254
- }
255
- await Promise.all(promises);
256
- return result;
257
- }
258
- /**
259
- *
260
- * @param event
261
- * @private
262
- */
263
- parseWithdrawalEvent(event) {
264
- switch (event.name) {
265
- case "spv_swap_vault::events::Fronted":
266
- return {
267
- type: base_1.SpvWithdrawalStateType.FRONTED,
268
- txId: event.txHash,
269
- owner: (0, Utils_1.toHex)(event.params.owner),
270
- vaultId: (0, Utils_1.toBigInt)(event.params.vault_id),
271
- recipient: (0, Utils_1.toHex)(event.params.recipient),
272
- fronter: (0, Utils_1.toHex)(event.params.fronting_address)
273
- };
274
- case "spv_swap_vault::events::Claimed":
275
- return {
276
- type: base_1.SpvWithdrawalStateType.CLAIMED,
277
- txId: event.txHash,
278
- owner: (0, Utils_1.toHex)(event.params.owner),
279
- vaultId: (0, Utils_1.toBigInt)(event.params.vault_id),
280
- recipient: (0, Utils_1.toHex)(event.params.recipient),
281
- claimer: (0, Utils_1.toHex)(event.params.caller),
282
- fronter: (0, Utils_1.toHex)(event.params.fronting_address)
283
- };
284
- case "spv_swap_vault::events::Closed":
285
- return {
286
- type: base_1.SpvWithdrawalStateType.CLOSED,
287
- txId: event.txHash,
288
- owner: (0, Utils_1.toHex)(event.params.owner),
289
- vaultId: (0, Utils_1.toBigInt)(event.params.vault_id),
290
- error: (0, Utils_1.bigNumberishToBuffer)(event.params.error).toString()
291
- };
292
- default:
293
- return null;
294
- }
295
- }
296
- /**
297
- * @inheritDoc
298
- */
299
- async getWithdrawalStates(withdrawalTxs) {
300
- const result = {};
301
- withdrawalTxs.forEach(withdrawalTx => {
302
- result[withdrawalTx.withdrawal.getTxId()] = {
303
- type: base_1.SpvWithdrawalStateType.NOT_FOUND
304
- };
305
- });
306
- const events = ["spv_swap_vault::events::Fronted", "spv_swap_vault::events::Claimed", "spv_swap_vault::events::Closed"];
307
- for (let i = 0; i < withdrawalTxs.length; i += this.Chain.config.maxGetLogKeys) {
308
- const checkWithdrawalTxs = withdrawalTxs.slice(i, i + this.Chain.config.maxGetLogKeys);
309
- const lows = [];
310
- const highs = [];
311
- let startHeight = undefined;
312
- checkWithdrawalTxs.forEach(withdrawalTx => {
313
- const txHash = buffer_1.Buffer.from(withdrawalTx.withdrawal.getTxId(), "hex").reverse();
314
- const txHashU256 = starknet_1.cairo.uint256("0x" + txHash.toString("hex"));
315
- lows.push((0, Utils_1.toHex)(txHashU256.low));
316
- highs.push((0, Utils_1.toHex)(txHashU256.high));
317
- if (startHeight !== null) {
318
- if (withdrawalTx.scStartBlockheight == null) {
319
- startHeight = null;
320
- }
321
- else {
322
- startHeight = Math.min(startHeight ?? Infinity, withdrawalTx.scStartBlockheight);
323
- }
324
- }
325
- });
326
- await this.Events.findInContractEventsForward(events, [lows, highs], async (event) => {
327
- const txId = (0, Utils_1.bigNumberishToBuffer)(event.params.btc_tx_hash, 32).reverse().toString("hex");
328
- if (result[txId] == null) {
329
- this.logger.warn(`getWithdrawalStates(): findInContractEvents-callback: loaded event for ${txId}, but transaction not found in input params!`);
330
- return;
331
- }
332
- const eventResult = this.parseWithdrawalEvent(event);
333
- if (eventResult != null)
334
- result[txId] = eventResult;
335
- }, startHeight);
336
- }
337
- return result;
338
- }
339
- /**
340
- * @inheritDoc
341
- */
342
- async getWithdrawalState(withdrawalTx, scStartBlockheight) {
343
- const txHash = buffer_1.Buffer.from(withdrawalTx.getTxId(), "hex").reverse();
344
- const txHashU256 = starknet_1.cairo.uint256("0x" + txHash.toString("hex"));
345
- let result = {
346
- type: base_1.SpvWithdrawalStateType.NOT_FOUND
347
- };
348
- const events = ["spv_swap_vault::events::Fronted", "spv_swap_vault::events::Claimed", "spv_swap_vault::events::Closed"];
349
- const keys = [(0, Utils_1.toHex)(txHashU256.low), (0, Utils_1.toHex)(txHashU256.high)];
350
- await this.Events.findInContractEventsForward(events, keys, async (event) => {
351
- const eventResult = this.parseWithdrawalEvent(event);
352
- if (eventResult != null)
353
- result = eventResult;
354
- }, scStartBlockheight);
355
- return result;
356
- }
357
- /**
358
- * @inheritDoc
359
- */
360
- getWithdrawalData(btcTx) {
361
- return Promise.resolve(new StarknetSpvWithdrawalData_1.StarknetSpvWithdrawalData(btcTx));
362
- }
363
- //OP_RETURN data encoding/decoding
364
- /**
365
- * @inheritDoc
366
- */
367
- fromOpReturnData(data) {
368
- return StarknetSpvVaultContract.fromOpReturnData(data);
369
- }
370
- /**
371
- * Parses withdrawal params from OP_RETURN data
372
- *
373
- * @param data data as specified in the OP_RETURN output of the transaction
374
- */
375
- static fromOpReturnData(data) {
376
- let rawAmount0 = 0n;
377
- let rawAmount1 = 0n;
378
- let executionHash = undefined;
379
- if (data.length === 40) {
380
- rawAmount0 = data.readBigInt64LE(32).valueOf();
381
- }
382
- else if (data.length === 48) {
383
- rawAmount0 = data.readBigInt64LE(32).valueOf();
384
- rawAmount1 = data.readBigInt64LE(40).valueOf();
385
- }
386
- else if (data.length === 72) {
387
- rawAmount0 = data.readBigInt64LE(32).valueOf();
388
- executionHash = data.slice(40, 72).toString("hex");
389
- }
390
- else if (data.length === 80) {
391
- rawAmount0 = data.readBigInt64LE(32).valueOf();
392
- rawAmount1 = data.readBigInt64LE(40).valueOf();
393
- executionHash = data.slice(48, 80).toString("hex");
394
- }
395
- else {
396
- throw new Error("Invalid OP_RETURN data length!");
397
- }
398
- if (executionHash != undefined) {
399
- const executionHashValue = BigInt("0x" + executionHash);
400
- if (executionHashValue >= STARK_PRIME_MOD)
401
- throw new Error("Execution hash not in range of starknet prime");
402
- }
403
- const recipient = "0x" + data.slice(0, 32).toString("hex");
404
- if (!StarknetAddresses_1.StarknetAddresses.isValidAddress(recipient))
405
- throw new Error("Invalid recipient specified");
406
- return { executionHash, rawAmounts: [rawAmount0, rawAmount1], recipient };
407
- }
408
- /**
409
- * @inheritDoc
410
- */
411
- toOpReturnData(recipient, rawAmounts, executionHash) {
412
- return StarknetSpvVaultContract.toOpReturnData(recipient, rawAmounts, executionHash);
413
- }
414
- /**
415
- * Serializes the withdrawal params to the OP_RETURN data
416
- *
417
- * @param recipient Recipient of the withdrawn tokens
418
- * @param rawAmounts Raw amount of tokens to withdraw
419
- * @param executionHash Optional execution hash of the actions to execute
420
- */
421
- static toOpReturnData(recipient, rawAmounts, executionHash) {
422
- if (!StarknetAddresses_1.StarknetAddresses.isValidAddress(recipient))
423
- throw new Error("Invalid recipient specified");
424
- if (rawAmounts.length < 1)
425
- throw new Error("At least 1 amount needs to be specified");
426
- if (rawAmounts.length > 2)
427
- throw new Error("At most 2 amounts need to be specified");
428
- rawAmounts.forEach(val => {
429
- if (val < 0n)
430
- throw new Error("Negative raw amount specified");
431
- if (val >= 2n ** 64n)
432
- throw new Error("Raw amount overflow");
433
- });
434
- if (executionHash != null) {
435
- const executionHashValue = (0, Utils_1.toBigInt)(executionHash);
436
- if (executionHashValue < 0n)
437
- throw new Error("Execution hash negative");
438
- if (executionHashValue >= STARK_PRIME_MOD)
439
- throw new Error("Execution hash not in range of starknet prime");
440
- }
441
- const recipientBuffer = buffer_1.Buffer.from(recipient.substring(2).padStart(64, "0"), "hex");
442
- const amount0Buffer = buffer_1.Buffer.from(rawAmounts[0].toString(16).padStart(16, "0"), "hex");
443
- const amount1Buffer = rawAmounts[1] == null || rawAmounts[1] === 0n ? buffer_1.Buffer.alloc(0) : buffer_1.Buffer.from(rawAmounts[1].toString(16).padStart(16, "0"), "hex");
444
- const executionHashBuffer = executionHash == null ? buffer_1.Buffer.alloc(0) : buffer_1.Buffer.from(executionHash.substring(2).padStart(64, "0"), "hex");
445
- return buffer_1.Buffer.concat([
446
- recipientBuffer,
447
- amount0Buffer.reverse(),
448
- amount1Buffer.reverse(),
449
- executionHashBuffer
450
- ]);
451
- }
452
- //Actions
453
- /**
454
- * @inheritDoc
455
- */
456
- async claim(signer, vault, txs, synchronizer, initAta, txOptions) {
457
- const result = await this.txsClaim(signer.getAddress(), vault, txs, synchronizer, initAta, txOptions?.feeRate);
458
- const [signature] = await this.Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
459
- return signature;
460
- }
461
- /**
462
- * @inheritDoc
463
- */
464
- async deposit(signer, vault, rawAmounts, txOptions) {
465
- const result = await this.txsDeposit(signer.getAddress(), vault, rawAmounts, txOptions?.feeRate);
466
- const [signature] = await this.Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
467
- return signature;
468
- }
469
- /**
470
- * @inheritDoc
471
- */
472
- async frontLiquidity(signer, vault, realWithdrawalTx, withdrawSequence, txOptions) {
473
- const result = await this.txsFrontLiquidity(signer.getAddress(), vault, realWithdrawalTx, withdrawSequence, txOptions?.feeRate);
474
- const [signature] = await this.Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
475
- return signature;
476
- }
477
- /**
478
- * @inheritDoc
479
- */
480
- async open(signer, vault, txOptions) {
481
- const result = await this.txsOpen(signer.getAddress(), vault, txOptions?.feeRate);
482
- const [signature] = await this.Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
483
- return signature;
484
- }
485
- //Transactions
486
- /**
487
- * @inheritDoc
488
- */
489
- async txsClaim(signer, vault, txs, synchronizer, initAta, feeRate) {
490
- if (!vault.isOpened())
491
- throw new Error("Cannot claim from a closed vault!");
492
- feeRate ?? (feeRate = await this.Chain.Fees.getFeeRate());
493
- const txsWithMerkleProofs = [];
494
- for (let tx of txs) {
495
- if (tx.tx.btcTx.blockhash == null)
496
- throw new Error(`Transaction ${tx.tx.btcTx.txid} doesn't have any blockhash, unconfirmed?`);
497
- const merkleProof = await this.bitcoinRpc.getMerkleProof(tx.tx.btcTx.txid, tx.tx.btcTx.blockhash);
498
- if (merkleProof == null)
499
- throw new Error(`Failed to get merkle proof for tx: ${tx.tx.btcTx.txid}!`);
500
- this.logger.debug("txsClaim(): merkle proof computed: ", merkleProof);
501
- txsWithMerkleProofs.push({
502
- ...merkleProof,
503
- ...tx
504
- });
505
- }
506
- const starknetTxs = [];
507
- const storedHeaders = await StarknetBtcRelay_1.StarknetBtcRelay.getCommitedHeadersAndSynchronize(signer, this.btcRelay, txsWithMerkleProofs.filter(tx => tx.storedHeader == null).map(tx => {
508
- return {
509
- blockhash: tx.tx.btcTx.blockhash,
510
- blockheight: tx.blockheight,
511
- requiredConfirmations: vault.getConfirmations()
512
- };
513
- }), starknetTxs, synchronizer, feeRate);
514
- if (storedHeaders == null)
515
- throw new Error("Cannot fetch committed header!");
516
- const actions = txsWithMerkleProofs.map(tx => {
517
- return this.Claim(signer, vault, tx.tx, tx.storedHeader ?? storedHeaders[tx.tx.btcTx.blockhash], tx.merkle, tx.pos);
518
- });
519
- let starknetAction = new StarknetAction_1.StarknetAction(signer, this.Chain);
520
- for (let action of actions) {
521
- starknetAction.add(action);
522
- if (starknetAction.ixsLength() >= this.maxClaimsPerTx) {
523
- await starknetAction.addToTxs(starknetTxs, feeRate);
524
- starknetAction = new StarknetAction_1.StarknetAction(signer, this.Chain);
525
- }
526
- }
527
- if (starknetAction.ixsLength() > 0) {
528
- await starknetAction.addToTxs(starknetTxs, feeRate);
529
- }
530
- this.logger.debug("txsClaim(): " + starknetTxs.length + " claim TXs created claiming " + txs.length + " txs, owner: " + vault.getOwner() +
531
- " vaultId: " + vault.getVaultId().toString(10));
532
- return starknetTxs;
533
- }
534
- /**
535
- * @inheritDoc
536
- */
537
- async txsDeposit(signer, vault, rawAmounts, feeRate) {
538
- if (!vault.isOpened())
539
- throw new Error("Cannot deposit to a closed vault!");
540
- //Approve first
541
- const vaultTokens = vault.getTokenData();
542
- const action = new StarknetAction_1.StarknetAction(signer, this.Chain);
543
- let realAmount0 = 0n;
544
- let realAmount1 = 0n;
545
- if (rawAmounts[0] != null && rawAmounts[0] !== 0n) {
546
- realAmount0 = rawAmounts[0] * vaultTokens[0].multiplier;
547
- action.add(this.Chain.Tokens.Approve(signer, this.contract.address, vaultTokens[0].token, realAmount0));
548
- }
549
- if (rawAmounts[1] != null && rawAmounts[1] !== 0n) {
550
- realAmount1 = rawAmounts[1] * vaultTokens[1].multiplier;
551
- action.add(this.Chain.Tokens.Approve(signer, this.contract.address, vaultTokens[1].token, realAmount1));
552
- }
553
- action.add(this.Deposit(signer, vault, rawAmounts));
554
- feeRate ?? (feeRate = await this.Chain.Fees.getFeeRate());
555
- this.logger.debug("txsDeposit(): deposit TX created," +
556
- " token0: " + vaultTokens[0].token + " rawAmount0: " + rawAmounts[0].toString(10) + " amount0: " + realAmount0.toString(10) +
557
- " token1: " + vaultTokens[1].token + " rawAmount1: " + (rawAmounts[1] ?? 0n).toString(10) + " amount1: " + realAmount1.toString(10));
558
- return [await action.tx(feeRate)];
559
- }
560
- /**
561
- * @inheritDoc
562
- */
563
- async txsFrontLiquidity(signer, vault, realWithdrawalTx, withdrawSequence, feeRate) {
564
- if (!vault.isOpened())
565
- throw new Error("Cannot front on a closed vault!");
566
- //Approve first
567
- const vaultTokens = vault.getTokenData();
568
- const action = new StarknetAction_1.StarknetAction(signer, this.Chain);
569
- const rawAmounts = realWithdrawalTx.getFrontingAmount();
570
- let realAmount0 = 0n;
571
- let realAmount1 = 0n;
572
- if (rawAmounts[0] != null && rawAmounts[0] !== 0n) {
573
- realAmount0 = rawAmounts[0] * vaultTokens[0].multiplier;
574
- action.add(this.Chain.Tokens.Approve(signer, this.contract.address, vaultTokens[0].token, realAmount0));
575
- }
576
- if (rawAmounts[1] != null && rawAmounts[1] !== 0n) {
577
- realAmount1 = rawAmounts[1] * vaultTokens[1].multiplier;
578
- action.add(this.Chain.Tokens.Approve(signer, this.contract.address, vaultTokens[1].token, realAmount1));
579
- }
580
- action.add(this.Front(signer, vault, realWithdrawalTx, withdrawSequence));
581
- feeRate ?? (feeRate = await this.Chain.Fees.getFeeRate());
582
- this.logger.debug("txsFrontLiquidity(): front TX created," +
583
- " token0: " + vaultTokens[0].token + " rawAmount0: " + rawAmounts[0].toString(10) + " amount0: " + realAmount0.toString(10) +
584
- " token1: " + vaultTokens[1].token + " rawAmount1: " + (rawAmounts[1] ?? 0n).toString(10) + " amount1: " + realAmount1.toString(10));
585
- return [await action.tx(feeRate)];
586
- }
587
- /**
588
- * @inheritDoc
589
- */
590
- async txsOpen(signer, vault, feeRate) {
591
- if (vault.isOpened())
592
- throw new Error("Cannot open an already opened vault!");
593
- const action = this.Open(signer, vault);
594
- feeRate ?? (feeRate = await this.Chain.Fees.getFeeRate());
595
- this.logger.debug("txsOpen(): open TX created, owner: " + vault.getOwner() +
596
- " vaultId: " + vault.getVaultId().toString(10));
597
- return [await action.tx(feeRate)];
598
- }
599
- /**
600
- * @inheritDoc
601
- */
602
- async getClaimFee(signer, vault, withdrawalData, feeRate) {
603
- feeRate ?? (feeRate = await this.Chain.Fees.getFeeRate());
604
- return StarknetFees_1.StarknetFees.getGasFee(withdrawalData == null ? StarknetSpvVaultContract.GasCosts.CLAIM_OPTIMISTIC_ESTIMATE : StarknetSpvVaultContract.GasCosts.CLAIM, feeRate);
605
- }
606
- /**
607
- * @inheritDoc
608
- */
609
- async getFrontFee(signer, vault, withdrawalData, feeRate) {
610
- feeRate ?? (feeRate = await this.Chain.Fees.getFeeRate());
611
- return StarknetFees_1.StarknetFees.getGasFee(StarknetSpvVaultContract.GasCosts.FRONT, feeRate);
612
- }
613
- }
614
- exports.StarknetSpvVaultContract = StarknetSpvVaultContract;
615
- StarknetSpvVaultContract.GasCosts = {
616
- DEPOSIT: { l1DataGas: 400, l2Gas: 4000000, l1Gas: 0 },
617
- OPEN: { l1DataGas: 1200, l2Gas: 3200000, l1Gas: 0 },
618
- FRONT: { l1DataGas: 800, l2Gas: 12000000, l1Gas: 0 },
619
- CLAIM: { l1DataGas: 1000, l2Gas: 400000000, l1Gas: 0 },
620
- CLAIM_OPTIMISTIC_ESTIMATE: { l1DataGas: 1000, l2Gas: 80000000, l1Gas: 0 } //If claimer uses sierra 1.7.0 or later
621
- };
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StarknetSpvVaultContract = void 0;
4
+ const base_1 = require("@atomiqlabs/base");
5
+ const buffer_1 = require("buffer");
6
+ const StarknetContractBase_1 = require("../contract/StarknetContractBase");
7
+ const StarknetBtcRelay_1 = require("../btcrelay/StarknetBtcRelay");
8
+ const starknet_1 = require("starknet");
9
+ const StarknetAction_1 = require("../chain/StarknetAction");
10
+ const SpvVaultContractAbi_1 = require("./SpvVaultContractAbi");
11
+ const StarknetSpvVaultData_1 = require("./StarknetSpvVaultData");
12
+ const StarknetSpvWithdrawalData_1 = require("./StarknetSpvWithdrawalData");
13
+ const Utils_1 = require("../../utils/Utils");
14
+ const StarknetAddresses_1 = require("../chain/modules/StarknetAddresses");
15
+ const StarknetFees_1 = require("../chain/modules/StarknetFees");
16
+ const spvVaultContractAddreses = {
17
+ [starknet_1.constants.StarknetChainId.SN_SEPOLIA]: "0x02d581ea838cd5ca46ba08660eddd064d50a0392f618e95310432147928d572e",
18
+ [starknet_1.constants.StarknetChainId.SN_MAIN]: "0x01932042992647771f3d0aa6ee526e65359c891fe05a285faaf4d3ffa373e132"
19
+ };
20
+ const spvVaultContractDeploymentHeights = {
21
+ [starknet_1.constants.StarknetChainId.SN_SEPOLIA]: 1118191,
22
+ [starknet_1.constants.StarknetChainId.SN_MAIN]: 1617295
23
+ };
24
+ const STARK_PRIME_MOD = 2n ** 251n + 17n * 2n ** 192n + 1n;
25
+ function decodeUtxo(utxo) {
26
+ const [txId, vout] = utxo.split(":");
27
+ return {
28
+ txHash: BigInt("0x" + buffer_1.Buffer.from(txId, "hex").reverse().toString("hex")),
29
+ vout: BigInt(vout)
30
+ };
31
+ }
32
+ /**
33
+ * Starknet SPV vault (UTXO-controlled vault) contract representation
34
+ *
35
+ * @category Swaps
36
+ */
37
+ class StarknetSpvVaultContract extends StarknetContractBase_1.StarknetContractBase {
38
+ constructor(chainInterface, btcRelay, bitcoinRpc, contractAddress = spvVaultContractAddreses[chainInterface.starknetChainId], contractDeploymentHeight) {
39
+ super(chainInterface, contractAddress, SpvVaultContractAbi_1.SpvVaultContractAbi, contractDeploymentHeight ??
40
+ (spvVaultContractAddreses[chainInterface.starknetChainId] === contractAddress
41
+ ? spvVaultContractDeploymentHeights[chainInterface.starknetChainId]
42
+ : undefined));
43
+ this.chainId = "STARKNET";
44
+ this.claimTimeout = 180;
45
+ this.maxClaimsPerTx = 10;
46
+ this.logger = (0, Utils_1.getLogger)("StarknetSpvVaultContract: ");
47
+ this.btcRelay = btcRelay;
48
+ this.bitcoinRpc = bitcoinRpc;
49
+ }
50
+ /**
51
+ * Returns a {@link StarknetAction} that opens up the spv vault with the passed data
52
+ *
53
+ * @param signer A starknet signer's address
54
+ * @param vault Vault data and configuration
55
+ */
56
+ Open(signer, vault) {
57
+ const { txHash, vout } = decodeUtxo(vault.getUtxo());
58
+ const tokens = vault.getTokenData();
59
+ if (tokens.length !== 2)
60
+ throw new Error("Must specify exactly 2 tokens for vault!");
61
+ return new StarknetAction_1.StarknetAction(signer, this.Chain, this.contract.populateTransaction.open(vault.getVaultId(), this.btcRelay.contract.address, starknet_1.cairo.tuple(starknet_1.cairo.uint256(txHash), vout), vault.getConfirmations(), tokens[0].token, tokens[1].token, tokens[0].multiplier, tokens[1].multiplier), StarknetSpvVaultContract.GasCosts.OPEN);
62
+ }
63
+ /**
64
+ * Returns a {@link StarknetAction} that deposits assets to the spv vault, amounts have to be already scaled!
65
+ * This also doesn't add the approval call!
66
+ *
67
+ * @param signer A starknet signer's address
68
+ * @param vault Vault data and configuration
69
+ * @param rawAmounts An array of amounts to deposit, since the vault supports 2 tokens, up to 2 amounts are allowed
70
+ */
71
+ Deposit(signer, vault, rawAmounts) {
72
+ return new StarknetAction_1.StarknetAction(signer, this.Chain, this.contract.populateTransaction.deposit(vault.getOwner(), vault.getVaultId(), rawAmounts[0], rawAmounts[1] ?? 0n), StarknetSpvVaultContract.GasCosts.DEPOSIT);
73
+ }
74
+ /**
75
+ * Returns a {@link StarknetAction} that fronts the vault withdrawal. This doesn't add the approval call!
76
+ *
77
+ * @param signer A starknet signer's address
78
+ * @param vault Vault data and configuration
79
+ * @param data Vault withdrawal transaction data to front
80
+ * @param withdrawalSequence Which withdrawal in sequence is this, used to prevent race conditions when 2 parties
81
+ * were to front at the same time
82
+ */
83
+ Front(signer, vault, data, withdrawalSequence) {
84
+ return new StarknetAction_1.StarknetAction(signer, this.Chain, this.contract.populateTransaction.front(vault.getOwner(), vault.getVaultId(), BigInt(withdrawalSequence), data.getTxHash(), data.serializeToStruct()), StarknetSpvVaultContract.GasCosts.FRONT);
85
+ }
86
+ /**
87
+ * Returns a {@link StarknetAction} that submits the withdrawal data and executes the vault withdrawal
88
+ *
89
+ * @param signer A starknet signer's address
90
+ * @param vault Vault data and configuration
91
+ * @param data Vault withdrawal transaction data to execute and claim assets based on it
92
+ * @param blockheader A stored and committed bitcoin blockheader where the bitcoin transaction got confirmed
93
+ * @param merkle Merkle proof for the bitcoin transaction
94
+ * @param position Position of the bitcoin transaction in the block - used for the merkle proof verification
95
+ */
96
+ Claim(signer, vault, data, blockheader, merkle, position) {
97
+ return new StarknetAction_1.StarknetAction(signer, this.Chain, {
98
+ contractAddress: this.contract.address,
99
+ entrypoint: "claim",
100
+ calldata: [
101
+ vault.getOwner(),
102
+ vault.getVaultId(),
103
+ ...(0, Utils_1.bufferToByteArray)(buffer_1.Buffer.from(data.btcTx.hex, "hex")),
104
+ ...blockheader.serialize(),
105
+ merkle.length,
106
+ ...merkle.map(Utils_1.bufferToU32Array).flat(),
107
+ position,
108
+ ].map(val => (0, Utils_1.toHex)(val, 0))
109
+ }, StarknetSpvVaultContract.GasCosts.CLAIM);
110
+ }
111
+ /**
112
+ * @inheritDoc
113
+ */
114
+ async checkWithdrawalTx(tx) {
115
+ const result = await this.Chain.provider.callContract({
116
+ contractAddress: this.contract.address,
117
+ entrypoint: "parse_bitcoin_tx",
118
+ calldata: (0, Utils_1.bufferToByteArray)(buffer_1.Buffer.from(tx.btcTx.hex, "hex"))
119
+ });
120
+ if (result == null)
121
+ throw new Error("Failed to parse transaction!");
122
+ }
123
+ /**
124
+ * @inheritDoc
125
+ */
126
+ createVaultData(owner, vaultId, utxo, confirmations, tokenData) {
127
+ if (tokenData.length !== 2)
128
+ throw new Error("Must specify 2 tokens in tokenData!");
129
+ return Promise.resolve(new StarknetSpvVaultData_1.StarknetSpvVaultData({
130
+ owner,
131
+ vaultId,
132
+ struct: {
133
+ relay_contract: this.btcRelay.contract.address,
134
+ token_0: tokenData[0].token,
135
+ token_1: tokenData[1].token,
136
+ token_0_multiplier: tokenData[0].multiplier,
137
+ token_1_multiplier: tokenData[1].multiplier,
138
+ utxo: starknet_1.cairo.tuple(starknet_1.cairo.uint256(0), 0),
139
+ confirmations: confirmations,
140
+ withdraw_count: 0,
141
+ deposit_count: 0,
142
+ token_0_amount: 0n,
143
+ token_1_amount: 0n
144
+ },
145
+ initialUtxo: utxo
146
+ }));
147
+ }
148
+ //Getters
149
+ /**
150
+ * @inheritDoc
151
+ */
152
+ async getVaultData(owner, vaultId) {
153
+ const struct = await this.contract.get_vault(owner, vaultId);
154
+ if ((0, Utils_1.toHex)(struct.relay_contract) !== (0, Utils_1.toHex)(this.btcRelay.contract.address))
155
+ return null;
156
+ return new StarknetSpvVaultData_1.StarknetSpvVaultData({
157
+ owner, vaultId, struct
158
+ });
159
+ }
160
+ /**
161
+ * @inheritDoc
162
+ */
163
+ async getMultipleVaultData(vaults) {
164
+ const result = {};
165
+ let promises = [];
166
+ //TODO: We can upgrade this to use multicall
167
+ for (let { owner, vaultId } of vaults) {
168
+ promises.push(this.getVaultData(owner, vaultId).then(val => {
169
+ result[owner] ?? (result[owner] = {});
170
+ result[owner][vaultId.toString(10)] = val;
171
+ }));
172
+ if (promises.length >= this.Chain.config.maxParallelCalls) {
173
+ await Promise.all(promises);
174
+ promises = [];
175
+ }
176
+ }
177
+ await Promise.all(promises);
178
+ return result;
179
+ }
180
+ /**
181
+ * @inheritDoc
182
+ */
183
+ async getVaultLatestUtxo(owner, vaultId) {
184
+ const vault = await this.getVaultData(owner, vaultId);
185
+ if (vault == null)
186
+ return null;
187
+ if (!vault.isOpened())
188
+ return null;
189
+ return vault.getUtxo();
190
+ }
191
+ /**
192
+ * @inheritDoc
193
+ */
194
+ async getVaultLatestUtxos(vaults) {
195
+ const result = {};
196
+ let promises = [];
197
+ //TODO: We can upgrade this to use multicall
198
+ for (let { owner, vaultId } of vaults) {
199
+ promises.push(this.getVaultLatestUtxo(owner, vaultId).then(val => {
200
+ result[owner] ?? (result[owner] = {});
201
+ result[owner][vaultId.toString(10)] = val;
202
+ }));
203
+ if (promises.length >= this.Chain.config.maxParallelCalls) {
204
+ await Promise.all(promises);
205
+ promises = [];
206
+ }
207
+ }
208
+ await Promise.all(promises);
209
+ return result;
210
+ }
211
+ /**
212
+ * @inheritDoc
213
+ */
214
+ async getAllVaults(owner) {
215
+ const openedVaults = new Set();
216
+ await this.Events.findInContractEventsForward(["spv_swap_vault::events::Opened", "spv_swap_vault::events::Closed"], owner == null ? null : [null, null, owner], (event) => {
217
+ const owner = (0, Utils_1.toHex)(event.params.owner);
218
+ const vaultId = (0, Utils_1.toBigInt)(event.params.vault_id);
219
+ const vaultIdentifier = owner + ":" + vaultId.toString(10);
220
+ if (event.name === "spv_swap_vault::events::Opened") {
221
+ openedVaults.add(vaultIdentifier);
222
+ }
223
+ else {
224
+ openedVaults.delete(vaultIdentifier);
225
+ }
226
+ return Promise.resolve(null);
227
+ });
228
+ const fetchedVaultData = await this.getMultipleVaultData([...openedVaults.keys()].map(identifier => {
229
+ const [owner, vaultIdStr] = identifier.split(":");
230
+ return { owner, vaultId: BigInt(vaultIdStr) };
231
+ }));
232
+ const vaults = [];
233
+ for (let owner in fetchedVaultData) {
234
+ for (let vaultIdStr in fetchedVaultData[owner]) {
235
+ const vault = fetchedVaultData[owner][vaultIdStr];
236
+ if (vault != null)
237
+ vaults.push(vault);
238
+ }
239
+ }
240
+ return vaults;
241
+ }
242
+ /**
243
+ * @inheritDoc
244
+ */
245
+ async getFronterAddress(owner, vaultId, withdrawal) {
246
+ const fronterAddress = await this.contract.get_fronter_address_by_id(owner, vaultId, "0x" + withdrawal.getFrontingId());
247
+ if ((0, Utils_1.toHex)(fronterAddress, 64) === "0x0000000000000000000000000000000000000000000000000000000000000000")
248
+ return null;
249
+ return fronterAddress;
250
+ }
251
+ /**
252
+ * @inheritDoc
253
+ */
254
+ async getFronterAddresses(withdrawals) {
255
+ const result = {};
256
+ let promises = [];
257
+ //TODO: We can upgrade this to use multicall
258
+ for (let { owner, vaultId, withdrawal } of withdrawals) {
259
+ promises.push(this.getFronterAddress(owner, vaultId, withdrawal).then(val => {
260
+ result[withdrawal.getTxId()] = val;
261
+ }));
262
+ if (promises.length >= this.Chain.config.maxParallelCalls) {
263
+ await Promise.all(promises);
264
+ promises = [];
265
+ }
266
+ }
267
+ await Promise.all(promises);
268
+ return result;
269
+ }
270
+ /**
271
+ *
272
+ * @param event
273
+ * @private
274
+ */
275
+ parseWithdrawalEvent(event) {
276
+ switch (event.name) {
277
+ case "spv_swap_vault::events::Fronted":
278
+ return {
279
+ type: base_1.SpvWithdrawalStateType.FRONTED,
280
+ btcTxId: (0, Utils_1.bigNumberishToBuffer)(event.params.btc_tx_hash, 32).reverse().toString("hex"),
281
+ owner: (0, Utils_1.toHex)(event.params.owner),
282
+ vaultId: (0, Utils_1.toBigInt)(event.params.vault_id),
283
+ recipient: (0, Utils_1.toHex)(event.params.recipient),
284
+ fronter: (0, Utils_1.toHex)(event.params.caller),
285
+ txId: event.txHash,
286
+ getTxBlock: async () => ({
287
+ blockHeight: event.blockNumber,
288
+ blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber)
289
+ })
290
+ };
291
+ case "spv_swap_vault::events::Claimed":
292
+ return {
293
+ type: base_1.SpvWithdrawalStateType.CLAIMED,
294
+ btcTxId: (0, Utils_1.bigNumberishToBuffer)(event.params.btc_tx_hash, 32).reverse().toString("hex"),
295
+ owner: (0, Utils_1.toHex)(event.params.owner),
296
+ vaultId: (0, Utils_1.toBigInt)(event.params.vault_id),
297
+ recipient: (0, Utils_1.toHex)(event.params.recipient),
298
+ claimer: (0, Utils_1.toHex)(event.params.caller),
299
+ fronter: (0, Utils_1.toHex)(event.params.fronting_address),
300
+ txId: event.txHash,
301
+ getTxBlock: async () => ({
302
+ blockHeight: event.blockNumber,
303
+ blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber)
304
+ })
305
+ };
306
+ case "spv_swap_vault::events::Closed":
307
+ return {
308
+ type: base_1.SpvWithdrawalStateType.CLOSED,
309
+ btcTxId: (0, Utils_1.bigNumberishToBuffer)(event.params.btc_tx_hash, 32).reverse().toString("hex"),
310
+ owner: (0, Utils_1.toHex)(event.params.owner),
311
+ vaultId: (0, Utils_1.toBigInt)(event.params.vault_id),
312
+ error: (0, Utils_1.bigNumberishToBuffer)(event.params.error).toString(),
313
+ txId: event.txHash,
314
+ getTxBlock: async () => ({
315
+ blockHeight: event.blockNumber,
316
+ blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber)
317
+ })
318
+ };
319
+ default:
320
+ return null;
321
+ }
322
+ }
323
+ /**
324
+ * @inheritDoc
325
+ */
326
+ async getWithdrawalStates(withdrawalTxs) {
327
+ const result = {};
328
+ withdrawalTxs.forEach(withdrawalTx => {
329
+ result[withdrawalTx.withdrawal.getTxId()] = {
330
+ type: base_1.SpvWithdrawalStateType.NOT_FOUND
331
+ };
332
+ });
333
+ const events = ["spv_swap_vault::events::Fronted", "spv_swap_vault::events::Claimed", "spv_swap_vault::events::Closed"];
334
+ for (let i = 0; i < withdrawalTxs.length; i += this.Chain.config.maxGetLogKeys) {
335
+ const checkWithdrawalTxs = withdrawalTxs.slice(i, i + this.Chain.config.maxGetLogKeys);
336
+ const lows = [];
337
+ const highs = [];
338
+ let startHeight = undefined;
339
+ checkWithdrawalTxs.forEach(withdrawalTx => {
340
+ const txHash = buffer_1.Buffer.from(withdrawalTx.withdrawal.getTxId(), "hex").reverse();
341
+ const txHashU256 = starknet_1.cairo.uint256("0x" + txHash.toString("hex"));
342
+ lows.push((0, Utils_1.toHex)(txHashU256.low));
343
+ highs.push((0, Utils_1.toHex)(txHashU256.high));
344
+ if (startHeight !== null) {
345
+ if (withdrawalTx.scStartBlockheight == null) {
346
+ startHeight = null;
347
+ }
348
+ else {
349
+ startHeight = Math.min(startHeight ?? Infinity, withdrawalTx.scStartBlockheight);
350
+ }
351
+ }
352
+ });
353
+ await this.Events.findInContractEventsForward(events, [lows, highs], async (event) => {
354
+ const txId = (0, Utils_1.bigNumberishToBuffer)(event.params.btc_tx_hash, 32).reverse().toString("hex");
355
+ if (result[txId] == null) {
356
+ this.logger.warn(`getWithdrawalStates(): findInContractEvents-callback: loaded event for ${txId}, but transaction not found in input params!`);
357
+ return;
358
+ }
359
+ const eventResult = this.parseWithdrawalEvent(event);
360
+ if (eventResult != null)
361
+ result[txId] = eventResult;
362
+ }, startHeight);
363
+ }
364
+ return result;
365
+ }
366
+ /**
367
+ * @inheritDoc
368
+ */
369
+ async getWithdrawalState(withdrawalTx, scStartBlockheight) {
370
+ const txHash = buffer_1.Buffer.from(withdrawalTx.getTxId(), "hex").reverse();
371
+ const txHashU256 = starknet_1.cairo.uint256("0x" + txHash.toString("hex"));
372
+ let result = {
373
+ type: base_1.SpvWithdrawalStateType.NOT_FOUND
374
+ };
375
+ const events = ["spv_swap_vault::events::Fronted", "spv_swap_vault::events::Claimed", "spv_swap_vault::events::Closed"];
376
+ const keys = [(0, Utils_1.toHex)(txHashU256.low), (0, Utils_1.toHex)(txHashU256.high)];
377
+ await this.Events.findInContractEventsForward(events, keys, async (event) => {
378
+ const eventResult = this.parseWithdrawalEvent(event);
379
+ if (eventResult != null)
380
+ result = eventResult;
381
+ }, scStartBlockheight);
382
+ return result;
383
+ }
384
+ async getHistoricalWithdrawalStates(recipient, startBlockheight) {
385
+ const { height: latestBlockheight } = await this.Chain.getFinalizedBlock();
386
+ const withdrawals = {};
387
+ const eventTypes = ["spv_swap_vault::events::Fronted", "spv_swap_vault::events::Claimed"];
388
+ await this.Events.findInContractEventsForward(eventTypes, [null, null, null, null, recipient], async (_event) => {
389
+ const eventResult = this.parseWithdrawalEvent(_event);
390
+ if (eventResult == null || eventResult.type === base_1.SpvWithdrawalStateType.CLOSED)
391
+ return null;
392
+ withdrawals[eventResult.btcTxId] = eventResult;
393
+ }, startBlockheight);
394
+ return {
395
+ withdrawals,
396
+ latestBlockheight
397
+ };
398
+ }
399
+ /**
400
+ * @inheritDoc
401
+ */
402
+ getWithdrawalData(btcTx) {
403
+ return Promise.resolve(new StarknetSpvWithdrawalData_1.StarknetSpvWithdrawalData(btcTx));
404
+ }
405
+ //OP_RETURN data encoding/decoding
406
+ /**
407
+ * @inheritDoc
408
+ */
409
+ fromOpReturnData(data) {
410
+ return StarknetSpvVaultContract.fromOpReturnData(data);
411
+ }
412
+ /**
413
+ * Parses withdrawal params from OP_RETURN data
414
+ *
415
+ * @param data data as specified in the OP_RETURN output of the transaction
416
+ */
417
+ static fromOpReturnData(data) {
418
+ let rawAmount0 = 0n;
419
+ let rawAmount1 = 0n;
420
+ let executionHash = undefined;
421
+ if (data.length === 40) {
422
+ rawAmount0 = data.readBigInt64LE(32).valueOf();
423
+ }
424
+ else if (data.length === 48) {
425
+ rawAmount0 = data.readBigInt64LE(32).valueOf();
426
+ rawAmount1 = data.readBigInt64LE(40).valueOf();
427
+ }
428
+ else if (data.length === 72) {
429
+ rawAmount0 = data.readBigInt64LE(32).valueOf();
430
+ executionHash = data.slice(40, 72).toString("hex");
431
+ }
432
+ else if (data.length === 80) {
433
+ rawAmount0 = data.readBigInt64LE(32).valueOf();
434
+ rawAmount1 = data.readBigInt64LE(40).valueOf();
435
+ executionHash = data.slice(48, 80).toString("hex");
436
+ }
437
+ else {
438
+ throw new Error("Invalid OP_RETURN data length!");
439
+ }
440
+ if (executionHash != undefined) {
441
+ const executionHashValue = BigInt("0x" + executionHash);
442
+ if (executionHashValue >= STARK_PRIME_MOD)
443
+ throw new Error("Execution hash not in range of starknet prime");
444
+ }
445
+ const recipient = "0x" + data.slice(0, 32).toString("hex");
446
+ if (!StarknetAddresses_1.StarknetAddresses.isValidAddress(recipient))
447
+ throw new Error("Invalid recipient specified");
448
+ return { executionHash, rawAmounts: [rawAmount0, rawAmount1], recipient };
449
+ }
450
+ /**
451
+ * @inheritDoc
452
+ */
453
+ toOpReturnData(recipient, rawAmounts, executionHash) {
454
+ return StarknetSpvVaultContract.toOpReturnData(recipient, rawAmounts, executionHash);
455
+ }
456
+ /**
457
+ * Serializes the withdrawal params to the OP_RETURN data
458
+ *
459
+ * @param recipient Recipient of the withdrawn tokens
460
+ * @param rawAmounts Raw amount of tokens to withdraw
461
+ * @param executionHash Optional execution hash of the actions to execute
462
+ */
463
+ static toOpReturnData(recipient, rawAmounts, executionHash) {
464
+ if (!StarknetAddresses_1.StarknetAddresses.isValidAddress(recipient))
465
+ throw new Error("Invalid recipient specified");
466
+ if (rawAmounts.length < 1)
467
+ throw new Error("At least 1 amount needs to be specified");
468
+ if (rawAmounts.length > 2)
469
+ throw new Error("At most 2 amounts need to be specified");
470
+ rawAmounts.forEach(val => {
471
+ if (val < 0n)
472
+ throw new Error("Negative raw amount specified");
473
+ if (val >= 2n ** 64n)
474
+ throw new Error("Raw amount overflow");
475
+ });
476
+ if (executionHash != null) {
477
+ const executionHashValue = (0, Utils_1.toBigInt)(executionHash);
478
+ if (executionHashValue < 0n)
479
+ throw new Error("Execution hash negative");
480
+ if (executionHashValue >= STARK_PRIME_MOD)
481
+ throw new Error("Execution hash not in range of starknet prime");
482
+ }
483
+ const recipientBuffer = buffer_1.Buffer.from(recipient.substring(2).padStart(64, "0"), "hex");
484
+ const amount0Buffer = buffer_1.Buffer.from(rawAmounts[0].toString(16).padStart(16, "0"), "hex");
485
+ const amount1Buffer = rawAmounts[1] == null || rawAmounts[1] === 0n ? buffer_1.Buffer.alloc(0) : buffer_1.Buffer.from(rawAmounts[1].toString(16).padStart(16, "0"), "hex");
486
+ const executionHashBuffer = executionHash == null ? buffer_1.Buffer.alloc(0) : buffer_1.Buffer.from(executionHash.substring(2).padStart(64, "0"), "hex");
487
+ return buffer_1.Buffer.concat([
488
+ recipientBuffer,
489
+ amount0Buffer.reverse(),
490
+ amount1Buffer.reverse(),
491
+ executionHashBuffer
492
+ ]);
493
+ }
494
+ //Actions
495
+ /**
496
+ * @inheritDoc
497
+ */
498
+ async claim(signer, vault, txs, synchronizer, initAta, txOptions) {
499
+ const result = await this.txsClaim(signer.getAddress(), vault, txs, synchronizer, initAta, txOptions?.feeRate);
500
+ const [signature] = await this.Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
501
+ return signature;
502
+ }
503
+ /**
504
+ * @inheritDoc
505
+ */
506
+ async deposit(signer, vault, rawAmounts, txOptions) {
507
+ const result = await this.txsDeposit(signer.getAddress(), vault, rawAmounts, txOptions?.feeRate);
508
+ const [signature] = await this.Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
509
+ return signature;
510
+ }
511
+ /**
512
+ * @inheritDoc
513
+ */
514
+ async frontLiquidity(signer, vault, realWithdrawalTx, withdrawSequence, txOptions) {
515
+ const result = await this.txsFrontLiquidity(signer.getAddress(), vault, realWithdrawalTx, withdrawSequence, txOptions?.feeRate);
516
+ const [signature] = await this.Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
517
+ return signature;
518
+ }
519
+ /**
520
+ * @inheritDoc
521
+ */
522
+ async open(signer, vault, txOptions) {
523
+ const result = await this.txsOpen(signer.getAddress(), vault, txOptions?.feeRate);
524
+ const [signature] = await this.Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
525
+ return signature;
526
+ }
527
+ //Transactions
528
+ /**
529
+ * @inheritDoc
530
+ */
531
+ async txsClaim(signer, vault, txs, synchronizer, initAta, feeRate) {
532
+ if (!vault.isOpened())
533
+ throw new Error("Cannot claim from a closed vault!");
534
+ feeRate ?? (feeRate = await this.Chain.Fees.getFeeRate());
535
+ const txsWithMerkleProofs = [];
536
+ for (let tx of txs) {
537
+ if (tx.tx.btcTx.blockhash == null)
538
+ throw new Error(`Transaction ${tx.tx.btcTx.txid} doesn't have any blockhash, unconfirmed?`);
539
+ const merkleProof = await this.bitcoinRpc.getMerkleProof(tx.tx.btcTx.txid, tx.tx.btcTx.blockhash);
540
+ if (merkleProof == null)
541
+ throw new Error(`Failed to get merkle proof for tx: ${tx.tx.btcTx.txid}!`);
542
+ this.logger.debug("txsClaim(): merkle proof computed: ", merkleProof);
543
+ txsWithMerkleProofs.push({
544
+ ...merkleProof,
545
+ ...tx
546
+ });
547
+ }
548
+ const starknetTxs = [];
549
+ const storedHeaders = await StarknetBtcRelay_1.StarknetBtcRelay.getCommitedHeadersAndSynchronize(signer, this.btcRelay, txsWithMerkleProofs.filter(tx => tx.storedHeader == null).map(tx => {
550
+ return {
551
+ blockhash: tx.tx.btcTx.blockhash,
552
+ blockheight: tx.blockheight,
553
+ requiredConfirmations: vault.getConfirmations()
554
+ };
555
+ }), starknetTxs, synchronizer, feeRate);
556
+ if (storedHeaders == null)
557
+ throw new Error("Cannot fetch committed header!");
558
+ const actions = txsWithMerkleProofs.map(tx => {
559
+ return this.Claim(signer, vault, tx.tx, tx.storedHeader ?? storedHeaders[tx.tx.btcTx.blockhash], tx.merkle, tx.pos);
560
+ });
561
+ let starknetAction = new StarknetAction_1.StarknetAction(signer, this.Chain);
562
+ for (let action of actions) {
563
+ starknetAction.add(action);
564
+ if (starknetAction.ixsLength() >= this.maxClaimsPerTx) {
565
+ await starknetAction.addToTxs(starknetTxs, feeRate);
566
+ starknetAction = new StarknetAction_1.StarknetAction(signer, this.Chain);
567
+ }
568
+ }
569
+ if (starknetAction.ixsLength() > 0) {
570
+ await starknetAction.addToTxs(starknetTxs, feeRate);
571
+ }
572
+ this.logger.debug("txsClaim(): " + starknetTxs.length + " claim TXs created claiming " + txs.length + " txs, owner: " + vault.getOwner() +
573
+ " vaultId: " + vault.getVaultId().toString(10));
574
+ return starknetTxs;
575
+ }
576
+ /**
577
+ * @inheritDoc
578
+ */
579
+ async txsDeposit(signer, vault, rawAmounts, feeRate) {
580
+ if (!vault.isOpened())
581
+ throw new Error("Cannot deposit to a closed vault!");
582
+ //Approve first
583
+ const vaultTokens = vault.getTokenData();
584
+ const action = new StarknetAction_1.StarknetAction(signer, this.Chain);
585
+ let realAmount0 = 0n;
586
+ let realAmount1 = 0n;
587
+ if (rawAmounts[0] != null && rawAmounts[0] !== 0n) {
588
+ realAmount0 = rawAmounts[0] * vaultTokens[0].multiplier;
589
+ action.add(this.Chain.Tokens.Approve(signer, this.contract.address, vaultTokens[0].token, realAmount0));
590
+ }
591
+ if (rawAmounts[1] != null && rawAmounts[1] !== 0n) {
592
+ realAmount1 = rawAmounts[1] * vaultTokens[1].multiplier;
593
+ action.add(this.Chain.Tokens.Approve(signer, this.contract.address, vaultTokens[1].token, realAmount1));
594
+ }
595
+ action.add(this.Deposit(signer, vault, rawAmounts));
596
+ feeRate ?? (feeRate = await this.Chain.Fees.getFeeRate());
597
+ this.logger.debug("txsDeposit(): deposit TX created," +
598
+ " token0: " + vaultTokens[0].token + " rawAmount0: " + rawAmounts[0].toString(10) + " amount0: " + realAmount0.toString(10) +
599
+ " token1: " + vaultTokens[1].token + " rawAmount1: " + (rawAmounts[1] ?? 0n).toString(10) + " amount1: " + realAmount1.toString(10));
600
+ return [await action.tx(feeRate)];
601
+ }
602
+ /**
603
+ * @inheritDoc
604
+ */
605
+ async txsFrontLiquidity(signer, vault, realWithdrawalTx, withdrawSequence, feeRate) {
606
+ if (!vault.isOpened())
607
+ throw new Error("Cannot front on a closed vault!");
608
+ //Approve first
609
+ const vaultTokens = vault.getTokenData();
610
+ const action = new StarknetAction_1.StarknetAction(signer, this.Chain);
611
+ const rawAmounts = realWithdrawalTx.getFrontingAmount();
612
+ let realAmount0 = 0n;
613
+ let realAmount1 = 0n;
614
+ if (rawAmounts[0] != null && rawAmounts[0] !== 0n) {
615
+ realAmount0 = rawAmounts[0] * vaultTokens[0].multiplier;
616
+ action.add(this.Chain.Tokens.Approve(signer, this.contract.address, vaultTokens[0].token, realAmount0));
617
+ }
618
+ if (rawAmounts[1] != null && rawAmounts[1] !== 0n) {
619
+ realAmount1 = rawAmounts[1] * vaultTokens[1].multiplier;
620
+ action.add(this.Chain.Tokens.Approve(signer, this.contract.address, vaultTokens[1].token, realAmount1));
621
+ }
622
+ action.add(this.Front(signer, vault, realWithdrawalTx, withdrawSequence));
623
+ feeRate ?? (feeRate = await this.Chain.Fees.getFeeRate());
624
+ this.logger.debug("txsFrontLiquidity(): front TX created," +
625
+ " token0: " + vaultTokens[0].token + " rawAmount0: " + rawAmounts[0].toString(10) + " amount0: " + realAmount0.toString(10) +
626
+ " token1: " + vaultTokens[1].token + " rawAmount1: " + (rawAmounts[1] ?? 0n).toString(10) + " amount1: " + realAmount1.toString(10));
627
+ return [await action.tx(feeRate)];
628
+ }
629
+ /**
630
+ * @inheritDoc
631
+ */
632
+ async txsOpen(signer, vault, feeRate) {
633
+ if (vault.isOpened())
634
+ throw new Error("Cannot open an already opened vault!");
635
+ const action = this.Open(signer, vault);
636
+ feeRate ?? (feeRate = await this.Chain.Fees.getFeeRate());
637
+ this.logger.debug("txsOpen(): open TX created, owner: " + vault.getOwner() +
638
+ " vaultId: " + vault.getVaultId().toString(10));
639
+ return [await action.tx(feeRate)];
640
+ }
641
+ /**
642
+ * @inheritDoc
643
+ */
644
+ async getClaimFee(signer, vault, withdrawalData, feeRate) {
645
+ feeRate ?? (feeRate = await this.Chain.Fees.getFeeRate());
646
+ return StarknetFees_1.StarknetFees.getGasFee(withdrawalData == null ? StarknetSpvVaultContract.GasCosts.CLAIM_OPTIMISTIC_ESTIMATE : StarknetSpvVaultContract.GasCosts.CLAIM, feeRate);
647
+ }
648
+ /**
649
+ * @inheritDoc
650
+ */
651
+ async getFrontFee(signer, vault, withdrawalData, feeRate) {
652
+ feeRate ?? (feeRate = await this.Chain.Fees.getFeeRate());
653
+ return StarknetFees_1.StarknetFees.getGasFee(StarknetSpvVaultContract.GasCosts.FRONT, feeRate);
654
+ }
655
+ }
656
+ exports.StarknetSpvVaultContract = StarknetSpvVaultContract;
657
+ StarknetSpvVaultContract.GasCosts = {
658
+ DEPOSIT: { l1DataGas: 400, l2Gas: 4000000, l1Gas: 0 },
659
+ OPEN: { l1DataGas: 1200, l2Gas: 3200000, l1Gas: 0 },
660
+ FRONT: { l1DataGas: 800, l2Gas: 12000000, l1Gas: 0 },
661
+ CLAIM: { l1DataGas: 1000, l2Gas: 400000000, l1Gas: 0 },
662
+ CLAIM_OPTIMISTIC_ESTIMATE: { l1DataGas: 1000, l2Gas: 80000000, l1Gas: 0 } //If claimer uses sierra 1.7.0 or later
663
+ };