@oydual31/more-vaults-sdk 0.1.0
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 +283 -0
- package/dist/ethers/index.cjs +973 -0
- package/dist/ethers/index.cjs.map +1 -0
- package/dist/ethers/index.d.cts +671 -0
- package/dist/ethers/index.d.ts +671 -0
- package/dist/ethers/index.js +924 -0
- package/dist/ethers/index.js.map +1 -0
- package/dist/viem/index.cjs +1426 -0
- package/dist/viem/index.cjs.map +1 -0
- package/dist/viem/index.d.cts +1291 -0
- package/dist/viem/index.d.ts +1291 -0
- package/dist/viem/index.js +1377 -0
- package/dist/viem/index.js.map +1 -0
- package/package.json +46 -0
- package/src/ethers/abis.ts +82 -0
- package/src/ethers/crossChainFlows.ts +206 -0
- package/src/ethers/depositFlows.ts +347 -0
- package/src/ethers/errors.ts +81 -0
- package/src/ethers/index.ts +103 -0
- package/src/ethers/preflight.ts +156 -0
- package/src/ethers/redeemFlows.ts +286 -0
- package/src/ethers/types.ts +67 -0
- package/src/ethers/userHelpers.ts +480 -0
- package/src/ethers/utils.ts +377 -0
- package/src/viem/abis.ts +392 -0
- package/src/viem/crossChainFlows.ts +220 -0
- package/src/viem/depositFlows.ts +331 -0
- package/src/viem/errors.ts +81 -0
- package/src/viem/index.ts +100 -0
- package/src/viem/preflight.ts +204 -0
- package/src/viem/redeemFlows.ts +337 -0
- package/src/viem/types.ts +56 -0
- package/src/viem/userHelpers.ts +489 -0
- package/src/viem/utils.ts +421 -0
|
@@ -0,0 +1,1377 @@
|
|
|
1
|
+
import { getAddress, zeroAddress, encodeAbiParameters, pad } from 'viem';
|
|
2
|
+
|
|
3
|
+
// src/viem/abis.ts
|
|
4
|
+
var VAULT_ABI = [
|
|
5
|
+
{
|
|
6
|
+
type: "function",
|
|
7
|
+
name: "deposit",
|
|
8
|
+
inputs: [
|
|
9
|
+
{ name: "assets", type: "uint256" },
|
|
10
|
+
{ name: "receiver", type: "address" }
|
|
11
|
+
],
|
|
12
|
+
outputs: [{ name: "shares", type: "uint256" }],
|
|
13
|
+
stateMutability: "nonpayable"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
type: "function",
|
|
17
|
+
name: "deposit",
|
|
18
|
+
inputs: [
|
|
19
|
+
{ name: "tokens", type: "address[]" },
|
|
20
|
+
{ name: "assets", type: "uint256[]" },
|
|
21
|
+
{ name: "receiver", type: "address" },
|
|
22
|
+
{ name: "minAmountOut", type: "uint256" }
|
|
23
|
+
],
|
|
24
|
+
outputs: [{ name: "shares", type: "uint256" }],
|
|
25
|
+
stateMutability: "payable"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
type: "function",
|
|
29
|
+
name: "mint",
|
|
30
|
+
inputs: [
|
|
31
|
+
{ name: "shares", type: "uint256" },
|
|
32
|
+
{ name: "receiver", type: "address" }
|
|
33
|
+
],
|
|
34
|
+
outputs: [{ name: "assets", type: "uint256" }],
|
|
35
|
+
stateMutability: "nonpayable"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
type: "function",
|
|
39
|
+
name: "withdraw",
|
|
40
|
+
inputs: [
|
|
41
|
+
{ name: "assets", type: "uint256" },
|
|
42
|
+
{ name: "receiver", type: "address" },
|
|
43
|
+
{ name: "owner", type: "address" }
|
|
44
|
+
],
|
|
45
|
+
outputs: [{ name: "shares", type: "uint256" }],
|
|
46
|
+
stateMutability: "nonpayable"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
type: "function",
|
|
50
|
+
name: "redeem",
|
|
51
|
+
inputs: [
|
|
52
|
+
{ name: "shares", type: "uint256" },
|
|
53
|
+
{ name: "receiver", type: "address" },
|
|
54
|
+
{ name: "owner", type: "address" }
|
|
55
|
+
],
|
|
56
|
+
outputs: [{ name: "assets", type: "uint256" }],
|
|
57
|
+
stateMutability: "nonpayable"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
type: "function",
|
|
61
|
+
name: "requestRedeem",
|
|
62
|
+
inputs: [
|
|
63
|
+
{ name: "_shares", type: "uint256" },
|
|
64
|
+
{ name: "_onBehalfOf", type: "address" }
|
|
65
|
+
],
|
|
66
|
+
outputs: [],
|
|
67
|
+
stateMutability: "nonpayable"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
type: "function",
|
|
71
|
+
name: "requestWithdraw",
|
|
72
|
+
inputs: [
|
|
73
|
+
{ name: "_assets", type: "uint256" },
|
|
74
|
+
{ name: "_onBehalfOf", type: "address" }
|
|
75
|
+
],
|
|
76
|
+
outputs: [],
|
|
77
|
+
stateMutability: "nonpayable"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
type: "function",
|
|
81
|
+
name: "getWithdrawalRequest",
|
|
82
|
+
inputs: [{ name: "_owner", type: "address" }],
|
|
83
|
+
outputs: [
|
|
84
|
+
{ name: "shares", type: "uint256" },
|
|
85
|
+
{ name: "timelockEndsAt", type: "uint256" }
|
|
86
|
+
],
|
|
87
|
+
stateMutability: "view"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
type: "function",
|
|
91
|
+
name: "totalAssets",
|
|
92
|
+
inputs: [],
|
|
93
|
+
outputs: [{ name: "_totalAssets", type: "uint256" }],
|
|
94
|
+
stateMutability: "view"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
type: "function",
|
|
98
|
+
name: "totalSupply",
|
|
99
|
+
inputs: [],
|
|
100
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
101
|
+
stateMutability: "view"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
type: "function",
|
|
105
|
+
name: "balanceOf",
|
|
106
|
+
inputs: [{ name: "account", type: "address" }],
|
|
107
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
108
|
+
stateMutability: "view"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
type: "function",
|
|
112
|
+
name: "asset",
|
|
113
|
+
inputs: [],
|
|
114
|
+
outputs: [{ name: "", type: "address" }],
|
|
115
|
+
stateMutability: "view"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
type: "function",
|
|
119
|
+
name: "convertToShares",
|
|
120
|
+
inputs: [{ name: "assets", type: "uint256" }],
|
|
121
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
122
|
+
stateMutability: "view"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
type: "function",
|
|
126
|
+
name: "convertToAssets",
|
|
127
|
+
inputs: [{ name: "shares", type: "uint256" }],
|
|
128
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
129
|
+
stateMutability: "view"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
type: "function",
|
|
133
|
+
name: "previewDeposit",
|
|
134
|
+
inputs: [{ name: "assets", type: "uint256" }],
|
|
135
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
136
|
+
stateMutability: "view"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
type: "function",
|
|
140
|
+
name: "previewRedeem",
|
|
141
|
+
inputs: [{ name: "shares", type: "uint256" }],
|
|
142
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
143
|
+
stateMutability: "view"
|
|
144
|
+
}
|
|
145
|
+
];
|
|
146
|
+
var BRIDGE_ABI = [
|
|
147
|
+
{
|
|
148
|
+
type: "function",
|
|
149
|
+
name: "initVaultActionRequest",
|
|
150
|
+
inputs: [
|
|
151
|
+
{ name: "actionType", type: "uint8" },
|
|
152
|
+
{ name: "actionCallData", type: "bytes" },
|
|
153
|
+
{ name: "amountLimit", type: "uint256" },
|
|
154
|
+
{ name: "extraOptions", type: "bytes" }
|
|
155
|
+
],
|
|
156
|
+
outputs: [{ name: "guid", type: "bytes32" }],
|
|
157
|
+
stateMutability: "payable"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
type: "function",
|
|
161
|
+
name: "getRequestInfo",
|
|
162
|
+
inputs: [{ name: "guid", type: "bytes32" }],
|
|
163
|
+
outputs: [
|
|
164
|
+
{
|
|
165
|
+
name: "",
|
|
166
|
+
type: "tuple",
|
|
167
|
+
components: [
|
|
168
|
+
{ name: "initiator", type: "address" },
|
|
169
|
+
{ name: "timestamp", type: "uint64" },
|
|
170
|
+
{ name: "actionType", type: "uint8" },
|
|
171
|
+
{ name: "actionCallData", type: "bytes" },
|
|
172
|
+
{ name: "fulfilled", type: "bool" },
|
|
173
|
+
{ name: "finalized", type: "bool" },
|
|
174
|
+
{ name: "refunded", type: "bool" },
|
|
175
|
+
{ name: "totalAssets", type: "uint256" },
|
|
176
|
+
{ name: "finalizationResult", type: "uint256" },
|
|
177
|
+
{ name: "amountLimit", type: "uint256" }
|
|
178
|
+
]
|
|
179
|
+
}
|
|
180
|
+
],
|
|
181
|
+
stateMutability: "view"
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
type: "function",
|
|
185
|
+
name: "getFinalizationResult",
|
|
186
|
+
inputs: [{ name: "guid", type: "bytes32" }],
|
|
187
|
+
outputs: [{ name: "result", type: "uint256" }],
|
|
188
|
+
stateMutability: "view"
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
type: "function",
|
|
192
|
+
name: "quoteAccountingFee",
|
|
193
|
+
inputs: [{ name: "extraOptions", type: "bytes" }],
|
|
194
|
+
outputs: [{ name: "nativeFee", type: "uint256" }],
|
|
195
|
+
stateMutability: "view"
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
type: "function",
|
|
199
|
+
name: "oraclesCrossChainAccounting",
|
|
200
|
+
inputs: [],
|
|
201
|
+
outputs: [{ name: "", type: "bool" }],
|
|
202
|
+
stateMutability: "view"
|
|
203
|
+
}
|
|
204
|
+
];
|
|
205
|
+
var CONFIG_ABI = [
|
|
206
|
+
{
|
|
207
|
+
type: "function",
|
|
208
|
+
name: "getEscrow",
|
|
209
|
+
inputs: [],
|
|
210
|
+
outputs: [{ name: "escrow", type: "address" }],
|
|
211
|
+
stateMutability: "view"
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
type: "function",
|
|
215
|
+
name: "getCrossChainAccountingManager",
|
|
216
|
+
inputs: [],
|
|
217
|
+
outputs: [{ name: "", type: "address" }],
|
|
218
|
+
stateMutability: "view"
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
type: "function",
|
|
222
|
+
name: "isHub",
|
|
223
|
+
inputs: [],
|
|
224
|
+
outputs: [{ name: "", type: "bool" }],
|
|
225
|
+
stateMutability: "view"
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
type: "function",
|
|
229
|
+
name: "getWithdrawalQueueStatus",
|
|
230
|
+
inputs: [],
|
|
231
|
+
outputs: [{ name: "", type: "bool" }],
|
|
232
|
+
stateMutability: "view"
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
type: "function",
|
|
236
|
+
name: "getWithdrawalTimelock",
|
|
237
|
+
inputs: [],
|
|
238
|
+
outputs: [{ name: "", type: "uint64" }],
|
|
239
|
+
stateMutability: "view"
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
type: "function",
|
|
243
|
+
name: "paused",
|
|
244
|
+
inputs: [],
|
|
245
|
+
outputs: [{ name: "", type: "bool" }],
|
|
246
|
+
stateMutability: "view"
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
type: "function",
|
|
250
|
+
name: "maxDeposit",
|
|
251
|
+
inputs: [{ name: "receiver", type: "address" }],
|
|
252
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
253
|
+
stateMutability: "view"
|
|
254
|
+
}
|
|
255
|
+
];
|
|
256
|
+
var ERC20_ABI = [
|
|
257
|
+
{
|
|
258
|
+
type: "function",
|
|
259
|
+
name: "approve",
|
|
260
|
+
inputs: [
|
|
261
|
+
{ name: "spender", type: "address" },
|
|
262
|
+
{ name: "value", type: "uint256" }
|
|
263
|
+
],
|
|
264
|
+
outputs: [{ name: "", type: "bool" }],
|
|
265
|
+
stateMutability: "nonpayable"
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
type: "function",
|
|
269
|
+
name: "allowance",
|
|
270
|
+
inputs: [
|
|
271
|
+
{ name: "owner", type: "address" },
|
|
272
|
+
{ name: "spender", type: "address" }
|
|
273
|
+
],
|
|
274
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
275
|
+
stateMutability: "view"
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
type: "function",
|
|
279
|
+
name: "balanceOf",
|
|
280
|
+
inputs: [{ name: "account", type: "address" }],
|
|
281
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
282
|
+
stateMutability: "view"
|
|
283
|
+
}
|
|
284
|
+
];
|
|
285
|
+
var METADATA_ABI = [
|
|
286
|
+
{ type: "function", name: "name", inputs: [], outputs: [{ name: "", type: "string" }], stateMutability: "view" },
|
|
287
|
+
{ type: "function", name: "symbol", inputs: [], outputs: [{ name: "", type: "string" }], stateMutability: "view" },
|
|
288
|
+
{ type: "function", name: "decimals", inputs: [], outputs: [{ name: "", type: "uint8" }], stateMutability: "view" }
|
|
289
|
+
];
|
|
290
|
+
var OFT_ABI = [
|
|
291
|
+
{
|
|
292
|
+
type: "function",
|
|
293
|
+
name: "send",
|
|
294
|
+
inputs: [
|
|
295
|
+
{
|
|
296
|
+
name: "_sendParam",
|
|
297
|
+
type: "tuple",
|
|
298
|
+
components: [
|
|
299
|
+
{ name: "dstEid", type: "uint32" },
|
|
300
|
+
{ name: "to", type: "bytes32" },
|
|
301
|
+
{ name: "amountLD", type: "uint256" },
|
|
302
|
+
{ name: "minAmountLD", type: "uint256" },
|
|
303
|
+
{ name: "extraOptions", type: "bytes" },
|
|
304
|
+
{ name: "composeMsg", type: "bytes" },
|
|
305
|
+
{ name: "oftCmd", type: "bytes" }
|
|
306
|
+
]
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
name: "_fee",
|
|
310
|
+
type: "tuple",
|
|
311
|
+
components: [
|
|
312
|
+
{ name: "nativeFee", type: "uint256" },
|
|
313
|
+
{ name: "lzTokenFee", type: "uint256" }
|
|
314
|
+
]
|
|
315
|
+
},
|
|
316
|
+
{ name: "_refundAddress", type: "address" }
|
|
317
|
+
],
|
|
318
|
+
outputs: [
|
|
319
|
+
{
|
|
320
|
+
name: "msgReceipt",
|
|
321
|
+
type: "tuple",
|
|
322
|
+
components: [
|
|
323
|
+
{ name: "guid", type: "bytes32" },
|
|
324
|
+
{ name: "nonce", type: "uint64" },
|
|
325
|
+
{
|
|
326
|
+
name: "fee",
|
|
327
|
+
type: "tuple",
|
|
328
|
+
components: [
|
|
329
|
+
{ name: "nativeFee", type: "uint256" },
|
|
330
|
+
{ name: "lzTokenFee", type: "uint256" }
|
|
331
|
+
]
|
|
332
|
+
}
|
|
333
|
+
]
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
name: "oftReceipt",
|
|
337
|
+
type: "tuple",
|
|
338
|
+
components: [
|
|
339
|
+
{ name: "amountSentLD", type: "uint256" },
|
|
340
|
+
{ name: "amountReceivedLD", type: "uint256" }
|
|
341
|
+
]
|
|
342
|
+
}
|
|
343
|
+
],
|
|
344
|
+
stateMutability: "payable"
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
type: "function",
|
|
348
|
+
name: "quoteSend",
|
|
349
|
+
inputs: [
|
|
350
|
+
{
|
|
351
|
+
name: "_sendParam",
|
|
352
|
+
type: "tuple",
|
|
353
|
+
components: [
|
|
354
|
+
{ name: "dstEid", type: "uint32" },
|
|
355
|
+
{ name: "to", type: "bytes32" },
|
|
356
|
+
{ name: "amountLD", type: "uint256" },
|
|
357
|
+
{ name: "minAmountLD", type: "uint256" },
|
|
358
|
+
{ name: "extraOptions", type: "bytes" },
|
|
359
|
+
{ name: "composeMsg", type: "bytes" },
|
|
360
|
+
{ name: "oftCmd", type: "bytes" }
|
|
361
|
+
]
|
|
362
|
+
},
|
|
363
|
+
{ name: "_payInLzToken", type: "bool" }
|
|
364
|
+
],
|
|
365
|
+
outputs: [
|
|
366
|
+
{
|
|
367
|
+
name: "msgFee",
|
|
368
|
+
type: "tuple",
|
|
369
|
+
components: [
|
|
370
|
+
{ name: "nativeFee", type: "uint256" },
|
|
371
|
+
{ name: "lzTokenFee", type: "uint256" }
|
|
372
|
+
]
|
|
373
|
+
}
|
|
374
|
+
],
|
|
375
|
+
stateMutability: "view"
|
|
376
|
+
}
|
|
377
|
+
];
|
|
378
|
+
|
|
379
|
+
// src/viem/types.ts
|
|
380
|
+
var ActionType = {
|
|
381
|
+
DEPOSIT: 0,
|
|
382
|
+
MINT: 1,
|
|
383
|
+
WITHDRAW: 2,
|
|
384
|
+
REDEEM: 3,
|
|
385
|
+
MULTI_ASSETS_DEPOSIT: 4,
|
|
386
|
+
ACCRUE_FEES: 5
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
// src/viem/errors.ts
|
|
390
|
+
var MoreVaultsError = class extends Error {
|
|
391
|
+
constructor(message) {
|
|
392
|
+
super(message);
|
|
393
|
+
this.name = "MoreVaultsError";
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
var VaultPausedError = class extends MoreVaultsError {
|
|
397
|
+
constructor(vault) {
|
|
398
|
+
super(`[MoreVaults] Vault ${vault} is paused. Cannot perform any actions.`);
|
|
399
|
+
this.name = "VaultPausedError";
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
var CapacityFullError = class extends MoreVaultsError {
|
|
403
|
+
constructor(vault) {
|
|
404
|
+
super(`[MoreVaults] Vault ${vault} has reached deposit capacity. No more deposits accepted.`);
|
|
405
|
+
this.name = "CapacityFullError";
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
var NotWhitelistedError = class extends MoreVaultsError {
|
|
409
|
+
constructor(vault, user) {
|
|
410
|
+
super(`[MoreVaults] Address ${user} is not whitelisted to deposit in vault ${vault}.`);
|
|
411
|
+
this.name = "NotWhitelistedError";
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
var InsufficientLiquidityError = class extends MoreVaultsError {
|
|
415
|
+
hubLiquid;
|
|
416
|
+
required;
|
|
417
|
+
constructor(vault, hubLiquid, required) {
|
|
418
|
+
super(
|
|
419
|
+
`[MoreVaults] Insufficient hub liquidity for redeem.
|
|
420
|
+
Hub liquid balance : ${hubLiquid}
|
|
421
|
+
Estimated required : ${required}
|
|
422
|
+
Submitting this redeem will waste the LayerZero fee \u2014 the request will be auto-refunded.
|
|
423
|
+
Ask the vault curator to repatriate liquidity from spoke chains first.`
|
|
424
|
+
);
|
|
425
|
+
this.name = "InsufficientLiquidityError";
|
|
426
|
+
this.hubLiquid = hubLiquid;
|
|
427
|
+
this.required = required;
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
var CCManagerNotConfiguredError = class extends MoreVaultsError {
|
|
431
|
+
constructor(vault) {
|
|
432
|
+
super(`[MoreVaults] CCManager not configured on vault ${vault}. Call setCrossChainAccountingManager(ccManagerAddress) as vault owner first.`);
|
|
433
|
+
this.name = "CCManagerNotConfiguredError";
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
var EscrowNotConfiguredError = class extends MoreVaultsError {
|
|
437
|
+
constructor(vault) {
|
|
438
|
+
super(`[MoreVaults] Escrow not configured for vault ${vault}. The registry must have an escrow set for this vault.`);
|
|
439
|
+
this.name = "EscrowNotConfiguredError";
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
var NotHubVaultError = class extends MoreVaultsError {
|
|
443
|
+
constructor(vault) {
|
|
444
|
+
super(`[MoreVaults] Vault ${vault} is not a hub vault. Async flows (D4/D5/R5) only work on hub vaults.`);
|
|
445
|
+
this.name = "NotHubVaultError";
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
var MissingEscrowAddressError = class extends MoreVaultsError {
|
|
449
|
+
constructor() {
|
|
450
|
+
super(`[MoreVaults] This flow requires an escrow address. Set VaultAddresses.escrow before calling async deposit/redeem flows.`);
|
|
451
|
+
this.name = "MissingEscrowAddressError";
|
|
452
|
+
}
|
|
453
|
+
};
|
|
454
|
+
async function getVaultStatus(publicClient, vault) {
|
|
455
|
+
const v = getAddress(vault);
|
|
456
|
+
const b1 = await publicClient.multicall({
|
|
457
|
+
contracts: [
|
|
458
|
+
{ address: v, abi: CONFIG_ABI, functionName: "isHub" },
|
|
459
|
+
{ address: v, abi: CONFIG_ABI, functionName: "paused" },
|
|
460
|
+
{ address: v, abi: BRIDGE_ABI, functionName: "oraclesCrossChainAccounting" },
|
|
461
|
+
{ address: v, abi: CONFIG_ABI, functionName: "getCrossChainAccountingManager" },
|
|
462
|
+
{ address: v, abi: CONFIG_ABI, functionName: "getEscrow" },
|
|
463
|
+
{ address: v, abi: CONFIG_ABI, functionName: "getWithdrawalQueueStatus" },
|
|
464
|
+
{ address: v, abi: CONFIG_ABI, functionName: "getWithdrawalTimelock" },
|
|
465
|
+
{ address: v, abi: CONFIG_ABI, functionName: "maxDeposit", args: [zeroAddress] },
|
|
466
|
+
{ address: v, abi: VAULT_ABI, functionName: "asset" },
|
|
467
|
+
{ address: v, abi: VAULT_ABI, functionName: "totalAssets" },
|
|
468
|
+
{ address: v, abi: VAULT_ABI, functionName: "totalSupply" },
|
|
469
|
+
{ address: v, abi: METADATA_ABI, functionName: "decimals" }
|
|
470
|
+
],
|
|
471
|
+
allowFailure: true
|
|
472
|
+
});
|
|
473
|
+
const isHub = b1[0].status === "success" ? b1[0].result : false;
|
|
474
|
+
const isPaused = b1[1].status === "success" ? b1[1].result : false;
|
|
475
|
+
const oraclesEnabled = b1[2].status === "success" ? b1[2].result : false;
|
|
476
|
+
const ccManager = b1[3].status === "success" ? b1[3].result : zeroAddress;
|
|
477
|
+
const escrow = b1[4].status === "success" ? b1[4].result : zeroAddress;
|
|
478
|
+
const withdrawalQueueEnabled = b1[5].status === "success" ? b1[5].result : false;
|
|
479
|
+
const withdrawalTimelockSeconds = b1[6].status === "success" ? b1[6].result : 0n;
|
|
480
|
+
const maxDepositRaw = b1[7].status === "success" ? b1[7].result : null;
|
|
481
|
+
const underlying = b1[8].status === "success" ? b1[8].result : zeroAddress;
|
|
482
|
+
const totalAssets = b1[9].status === "success" ? b1[9].result : 0n;
|
|
483
|
+
const totalSupply = b1[10].status === "success" ? b1[10].result : 0n;
|
|
484
|
+
const decimals = b1[11].status === "success" ? Number(b1[11].result) : 18;
|
|
485
|
+
const oneShare = 10n ** BigInt(decimals);
|
|
486
|
+
const b2 = await publicClient.multicall({
|
|
487
|
+
contracts: [
|
|
488
|
+
{ address: getAddress(underlying), abi: ERC20_ABI, functionName: "balanceOf", args: [v] },
|
|
489
|
+
{ address: v, abi: VAULT_ABI, functionName: "convertToAssets", args: [oneShare] }
|
|
490
|
+
],
|
|
491
|
+
allowFailure: true
|
|
492
|
+
});
|
|
493
|
+
const hubLiquidBalance = b2[0].status === "success" ? b2[0].result : 0n;
|
|
494
|
+
const sharePrice = b2[1].status === "success" ? b2[1].result : 0n;
|
|
495
|
+
const spokesDeployedBalance = totalAssets > hubLiquidBalance ? totalAssets - hubLiquidBalance : 0n;
|
|
496
|
+
const MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
|
497
|
+
const depositAccessRestricted = maxDepositRaw === null;
|
|
498
|
+
const effectiveCapacity = depositAccessRestricted ? MAX_UINT256 : maxDepositRaw;
|
|
499
|
+
let mode;
|
|
500
|
+
if (isPaused) {
|
|
501
|
+
mode = "paused";
|
|
502
|
+
} else if (effectiveCapacity === 0n) {
|
|
503
|
+
mode = "full";
|
|
504
|
+
} else if (!isHub) {
|
|
505
|
+
mode = "local";
|
|
506
|
+
} else if (oraclesEnabled) {
|
|
507
|
+
mode = "cross-chain-oracle";
|
|
508
|
+
} else {
|
|
509
|
+
mode = "cross-chain-async";
|
|
510
|
+
}
|
|
511
|
+
let recommendedDepositFlow;
|
|
512
|
+
let recommendedRedeemFlow;
|
|
513
|
+
if (mode === "paused" || mode === "full") {
|
|
514
|
+
recommendedDepositFlow = "none";
|
|
515
|
+
recommendedRedeemFlow = mode === "paused" ? "none" : "redeemShares";
|
|
516
|
+
} else if (mode === "cross-chain-async") {
|
|
517
|
+
recommendedDepositFlow = "depositAsync";
|
|
518
|
+
recommendedRedeemFlow = "redeemAsync";
|
|
519
|
+
} else {
|
|
520
|
+
recommendedDepositFlow = "depositSimple";
|
|
521
|
+
recommendedRedeemFlow = "redeemShares";
|
|
522
|
+
}
|
|
523
|
+
const maxImmediateRedeemAssets = isHub && !oraclesEnabled ? hubLiquidBalance : totalAssets;
|
|
524
|
+
const issues = [];
|
|
525
|
+
if (isPaused) {
|
|
526
|
+
issues.push("Vault is paused \u2014 no deposits or redeems are possible.");
|
|
527
|
+
}
|
|
528
|
+
if (effectiveCapacity === 0n && !isPaused) {
|
|
529
|
+
issues.push("Deposit capacity is full \u2014 increase depositCapacity via setDepositCapacity().");
|
|
530
|
+
}
|
|
531
|
+
if (depositAccessRestricted) {
|
|
532
|
+
issues.push("Deposit access is restricted (whitelist or other access control). Only approved addresses can deposit.");
|
|
533
|
+
}
|
|
534
|
+
if (isHub && !oraclesEnabled && ccManager === zeroAddress) {
|
|
535
|
+
issues.push(
|
|
536
|
+
"CCManager not configured \u2014 async flows will revert. Call setCrossChainAccountingManager(address) as vault owner."
|
|
537
|
+
);
|
|
538
|
+
}
|
|
539
|
+
if (isHub && !oraclesEnabled && escrow === zeroAddress) {
|
|
540
|
+
issues.push(
|
|
541
|
+
"Escrow not configured in registry \u2014 async flows will revert. Set the escrow via the MoreVaultsRegistry."
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
if (isHub) {
|
|
545
|
+
if (hubLiquidBalance === 0n) {
|
|
546
|
+
issues.push(
|
|
547
|
+
`Hub has no liquid assets (hubLiquidBalance = 0). All redeems will be auto-refunded until the curator repatriates funds from spokes via executeBridging().`
|
|
548
|
+
);
|
|
549
|
+
} else if (totalAssets > 0n && hubLiquidBalance * 10n < totalAssets) {
|
|
550
|
+
const pct = Number(hubLiquidBalance * 10000n / totalAssets) / 100;
|
|
551
|
+
issues.push(
|
|
552
|
+
`Low hub liquidity: ${hubLiquidBalance} units liquid on hub (${pct.toFixed(1)}% of TVL). Redeems above ${hubLiquidBalance} underlying units will be auto-refunded. Curator must call executeBridging() to repatriate from spokes.`
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
if (spokesDeployedBalance > 0n) {
|
|
556
|
+
const pct = (Number(spokesDeployedBalance) / Number(totalAssets || 1n) * 100).toFixed(1);
|
|
557
|
+
issues.push(
|
|
558
|
+
`${spokesDeployedBalance} units (~${pct}% of TVL) are deployed on spoke chains earning yield. These are NOT immediately redeemable \u2014 they require a curator repatriation (executeBridging) before users can withdraw them.`
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return {
|
|
563
|
+
mode,
|
|
564
|
+
recommendedDepositFlow,
|
|
565
|
+
recommendedRedeemFlow,
|
|
566
|
+
isHub,
|
|
567
|
+
isPaused,
|
|
568
|
+
oracleAccountingEnabled: oraclesEnabled,
|
|
569
|
+
ccManager,
|
|
570
|
+
escrow,
|
|
571
|
+
withdrawalQueueEnabled,
|
|
572
|
+
withdrawalTimelockSeconds: BigInt(withdrawalTimelockSeconds),
|
|
573
|
+
remainingDepositCapacity: effectiveCapacity,
|
|
574
|
+
depositAccessRestricted,
|
|
575
|
+
underlying,
|
|
576
|
+
totalAssets,
|
|
577
|
+
totalSupply,
|
|
578
|
+
decimals,
|
|
579
|
+
sharePrice,
|
|
580
|
+
hubLiquidBalance,
|
|
581
|
+
spokesDeployedBalance,
|
|
582
|
+
maxImmediateRedeemAssets,
|
|
583
|
+
issues
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
async function ensureAllowance(walletClient, publicClient, token, spender, amount) {
|
|
587
|
+
const account = walletClient.account;
|
|
588
|
+
const allowance = await publicClient.readContract({
|
|
589
|
+
address: getAddress(token),
|
|
590
|
+
abi: ERC20_ABI,
|
|
591
|
+
functionName: "allowance",
|
|
592
|
+
args: [account.address, getAddress(spender)]
|
|
593
|
+
});
|
|
594
|
+
if (allowance < amount) {
|
|
595
|
+
const hash = await walletClient.writeContract({
|
|
596
|
+
address: getAddress(token),
|
|
597
|
+
abi: ERC20_ABI,
|
|
598
|
+
functionName: "approve",
|
|
599
|
+
args: [getAddress(spender), amount],
|
|
600
|
+
account,
|
|
601
|
+
chain: walletClient.chain
|
|
602
|
+
});
|
|
603
|
+
await publicClient.waitForTransactionReceipt({ hash });
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
async function quoteLzFee(publicClient, vault, extraOptions = "0x") {
|
|
607
|
+
return publicClient.readContract({
|
|
608
|
+
address: getAddress(vault),
|
|
609
|
+
abi: BRIDGE_ABI,
|
|
610
|
+
functionName: "quoteAccountingFee",
|
|
611
|
+
args: [extraOptions]
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
async function isAsyncMode(publicClient, vault) {
|
|
615
|
+
const v = getAddress(vault);
|
|
616
|
+
const isHub = await publicClient.readContract({
|
|
617
|
+
address: v,
|
|
618
|
+
abi: CONFIG_ABI,
|
|
619
|
+
functionName: "isHub"
|
|
620
|
+
});
|
|
621
|
+
if (!isHub) return false;
|
|
622
|
+
const oraclesEnabled = await publicClient.readContract({
|
|
623
|
+
address: v,
|
|
624
|
+
abi: BRIDGE_ABI,
|
|
625
|
+
functionName: "oraclesCrossChainAccounting"
|
|
626
|
+
});
|
|
627
|
+
return !oraclesEnabled;
|
|
628
|
+
}
|
|
629
|
+
async function getAsyncRequestStatus(publicClient, vault, guid) {
|
|
630
|
+
const info = await publicClient.readContract({
|
|
631
|
+
address: getAddress(vault),
|
|
632
|
+
abi: BRIDGE_ABI,
|
|
633
|
+
functionName: "getRequestInfo",
|
|
634
|
+
args: [guid]
|
|
635
|
+
});
|
|
636
|
+
const finalizationResult = await publicClient.readContract({
|
|
637
|
+
address: getAddress(vault),
|
|
638
|
+
abi: BRIDGE_ABI,
|
|
639
|
+
functionName: "getFinalizationResult",
|
|
640
|
+
args: [guid]
|
|
641
|
+
});
|
|
642
|
+
return {
|
|
643
|
+
fulfilled: info.fulfilled,
|
|
644
|
+
finalized: info.finalized,
|
|
645
|
+
result: finalizationResult
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
async function preflightAsync(publicClient, vault, escrow) {
|
|
649
|
+
const v = getAddress(vault);
|
|
650
|
+
const [ccManager, registeredEscrow, isHub, oraclesEnabled, isPaused] = await Promise.all([
|
|
651
|
+
publicClient.readContract({
|
|
652
|
+
address: v,
|
|
653
|
+
abi: CONFIG_ABI,
|
|
654
|
+
functionName: "getCrossChainAccountingManager"
|
|
655
|
+
}),
|
|
656
|
+
publicClient.readContract({
|
|
657
|
+
address: v,
|
|
658
|
+
abi: CONFIG_ABI,
|
|
659
|
+
functionName: "getEscrow"
|
|
660
|
+
}),
|
|
661
|
+
publicClient.readContract({
|
|
662
|
+
address: v,
|
|
663
|
+
abi: CONFIG_ABI,
|
|
664
|
+
functionName: "isHub"
|
|
665
|
+
}),
|
|
666
|
+
publicClient.readContract({
|
|
667
|
+
address: v,
|
|
668
|
+
abi: BRIDGE_ABI,
|
|
669
|
+
functionName: "oraclesCrossChainAccounting"
|
|
670
|
+
}),
|
|
671
|
+
publicClient.readContract({
|
|
672
|
+
address: v,
|
|
673
|
+
abi: CONFIG_ABI,
|
|
674
|
+
functionName: "paused"
|
|
675
|
+
})
|
|
676
|
+
]);
|
|
677
|
+
if (ccManager === zeroAddress) {
|
|
678
|
+
throw new Error(
|
|
679
|
+
`[MoreVaults] CCManager not configured on vault ${vault}. Call setCrossChainAccountingManager(ccManagerAddress) as vault owner first.`
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
if (registeredEscrow === zeroAddress) {
|
|
683
|
+
throw new Error(
|
|
684
|
+
`[MoreVaults] Escrow not configured for vault ${vault}. The registry must have an escrow set for this vault.`
|
|
685
|
+
);
|
|
686
|
+
}
|
|
687
|
+
if (!isHub) {
|
|
688
|
+
throw new Error(
|
|
689
|
+
`[MoreVaults] Vault ${vault} is not a hub vault. Async flows (D4/D5/R5) only work on hub vaults.`
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
if (oraclesEnabled) {
|
|
693
|
+
throw new Error(
|
|
694
|
+
`[MoreVaults] Vault ${vault} has oracle-based cross-chain accounting enabled. Use depositSimple/depositCrossChainOracleOn instead of async flows.`
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
if (isPaused) {
|
|
698
|
+
throw new Error(
|
|
699
|
+
`[MoreVaults] Vault ${vault} is paused. Cannot perform any actions.`
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
async function preflightRedeemLiquidity(publicClient, vault, shares) {
|
|
704
|
+
const v = getAddress(vault);
|
|
705
|
+
const underlying = await publicClient.readContract({
|
|
706
|
+
address: v,
|
|
707
|
+
abi: VAULT_ABI,
|
|
708
|
+
functionName: "asset"
|
|
709
|
+
});
|
|
710
|
+
const [hubLiquid, assetsNeeded] = await Promise.all([
|
|
711
|
+
publicClient.readContract({
|
|
712
|
+
address: getAddress(underlying),
|
|
713
|
+
abi: ERC20_ABI,
|
|
714
|
+
functionName: "balanceOf",
|
|
715
|
+
args: [v]
|
|
716
|
+
}),
|
|
717
|
+
publicClient.readContract({
|
|
718
|
+
address: v,
|
|
719
|
+
abi: VAULT_ABI,
|
|
720
|
+
functionName: "convertToAssets",
|
|
721
|
+
args: [shares]
|
|
722
|
+
})
|
|
723
|
+
]);
|
|
724
|
+
if (hubLiquid < assetsNeeded) {
|
|
725
|
+
throw new Error(
|
|
726
|
+
`[MoreVaults] Insufficient hub liquidity for redeem.
|
|
727
|
+
Hub liquid balance : ${hubLiquid}
|
|
728
|
+
Estimated required : ${assetsNeeded}
|
|
729
|
+
Submitting this redeem will waste the LayerZero fee \u2014 the request will be auto-refunded.
|
|
730
|
+
Ask the vault curator to repatriate liquidity from spoke chains first.`
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
async function preflightSync(publicClient, vault) {
|
|
735
|
+
const v = getAddress(vault);
|
|
736
|
+
const [isPaused, depositCapResult] = await Promise.all([
|
|
737
|
+
publicClient.readContract({
|
|
738
|
+
address: v,
|
|
739
|
+
abi: CONFIG_ABI,
|
|
740
|
+
functionName: "paused"
|
|
741
|
+
}),
|
|
742
|
+
publicClient.readContract({
|
|
743
|
+
address: v,
|
|
744
|
+
abi: CONFIG_ABI,
|
|
745
|
+
functionName: "maxDeposit",
|
|
746
|
+
args: [zeroAddress]
|
|
747
|
+
}).catch(() => null)
|
|
748
|
+
]);
|
|
749
|
+
if (isPaused) {
|
|
750
|
+
throw new Error(
|
|
751
|
+
`[MoreVaults] Vault ${vault} is paused. Cannot perform any actions.`
|
|
752
|
+
);
|
|
753
|
+
}
|
|
754
|
+
if (depositCapResult !== null && depositCapResult === 0n) {
|
|
755
|
+
throw new Error(
|
|
756
|
+
`[MoreVaults] Vault ${vault} has reached deposit capacity. No more deposits accepted.`
|
|
757
|
+
);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
// src/viem/depositFlows.ts
|
|
762
|
+
async function depositSimple(walletClient, publicClient, addresses, assets, receiver) {
|
|
763
|
+
const account = walletClient.account;
|
|
764
|
+
const vault = getAddress(addresses.vault);
|
|
765
|
+
await preflightSync(publicClient, vault);
|
|
766
|
+
const underlying = await publicClient.readContract({
|
|
767
|
+
address: vault,
|
|
768
|
+
abi: VAULT_ABI,
|
|
769
|
+
functionName: "asset"
|
|
770
|
+
});
|
|
771
|
+
await ensureAllowance(walletClient, publicClient, underlying, vault, assets);
|
|
772
|
+
const { result: shares } = await publicClient.simulateContract({
|
|
773
|
+
address: vault,
|
|
774
|
+
abi: VAULT_ABI,
|
|
775
|
+
functionName: "deposit",
|
|
776
|
+
args: [assets, getAddress(receiver)],
|
|
777
|
+
account: account.address
|
|
778
|
+
});
|
|
779
|
+
const txHash = await walletClient.writeContract({
|
|
780
|
+
address: vault,
|
|
781
|
+
abi: VAULT_ABI,
|
|
782
|
+
functionName: "deposit",
|
|
783
|
+
args: [assets, getAddress(receiver)],
|
|
784
|
+
account,
|
|
785
|
+
chain: walletClient.chain
|
|
786
|
+
});
|
|
787
|
+
return { txHash, shares };
|
|
788
|
+
}
|
|
789
|
+
async function depositMultiAsset(walletClient, publicClient, addresses, tokens, amounts, receiver, minShares) {
|
|
790
|
+
const account = walletClient.account;
|
|
791
|
+
const vault = getAddress(addresses.vault);
|
|
792
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
793
|
+
await ensureAllowance(walletClient, publicClient, tokens[i], vault, amounts[i]);
|
|
794
|
+
}
|
|
795
|
+
const { result: shares } = await publicClient.simulateContract({
|
|
796
|
+
address: vault,
|
|
797
|
+
abi: VAULT_ABI,
|
|
798
|
+
functionName: "deposit",
|
|
799
|
+
args: [tokens, amounts, getAddress(receiver), minShares],
|
|
800
|
+
account: account.address
|
|
801
|
+
});
|
|
802
|
+
const txHash = await walletClient.writeContract({
|
|
803
|
+
address: vault,
|
|
804
|
+
abi: VAULT_ABI,
|
|
805
|
+
functionName: "deposit",
|
|
806
|
+
args: [tokens, amounts, getAddress(receiver), minShares],
|
|
807
|
+
account,
|
|
808
|
+
chain: walletClient.chain
|
|
809
|
+
});
|
|
810
|
+
return { txHash, shares };
|
|
811
|
+
}
|
|
812
|
+
async function depositAsync(walletClient, publicClient, addresses, assets, receiver, lzFee, extraOptions = "0x") {
|
|
813
|
+
const account = walletClient.account;
|
|
814
|
+
const vault = getAddress(addresses.vault);
|
|
815
|
+
if (!addresses.escrow) throw new MissingEscrowAddressError();
|
|
816
|
+
const escrow = getAddress(addresses.escrow);
|
|
817
|
+
await preflightAsync(publicClient, vault);
|
|
818
|
+
const underlying = await publicClient.readContract({
|
|
819
|
+
address: vault,
|
|
820
|
+
abi: VAULT_ABI,
|
|
821
|
+
functionName: "asset"
|
|
822
|
+
});
|
|
823
|
+
await ensureAllowance(walletClient, publicClient, underlying, escrow, assets);
|
|
824
|
+
const actionCallData = encodeAbiParameters(
|
|
825
|
+
[{ type: "uint256", name: "assets" }, { type: "address", name: "receiver" }],
|
|
826
|
+
[assets, getAddress(receiver)]
|
|
827
|
+
);
|
|
828
|
+
const { result: guid } = await publicClient.simulateContract({
|
|
829
|
+
address: vault,
|
|
830
|
+
abi: BRIDGE_ABI,
|
|
831
|
+
functionName: "initVaultActionRequest",
|
|
832
|
+
args: [ActionType.DEPOSIT, actionCallData, 0n, extraOptions],
|
|
833
|
+
value: lzFee,
|
|
834
|
+
account: account.address
|
|
835
|
+
});
|
|
836
|
+
const txHash = await walletClient.writeContract({
|
|
837
|
+
address: vault,
|
|
838
|
+
abi: BRIDGE_ABI,
|
|
839
|
+
functionName: "initVaultActionRequest",
|
|
840
|
+
args: [ActionType.DEPOSIT, actionCallData, 0n, extraOptions],
|
|
841
|
+
value: lzFee,
|
|
842
|
+
account,
|
|
843
|
+
chain: walletClient.chain
|
|
844
|
+
});
|
|
845
|
+
return { txHash, guid };
|
|
846
|
+
}
|
|
847
|
+
async function mintAsync(walletClient, publicClient, addresses, shares, maxAssets, receiver, lzFee, extraOptions = "0x") {
|
|
848
|
+
const account = walletClient.account;
|
|
849
|
+
const vault = getAddress(addresses.vault);
|
|
850
|
+
if (!addresses.escrow) throw new MissingEscrowAddressError();
|
|
851
|
+
const escrow = getAddress(addresses.escrow);
|
|
852
|
+
await preflightAsync(publicClient, vault);
|
|
853
|
+
const underlying = await publicClient.readContract({
|
|
854
|
+
address: vault,
|
|
855
|
+
abi: VAULT_ABI,
|
|
856
|
+
functionName: "asset"
|
|
857
|
+
});
|
|
858
|
+
await ensureAllowance(walletClient, publicClient, underlying, escrow, maxAssets);
|
|
859
|
+
const actionCallData = encodeAbiParameters(
|
|
860
|
+
[{ type: "uint256", name: "shares" }, { type: "address", name: "receiver" }],
|
|
861
|
+
[shares, getAddress(receiver)]
|
|
862
|
+
);
|
|
863
|
+
const { result: guid } = await publicClient.simulateContract({
|
|
864
|
+
address: vault,
|
|
865
|
+
abi: BRIDGE_ABI,
|
|
866
|
+
functionName: "initVaultActionRequest",
|
|
867
|
+
args: [ActionType.MINT, actionCallData, maxAssets, extraOptions],
|
|
868
|
+
value: lzFee,
|
|
869
|
+
account: account.address
|
|
870
|
+
});
|
|
871
|
+
const txHash = await walletClient.writeContract({
|
|
872
|
+
address: vault,
|
|
873
|
+
abi: BRIDGE_ABI,
|
|
874
|
+
functionName: "initVaultActionRequest",
|
|
875
|
+
args: [ActionType.MINT, actionCallData, maxAssets, extraOptions],
|
|
876
|
+
value: lzFee,
|
|
877
|
+
account,
|
|
878
|
+
chain: walletClient.chain
|
|
879
|
+
});
|
|
880
|
+
return { txHash, guid };
|
|
881
|
+
}
|
|
882
|
+
async function smartDeposit(walletClient, publicClient, addresses, assets, receiver, extraOptions = "0x") {
|
|
883
|
+
const vault = getAddress(addresses.vault);
|
|
884
|
+
const status = await getVaultStatus(publicClient, vault);
|
|
885
|
+
if (status.mode === "paused") {
|
|
886
|
+
throw new VaultPausedError(vault);
|
|
887
|
+
}
|
|
888
|
+
if (status.mode === "full") {
|
|
889
|
+
throw new CapacityFullError(vault);
|
|
890
|
+
}
|
|
891
|
+
if (status.recommendedDepositFlow === "depositAsync") {
|
|
892
|
+
const lzFee = await quoteLzFee(publicClient, vault, extraOptions);
|
|
893
|
+
return depositAsync(walletClient, publicClient, addresses, assets, receiver, lzFee, extraOptions);
|
|
894
|
+
}
|
|
895
|
+
return depositSimple(walletClient, publicClient, addresses, assets, receiver);
|
|
896
|
+
}
|
|
897
|
+
async function depositFromSpoke(walletClient, publicClient, spokeOFT, hubEid, spokeEid, amount, receiver, lzFee, minMsgValue = 0n, minSharesOut = 0n, minAmountLD, extraOptions = "0x") {
|
|
898
|
+
const account = walletClient.account;
|
|
899
|
+
const oft = getAddress(spokeOFT);
|
|
900
|
+
await ensureAllowance(walletClient, publicClient, oft, oft, amount);
|
|
901
|
+
const receiverBytes32 = pad(getAddress(receiver), { size: 32 });
|
|
902
|
+
const hopSendParam = {
|
|
903
|
+
dstEid: spokeEid,
|
|
904
|
+
to: receiverBytes32,
|
|
905
|
+
amountLD: 0n,
|
|
906
|
+
minAmountLD: minSharesOut,
|
|
907
|
+
extraOptions: "0x",
|
|
908
|
+
composeMsg: "0x",
|
|
909
|
+
oftCmd: "0x"
|
|
910
|
+
};
|
|
911
|
+
const composeMsgBytes = encodeAbiParameters(
|
|
912
|
+
[
|
|
913
|
+
{
|
|
914
|
+
type: "tuple",
|
|
915
|
+
name: "hopSendParam",
|
|
916
|
+
components: [
|
|
917
|
+
{ type: "uint32", name: "dstEid" },
|
|
918
|
+
{ type: "bytes32", name: "to" },
|
|
919
|
+
{ type: "uint256", name: "amountLD" },
|
|
920
|
+
{ type: "uint256", name: "minAmountLD" },
|
|
921
|
+
{ type: "bytes", name: "extraOptions" },
|
|
922
|
+
{ type: "bytes", name: "composeMsg" },
|
|
923
|
+
{ type: "bytes", name: "oftCmd" }
|
|
924
|
+
]
|
|
925
|
+
},
|
|
926
|
+
{ type: "uint256", name: "minMsgValue" }
|
|
927
|
+
],
|
|
928
|
+
[hopSendParam, minMsgValue]
|
|
929
|
+
);
|
|
930
|
+
const sendParam = {
|
|
931
|
+
dstEid: hubEid,
|
|
932
|
+
to: receiverBytes32,
|
|
933
|
+
amountLD: amount,
|
|
934
|
+
minAmountLD: minAmountLD ?? amount,
|
|
935
|
+
extraOptions,
|
|
936
|
+
composeMsg: composeMsgBytes,
|
|
937
|
+
oftCmd: "0x"
|
|
938
|
+
};
|
|
939
|
+
const fee = {
|
|
940
|
+
nativeFee: lzFee,
|
|
941
|
+
lzTokenFee: 0n
|
|
942
|
+
};
|
|
943
|
+
const txHash = await walletClient.writeContract({
|
|
944
|
+
address: oft,
|
|
945
|
+
abi: OFT_ABI,
|
|
946
|
+
functionName: "send",
|
|
947
|
+
args: [sendParam, fee, account.address],
|
|
948
|
+
value: lzFee,
|
|
949
|
+
account,
|
|
950
|
+
chain: walletClient.chain
|
|
951
|
+
});
|
|
952
|
+
return { txHash };
|
|
953
|
+
}
|
|
954
|
+
async function quoteDepositFromSpokeFee(publicClient, spokeOFT, hubEid, spokeEid, amount, receiver, minMsgValue = 0n, minSharesOut = 0n, minAmountLD, extraOptions = "0x") {
|
|
955
|
+
const oft = getAddress(spokeOFT);
|
|
956
|
+
const receiverBytes32 = pad(getAddress(receiver), { size: 32 });
|
|
957
|
+
const hopSendParam = {
|
|
958
|
+
dstEid: spokeEid,
|
|
959
|
+
to: receiverBytes32,
|
|
960
|
+
amountLD: 0n,
|
|
961
|
+
minAmountLD: minSharesOut,
|
|
962
|
+
extraOptions: "0x",
|
|
963
|
+
composeMsg: "0x",
|
|
964
|
+
oftCmd: "0x"
|
|
965
|
+
};
|
|
966
|
+
const composeMsgBytes = encodeAbiParameters(
|
|
967
|
+
[
|
|
968
|
+
{
|
|
969
|
+
type: "tuple",
|
|
970
|
+
name: "hopSendParam",
|
|
971
|
+
components: [
|
|
972
|
+
{ type: "uint32", name: "dstEid" },
|
|
973
|
+
{ type: "bytes32", name: "to" },
|
|
974
|
+
{ type: "uint256", name: "amountLD" },
|
|
975
|
+
{ type: "uint256", name: "minAmountLD" },
|
|
976
|
+
{ type: "bytes", name: "extraOptions" },
|
|
977
|
+
{ type: "bytes", name: "composeMsg" },
|
|
978
|
+
{ type: "bytes", name: "oftCmd" }
|
|
979
|
+
]
|
|
980
|
+
},
|
|
981
|
+
{ type: "uint256", name: "minMsgValue" }
|
|
982
|
+
],
|
|
983
|
+
[hopSendParam, minMsgValue]
|
|
984
|
+
);
|
|
985
|
+
const sendParam = {
|
|
986
|
+
dstEid: hubEid,
|
|
987
|
+
to: receiverBytes32,
|
|
988
|
+
amountLD: amount,
|
|
989
|
+
minAmountLD: minAmountLD ?? amount,
|
|
990
|
+
extraOptions,
|
|
991
|
+
composeMsg: composeMsgBytes,
|
|
992
|
+
oftCmd: "0x"
|
|
993
|
+
};
|
|
994
|
+
const fee = await publicClient.readContract({
|
|
995
|
+
address: oft,
|
|
996
|
+
abi: OFT_ABI,
|
|
997
|
+
functionName: "quoteSend",
|
|
998
|
+
args: [sendParam, false]
|
|
999
|
+
});
|
|
1000
|
+
return fee.nativeFee;
|
|
1001
|
+
}
|
|
1002
|
+
async function redeemShares(walletClient, publicClient, addresses, shares, receiver, owner) {
|
|
1003
|
+
const account = walletClient.account;
|
|
1004
|
+
const vault = getAddress(addresses.vault);
|
|
1005
|
+
const { result: assets } = await publicClient.simulateContract({
|
|
1006
|
+
address: vault,
|
|
1007
|
+
abi: VAULT_ABI,
|
|
1008
|
+
functionName: "redeem",
|
|
1009
|
+
args: [shares, getAddress(receiver), getAddress(owner)],
|
|
1010
|
+
account: account.address
|
|
1011
|
+
});
|
|
1012
|
+
const txHash = await walletClient.writeContract({
|
|
1013
|
+
address: vault,
|
|
1014
|
+
abi: VAULT_ABI,
|
|
1015
|
+
functionName: "redeem",
|
|
1016
|
+
args: [shares, getAddress(receiver), getAddress(owner)],
|
|
1017
|
+
account,
|
|
1018
|
+
chain: walletClient.chain
|
|
1019
|
+
});
|
|
1020
|
+
return { txHash, assets };
|
|
1021
|
+
}
|
|
1022
|
+
async function withdrawAssets(walletClient, publicClient, addresses, assets, receiver, owner) {
|
|
1023
|
+
const account = walletClient.account;
|
|
1024
|
+
const vault = getAddress(addresses.vault);
|
|
1025
|
+
const { result: sharesBurned } = await publicClient.simulateContract({
|
|
1026
|
+
address: vault,
|
|
1027
|
+
abi: VAULT_ABI,
|
|
1028
|
+
functionName: "withdraw",
|
|
1029
|
+
args: [assets, getAddress(receiver), getAddress(owner)],
|
|
1030
|
+
account: account.address
|
|
1031
|
+
});
|
|
1032
|
+
const txHash = await walletClient.writeContract({
|
|
1033
|
+
address: vault,
|
|
1034
|
+
abi: VAULT_ABI,
|
|
1035
|
+
functionName: "withdraw",
|
|
1036
|
+
args: [assets, getAddress(receiver), getAddress(owner)],
|
|
1037
|
+
account,
|
|
1038
|
+
chain: walletClient.chain
|
|
1039
|
+
});
|
|
1040
|
+
return { txHash, assets };
|
|
1041
|
+
}
|
|
1042
|
+
async function requestRedeem(walletClient, publicClient, addresses, shares, owner) {
|
|
1043
|
+
const account = walletClient.account;
|
|
1044
|
+
const vault = getAddress(addresses.vault);
|
|
1045
|
+
await publicClient.simulateContract({
|
|
1046
|
+
address: vault,
|
|
1047
|
+
abi: VAULT_ABI,
|
|
1048
|
+
functionName: "requestRedeem",
|
|
1049
|
+
args: [shares, getAddress(owner)],
|
|
1050
|
+
account: account.address
|
|
1051
|
+
});
|
|
1052
|
+
const txHash = await walletClient.writeContract({
|
|
1053
|
+
address: vault,
|
|
1054
|
+
abi: VAULT_ABI,
|
|
1055
|
+
functionName: "requestRedeem",
|
|
1056
|
+
args: [shares, getAddress(owner)],
|
|
1057
|
+
account,
|
|
1058
|
+
chain: walletClient.chain
|
|
1059
|
+
});
|
|
1060
|
+
return { txHash };
|
|
1061
|
+
}
|
|
1062
|
+
async function getWithdrawalRequest(publicClient, vault, owner) {
|
|
1063
|
+
const [shares, timelockEndsAt] = await publicClient.readContract({
|
|
1064
|
+
address: getAddress(vault),
|
|
1065
|
+
abi: VAULT_ABI,
|
|
1066
|
+
functionName: "getWithdrawalRequest",
|
|
1067
|
+
args: [getAddress(owner)]
|
|
1068
|
+
});
|
|
1069
|
+
if (shares === 0n) return null;
|
|
1070
|
+
return { shares, timelockEndsAt };
|
|
1071
|
+
}
|
|
1072
|
+
async function redeemAsync(walletClient, publicClient, addresses, shares, receiver, owner, lzFee, extraOptions = "0x") {
|
|
1073
|
+
const account = walletClient.account;
|
|
1074
|
+
const vault = getAddress(addresses.vault);
|
|
1075
|
+
if (!addresses.escrow) throw new MissingEscrowAddressError();
|
|
1076
|
+
const escrow = getAddress(addresses.escrow);
|
|
1077
|
+
await preflightAsync(publicClient, vault);
|
|
1078
|
+
await preflightRedeemLiquidity(publicClient, vault, shares);
|
|
1079
|
+
await ensureAllowance(walletClient, publicClient, vault, escrow, shares);
|
|
1080
|
+
const actionCallData = encodeAbiParameters(
|
|
1081
|
+
[{ type: "uint256", name: "shares" }, { type: "address", name: "receiver" }, { type: "address", name: "owner" }],
|
|
1082
|
+
[shares, getAddress(receiver), getAddress(owner)]
|
|
1083
|
+
);
|
|
1084
|
+
const { result: guid } = await publicClient.simulateContract({
|
|
1085
|
+
address: vault,
|
|
1086
|
+
abi: BRIDGE_ABI,
|
|
1087
|
+
functionName: "initVaultActionRequest",
|
|
1088
|
+
args: [ActionType.REDEEM, actionCallData, 0n, extraOptions],
|
|
1089
|
+
value: lzFee,
|
|
1090
|
+
account: account.address
|
|
1091
|
+
});
|
|
1092
|
+
const txHash = await walletClient.writeContract({
|
|
1093
|
+
address: vault,
|
|
1094
|
+
abi: BRIDGE_ABI,
|
|
1095
|
+
functionName: "initVaultActionRequest",
|
|
1096
|
+
args: [ActionType.REDEEM, actionCallData, 0n, extraOptions],
|
|
1097
|
+
value: lzFee,
|
|
1098
|
+
account,
|
|
1099
|
+
chain: walletClient.chain
|
|
1100
|
+
});
|
|
1101
|
+
return { txHash, guid };
|
|
1102
|
+
}
|
|
1103
|
+
async function bridgeSharesToHub(walletClient, publicClient, shareOFT, hubChainEid, shares, receiver, lzFee) {
|
|
1104
|
+
const account = walletClient.account;
|
|
1105
|
+
const oft = getAddress(shareOFT);
|
|
1106
|
+
await ensureAllowance(walletClient, publicClient, oft, oft, shares);
|
|
1107
|
+
const toBytes32 = pad(getAddress(receiver), { size: 32 });
|
|
1108
|
+
const sendParam = {
|
|
1109
|
+
dstEid: hubChainEid,
|
|
1110
|
+
to: toBytes32,
|
|
1111
|
+
amountLD: shares,
|
|
1112
|
+
minAmountLD: shares,
|
|
1113
|
+
// shares should bridge 1:1
|
|
1114
|
+
extraOptions: "0x",
|
|
1115
|
+
composeMsg: "0x",
|
|
1116
|
+
oftCmd: "0x"
|
|
1117
|
+
};
|
|
1118
|
+
const fee = {
|
|
1119
|
+
nativeFee: lzFee,
|
|
1120
|
+
lzTokenFee: 0n
|
|
1121
|
+
};
|
|
1122
|
+
const txHash = await walletClient.writeContract({
|
|
1123
|
+
address: oft,
|
|
1124
|
+
abi: OFT_ABI,
|
|
1125
|
+
functionName: "send",
|
|
1126
|
+
args: [sendParam, fee, account.address],
|
|
1127
|
+
value: lzFee,
|
|
1128
|
+
account,
|
|
1129
|
+
chain: walletClient.chain
|
|
1130
|
+
});
|
|
1131
|
+
return { txHash };
|
|
1132
|
+
}
|
|
1133
|
+
async function getUserPosition(publicClient, vault, user) {
|
|
1134
|
+
const v = getAddress(vault);
|
|
1135
|
+
const u = getAddress(user);
|
|
1136
|
+
const [sharesResult, decimalsResult, withdrawalRequestResult] = await publicClient.multicall({
|
|
1137
|
+
contracts: [
|
|
1138
|
+
{ address: v, abi: VAULT_ABI, functionName: "balanceOf", args: [u] },
|
|
1139
|
+
{ address: v, abi: METADATA_ABI, functionName: "decimals" },
|
|
1140
|
+
{ address: v, abi: VAULT_ABI, functionName: "getWithdrawalRequest", args: [u] }
|
|
1141
|
+
],
|
|
1142
|
+
allowFailure: false
|
|
1143
|
+
});
|
|
1144
|
+
const block = await publicClient.getBlock();
|
|
1145
|
+
const shares = sharesResult;
|
|
1146
|
+
const decimals = decimalsResult;
|
|
1147
|
+
const withdrawalRequest = withdrawalRequestResult;
|
|
1148
|
+
const [withdrawShares, timelockEndsAt] = withdrawalRequest;
|
|
1149
|
+
const oneShare = 10n ** BigInt(decimals);
|
|
1150
|
+
const [estimatedAssets, sharePrice] = await Promise.all([
|
|
1151
|
+
shares === 0n ? Promise.resolve(0n) : publicClient.readContract({ address: v, abi: VAULT_ABI, functionName: "convertToAssets", args: [shares] }),
|
|
1152
|
+
publicClient.readContract({ address: v, abi: VAULT_ABI, functionName: "convertToAssets", args: [oneShare] })
|
|
1153
|
+
]);
|
|
1154
|
+
const currentTimestamp = block.timestamp;
|
|
1155
|
+
const pendingWithdrawal = withdrawShares === 0n ? null : {
|
|
1156
|
+
shares: withdrawShares,
|
|
1157
|
+
timelockEndsAt,
|
|
1158
|
+
canRedeemNow: timelockEndsAt === 0n || currentTimestamp >= timelockEndsAt
|
|
1159
|
+
};
|
|
1160
|
+
return {
|
|
1161
|
+
shares,
|
|
1162
|
+
estimatedAssets,
|
|
1163
|
+
sharePrice,
|
|
1164
|
+
decimals,
|
|
1165
|
+
pendingWithdrawal
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
1168
|
+
async function previewDeposit(publicClient, vault, assets) {
|
|
1169
|
+
return publicClient.readContract({
|
|
1170
|
+
address: getAddress(vault),
|
|
1171
|
+
abi: VAULT_ABI,
|
|
1172
|
+
functionName: "previewDeposit",
|
|
1173
|
+
args: [assets]
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
async function previewRedeem(publicClient, vault, shares) {
|
|
1177
|
+
return publicClient.readContract({
|
|
1178
|
+
address: getAddress(vault),
|
|
1179
|
+
abi: VAULT_ABI,
|
|
1180
|
+
functionName: "previewRedeem",
|
|
1181
|
+
args: [shares]
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1184
|
+
async function canDeposit(publicClient, vault, user) {
|
|
1185
|
+
const v = getAddress(vault);
|
|
1186
|
+
const isPaused = await publicClient.readContract({
|
|
1187
|
+
address: v,
|
|
1188
|
+
abi: CONFIG_ABI,
|
|
1189
|
+
functionName: "paused"
|
|
1190
|
+
});
|
|
1191
|
+
if (isPaused) {
|
|
1192
|
+
return { allowed: false, reason: "paused" };
|
|
1193
|
+
}
|
|
1194
|
+
let maxDepositAmount;
|
|
1195
|
+
try {
|
|
1196
|
+
maxDepositAmount = await publicClient.readContract({
|
|
1197
|
+
address: v,
|
|
1198
|
+
abi: CONFIG_ABI,
|
|
1199
|
+
functionName: "maxDeposit",
|
|
1200
|
+
args: [getAddress(user)]
|
|
1201
|
+
});
|
|
1202
|
+
} catch {
|
|
1203
|
+
return { allowed: false, reason: "not-whitelisted" };
|
|
1204
|
+
}
|
|
1205
|
+
if (maxDepositAmount === 0n) {
|
|
1206
|
+
return { allowed: false, reason: "capacity-full" };
|
|
1207
|
+
}
|
|
1208
|
+
return { allowed: true, reason: "ok" };
|
|
1209
|
+
}
|
|
1210
|
+
async function getVaultMetadata(publicClient, vault) {
|
|
1211
|
+
const v = getAddress(vault);
|
|
1212
|
+
const b1 = await publicClient.multicall({
|
|
1213
|
+
contracts: [
|
|
1214
|
+
{ address: v, abi: METADATA_ABI, functionName: "name" },
|
|
1215
|
+
{ address: v, abi: METADATA_ABI, functionName: "symbol" },
|
|
1216
|
+
{ address: v, abi: METADATA_ABI, functionName: "decimals" },
|
|
1217
|
+
{ address: v, abi: VAULT_ABI, functionName: "asset" }
|
|
1218
|
+
],
|
|
1219
|
+
allowFailure: false
|
|
1220
|
+
});
|
|
1221
|
+
const [name, symbol, decimals, underlying] = b1;
|
|
1222
|
+
const underlyingAddr = getAddress(underlying);
|
|
1223
|
+
const b2 = await publicClient.multicall({
|
|
1224
|
+
contracts: [
|
|
1225
|
+
{ address: underlyingAddr, abi: METADATA_ABI, functionName: "symbol" },
|
|
1226
|
+
{ address: underlyingAddr, abi: METADATA_ABI, functionName: "decimals" }
|
|
1227
|
+
],
|
|
1228
|
+
allowFailure: false
|
|
1229
|
+
});
|
|
1230
|
+
const [underlyingSymbol, underlyingDecimals] = b2;
|
|
1231
|
+
return {
|
|
1232
|
+
name,
|
|
1233
|
+
symbol,
|
|
1234
|
+
decimals,
|
|
1235
|
+
underlying: underlyingAddr,
|
|
1236
|
+
underlyingSymbol,
|
|
1237
|
+
underlyingDecimals
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
async function getAsyncRequestStatusLabel(publicClient, vault, guid) {
|
|
1241
|
+
const v = getAddress(vault);
|
|
1242
|
+
const [info, finalizationResult] = await Promise.all([
|
|
1243
|
+
publicClient.readContract({
|
|
1244
|
+
address: v,
|
|
1245
|
+
abi: BRIDGE_ABI,
|
|
1246
|
+
functionName: "getRequestInfo",
|
|
1247
|
+
args: [guid]
|
|
1248
|
+
}),
|
|
1249
|
+
publicClient.readContract({
|
|
1250
|
+
address: v,
|
|
1251
|
+
abi: BRIDGE_ABI,
|
|
1252
|
+
functionName: "getFinalizationResult",
|
|
1253
|
+
args: [guid]
|
|
1254
|
+
})
|
|
1255
|
+
]);
|
|
1256
|
+
if (info.refunded) {
|
|
1257
|
+
return {
|
|
1258
|
+
status: "refunded",
|
|
1259
|
+
label: "Request refunded \u2014 tokens returned to initiator",
|
|
1260
|
+
result: 0n
|
|
1261
|
+
};
|
|
1262
|
+
}
|
|
1263
|
+
if (info.finalized) {
|
|
1264
|
+
return {
|
|
1265
|
+
status: "completed",
|
|
1266
|
+
label: "Completed",
|
|
1267
|
+
result: finalizationResult
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
if (info.fulfilled) {
|
|
1271
|
+
return {
|
|
1272
|
+
status: "ready-to-execute",
|
|
1273
|
+
label: "Oracle responded \u2014 ready to execute",
|
|
1274
|
+
result: 0n
|
|
1275
|
+
};
|
|
1276
|
+
}
|
|
1277
|
+
return {
|
|
1278
|
+
status: "pending",
|
|
1279
|
+
label: "Waiting for cross-chain oracle response...",
|
|
1280
|
+
result: 0n
|
|
1281
|
+
};
|
|
1282
|
+
}
|
|
1283
|
+
async function getUserBalances(publicClient, vault, user) {
|
|
1284
|
+
const v = getAddress(vault);
|
|
1285
|
+
const u = getAddress(user);
|
|
1286
|
+
const [shareBalance, , underlying] = await publicClient.multicall({
|
|
1287
|
+
contracts: [
|
|
1288
|
+
{ address: v, abi: VAULT_ABI, functionName: "balanceOf", args: [u] },
|
|
1289
|
+
{ address: v, abi: METADATA_ABI, functionName: "decimals" },
|
|
1290
|
+
{ address: v, abi: VAULT_ABI, functionName: "asset" }
|
|
1291
|
+
],
|
|
1292
|
+
allowFailure: false
|
|
1293
|
+
});
|
|
1294
|
+
const underlyingAddr = getAddress(underlying);
|
|
1295
|
+
const [underlyingBalance, estimatedAssets] = await Promise.all([
|
|
1296
|
+
publicClient.readContract({
|
|
1297
|
+
address: underlyingAddr,
|
|
1298
|
+
abi: ERC20_ABI,
|
|
1299
|
+
functionName: "balanceOf",
|
|
1300
|
+
args: [u]
|
|
1301
|
+
}),
|
|
1302
|
+
shareBalance === 0n ? Promise.resolve(0n) : publicClient.readContract({
|
|
1303
|
+
address: v,
|
|
1304
|
+
abi: VAULT_ABI,
|
|
1305
|
+
functionName: "convertToAssets",
|
|
1306
|
+
args: [shareBalance]
|
|
1307
|
+
})
|
|
1308
|
+
]);
|
|
1309
|
+
return {
|
|
1310
|
+
shareBalance,
|
|
1311
|
+
underlyingBalance,
|
|
1312
|
+
estimatedAssets
|
|
1313
|
+
};
|
|
1314
|
+
}
|
|
1315
|
+
async function getMaxWithdrawable(publicClient, vault, user) {
|
|
1316
|
+
const v = getAddress(vault);
|
|
1317
|
+
const u = getAddress(user);
|
|
1318
|
+
const [isHub, oraclesEnabled, userShares, underlying] = await publicClient.multicall({
|
|
1319
|
+
contracts: [
|
|
1320
|
+
{ address: v, abi: CONFIG_ABI, functionName: "isHub" },
|
|
1321
|
+
{ address: v, abi: BRIDGE_ABI, functionName: "oraclesCrossChainAccounting" },
|
|
1322
|
+
{ address: v, abi: VAULT_ABI, functionName: "balanceOf", args: [u] },
|
|
1323
|
+
{ address: v, abi: VAULT_ABI, functionName: "asset" }
|
|
1324
|
+
],
|
|
1325
|
+
allowFailure: false
|
|
1326
|
+
});
|
|
1327
|
+
if (userShares === 0n) {
|
|
1328
|
+
return { shares: 0n, assets: 0n };
|
|
1329
|
+
}
|
|
1330
|
+
const underlyingAddr = getAddress(underlying);
|
|
1331
|
+
const [estimatedAssets, hubLiquidBalance] = await Promise.all([
|
|
1332
|
+
publicClient.readContract({
|
|
1333
|
+
address: v,
|
|
1334
|
+
abi: VAULT_ABI,
|
|
1335
|
+
functionName: "convertToAssets",
|
|
1336
|
+
args: [userShares]
|
|
1337
|
+
}),
|
|
1338
|
+
publicClient.readContract({
|
|
1339
|
+
address: underlyingAddr,
|
|
1340
|
+
abi: ERC20_ABI,
|
|
1341
|
+
functionName: "balanceOf",
|
|
1342
|
+
args: [v]
|
|
1343
|
+
})
|
|
1344
|
+
]);
|
|
1345
|
+
let maxAssets;
|
|
1346
|
+
if (isHub && !oraclesEnabled) {
|
|
1347
|
+
maxAssets = estimatedAssets < hubLiquidBalance ? estimatedAssets : hubLiquidBalance;
|
|
1348
|
+
} else {
|
|
1349
|
+
maxAssets = estimatedAssets;
|
|
1350
|
+
}
|
|
1351
|
+
let maxShares;
|
|
1352
|
+
if (maxAssets < estimatedAssets) {
|
|
1353
|
+
maxShares = await publicClient.readContract({
|
|
1354
|
+
address: v,
|
|
1355
|
+
abi: VAULT_ABI,
|
|
1356
|
+
functionName: "convertToShares",
|
|
1357
|
+
args: [maxAssets]
|
|
1358
|
+
});
|
|
1359
|
+
} else {
|
|
1360
|
+
maxShares = userShares;
|
|
1361
|
+
}
|
|
1362
|
+
return {
|
|
1363
|
+
shares: maxShares,
|
|
1364
|
+
assets: maxAssets
|
|
1365
|
+
};
|
|
1366
|
+
}
|
|
1367
|
+
async function getVaultSummary(publicClient, vault) {
|
|
1368
|
+
const [status, metadata] = await Promise.all([
|
|
1369
|
+
getVaultStatus(publicClient, vault),
|
|
1370
|
+
getVaultMetadata(publicClient, vault)
|
|
1371
|
+
]);
|
|
1372
|
+
return { ...status, ...metadata };
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
export { ActionType, BRIDGE_ABI, CCManagerNotConfiguredError, CONFIG_ABI, CapacityFullError, ERC20_ABI, EscrowNotConfiguredError, InsufficientLiquidityError, METADATA_ABI, MissingEscrowAddressError, MoreVaultsError, NotHubVaultError, NotWhitelistedError, OFT_ABI, VAULT_ABI, VaultPausedError, bridgeSharesToHub, canDeposit, depositAsync, depositSimple as depositCrossChainOracleOn, depositFromSpoke, depositFromSpoke as depositFromSpokeAsync, depositMultiAsset, depositSimple, ensureAllowance, getAsyncRequestStatus, getAsyncRequestStatusLabel, getMaxWithdrawable, getUserBalances, getUserPosition, getVaultMetadata, getVaultStatus, getVaultSummary, getWithdrawalRequest, isAsyncMode, mintAsync, preflightAsync, preflightRedeemLiquidity, preflightSync, previewDeposit, previewRedeem, quoteDepositFromSpokeFee, quoteLzFee, redeemAsync, redeemShares, requestRedeem, smartDeposit, withdrawAssets };
|
|
1376
|
+
//# sourceMappingURL=index.js.map
|
|
1377
|
+
//# sourceMappingURL=index.js.map
|