@oydual31/more-vaults-sdk 0.1.2 → 0.1.3

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.
@@ -0,0 +1,1108 @@
1
+ 'use strict';
2
+
3
+ var reactQuery = require('@tanstack/react-query');
4
+ var wagmi = require('wagmi');
5
+ var viem = require('viem');
6
+ var react = require('react');
7
+
8
+ // src/react/useVaultStatus.ts
9
+
10
+ // src/viem/abis.ts
11
+ var VAULT_ABI = [
12
+ {
13
+ type: "function",
14
+ name: "deposit",
15
+ inputs: [
16
+ { name: "assets", type: "uint256" },
17
+ { name: "receiver", type: "address" }
18
+ ],
19
+ outputs: [{ name: "shares", type: "uint256" }],
20
+ stateMutability: "nonpayable"
21
+ },
22
+ {
23
+ type: "function",
24
+ name: "deposit",
25
+ inputs: [
26
+ { name: "tokens", type: "address[]" },
27
+ { name: "assets", type: "uint256[]" },
28
+ { name: "receiver", type: "address" },
29
+ { name: "minAmountOut", type: "uint256" }
30
+ ],
31
+ outputs: [{ name: "shares", type: "uint256" }],
32
+ stateMutability: "payable"
33
+ },
34
+ {
35
+ type: "function",
36
+ name: "mint",
37
+ inputs: [
38
+ { name: "shares", type: "uint256" },
39
+ { name: "receiver", type: "address" }
40
+ ],
41
+ outputs: [{ name: "assets", type: "uint256" }],
42
+ stateMutability: "nonpayable"
43
+ },
44
+ {
45
+ type: "function",
46
+ name: "withdraw",
47
+ inputs: [
48
+ { name: "assets", type: "uint256" },
49
+ { name: "receiver", type: "address" },
50
+ { name: "owner", type: "address" }
51
+ ],
52
+ outputs: [{ name: "shares", type: "uint256" }],
53
+ stateMutability: "nonpayable"
54
+ },
55
+ {
56
+ type: "function",
57
+ name: "redeem",
58
+ inputs: [
59
+ { name: "shares", type: "uint256" },
60
+ { name: "receiver", type: "address" },
61
+ { name: "owner", type: "address" }
62
+ ],
63
+ outputs: [{ name: "assets", type: "uint256" }],
64
+ stateMutability: "nonpayable"
65
+ },
66
+ {
67
+ type: "function",
68
+ name: "requestRedeem",
69
+ inputs: [
70
+ { name: "_shares", type: "uint256" },
71
+ { name: "_onBehalfOf", type: "address" }
72
+ ],
73
+ outputs: [],
74
+ stateMutability: "nonpayable"
75
+ },
76
+ {
77
+ type: "function",
78
+ name: "requestWithdraw",
79
+ inputs: [
80
+ { name: "_assets", type: "uint256" },
81
+ { name: "_onBehalfOf", type: "address" }
82
+ ],
83
+ outputs: [],
84
+ stateMutability: "nonpayable"
85
+ },
86
+ {
87
+ type: "function",
88
+ name: "getWithdrawalRequest",
89
+ inputs: [{ name: "_owner", type: "address" }],
90
+ outputs: [
91
+ { name: "shares", type: "uint256" },
92
+ { name: "timelockEndsAt", type: "uint256" }
93
+ ],
94
+ stateMutability: "view"
95
+ },
96
+ {
97
+ type: "function",
98
+ name: "totalAssets",
99
+ inputs: [],
100
+ outputs: [{ name: "_totalAssets", type: "uint256" }],
101
+ stateMutability: "view"
102
+ },
103
+ {
104
+ type: "function",
105
+ name: "totalSupply",
106
+ inputs: [],
107
+ outputs: [{ name: "", type: "uint256" }],
108
+ stateMutability: "view"
109
+ },
110
+ {
111
+ type: "function",
112
+ name: "balanceOf",
113
+ inputs: [{ name: "account", type: "address" }],
114
+ outputs: [{ name: "", type: "uint256" }],
115
+ stateMutability: "view"
116
+ },
117
+ {
118
+ type: "function",
119
+ name: "asset",
120
+ inputs: [],
121
+ outputs: [{ name: "", type: "address" }],
122
+ stateMutability: "view"
123
+ },
124
+ {
125
+ type: "function",
126
+ name: "convertToShares",
127
+ inputs: [{ name: "assets", type: "uint256" }],
128
+ outputs: [{ name: "", type: "uint256" }],
129
+ stateMutability: "view"
130
+ },
131
+ {
132
+ type: "function",
133
+ name: "convertToAssets",
134
+ inputs: [{ name: "shares", type: "uint256" }],
135
+ outputs: [{ name: "", type: "uint256" }],
136
+ stateMutability: "view"
137
+ },
138
+ {
139
+ type: "function",
140
+ name: "previewDeposit",
141
+ inputs: [{ name: "assets", type: "uint256" }],
142
+ outputs: [{ name: "", type: "uint256" }],
143
+ stateMutability: "view"
144
+ },
145
+ {
146
+ type: "function",
147
+ name: "previewRedeem",
148
+ inputs: [{ name: "shares", type: "uint256" }],
149
+ outputs: [{ name: "", type: "uint256" }],
150
+ stateMutability: "view"
151
+ }
152
+ ];
153
+ var BRIDGE_ABI = [
154
+ {
155
+ type: "function",
156
+ name: "initVaultActionRequest",
157
+ inputs: [
158
+ { name: "actionType", type: "uint8" },
159
+ { name: "actionCallData", type: "bytes" },
160
+ { name: "amountLimit", type: "uint256" },
161
+ { name: "extraOptions", type: "bytes" }
162
+ ],
163
+ outputs: [{ name: "guid", type: "bytes32" }],
164
+ stateMutability: "payable"
165
+ },
166
+ {
167
+ type: "function",
168
+ name: "getRequestInfo",
169
+ inputs: [{ name: "guid", type: "bytes32" }],
170
+ outputs: [
171
+ {
172
+ name: "",
173
+ type: "tuple",
174
+ components: [
175
+ { name: "initiator", type: "address" },
176
+ { name: "timestamp", type: "uint64" },
177
+ { name: "actionType", type: "uint8" },
178
+ { name: "actionCallData", type: "bytes" },
179
+ { name: "fulfilled", type: "bool" },
180
+ { name: "finalized", type: "bool" },
181
+ { name: "refunded", type: "bool" },
182
+ { name: "totalAssets", type: "uint256" },
183
+ { name: "finalizationResult", type: "uint256" },
184
+ { name: "amountLimit", type: "uint256" }
185
+ ]
186
+ }
187
+ ],
188
+ stateMutability: "view"
189
+ },
190
+ {
191
+ type: "function",
192
+ name: "getFinalizationResult",
193
+ inputs: [{ name: "guid", type: "bytes32" }],
194
+ outputs: [{ name: "result", type: "uint256" }],
195
+ stateMutability: "view"
196
+ },
197
+ {
198
+ type: "function",
199
+ name: "quoteAccountingFee",
200
+ inputs: [{ name: "extraOptions", type: "bytes" }],
201
+ outputs: [{ name: "nativeFee", type: "uint256" }],
202
+ stateMutability: "view"
203
+ },
204
+ {
205
+ type: "function",
206
+ name: "oraclesCrossChainAccounting",
207
+ inputs: [],
208
+ outputs: [{ name: "", type: "bool" }],
209
+ stateMutability: "view"
210
+ }
211
+ ];
212
+ var CONFIG_ABI = [
213
+ {
214
+ type: "function",
215
+ name: "getEscrow",
216
+ inputs: [],
217
+ outputs: [{ name: "escrow", type: "address" }],
218
+ stateMutability: "view"
219
+ },
220
+ {
221
+ type: "function",
222
+ name: "getCrossChainAccountingManager",
223
+ inputs: [],
224
+ outputs: [{ name: "", type: "address" }],
225
+ stateMutability: "view"
226
+ },
227
+ {
228
+ type: "function",
229
+ name: "isHub",
230
+ inputs: [],
231
+ outputs: [{ name: "", type: "bool" }],
232
+ stateMutability: "view"
233
+ },
234
+ {
235
+ type: "function",
236
+ name: "getWithdrawalQueueStatus",
237
+ inputs: [],
238
+ outputs: [{ name: "", type: "bool" }],
239
+ stateMutability: "view"
240
+ },
241
+ {
242
+ type: "function",
243
+ name: "getWithdrawalTimelock",
244
+ inputs: [],
245
+ outputs: [{ name: "", type: "uint64" }],
246
+ stateMutability: "view"
247
+ },
248
+ {
249
+ type: "function",
250
+ name: "paused",
251
+ inputs: [],
252
+ outputs: [{ name: "", type: "bool" }],
253
+ stateMutability: "view"
254
+ },
255
+ {
256
+ type: "function",
257
+ name: "maxDeposit",
258
+ inputs: [{ name: "receiver", type: "address" }],
259
+ outputs: [{ name: "", type: "uint256" }],
260
+ stateMutability: "view"
261
+ }
262
+ ];
263
+ var ERC20_ABI = [
264
+ {
265
+ type: "function",
266
+ name: "approve",
267
+ inputs: [
268
+ { name: "spender", type: "address" },
269
+ { name: "value", type: "uint256" }
270
+ ],
271
+ outputs: [{ name: "", type: "bool" }],
272
+ stateMutability: "nonpayable"
273
+ },
274
+ {
275
+ type: "function",
276
+ name: "allowance",
277
+ inputs: [
278
+ { name: "owner", type: "address" },
279
+ { name: "spender", type: "address" }
280
+ ],
281
+ outputs: [{ name: "", type: "uint256" }],
282
+ stateMutability: "view"
283
+ },
284
+ {
285
+ type: "function",
286
+ name: "balanceOf",
287
+ inputs: [{ name: "account", type: "address" }],
288
+ outputs: [{ name: "", type: "uint256" }],
289
+ stateMutability: "view"
290
+ }
291
+ ];
292
+ var METADATA_ABI = [
293
+ { type: "function", name: "name", inputs: [], outputs: [{ name: "", type: "string" }], stateMutability: "view" },
294
+ { type: "function", name: "symbol", inputs: [], outputs: [{ name: "", type: "string" }], stateMutability: "view" },
295
+ { type: "function", name: "decimals", inputs: [], outputs: [{ name: "", type: "uint8" }], stateMutability: "view" }
296
+ ];
297
+
298
+ // src/viem/types.ts
299
+ var ActionType = {
300
+ DEPOSIT: 0,
301
+ REDEEM: 3};
302
+
303
+ // src/viem/errors.ts
304
+ var MoreVaultsError = class extends Error {
305
+ constructor(message) {
306
+ super(message);
307
+ this.name = "MoreVaultsError";
308
+ }
309
+ };
310
+ var MissingEscrowAddressError = class extends MoreVaultsError {
311
+ constructor() {
312
+ super(`[MoreVaults] This flow requires an escrow address. Set VaultAddresses.escrow before calling async deposit/redeem flows.`);
313
+ this.name = "MissingEscrowAddressError";
314
+ }
315
+ };
316
+ var WrongChainError = class extends MoreVaultsError {
317
+ constructor(currentChainId, expectedChainId) {
318
+ super(
319
+ `Wrong network: wallet is on chain ${currentChainId}, but the vault hub requires chain ${expectedChainId}. Switch networks before proceeding.`
320
+ );
321
+ this.name = "WrongChainError";
322
+ }
323
+ };
324
+ async function getVaultStatus(publicClient, vault) {
325
+ const v = viem.getAddress(vault);
326
+ const b1 = await publicClient.multicall({
327
+ contracts: [
328
+ { address: v, abi: CONFIG_ABI, functionName: "isHub" },
329
+ { address: v, abi: CONFIG_ABI, functionName: "paused" },
330
+ { address: v, abi: BRIDGE_ABI, functionName: "oraclesCrossChainAccounting" },
331
+ { address: v, abi: CONFIG_ABI, functionName: "getCrossChainAccountingManager" },
332
+ { address: v, abi: CONFIG_ABI, functionName: "getEscrow" },
333
+ { address: v, abi: CONFIG_ABI, functionName: "getWithdrawalQueueStatus" },
334
+ { address: v, abi: CONFIG_ABI, functionName: "getWithdrawalTimelock" },
335
+ { address: v, abi: CONFIG_ABI, functionName: "maxDeposit", args: [viem.zeroAddress] },
336
+ { address: v, abi: VAULT_ABI, functionName: "asset" },
337
+ { address: v, abi: VAULT_ABI, functionName: "totalAssets" },
338
+ { address: v, abi: VAULT_ABI, functionName: "totalSupply" },
339
+ { address: v, abi: METADATA_ABI, functionName: "decimals" }
340
+ ],
341
+ allowFailure: true
342
+ });
343
+ const isHub = b1[0].status === "success" ? b1[0].result : false;
344
+ const isPaused = b1[1].status === "success" ? b1[1].result : false;
345
+ const oraclesEnabled = b1[2].status === "success" ? b1[2].result : false;
346
+ const ccManager = b1[3].status === "success" ? b1[3].result : viem.zeroAddress;
347
+ const escrow = b1[4].status === "success" ? b1[4].result : viem.zeroAddress;
348
+ const withdrawalQueueEnabled = b1[5].status === "success" ? b1[5].result : false;
349
+ const withdrawalTimelockSeconds = b1[6].status === "success" ? b1[6].result : 0n;
350
+ const maxDepositRaw = b1[7].status === "success" ? b1[7].result : null;
351
+ const underlying = b1[8].status === "success" ? b1[8].result : viem.zeroAddress;
352
+ const totalAssets = b1[9].status === "success" ? b1[9].result : 0n;
353
+ const totalSupply = b1[10].status === "success" ? b1[10].result : 0n;
354
+ const decimals = b1[11].status === "success" ? Number(b1[11].result) : 18;
355
+ const oneShare = 10n ** BigInt(decimals);
356
+ const b2 = await publicClient.multicall({
357
+ contracts: [
358
+ { address: viem.getAddress(underlying), abi: ERC20_ABI, functionName: "balanceOf", args: [v] },
359
+ { address: v, abi: VAULT_ABI, functionName: "convertToAssets", args: [oneShare] }
360
+ ],
361
+ allowFailure: true
362
+ });
363
+ const hubLiquidBalance = b2[0].status === "success" ? b2[0].result : 0n;
364
+ const sharePrice = b2[1].status === "success" ? b2[1].result : 0n;
365
+ const spokesDeployedBalance = totalAssets > hubLiquidBalance ? totalAssets - hubLiquidBalance : 0n;
366
+ const MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
367
+ const depositAccessRestricted = maxDepositRaw === null;
368
+ const effectiveCapacity = depositAccessRestricted ? MAX_UINT256 : maxDepositRaw;
369
+ let mode;
370
+ if (isPaused) {
371
+ mode = "paused";
372
+ } else if (effectiveCapacity === 0n) {
373
+ mode = "full";
374
+ } else if (!isHub) {
375
+ mode = "local";
376
+ } else if (oraclesEnabled) {
377
+ mode = "cross-chain-oracle";
378
+ } else {
379
+ mode = "cross-chain-async";
380
+ }
381
+ let recommendedDepositFlow;
382
+ let recommendedRedeemFlow;
383
+ if (mode === "paused" || mode === "full") {
384
+ recommendedDepositFlow = "none";
385
+ recommendedRedeemFlow = mode === "paused" ? "none" : "redeemShares";
386
+ } else if (mode === "cross-chain-async") {
387
+ recommendedDepositFlow = "depositAsync";
388
+ recommendedRedeemFlow = "redeemAsync";
389
+ } else {
390
+ recommendedDepositFlow = "depositSimple";
391
+ recommendedRedeemFlow = "redeemShares";
392
+ }
393
+ const maxImmediateRedeemAssets = isHub && !oraclesEnabled ? hubLiquidBalance : totalAssets;
394
+ const issues = [];
395
+ if (isPaused) {
396
+ issues.push("Vault is paused \u2014 no deposits or redeems are possible.");
397
+ }
398
+ if (effectiveCapacity === 0n && !isPaused) {
399
+ issues.push("Deposit capacity is full \u2014 increase depositCapacity via setDepositCapacity().");
400
+ }
401
+ if (depositAccessRestricted) {
402
+ issues.push("Deposit access is restricted (whitelist or other access control). Only approved addresses can deposit.");
403
+ }
404
+ if (isHub && !oraclesEnabled && ccManager === viem.zeroAddress) {
405
+ issues.push(
406
+ "CCManager not configured \u2014 async flows will revert. Call setCrossChainAccountingManager(address) as vault owner."
407
+ );
408
+ }
409
+ if (isHub && !oraclesEnabled && escrow === viem.zeroAddress) {
410
+ issues.push(
411
+ "Escrow not configured in registry \u2014 async flows will revert. Set the escrow via the MoreVaultsRegistry."
412
+ );
413
+ }
414
+ if (isHub) {
415
+ if (hubLiquidBalance === 0n) {
416
+ issues.push(
417
+ `Hub has no liquid assets (hubLiquidBalance = 0). All redeems will be auto-refunded until the curator repatriates funds from spokes via executeBridging().`
418
+ );
419
+ } else if (totalAssets > 0n && hubLiquidBalance * 10n < totalAssets) {
420
+ const pct = Number(hubLiquidBalance * 10000n / totalAssets) / 100;
421
+ issues.push(
422
+ `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.`
423
+ );
424
+ }
425
+ if (spokesDeployedBalance > 0n) {
426
+ const pct = (Number(spokesDeployedBalance) / Number(totalAssets || 1n) * 100).toFixed(1);
427
+ issues.push(
428
+ `${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.`
429
+ );
430
+ }
431
+ }
432
+ return {
433
+ mode,
434
+ recommendedDepositFlow,
435
+ recommendedRedeemFlow,
436
+ isHub,
437
+ isPaused,
438
+ oracleAccountingEnabled: oraclesEnabled,
439
+ ccManager,
440
+ escrow,
441
+ withdrawalQueueEnabled,
442
+ withdrawalTimelockSeconds: BigInt(withdrawalTimelockSeconds),
443
+ remainingDepositCapacity: effectiveCapacity,
444
+ depositAccessRestricted,
445
+ underlying,
446
+ totalAssets,
447
+ totalSupply,
448
+ decimals,
449
+ sharePrice,
450
+ hubLiquidBalance,
451
+ spokesDeployedBalance,
452
+ maxImmediateRedeemAssets,
453
+ issues
454
+ };
455
+ }
456
+ async function ensureAllowance(walletClient, publicClient, token, spender, amount) {
457
+ const account = walletClient.account;
458
+ const allowance = await publicClient.readContract({
459
+ address: viem.getAddress(token),
460
+ abi: ERC20_ABI,
461
+ functionName: "allowance",
462
+ args: [account.address, viem.getAddress(spender)]
463
+ });
464
+ if (allowance < amount) {
465
+ const hash = await walletClient.writeContract({
466
+ address: viem.getAddress(token),
467
+ abi: ERC20_ABI,
468
+ functionName: "approve",
469
+ args: [viem.getAddress(spender), amount],
470
+ account,
471
+ chain: walletClient.chain
472
+ });
473
+ await publicClient.waitForTransactionReceipt({ hash });
474
+ }
475
+ }
476
+ async function quoteLzFee(publicClient, vault, extraOptions = "0x") {
477
+ return publicClient.readContract({
478
+ address: viem.getAddress(vault),
479
+ abi: BRIDGE_ABI,
480
+ functionName: "quoteAccountingFee",
481
+ args: [extraOptions]
482
+ });
483
+ }
484
+ async function preflightAsync(publicClient, vault, escrow) {
485
+ const v = viem.getAddress(vault);
486
+ const [ccManager, registeredEscrow, isHub, oraclesEnabled, isPaused] = await Promise.all([
487
+ publicClient.readContract({
488
+ address: v,
489
+ abi: CONFIG_ABI,
490
+ functionName: "getCrossChainAccountingManager"
491
+ }),
492
+ publicClient.readContract({
493
+ address: v,
494
+ abi: CONFIG_ABI,
495
+ functionName: "getEscrow"
496
+ }),
497
+ publicClient.readContract({
498
+ address: v,
499
+ abi: CONFIG_ABI,
500
+ functionName: "isHub"
501
+ }),
502
+ publicClient.readContract({
503
+ address: v,
504
+ abi: BRIDGE_ABI,
505
+ functionName: "oraclesCrossChainAccounting"
506
+ }),
507
+ publicClient.readContract({
508
+ address: v,
509
+ abi: CONFIG_ABI,
510
+ functionName: "paused"
511
+ })
512
+ ]);
513
+ if (ccManager === viem.zeroAddress) {
514
+ throw new Error(
515
+ `[MoreVaults] CCManager not configured on vault ${vault}. Call setCrossChainAccountingManager(ccManagerAddress) as vault owner first.`
516
+ );
517
+ }
518
+ if (registeredEscrow === viem.zeroAddress) {
519
+ throw new Error(
520
+ `[MoreVaults] Escrow not configured for vault ${vault}. The registry must have an escrow set for this vault.`
521
+ );
522
+ }
523
+ if (!isHub) {
524
+ throw new Error(
525
+ `[MoreVaults] Vault ${vault} is not a hub vault. Async flows (D4/D5/R5) only work on hub vaults.`
526
+ );
527
+ }
528
+ if (oraclesEnabled) {
529
+ throw new Error(
530
+ `[MoreVaults] Vault ${vault} has oracle-based cross-chain accounting enabled. Use depositSimple/depositCrossChainOracleOn instead of async flows.`
531
+ );
532
+ }
533
+ if (isPaused) {
534
+ throw new Error(
535
+ `[MoreVaults] Vault ${vault} is paused. Cannot perform any actions.`
536
+ );
537
+ }
538
+ }
539
+ async function preflightRedeemLiquidity(publicClient, vault, shares) {
540
+ const v = viem.getAddress(vault);
541
+ const underlying = await publicClient.readContract({
542
+ address: v,
543
+ abi: VAULT_ABI,
544
+ functionName: "asset"
545
+ });
546
+ const [hubLiquid, assetsNeeded] = await Promise.all([
547
+ publicClient.readContract({
548
+ address: viem.getAddress(underlying),
549
+ abi: ERC20_ABI,
550
+ functionName: "balanceOf",
551
+ args: [v]
552
+ }),
553
+ publicClient.readContract({
554
+ address: v,
555
+ abi: VAULT_ABI,
556
+ functionName: "convertToAssets",
557
+ args: [shares]
558
+ })
559
+ ]);
560
+ if (hubLiquid < assetsNeeded) {
561
+ throw new Error(
562
+ `[MoreVaults] Insufficient hub liquidity for redeem.
563
+ Hub liquid balance : ${hubLiquid}
564
+ Estimated required : ${assetsNeeded}
565
+ Submitting this redeem will waste the LayerZero fee \u2014 the request will be auto-refunded.
566
+ Ask the vault curator to repatriate liquidity from spoke chains first.`
567
+ );
568
+ }
569
+ }
570
+ async function preflightSync(publicClient, vault) {
571
+ const v = viem.getAddress(vault);
572
+ const [isPaused, depositCapResult] = await Promise.all([
573
+ publicClient.readContract({
574
+ address: v,
575
+ abi: CONFIG_ABI,
576
+ functionName: "paused"
577
+ }),
578
+ publicClient.readContract({
579
+ address: v,
580
+ abi: CONFIG_ABI,
581
+ functionName: "maxDeposit",
582
+ args: [viem.zeroAddress]
583
+ }).catch(() => null)
584
+ ]);
585
+ if (isPaused) {
586
+ throw new Error(
587
+ `[MoreVaults] Vault ${vault} is paused. Cannot perform any actions.`
588
+ );
589
+ }
590
+ if (depositCapResult !== null && depositCapResult === 0n) {
591
+ throw new Error(
592
+ `[MoreVaults] Vault ${vault} has reached deposit capacity. No more deposits accepted.`
593
+ );
594
+ }
595
+ }
596
+
597
+ // src/viem/chainValidation.ts
598
+ function validateWalletChain(walletClient, hubChainId) {
599
+ if (!hubChainId) return;
600
+ const current = walletClient.chain?.id;
601
+ if (current !== void 0 && current !== hubChainId) {
602
+ throw new WrongChainError(current, hubChainId);
603
+ }
604
+ }
605
+
606
+ // src/viem/depositFlows.ts
607
+ async function depositSimple(walletClient, publicClient, addresses, assets, receiver) {
608
+ const account = walletClient.account;
609
+ const vault = viem.getAddress(addresses.vault);
610
+ validateWalletChain(walletClient, addresses.hubChainId);
611
+ await preflightSync(publicClient, vault);
612
+ const underlying = await publicClient.readContract({
613
+ address: vault,
614
+ abi: VAULT_ABI,
615
+ functionName: "asset"
616
+ });
617
+ await ensureAllowance(walletClient, publicClient, underlying, vault, assets);
618
+ const { result: shares } = await publicClient.simulateContract({
619
+ address: vault,
620
+ abi: VAULT_ABI,
621
+ functionName: "deposit",
622
+ args: [assets, viem.getAddress(receiver)],
623
+ account: account.address
624
+ });
625
+ const txHash = await walletClient.writeContract({
626
+ address: vault,
627
+ abi: VAULT_ABI,
628
+ functionName: "deposit",
629
+ args: [assets, viem.getAddress(receiver)],
630
+ account,
631
+ chain: walletClient.chain
632
+ });
633
+ return { txHash, shares };
634
+ }
635
+ async function depositAsync(walletClient, publicClient, addresses, assets, receiver, lzFee, extraOptions = "0x") {
636
+ const account = walletClient.account;
637
+ const vault = viem.getAddress(addresses.vault);
638
+ if (!addresses.escrow) throw new MissingEscrowAddressError();
639
+ const escrow = viem.getAddress(addresses.escrow);
640
+ validateWalletChain(walletClient, addresses.hubChainId);
641
+ await preflightAsync(publicClient, vault);
642
+ const underlying = await publicClient.readContract({
643
+ address: vault,
644
+ abi: VAULT_ABI,
645
+ functionName: "asset"
646
+ });
647
+ await ensureAllowance(walletClient, publicClient, underlying, escrow, assets);
648
+ const actionCallData = viem.encodeAbiParameters(
649
+ [{ type: "uint256", name: "assets" }, { type: "address", name: "receiver" }],
650
+ [assets, viem.getAddress(receiver)]
651
+ );
652
+ const { result: guid } = await publicClient.simulateContract({
653
+ address: vault,
654
+ abi: BRIDGE_ABI,
655
+ functionName: "initVaultActionRequest",
656
+ args: [ActionType.DEPOSIT, actionCallData, 0n, extraOptions],
657
+ value: lzFee,
658
+ account: account.address
659
+ });
660
+ const txHash = await walletClient.writeContract({
661
+ address: vault,
662
+ abi: BRIDGE_ABI,
663
+ functionName: "initVaultActionRequest",
664
+ args: [ActionType.DEPOSIT, actionCallData, 0n, extraOptions],
665
+ value: lzFee,
666
+ account,
667
+ chain: walletClient.chain
668
+ });
669
+ return { txHash, guid };
670
+ }
671
+ async function redeemShares(walletClient, publicClient, addresses, shares, receiver, owner) {
672
+ const account = walletClient.account;
673
+ const vault = viem.getAddress(addresses.vault);
674
+ validateWalletChain(walletClient, addresses.hubChainId);
675
+ const { result: assets } = await publicClient.simulateContract({
676
+ address: vault,
677
+ abi: VAULT_ABI,
678
+ functionName: "redeem",
679
+ args: [shares, viem.getAddress(receiver), viem.getAddress(owner)],
680
+ account: account.address
681
+ });
682
+ const txHash = await walletClient.writeContract({
683
+ address: vault,
684
+ abi: VAULT_ABI,
685
+ functionName: "redeem",
686
+ args: [shares, viem.getAddress(receiver), viem.getAddress(owner)],
687
+ account,
688
+ chain: walletClient.chain
689
+ });
690
+ return { txHash, assets };
691
+ }
692
+ async function redeemAsync(walletClient, publicClient, addresses, shares, receiver, owner, lzFee, extraOptions = "0x") {
693
+ const account = walletClient.account;
694
+ const vault = viem.getAddress(addresses.vault);
695
+ if (!addresses.escrow) throw new MissingEscrowAddressError();
696
+ const escrow = viem.getAddress(addresses.escrow);
697
+ validateWalletChain(walletClient, addresses.hubChainId);
698
+ await preflightAsync(publicClient, vault);
699
+ await preflightRedeemLiquidity(publicClient, vault, shares);
700
+ await ensureAllowance(walletClient, publicClient, vault, escrow, shares);
701
+ const actionCallData = viem.encodeAbiParameters(
702
+ [{ type: "uint256", name: "shares" }, { type: "address", name: "receiver" }, { type: "address", name: "owner" }],
703
+ [shares, viem.getAddress(receiver), viem.getAddress(owner)]
704
+ );
705
+ const { result: guid } = await publicClient.simulateContract({
706
+ address: vault,
707
+ abi: BRIDGE_ABI,
708
+ functionName: "initVaultActionRequest",
709
+ args: [ActionType.REDEEM, actionCallData, 0n, extraOptions],
710
+ value: lzFee,
711
+ account: account.address
712
+ });
713
+ const txHash = await walletClient.writeContract({
714
+ address: vault,
715
+ abi: BRIDGE_ABI,
716
+ functionName: "initVaultActionRequest",
717
+ args: [ActionType.REDEEM, actionCallData, 0n, extraOptions],
718
+ value: lzFee,
719
+ account,
720
+ chain: walletClient.chain
721
+ });
722
+ return { txHash, guid };
723
+ }
724
+ async function getUserPosition(publicClient, vault, user) {
725
+ const v = viem.getAddress(vault);
726
+ const u = viem.getAddress(user);
727
+ const [sharesResult, decimalsResult, withdrawalRequestResult] = await publicClient.multicall({
728
+ contracts: [
729
+ { address: v, abi: VAULT_ABI, functionName: "balanceOf", args: [u] },
730
+ { address: v, abi: METADATA_ABI, functionName: "decimals" },
731
+ { address: v, abi: VAULT_ABI, functionName: "getWithdrawalRequest", args: [u] }
732
+ ],
733
+ allowFailure: false
734
+ });
735
+ const block = await publicClient.getBlock();
736
+ const shares = sharesResult;
737
+ const decimals = decimalsResult;
738
+ const withdrawalRequest = withdrawalRequestResult;
739
+ const [withdrawShares, timelockEndsAt] = withdrawalRequest;
740
+ const oneShare = 10n ** BigInt(decimals);
741
+ const [estimatedAssets, sharePrice] = await Promise.all([
742
+ shares === 0n ? Promise.resolve(0n) : publicClient.readContract({ address: v, abi: VAULT_ABI, functionName: "convertToAssets", args: [shares] }),
743
+ publicClient.readContract({ address: v, abi: VAULT_ABI, functionName: "convertToAssets", args: [oneShare] })
744
+ ]);
745
+ const currentTimestamp = block.timestamp;
746
+ const pendingWithdrawal = withdrawShares === 0n ? null : {
747
+ shares: withdrawShares,
748
+ timelockEndsAt,
749
+ canRedeemNow: timelockEndsAt === 0n || currentTimestamp >= timelockEndsAt
750
+ };
751
+ return {
752
+ shares,
753
+ estimatedAssets,
754
+ sharePrice,
755
+ decimals,
756
+ pendingWithdrawal
757
+ };
758
+ }
759
+ async function getVaultMetadata(publicClient, vault) {
760
+ const v = viem.getAddress(vault);
761
+ const b1 = await publicClient.multicall({
762
+ contracts: [
763
+ { address: v, abi: METADATA_ABI, functionName: "name" },
764
+ { address: v, abi: METADATA_ABI, functionName: "symbol" },
765
+ { address: v, abi: METADATA_ABI, functionName: "decimals" },
766
+ { address: v, abi: VAULT_ABI, functionName: "asset" }
767
+ ],
768
+ allowFailure: false
769
+ });
770
+ const [name, symbol, decimals, underlying] = b1;
771
+ const underlyingAddr = viem.getAddress(underlying);
772
+ const b2 = await publicClient.multicall({
773
+ contracts: [
774
+ { address: underlyingAddr, abi: METADATA_ABI, functionName: "symbol" },
775
+ { address: underlyingAddr, abi: METADATA_ABI, functionName: "decimals" }
776
+ ],
777
+ allowFailure: false
778
+ });
779
+ const [underlyingSymbol, underlyingDecimals] = b2;
780
+ return {
781
+ name,
782
+ symbol,
783
+ decimals,
784
+ underlying: underlyingAddr,
785
+ underlyingSymbol,
786
+ underlyingDecimals
787
+ };
788
+ }
789
+ async function getAsyncRequestStatusLabel(publicClient, vault, guid) {
790
+ const v = viem.getAddress(vault);
791
+ const [info, finalizationResult] = await Promise.all([
792
+ publicClient.readContract({
793
+ address: v,
794
+ abi: BRIDGE_ABI,
795
+ functionName: "getRequestInfo",
796
+ args: [guid]
797
+ }),
798
+ publicClient.readContract({
799
+ address: v,
800
+ abi: BRIDGE_ABI,
801
+ functionName: "getFinalizationResult",
802
+ args: [guid]
803
+ })
804
+ ]);
805
+ if (info.refunded) {
806
+ return {
807
+ status: "refunded",
808
+ label: "Request refunded \u2014 tokens returned to initiator",
809
+ result: 0n
810
+ };
811
+ }
812
+ if (info.finalized) {
813
+ return {
814
+ status: "completed",
815
+ label: "Completed",
816
+ result: finalizationResult
817
+ };
818
+ }
819
+ if (info.fulfilled) {
820
+ return {
821
+ status: "ready-to-execute",
822
+ label: "Oracle responded \u2014 ready to execute",
823
+ result: 0n
824
+ };
825
+ }
826
+ return {
827
+ status: "pending",
828
+ label: "Waiting for cross-chain oracle response...",
829
+ result: 0n
830
+ };
831
+ }
832
+
833
+ // src/viem/wagmiCompat.ts
834
+ function asSdkClient(client) {
835
+ if (!client) throw new Error("[MoreVaults] No public client available. Make sure wagmi is configured correctly.");
836
+ return client;
837
+ }
838
+
839
+ // src/react/useVaultStatus.ts
840
+ function useVaultStatus(vault, chainId, options) {
841
+ const publicClient = wagmi.usePublicClient({ chainId });
842
+ return reactQuery.useQuery({
843
+ queryKey: ["vaultStatus", vault, chainId],
844
+ queryFn: () => getVaultStatus(asSdkClient(publicClient), vault),
845
+ enabled: !!vault && !!publicClient,
846
+ refetchInterval: options?.refetchInterval ?? 3e4,
847
+ staleTime: 15e3
848
+ });
849
+ }
850
+ function useVaultMetadata(vault, chainId) {
851
+ const publicClient = wagmi.usePublicClient({ chainId });
852
+ return reactQuery.useQuery({
853
+ queryKey: ["vaultMetadata", vault, chainId],
854
+ queryFn: () => getVaultMetadata(asSdkClient(publicClient), vault),
855
+ enabled: !!vault && !!publicClient,
856
+ // Metadata (name, symbol, underlying) changes very rarely — 5 min stale time
857
+ staleTime: 5 * 6e4,
858
+ refetchInterval: 5 * 6e4
859
+ });
860
+ }
861
+ function useUserPosition(vault, user, chainId) {
862
+ const publicClient = wagmi.usePublicClient({ chainId });
863
+ return reactQuery.useQuery({
864
+ queryKey: ["userPosition", vault, user, chainId],
865
+ queryFn: () => getUserPosition(asSdkClient(publicClient), vault, user),
866
+ enabled: !!vault && !!user && !!publicClient,
867
+ refetchInterval: 15e3,
868
+ staleTime: 1e4
869
+ });
870
+ }
871
+ function useLzFee(vault, chainId) {
872
+ const publicClient = wagmi.usePublicClient({ chainId });
873
+ const query = reactQuery.useQuery({
874
+ queryKey: ["lzFee", vault, chainId],
875
+ queryFn: () => quoteLzFee(asSdkClient(publicClient), vault),
876
+ enabled: !!vault && !!publicClient,
877
+ refetchInterval: 6e4,
878
+ staleTime: 3e4
879
+ });
880
+ return {
881
+ ...query,
882
+ fee: query.data,
883
+ feeWithBuffer: query.data ? query.data * 101n / 100n : void 0
884
+ };
885
+ }
886
+ function useAsyncRequestStatus(vault, guid, chainId) {
887
+ const publicClient = wagmi.usePublicClient({ chainId });
888
+ return reactQuery.useQuery({
889
+ queryKey: ["asyncRequestStatus", vault, guid, chainId],
890
+ queryFn: () => getAsyncRequestStatusLabel(asSdkClient(publicClient), vault, guid),
891
+ enabled: !!vault && !!guid && !!publicClient,
892
+ refetchInterval: (query) => {
893
+ const status = query.state.data?.status;
894
+ if (status === "completed" || status === "refunded") return false;
895
+ return 1e4;
896
+ }
897
+ });
898
+ }
899
+ function useOmniDeposit(vault, hubChainId) {
900
+ const { data: walletClient } = wagmi.useWalletClient({ chainId: hubChainId });
901
+ const publicClient = wagmi.usePublicClient({ chainId: hubChainId });
902
+ const currentChainId = wagmi.useChainId();
903
+ const [isLoading, setIsLoading] = react.useState(false);
904
+ const [txHash, setTxHash] = react.useState();
905
+ const [guid, setGuid] = react.useState();
906
+ const [error, setError] = react.useState();
907
+ const { feeWithBuffer } = useLzFee(vault, hubChainId);
908
+ const { data: requestStatus } = useAsyncRequestStatus(vault, guid, hubChainId);
909
+ const wrongChain = currentChainId !== hubChainId;
910
+ const deposit = react.useCallback(
911
+ async (amountInWei, receiver) => {
912
+ if (!vault || !walletClient || !publicClient || !feeWithBuffer) return;
913
+ setIsLoading(true);
914
+ setError(void 0);
915
+ try {
916
+ const pc = asSdkClient(publicClient);
917
+ const status = await getVaultStatus(pc, vault);
918
+ const result = await depositAsync(
919
+ walletClient,
920
+ pc,
921
+ { vault, escrow: status.escrow, hubChainId },
922
+ amountInWei,
923
+ receiver,
924
+ feeWithBuffer
925
+ );
926
+ setTxHash(result.txHash);
927
+ setGuid(result.guid);
928
+ } catch (err) {
929
+ setError(err instanceof Error ? err : new Error(String(err)));
930
+ } finally {
931
+ setIsLoading(false);
932
+ }
933
+ },
934
+ [vault, walletClient, publicClient, feeWithBuffer, hubChainId]
935
+ );
936
+ const reset = react.useCallback(() => {
937
+ setTxHash(void 0);
938
+ setGuid(void 0);
939
+ setError(void 0);
940
+ setIsLoading(false);
941
+ }, []);
942
+ return { deposit, isLoading, txHash, guid, requestStatus, wrongChain, error, reset };
943
+ }
944
+ function useOmniRedeem(vault, hubChainId) {
945
+ const { data: walletClient } = wagmi.useWalletClient({ chainId: hubChainId });
946
+ const publicClient = wagmi.usePublicClient({ chainId: hubChainId });
947
+ const currentChainId = wagmi.useChainId();
948
+ const [isLoading, setIsLoading] = react.useState(false);
949
+ const [txHash, setTxHash] = react.useState();
950
+ const [guid, setGuid] = react.useState();
951
+ const [error, setError] = react.useState();
952
+ const { feeWithBuffer } = useLzFee(vault, hubChainId);
953
+ const { data: requestStatus } = useAsyncRequestStatus(vault, guid, hubChainId);
954
+ const wrongChain = currentChainId !== hubChainId;
955
+ const redeem = react.useCallback(
956
+ async (sharesInWei, receiver, owner) => {
957
+ if (!vault || !walletClient || !publicClient || !feeWithBuffer) return;
958
+ setIsLoading(true);
959
+ setError(void 0);
960
+ try {
961
+ const pc = asSdkClient(publicClient);
962
+ const status = await getVaultStatus(pc, vault);
963
+ const result = await redeemAsync(
964
+ walletClient,
965
+ pc,
966
+ { vault, escrow: status.escrow, hubChainId },
967
+ sharesInWei,
968
+ receiver,
969
+ owner,
970
+ feeWithBuffer
971
+ );
972
+ setTxHash(result.txHash);
973
+ setGuid(result.guid);
974
+ } catch (err) {
975
+ setError(err instanceof Error ? err : new Error(String(err)));
976
+ } finally {
977
+ setIsLoading(false);
978
+ }
979
+ },
980
+ [vault, walletClient, publicClient, feeWithBuffer, hubChainId]
981
+ );
982
+ const reset = react.useCallback(() => {
983
+ setTxHash(void 0);
984
+ setGuid(void 0);
985
+ setError(void 0);
986
+ setIsLoading(false);
987
+ }, []);
988
+ return { redeem, isLoading, txHash, guid, requestStatus, wrongChain, error, reset };
989
+ }
990
+ function useDepositSimple(vault, chainId) {
991
+ const { data: walletClient } = wagmi.useWalletClient({ chainId });
992
+ const publicClient = wagmi.usePublicClient({ chainId });
993
+ const [isLoading, setIsLoading] = react.useState(false);
994
+ const [result, setResult] = react.useState();
995
+ const [error, setError] = react.useState();
996
+ const deposit = react.useCallback(
997
+ async (amountInWei, receiver) => {
998
+ if (!vault || !walletClient || !publicClient) return;
999
+ setIsLoading(true);
1000
+ setError(void 0);
1001
+ try {
1002
+ const res = await depositSimple(
1003
+ walletClient,
1004
+ asSdkClient(publicClient),
1005
+ { vault, hubChainId: chainId },
1006
+ amountInWei,
1007
+ receiver
1008
+ );
1009
+ setResult(res);
1010
+ } catch (err) {
1011
+ setError(err instanceof Error ? err : new Error(String(err)));
1012
+ } finally {
1013
+ setIsLoading(false);
1014
+ }
1015
+ },
1016
+ [vault, walletClient, publicClient, chainId]
1017
+ );
1018
+ const reset = react.useCallback(() => {
1019
+ setResult(void 0);
1020
+ setError(void 0);
1021
+ setIsLoading(false);
1022
+ }, []);
1023
+ return {
1024
+ deposit,
1025
+ isLoading,
1026
+ txHash: result?.txHash,
1027
+ shares: result?.shares,
1028
+ error,
1029
+ reset
1030
+ };
1031
+ }
1032
+ function useRedeemShares(vault, chainId) {
1033
+ const { data: walletClient } = wagmi.useWalletClient({ chainId });
1034
+ const publicClient = wagmi.usePublicClient({ chainId });
1035
+ const [isLoading, setIsLoading] = react.useState(false);
1036
+ const [result, setResult] = react.useState();
1037
+ const [error, setError] = react.useState();
1038
+ const redeem = react.useCallback(
1039
+ async (sharesInWei, receiver, owner) => {
1040
+ if (!vault || !walletClient || !publicClient) return;
1041
+ setIsLoading(true);
1042
+ setError(void 0);
1043
+ try {
1044
+ const res = await redeemShares(
1045
+ walletClient,
1046
+ asSdkClient(publicClient),
1047
+ { vault, hubChainId: chainId },
1048
+ sharesInWei,
1049
+ receiver,
1050
+ owner
1051
+ );
1052
+ setResult(res);
1053
+ } catch (err) {
1054
+ setError(err instanceof Error ? err : new Error(String(err)));
1055
+ } finally {
1056
+ setIsLoading(false);
1057
+ }
1058
+ },
1059
+ [vault, walletClient, publicClient, chainId]
1060
+ );
1061
+ const reset = react.useCallback(() => {
1062
+ setResult(void 0);
1063
+ setError(void 0);
1064
+ setIsLoading(false);
1065
+ }, []);
1066
+ return {
1067
+ redeem,
1068
+ isLoading,
1069
+ txHash: result?.txHash,
1070
+ assets: result?.assets,
1071
+ error,
1072
+ reset
1073
+ };
1074
+ }
1075
+
1076
+ // src/react/useSmartDeposit.ts
1077
+ function useSmartDeposit(vault, hubChainId) {
1078
+ const { data: status } = useVaultStatus(vault, hubChainId);
1079
+ const omni = useOmniDeposit(vault, hubChainId);
1080
+ const simple = useDepositSimple(vault, hubChainId);
1081
+ const isAsync = status?.mode === "cross-chain-async";
1082
+ const deposit = isAsync ? omni.deposit : simple.deposit;
1083
+ return {
1084
+ deposit,
1085
+ isLoading: isAsync ? omni.isLoading : simple.isLoading,
1086
+ txHash: isAsync ? omni.txHash : simple.txHash,
1087
+ shares: isAsync ? void 0 : simple.shares,
1088
+ guid: isAsync ? omni.guid : void 0,
1089
+ requestStatus: isAsync ? omni.requestStatus : void 0,
1090
+ wrongChain: isAsync ? omni.wrongChain : false,
1091
+ vaultMode: status?.mode,
1092
+ error: isAsync ? omni.error : simple.error,
1093
+ reset: isAsync ? omni.reset : simple.reset
1094
+ };
1095
+ }
1096
+
1097
+ exports.useAsyncRequestStatus = useAsyncRequestStatus;
1098
+ exports.useDepositSimple = useDepositSimple;
1099
+ exports.useLzFee = useLzFee;
1100
+ exports.useOmniDeposit = useOmniDeposit;
1101
+ exports.useOmniRedeem = useOmniRedeem;
1102
+ exports.useRedeemShares = useRedeemShares;
1103
+ exports.useSmartDeposit = useSmartDeposit;
1104
+ exports.useUserPosition = useUserPosition;
1105
+ exports.useVaultMetadata = useVaultMetadata;
1106
+ exports.useVaultStatus = useVaultStatus;
1107
+ //# sourceMappingURL=index.cjs.map
1108
+ //# sourceMappingURL=index.cjs.map