@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,377 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility helpers for the MoreVaults ethers.js v6 SDK.
|
|
3
|
+
*
|
|
4
|
+
* All reads use Provider (read-only). Writes use Signer.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Contract, Interface, ZeroAddress } from "ethers";
|
|
8
|
+
import type { Provider, Signer } from "ethers";
|
|
9
|
+
import { BRIDGE_ABI, CONFIG_ABI, ERC20_ABI, VAULT_ABI } from "./abis";
|
|
10
|
+
|
|
11
|
+
// Multicall3 — deployed at the same address on every EVM chain
|
|
12
|
+
const MULTICALL3_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11";
|
|
13
|
+
const MULTICALL3_ABI = [
|
|
14
|
+
"function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)",
|
|
15
|
+
] as const;
|
|
16
|
+
import type { CrossChainRequestInfo } from "./types";
|
|
17
|
+
|
|
18
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
19
|
+
|
|
20
|
+
export type VaultMode =
|
|
21
|
+
| "local" // single-chain vault, no cross-chain
|
|
22
|
+
| "cross-chain-oracle" // hub with oracle-based accounting (sync)
|
|
23
|
+
| "cross-chain-async" // hub with off-chain accounting (async, D4/D5/R5)
|
|
24
|
+
| "paused" // vault is paused
|
|
25
|
+
| "full"; // deposit capacity reached
|
|
26
|
+
|
|
27
|
+
export interface VaultStatus {
|
|
28
|
+
/** Vault operating mode — determines which SDK flow to use */
|
|
29
|
+
mode: VaultMode;
|
|
30
|
+
/** Which deposit function to call given the current configuration */
|
|
31
|
+
recommendedDepositFlow: "depositSimple" | "depositAsync" | "mintAsync" | "none";
|
|
32
|
+
/** Which redeem function to call given the current configuration */
|
|
33
|
+
recommendedRedeemFlow: "redeemShares" | "redeemAsync" | "none";
|
|
34
|
+
|
|
35
|
+
// ── Configuration ──────────────────────────────────────────────────────────
|
|
36
|
+
isHub: boolean;
|
|
37
|
+
isPaused: boolean;
|
|
38
|
+
oracleAccountingEnabled: boolean;
|
|
39
|
+
|
|
40
|
+
/** address(0) means CCManager is not set — async flows will fail */
|
|
41
|
+
ccManager: string;
|
|
42
|
+
/** address(0) means escrow is not configured in the registry */
|
|
43
|
+
escrow: string;
|
|
44
|
+
|
|
45
|
+
// ── Withdrawal queue ───────────────────────────────────────────────────────
|
|
46
|
+
withdrawalQueueEnabled: boolean;
|
|
47
|
+
/** Timelock duration in seconds (0 = no timelock) */
|
|
48
|
+
withdrawalTimelockSeconds: bigint;
|
|
49
|
+
|
|
50
|
+
// ── Capacity ───────────────────────────────────────────────────────────────
|
|
51
|
+
/**
|
|
52
|
+
* Remaining deposit capacity in underlying token decimals.
|
|
53
|
+
* `type(uint256).max` = no cap configured (unlimited).
|
|
54
|
+
* `0n` = vault is full — no more deposits accepted.
|
|
55
|
+
* If `depositAccessRestricted = true`, this value is `type(uint256).max` but
|
|
56
|
+
* deposits are still gated by whitelist or other access control.
|
|
57
|
+
*/
|
|
58
|
+
remainingDepositCapacity: bigint;
|
|
59
|
+
/**
|
|
60
|
+
* True when `maxDeposit(address(0))` reverted, indicating the vault uses
|
|
61
|
+
* whitelist or other access control to restrict who can deposit.
|
|
62
|
+
*/
|
|
63
|
+
depositAccessRestricted: boolean;
|
|
64
|
+
|
|
65
|
+
// ── Vault metrics ──────────────────────────────────────────────────────────
|
|
66
|
+
underlying: string;
|
|
67
|
+
totalAssets: bigint;
|
|
68
|
+
totalSupply: bigint;
|
|
69
|
+
/** Vault share token decimals. Use this for display — never hardcode 18. */
|
|
70
|
+
decimals: number;
|
|
71
|
+
/**
|
|
72
|
+
* Price of 1 full share expressed in underlying token units.
|
|
73
|
+
* = convertToAssets(10^decimals). Grows over time as the vault earns yield.
|
|
74
|
+
*/
|
|
75
|
+
sharePrice: bigint;
|
|
76
|
+
/**
|
|
77
|
+
* Underlying token balance held directly on the hub chain.
|
|
78
|
+
* This is the only portion that can be paid out to redeeming users immediately.
|
|
79
|
+
* (= ERC-20.balanceOf(vault) on the hub)
|
|
80
|
+
*/
|
|
81
|
+
hubLiquidBalance: bigint;
|
|
82
|
+
/**
|
|
83
|
+
* Approximate value deployed to spoke chains (totalAssets − hubLiquidBalance).
|
|
84
|
+
* These funds are NOT immediately redeemable — the vault curator must
|
|
85
|
+
* call executeBridging to repatriate them before large redeems can succeed.
|
|
86
|
+
*/
|
|
87
|
+
spokesDeployedBalance: bigint;
|
|
88
|
+
/**
|
|
89
|
+
* Maximum assets that can be redeemed right now without curator intervention.
|
|
90
|
+
* - For hub vaults: equals `hubLiquidBalance`.
|
|
91
|
+
* - For local/oracle vaults: equals `totalAssets`.
|
|
92
|
+
*/
|
|
93
|
+
maxImmediateRedeemAssets: bigint;
|
|
94
|
+
|
|
95
|
+
// ── Issues — empty when everything is correctly configured ─────────────────
|
|
96
|
+
/**
|
|
97
|
+
* Human-readable list of configuration problems that would cause transactions
|
|
98
|
+
* to fail. Empty array = vault is ready to use.
|
|
99
|
+
*/
|
|
100
|
+
issues: string[];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Ensure the spender has sufficient ERC-20 allowance; approve if not.
|
|
105
|
+
*
|
|
106
|
+
* @param signer Wallet signer with account attached
|
|
107
|
+
* @param provider Read-only provider for allowance checks
|
|
108
|
+
* @param token ERC-20 token address
|
|
109
|
+
* @param spender Address to approve
|
|
110
|
+
* @param amount Minimum required allowance
|
|
111
|
+
*/
|
|
112
|
+
export async function ensureAllowance(
|
|
113
|
+
signer: Signer,
|
|
114
|
+
provider: Provider,
|
|
115
|
+
token: string,
|
|
116
|
+
spender: string,
|
|
117
|
+
amount: bigint
|
|
118
|
+
): Promise<void> {
|
|
119
|
+
const owner = await signer.getAddress();
|
|
120
|
+
const erc20Read = new Contract(token, ERC20_ABI, provider);
|
|
121
|
+
const current: bigint = await erc20Read.allowance(owner, spender);
|
|
122
|
+
if (current < amount) {
|
|
123
|
+
const erc20Write = new Contract(token, ERC20_ABI, signer);
|
|
124
|
+
const tx = await erc20Write.approve(spender, amount);
|
|
125
|
+
await tx.wait();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Quote the LayerZero native fee required for async vault actions.
|
|
131
|
+
*
|
|
132
|
+
* @param provider Read-only provider
|
|
133
|
+
* @param vault Vault address (diamond proxy)
|
|
134
|
+
* @param extraOptions Optional LZ extra options bytes (default 0x)
|
|
135
|
+
* @returns Required native fee in wei
|
|
136
|
+
*/
|
|
137
|
+
export async function quoteLzFee(
|
|
138
|
+
provider: Provider,
|
|
139
|
+
vault: string,
|
|
140
|
+
extraOptions: string = "0x"
|
|
141
|
+
): Promise<bigint> {
|
|
142
|
+
const bridge = new Contract(vault, BRIDGE_ABI, provider);
|
|
143
|
+
const fee: bigint = await bridge.quoteAccountingFee(extraOptions);
|
|
144
|
+
return fee;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Check if a vault is operating in async mode (cross-chain hub with oracle OFF).
|
|
149
|
+
*
|
|
150
|
+
* @param provider Read-only provider
|
|
151
|
+
* @param vault Vault address
|
|
152
|
+
* @returns true if the vault requires async cross-chain flows
|
|
153
|
+
*/
|
|
154
|
+
export async function isAsyncMode(
|
|
155
|
+
provider: Provider,
|
|
156
|
+
vault: string
|
|
157
|
+
): Promise<boolean> {
|
|
158
|
+
const config = new Contract(vault, CONFIG_ABI, provider);
|
|
159
|
+
const bridge = new Contract(vault, BRIDGE_ABI, provider);
|
|
160
|
+
|
|
161
|
+
const [isHub, oraclesEnabled]: [boolean, boolean] = await Promise.all([
|
|
162
|
+
config.isHub(),
|
|
163
|
+
bridge.oraclesCrossChainAccounting(),
|
|
164
|
+
]);
|
|
165
|
+
|
|
166
|
+
if (!isHub) return false;
|
|
167
|
+
return !oraclesEnabled;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Poll for async request completion status.
|
|
172
|
+
*
|
|
173
|
+
* @param provider Read-only provider
|
|
174
|
+
* @param vault Vault address
|
|
175
|
+
* @param guid Request GUID returned by the async flow
|
|
176
|
+
* @returns Whether the request is fulfilled, finalized, and the result
|
|
177
|
+
*/
|
|
178
|
+
export async function getAsyncRequestStatus(
|
|
179
|
+
provider: Provider,
|
|
180
|
+
vault: string,
|
|
181
|
+
guid: string
|
|
182
|
+
): Promise<{ fulfilled: boolean; finalized: boolean; result: bigint }> {
|
|
183
|
+
const bridge = new Contract(vault, BRIDGE_ABI, provider);
|
|
184
|
+
|
|
185
|
+
const [info, finalizationResult]: [CrossChainRequestInfo, bigint] =
|
|
186
|
+
await Promise.all([
|
|
187
|
+
bridge.getRequestInfo(guid),
|
|
188
|
+
bridge.getFinalizationResult(guid),
|
|
189
|
+
]);
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
fulfilled: info.fulfilled,
|
|
193
|
+
finalized: info.finalized,
|
|
194
|
+
result: finalizationResult,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Read the full configuration and operational status of a vault.
|
|
200
|
+
*
|
|
201
|
+
* All independent reads are fired in parallel.
|
|
202
|
+
*
|
|
203
|
+
* @param provider Read-only provider
|
|
204
|
+
* @param vault Vault address (diamond proxy)
|
|
205
|
+
* @returns Full vault status snapshot
|
|
206
|
+
*/
|
|
207
|
+
export async function getVaultStatus(
|
|
208
|
+
provider: Provider,
|
|
209
|
+
vault: string
|
|
210
|
+
): Promise<VaultStatus> {
|
|
211
|
+
const mc = new Contract(MULTICALL3_ADDRESS, MULTICALL3_ABI, provider);
|
|
212
|
+
const configIface = new Interface(CONFIG_ABI as unknown as string[]);
|
|
213
|
+
const bridgeIface = new Interface(BRIDGE_ABI as unknown as string[]);
|
|
214
|
+
const vaultIface = new Interface(VAULT_ABI as unknown as string[]);
|
|
215
|
+
const decimalsIface = new Interface(["function decimals() view returns (uint8)"]);
|
|
216
|
+
|
|
217
|
+
// ── Batch 1: 12 calls → 1 eth_call via Multicall3.aggregate3 ─────────────
|
|
218
|
+
const b1Calls = [
|
|
219
|
+
{ target: vault, allowFailure: false, callData: configIface.encodeFunctionData("isHub") },
|
|
220
|
+
{ target: vault, allowFailure: false, callData: configIface.encodeFunctionData("paused") },
|
|
221
|
+
{ target: vault, allowFailure: false, callData: bridgeIface.encodeFunctionData("oraclesCrossChainAccounting") },
|
|
222
|
+
{ target: vault, allowFailure: false, callData: configIface.encodeFunctionData("getCrossChainAccountingManager") },
|
|
223
|
+
{ target: vault, allowFailure: false, callData: configIface.encodeFunctionData("getEscrow") },
|
|
224
|
+
{ target: vault, allowFailure: false, callData: configIface.encodeFunctionData("getWithdrawalQueueStatus") },
|
|
225
|
+
{ target: vault, allowFailure: false, callData: configIface.encodeFunctionData("getWithdrawalTimelock") },
|
|
226
|
+
// allowFailure=true: maxDeposit reverts on whitelisted vaults with address(0)
|
|
227
|
+
{ target: vault, allowFailure: true, callData: configIface.encodeFunctionData("maxDeposit", [ZeroAddress]) },
|
|
228
|
+
{ target: vault, allowFailure: false, callData: vaultIface.encodeFunctionData("asset") },
|
|
229
|
+
{ target: vault, allowFailure: false, callData: vaultIface.encodeFunctionData("totalAssets") },
|
|
230
|
+
{ target: vault, allowFailure: false, callData: vaultIface.encodeFunctionData("totalSupply") },
|
|
231
|
+
{ target: vault, allowFailure: false, callData: decimalsIface.encodeFunctionData("decimals") },
|
|
232
|
+
];
|
|
233
|
+
|
|
234
|
+
const b1: { success: boolean; returnData: string }[] = await mc.aggregate3.staticCall(b1Calls);
|
|
235
|
+
|
|
236
|
+
const isHub = configIface.decodeFunctionResult("isHub", b1[0].returnData)[0] as boolean;
|
|
237
|
+
const isPaused = configIface.decodeFunctionResult("paused", b1[1].returnData)[0] as boolean;
|
|
238
|
+
const oraclesEnabled = bridgeIface.decodeFunctionResult("oraclesCrossChainAccounting", b1[2].returnData)[0] as boolean;
|
|
239
|
+
const ccManager = configIface.decodeFunctionResult("getCrossChainAccountingManager", b1[3].returnData)[0] as string;
|
|
240
|
+
const escrow = configIface.decodeFunctionResult("getEscrow", b1[4].returnData)[0] as string;
|
|
241
|
+
const withdrawalQueueEnabled = configIface.decodeFunctionResult("getWithdrawalQueueStatus", b1[5].returnData)[0] as boolean;
|
|
242
|
+
const withdrawalTimelockSeconds = configIface.decodeFunctionResult("getWithdrawalTimelock", b1[6].returnData)[0] as bigint;
|
|
243
|
+
// null sentinel: reverted means whitelist/ACL
|
|
244
|
+
const maxDepositRaw = b1[7].success
|
|
245
|
+
? configIface.decodeFunctionResult("maxDeposit", b1[7].returnData)[0] as bigint
|
|
246
|
+
: null;
|
|
247
|
+
const underlying = vaultIface.decodeFunctionResult("asset", b1[8].returnData)[0] as string;
|
|
248
|
+
const totalAssets = vaultIface.decodeFunctionResult("totalAssets", b1[9].returnData)[0] as bigint;
|
|
249
|
+
const totalSupply = vaultIface.decodeFunctionResult("totalSupply", b1[10].returnData)[0] as bigint;
|
|
250
|
+
const decimalsRaw = decimalsIface.decodeFunctionResult("decimals", b1[11].returnData)[0];
|
|
251
|
+
const decimalsNum = Number(decimalsRaw);
|
|
252
|
+
const oneShare = 10n ** BigInt(decimalsNum);
|
|
253
|
+
|
|
254
|
+
// ── Batch 2: 2 calls → 1 eth_call (depends on underlying + decimals) ─────
|
|
255
|
+
const erc20Iface = new Interface(ERC20_ABI as unknown as string[]);
|
|
256
|
+
const b2Calls = [
|
|
257
|
+
{ target: underlying, allowFailure: false, callData: erc20Iface.encodeFunctionData("balanceOf", [vault]) },
|
|
258
|
+
{ target: vault, allowFailure: false, callData: vaultIface.encodeFunctionData("convertToAssets", [oneShare]) },
|
|
259
|
+
];
|
|
260
|
+
|
|
261
|
+
const b2: { success: boolean; returnData: string }[] = await mc.aggregate3.staticCall(b2Calls);
|
|
262
|
+
|
|
263
|
+
const hubLiquidBalance = erc20Iface.decodeFunctionResult("balanceOf", b2[0].returnData)[0] as bigint;
|
|
264
|
+
const sharePrice = vaultIface.decodeFunctionResult("convertToAssets", b2[1].returnData)[0] as bigint;
|
|
265
|
+
|
|
266
|
+
const spokesDeployedBalance: bigint = totalAssets > hubLiquidBalance ? totalAssets - hubLiquidBalance : 0n;
|
|
267
|
+
|
|
268
|
+
// null = maxDeposit reverted → whitelist/ACL vault
|
|
269
|
+
const MAX_UINT256 = BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
|
|
270
|
+
const depositAccessRestricted = maxDepositRaw === null;
|
|
271
|
+
const effectiveCapacity: bigint = depositAccessRestricted ? MAX_UINT256 : maxDepositRaw!;
|
|
272
|
+
|
|
273
|
+
// ── Derive mode ────────────────────────────────────────────────────────────
|
|
274
|
+
let mode: VaultMode;
|
|
275
|
+
if (isPaused) {
|
|
276
|
+
mode = "paused";
|
|
277
|
+
} else if (effectiveCapacity === 0n) {
|
|
278
|
+
mode = "full";
|
|
279
|
+
} else if (!isHub) {
|
|
280
|
+
mode = "local";
|
|
281
|
+
} else if (oraclesEnabled) {
|
|
282
|
+
mode = "cross-chain-oracle";
|
|
283
|
+
} else {
|
|
284
|
+
mode = "cross-chain-async";
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// ── Recommended flows ──────────────────────────────────────────────────────
|
|
288
|
+
let recommendedDepositFlow: VaultStatus["recommendedDepositFlow"];
|
|
289
|
+
let recommendedRedeemFlow: VaultStatus["recommendedRedeemFlow"];
|
|
290
|
+
|
|
291
|
+
if (mode === "paused" || mode === "full") {
|
|
292
|
+
recommendedDepositFlow = "none";
|
|
293
|
+
recommendedRedeemFlow = mode === "paused" ? "none" : "redeemShares";
|
|
294
|
+
} else if (mode === "cross-chain-async") {
|
|
295
|
+
recommendedDepositFlow = "depositAsync";
|
|
296
|
+
recommendedRedeemFlow = "redeemAsync";
|
|
297
|
+
} else {
|
|
298
|
+
// local or cross-chain-oracle
|
|
299
|
+
recommendedDepositFlow = "depositSimple";
|
|
300
|
+
recommendedRedeemFlow = "redeemShares";
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// ── Issues ─────────────────────────────────────────────────────────────────
|
|
304
|
+
const issues: string[] = [];
|
|
305
|
+
|
|
306
|
+
if (isPaused) {
|
|
307
|
+
issues.push("Vault is paused — no deposits or redeems are possible.");
|
|
308
|
+
}
|
|
309
|
+
if (effectiveCapacity === 0n && !isPaused) {
|
|
310
|
+
issues.push(
|
|
311
|
+
"Deposit capacity is full — increase depositCapacity via setDepositCapacity()."
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
if (isHub && !oraclesEnabled && ccManager === ZeroAddress) {
|
|
315
|
+
issues.push(
|
|
316
|
+
"CCManager not configured — async flows will revert. Call setCrossChainAccountingManager(address) as vault owner."
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
if (isHub && !oraclesEnabled && escrow === ZeroAddress) {
|
|
320
|
+
issues.push(
|
|
321
|
+
"Escrow not configured in registry — async flows will revert. Set the escrow via the MoreVaultsRegistry."
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
if (depositAccessRestricted) {
|
|
325
|
+
issues.push("Deposit access is restricted (whitelist or other access control). Only approved addresses can deposit.");
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// ── maxImmediateRedeemAssets ────────────────────────────────────────────────
|
|
329
|
+
const maxImmediateRedeemAssets: bigint = isHub && !oraclesEnabled ? hubLiquidBalance : totalAssets;
|
|
330
|
+
|
|
331
|
+
if (isHub) {
|
|
332
|
+
if (hubLiquidBalance === 0n) {
|
|
333
|
+
issues.push(
|
|
334
|
+
`Hub has no liquid assets (hubLiquidBalance = 0). All redeems will be auto-refunded until the curator repatriates funds from spokes via executeBridging().`
|
|
335
|
+
);
|
|
336
|
+
} else if (totalAssets > 0n && hubLiquidBalance * 10n < totalAssets) {
|
|
337
|
+
const pct = Number((hubLiquidBalance * 10000n) / totalAssets) / 100;
|
|
338
|
+
issues.push(
|
|
339
|
+
`Low hub liquidity: ${hubLiquidBalance} units liquid on hub (${pct.toFixed(1)}% of TVL). ` +
|
|
340
|
+
`Redeems above ${hubLiquidBalance} underlying units will be auto-refunded. ` +
|
|
341
|
+
`Curator must call executeBridging() to repatriate from spokes.`
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
if (spokesDeployedBalance > 0n) {
|
|
345
|
+
const total = totalAssets;
|
|
346
|
+
issues.push(
|
|
347
|
+
`${spokesDeployedBalance} units (~${((Number(spokesDeployedBalance) / Number(total || 1n)) * 100).toFixed(1)}% of TVL) ` +
|
|
348
|
+
`are deployed on spoke chains earning yield. These are NOT immediately redeemable — ` +
|
|
349
|
+
`they require a curator repatriation (executeBridging) before users can withdraw them.`
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return {
|
|
355
|
+
mode,
|
|
356
|
+
recommendedDepositFlow,
|
|
357
|
+
recommendedRedeemFlow,
|
|
358
|
+
isHub,
|
|
359
|
+
isPaused,
|
|
360
|
+
oracleAccountingEnabled: oraclesEnabled,
|
|
361
|
+
ccManager,
|
|
362
|
+
escrow,
|
|
363
|
+
withdrawalQueueEnabled,
|
|
364
|
+
withdrawalTimelockSeconds: BigInt(withdrawalTimelockSeconds),
|
|
365
|
+
remainingDepositCapacity: effectiveCapacity,
|
|
366
|
+
depositAccessRestricted,
|
|
367
|
+
underlying,
|
|
368
|
+
totalAssets,
|
|
369
|
+
totalSupply,
|
|
370
|
+
decimals: decimalsNum,
|
|
371
|
+
sharePrice,
|
|
372
|
+
hubLiquidBalance,
|
|
373
|
+
spokesDeployedBalance,
|
|
374
|
+
maxImmediateRedeemAssets,
|
|
375
|
+
issues,
|
|
376
|
+
};
|
|
377
|
+
}
|