@oydual31/more-vaults-sdk 0.3.3 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/ethers/index.cjs +1794 -315
  2. package/dist/ethers/index.cjs.map +1 -1
  3. package/dist/ethers/index.d.cts +1147 -1
  4. package/dist/ethers/index.d.ts +1147 -1
  5. package/dist/ethers/index.js +1752 -317
  6. package/dist/ethers/index.js.map +1 -1
  7. package/dist/react/index.cjs +644 -0
  8. package/dist/react/index.cjs.map +1 -1
  9. package/dist/react/index.d.cts +111 -2
  10. package/dist/react/index.d.ts +111 -2
  11. package/dist/react/index.js +638 -3
  12. package/dist/react/index.js.map +1 -1
  13. package/dist/{spokeRoutes-BIafSbQ3.d.cts → spokeRoutes-B8Lnk-t4.d.cts} +191 -2
  14. package/dist/{spokeRoutes-BIafSbQ3.d.ts → spokeRoutes-B8Lnk-t4.d.ts} +191 -2
  15. package/dist/viem/index.d.cts +4 -192
  16. package/dist/viem/index.d.ts +4 -192
  17. package/package.json +1 -1
  18. package/src/ethers/abis.ts +92 -0
  19. package/src/ethers/chains.ts +191 -0
  20. package/src/ethers/crossChainFlows.ts +208 -0
  21. package/src/ethers/curatorMulticall.ts +195 -0
  22. package/src/ethers/curatorStatus.ts +319 -0
  23. package/src/ethers/curatorSwaps.ts +192 -0
  24. package/src/ethers/distribution.ts +156 -0
  25. package/src/ethers/index.ts +96 -1
  26. package/src/ethers/preflight.ts +225 -1
  27. package/src/ethers/redeemFlows.ts +160 -1
  28. package/src/ethers/spokeRoutes.ts +361 -0
  29. package/src/ethers/topology.ts +240 -0
  30. package/src/ethers/types.ts +95 -0
  31. package/src/ethers/userHelpers.ts +193 -0
  32. package/src/ethers/utils.ts +28 -0
  33. package/src/react/index.ts +25 -0
  34. package/src/react/useCuratorVaultStatus.ts +32 -0
  35. package/src/react/useExecuteActions.ts +23 -0
  36. package/src/react/useIsCurator.ts +30 -0
  37. package/src/react/usePendingActions.ts +33 -0
  38. package/src/react/useProtocolWhitelist.ts +30 -0
  39. package/src/react/useSubmitActions.ts +27 -0
  40. package/src/react/useVaultAnalysis.ts +32 -0
  41. package/src/react/useVaultAssetBreakdown.ts +32 -0
  42. package/src/react/useVetoActions.ts +23 -0
@@ -8,29 +8,356 @@ var CHAIN_IDS = {
8
8
  flowEVMTestnet: 545,
9
9
  arbitrum: 42161,
10
10
  base: 8453,
11
- ethereum: 1
11
+ ethereum: 1,
12
+ optimism: 10,
13
+ sonic: 146,
14
+ bsc: 56
12
15
  };
13
16
  var LZ_EIDS = {
14
17
  flowMainnet: 30336,
15
18
  flowTestnet: 30333,
16
19
  arbitrum: 30110,
17
20
  base: 30184,
18
- ethereum: 30101
21
+ ethereum: 30101,
22
+ optimism: 30111,
23
+ sonic: 30332,
24
+ bsc: 30102
19
25
  };
20
26
  var EID_TO_CHAIN_ID = {
21
27
  [LZ_EIDS.flowMainnet]: CHAIN_IDS.flowEVMMainnet,
22
28
  [LZ_EIDS.flowTestnet]: CHAIN_IDS.flowEVMTestnet,
23
29
  [LZ_EIDS.arbitrum]: CHAIN_IDS.arbitrum,
24
30
  [LZ_EIDS.base]: CHAIN_IDS.base,
25
- [LZ_EIDS.ethereum]: CHAIN_IDS.ethereum
31
+ [LZ_EIDS.ethereum]: CHAIN_IDS.ethereum,
32
+ [LZ_EIDS.optimism]: CHAIN_IDS.optimism,
33
+ [LZ_EIDS.sonic]: CHAIN_IDS.sonic,
34
+ [LZ_EIDS.bsc]: CHAIN_IDS.bsc
26
35
  };
27
36
  var CHAIN_ID_TO_EID = {
28
37
  [CHAIN_IDS.flowEVMMainnet]: LZ_EIDS.flowMainnet,
29
38
  [CHAIN_IDS.flowEVMTestnet]: LZ_EIDS.flowTestnet,
30
39
  [CHAIN_IDS.arbitrum]: LZ_EIDS.arbitrum,
31
40
  [CHAIN_IDS.base]: LZ_EIDS.base,
32
- [CHAIN_IDS.ethereum]: LZ_EIDS.ethereum
41
+ [CHAIN_IDS.ethereum]: LZ_EIDS.ethereum,
42
+ [CHAIN_IDS.optimism]: LZ_EIDS.optimism,
43
+ [CHAIN_IDS.sonic]: LZ_EIDS.sonic,
44
+ [CHAIN_IDS.bsc]: LZ_EIDS.bsc
33
45
  };
46
+ var OFT_ROUTES = {
47
+ /**
48
+ * stgUSDC — USDC bridged via Stargate v2.
49
+ * Underlying on Eth/Arb/Base/Op: native USDC. On Flow: stgUSDC (Stargate's wrapped USDC).
50
+ */
51
+ stgUSDC: {
52
+ [
53
+ 747
54
+ /* flowEVMMainnet */
55
+ ]: { oft: "0xAF54BE5B6eEc24d6BFACf1cce4eaF680A8239398", token: "0xF1815bd50389c46847f0Bda824eC8da914045D14" },
56
+ [
57
+ 1
58
+ /* ethereum */
59
+ ]: { oft: "0xc026395860Db2d07ee33e05fE50ed7bD583189C7", token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" },
60
+ [
61
+ 42161
62
+ /* arbitrum */
63
+ ]: { oft: "0xe8CDF27AcD73a434D661C84887215F7598e7d0d3", token: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831" },
64
+ [
65
+ 8453
66
+ /* base */
67
+ ]: { oft: "0x27a16dc786820B16E5c9028b75B99F6f604b5d26", token: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" },
68
+ [
69
+ 10
70
+ /* optimism */
71
+ ]: { oft: "0xcE8CcA271Ebc0533920C83d39F417ED6A0abB7D0", token: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85" },
72
+ [
73
+ 146
74
+ /* sonic */
75
+ ]: { oft: "0xA272fFe20cFfe769CdFc4b63088DCD2C82a2D8F9", token: "0x29219dd400f2Bf60E5a23d13Be72B486D4038894" }
76
+ },
77
+ /**
78
+ * USDT — USDT bridged via Stargate v2.
79
+ */
80
+ USDT: {
81
+ [
82
+ 747
83
+ /* flowEVMMainnet */
84
+ ]: { oft: "0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6", token: "0x674843C06FF83502ddb4D37c2E09C01cdA38cbc8" },
85
+ [
86
+ 1
87
+ /* ethereum */
88
+ ]: { oft: "0x933597a323Eb81cAe705C5bC29985172fd5A3973", token: "0xdAC17F958D2ee523a2206206994597C13D831ec7" },
89
+ [
90
+ 42161
91
+ /* arbitrum */
92
+ ]: { oft: "0xcE8CcA271Ebc0533920C83d39F417ED6A0abB7D0", token: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9" },
93
+ [
94
+ 10
95
+ /* optimism */
96
+ ]: { oft: "0x19cFCE47eD54a88614648DC3f19A5980097007dD", token: "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58" }
97
+ },
98
+ /**
99
+ * USDF — USD Flow OFT. Bridges PYUSD (Ethereum) ↔ USDF (Flow EVM).
100
+ */
101
+ USDF: {
102
+ [
103
+ 747
104
+ /* flowEVMMainnet */
105
+ ]: { oft: "0x2aabea2058b5ac2d339b163c6ab6f2b6d53aabed", token: "0x2aabea2058b5ac2d339b163c6ab6f2b6d53aabed" },
106
+ [
107
+ 1
108
+ /* ethereum */
109
+ ]: { oft: "0xfa0e06b54986ad96de87a8c56fea76fbd8d493f8", token: "0x6c3ea9036406852006290770BEdFcAbA0e23A0e8" }
110
+ },
111
+ /**
112
+ * PYUSD — PayPal USD bridged via OFTAdapter (Paxos / LayerZero).
113
+ */
114
+ PYUSD: {
115
+ [
116
+ 747
117
+ /* flowEVMMainnet */
118
+ ]: { oft: "0x26d27d5AF2F6f1c14F40013C8619d97aaf015509", token: "0x99aF3EeA856556646C98c8B9b2548Fe815240750" },
119
+ [
120
+ 42161
121
+ /* arbitrum */
122
+ ]: { oft: "0x3CD2b89C49D130C08f1d683225b2e5DeB63ff876", token: "0x46850aD61C2B7d64d08c9C754F45254596696984" }
123
+ },
124
+ /**
125
+ * WFLOW — Wrapped FLOW NativeOFTAdapter (issued by Flow Foundation).
126
+ */
127
+ WFLOW: {
128
+ [
129
+ 747
130
+ /* flowEVMMainnet */
131
+ ]: { oft: "0xd296588850bee2770136464ffdddd78c32f2a07c", token: "0xd296588850bee2770136464ffdddd78c32f2a07c" },
132
+ [
133
+ 1
134
+ /* ethereum */
135
+ ]: { oft: "0xc1b45896b5fc9422a8f779653808297bb4f546f9", token: "0x5c147e74D63B1D31AA3Fd78Eb229B65161983B2b" }
136
+ },
137
+ /**
138
+ * WETH — ETH OFT via Stargate v2. underlying = native ETH (no approval needed).
139
+ */
140
+ WETH: {
141
+ [
142
+ 747
143
+ /* flowEVMMainnet */
144
+ ]: { oft: "0x45f1A95A4D3f3836523F5c83673c797f4d4d263B", token: "0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590" },
145
+ [
146
+ 1
147
+ /* ethereum */
148
+ ]: { oft: "0x77b2043768d28E9C9aB44E1aBfC95944bcE57931", token: "0x0000000000000000000000000000000000000000" },
149
+ [
150
+ 42161
151
+ /* arbitrum */
152
+ ]: { oft: "0xA45B5130f36CDcA45667738e2a258AB09f4A5f7F", token: "0x0000000000000000000000000000000000000000" },
153
+ [
154
+ 8453
155
+ /* base */
156
+ ]: { oft: "0xdc181Bd607330aeeBEF6ea62e03e5e1Fb4B6F7C7", token: "0x0000000000000000000000000000000000000000" }
157
+ },
158
+ /**
159
+ * sUSDe — Ethena staked USDe (yield-bearing stablecoin).
160
+ */
161
+ sUSDe: {
162
+ [
163
+ 1
164
+ /* ethereum */
165
+ ]: { oft: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2", token: "0x9D39A5DE30e57443BfF2A8307A4256c8797A3497" },
166
+ [
167
+ 42161
168
+ /* arbitrum */
169
+ ]: { oft: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2", token: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2" },
170
+ [
171
+ 8453
172
+ /* base */
173
+ ]: { oft: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2", token: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2" },
174
+ [
175
+ 10
176
+ /* optimism */
177
+ ]: { oft: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2", token: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2" },
178
+ [
179
+ 56
180
+ /* bsc */
181
+ ]: { oft: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2", token: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2" }
182
+ },
183
+ /**
184
+ * USDe — Ethena USD stablecoin.
185
+ */
186
+ USDe: {
187
+ [
188
+ 1
189
+ /* ethereum */
190
+ ]: { oft: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34", token: "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3" },
191
+ [
192
+ 42161
193
+ /* arbitrum */
194
+ ]: { oft: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34", token: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34" },
195
+ [
196
+ 8453
197
+ /* base */
198
+ ]: { oft: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34", token: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34" },
199
+ [
200
+ 10
201
+ /* optimism */
202
+ ]: { oft: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34", token: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34" },
203
+ [
204
+ 56
205
+ /* bsc */
206
+ ]: { oft: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34", token: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34" }
207
+ },
208
+ /**
209
+ * weETH — Ether.Fi liquid restaking token.
210
+ */
211
+ weETH: {
212
+ [
213
+ 1
214
+ /* ethereum */
215
+ ]: { oft: "0xcd2eb13d6831d4602d80e5db9230a57596cdca63", token: "0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee" },
216
+ [
217
+ 8453
218
+ /* base */
219
+ ]: { oft: "0x04c0599ae5a44757c0af6f9ec3b93da8976c150a", token: "0x04c0599ae5a44757c0af6f9ec3b93da8976c150a" },
220
+ [
221
+ 10
222
+ /* optimism */
223
+ ]: { oft: "0x5a7facb970d094b6c7ff1df0ea68d99e6e73cbff", token: "0x5a7facb970d094b6c7ff1df0ea68d99e6e73cbff" },
224
+ [
225
+ 56
226
+ /* bsc */
227
+ ]: { oft: "0x04c0599ae5a44757c0af6f9ec3b93da8976c150a", token: "0x04c0599ae5a44757c0af6f9ec3b93da8976c150a" },
228
+ [
229
+ 146
230
+ /* sonic */
231
+ ]: { oft: "0xa3d68b74bf0528fdd07263c60d6488749044914b", token: "0xa3d68b74bf0528fdd07263c60d6488749044914b" }
232
+ },
233
+ /**
234
+ * rsETH — Kelp DAO liquid restaking token.
235
+ */
236
+ rsETH: {
237
+ [
238
+ 1
239
+ /* ethereum */
240
+ ]: { oft: "0x85d456b2dff1fd8245387c0bfb64dfb700e98ef3", token: "0xA1290d69c65A6Fe4DF752f95823fae25cB99e5A7" },
241
+ [
242
+ 42161
243
+ /* arbitrum */
244
+ ]: { oft: "0x4186bfc76e2e237523cbc30fd220fe055156b41f", token: "0x4186bfc76e2e237523cbc30fd220fe055156b41f" },
245
+ [
246
+ 8453
247
+ /* base */
248
+ ]: { oft: "0x1bc71130a0e39942a7658878169764bbd8a45993", token: "0x1bc71130a0e39942a7658878169764bbd8a45993" },
249
+ [
250
+ 10
251
+ /* optimism */
252
+ ]: { oft: "0x4186bfc76e2e237523cbc30fd220fe055156b41f", token: "0x4186bfc76e2e237523cbc30fd220fe055156b41f" },
253
+ [
254
+ 146
255
+ /* sonic */
256
+ ]: { oft: "0xd75787ba9aba324420d522bda84c08c87e5099b1", token: "0xd75787ba9aba324420d522bda84c08c87e5099b1" }
257
+ },
258
+ /**
259
+ * rswETH — Swell Network liquid restaking token.
260
+ */
261
+ rswETH: {
262
+ [
263
+ 1
264
+ /* ethereum */
265
+ ]: { oft: "0x1486d39646cdee84619bd05997319545a8575079", token: "0xFAe103DC9cf190eD75350761e95403b7b8aFa6c0" },
266
+ [
267
+ 42161
268
+ /* arbitrum */
269
+ ]: { oft: "0xb1fe27b32ffb5ce54e272c096547f1e86c19e72f", token: "0xb1fe27b32ffb5ce54e272c096547f1e86c19e72f" },
270
+ [
271
+ 8453
272
+ /* base */
273
+ ]: { oft: "0x850cdf416668210ed0c36bfff5d21921c7ada3b8", token: "0x850cdf416668210ed0c36bfff5d21921c7ada3b8" }
274
+ },
275
+ /**
276
+ * USR — Resolv Labs USD stablecoin.
277
+ */
278
+ USR: {
279
+ [
280
+ 1
281
+ /* ethereum */
282
+ ]: { oft: "0xd2ee2776f34ef4e7325745b06e6d464b08d4be0e", token: "0x66a1E37c9b0eAddca17d3662D6c05F4DECf3e110" },
283
+ [
284
+ 42161
285
+ /* arbitrum */
286
+ ]: { oft: "0x2492d0006411af6c8bbb1c8afc1b0197350a79e9", token: "0x2492d0006411af6c8bbb1c8afc1b0197350a79e9" },
287
+ [
288
+ 8453
289
+ /* base */
290
+ ]: { oft: "0x35e5db674d8e93a03d814fa0ada70731efe8a4b9", token: "0x35e5db674d8e93a03d814fa0ada70731efe8a4b9" },
291
+ [
292
+ 56
293
+ /* bsc */
294
+ ]: { oft: "0x2492d0006411af6c8bbb1c8afc1b0197350a79e9", token: "0x2492d0006411af6c8bbb1c8afc1b0197350a79e9" }
295
+ },
296
+ /**
297
+ * wstUSR — Resolv Labs wrapped staked USR (yield-bearing).
298
+ */
299
+ wstUSR: {
300
+ [
301
+ 1
302
+ /* ethereum */
303
+ ]: { oft: "0xab17c1fe647c37ceb9b96d1c27dd189bf8451978", token: "0x1202F5C7b4B9E47a1A484E8B270be34dbbC75055" },
304
+ [
305
+ 42161
306
+ /* arbitrum */
307
+ ]: { oft: "0x66cfbd79257dc5217903a36293120282548e2254", token: "0x66cfbd79257dc5217903a36293120282548e2254" },
308
+ [
309
+ 8453
310
+ /* base */
311
+ ]: { oft: "0xb67675158b412d53fe6b68946483ba920b135ba1", token: "0xb67675158b412d53fe6b68946483ba920b135ba1" },
312
+ [
313
+ 56
314
+ /* bsc */
315
+ ]: { oft: "0x4254813524695def4163a169e901f3d7a1a55429", token: "0x4254813524695def4163a169e901f3d7a1a55429" }
316
+ },
317
+ /**
318
+ * USDtb — Ethena treasury-backed stablecoin.
319
+ */
320
+ USDtb: {
321
+ [
322
+ 1
323
+ /* ethereum */
324
+ ]: { oft: "0xc708b6887db46005da033501f8aebee72d191a5d", token: "0xC139190F447e929f090Edeb554D95AbB8b18aC1C" },
325
+ [
326
+ 42161
327
+ /* arbitrum */
328
+ ]: { oft: "0xc708b6887db46005da033501f8aebee72d191a5d", token: "0xc708b6887db46005da033501f8aebee72d191a5d" },
329
+ [
330
+ 8453
331
+ /* base */
332
+ ]: { oft: "0xc708b6887db46005da033501f8aebee72d191a5d", token: "0xc708b6887db46005da033501f8aebee72d191a5d" }
333
+ }
334
+ };
335
+ var UNISWAP_V3_ROUTERS = {
336
+ [8453]: "0x2626664c2603336E57B271c5C0b26F421741e481",
337
+ // Base — SwapRouter02 (no deadline)
338
+ [1]: "0xE592427A0AEce92De3Edee1F18E0157C05861564",
339
+ // Ethereum — SwapRouter
340
+ [42161]: "0xE592427A0AEce92De3Edee1F18E0157C05861564",
341
+ // Arbitrum — SwapRouter
342
+ [10]: "0xE592427A0AEce92De3Edee1F18E0157C05861564",
343
+ // Optimism — SwapRouter
344
+ [747]: "0xeEDC6Ff75e1b10B903D9013c358e446a73d35341"
345
+ // Flow EVM — FlowSwap V3 SwapRouter
346
+ };
347
+ var PUBLIC_RPCS = {
348
+ 1: ["https://ethereum-rpc.publicnode.com", "https://eth.drpc.org", "https://eth.llamarpc.com"],
349
+ 10: ["https://mainnet.optimism.io", "https://optimism-rpc.publicnode.com"],
350
+ 42161: ["https://arbitrum-one-rpc.publicnode.com", "https://arbitrum.publicnode.com"],
351
+ 8453: ["https://base-rpc.publicnode.com", "https://base.llamarpc.com", "https://mainnet.base.org"],
352
+ 747: ["https://mainnet.evm.nodes.onflow.org"],
353
+ 146: ["https://rpc.soniclabs.com"],
354
+ 56: ["https://bsc-dataseed1.binance.org", "https://bsc-dataseed2.binance.org"]
355
+ };
356
+ function createChainProvider(chainId) {
357
+ const rpcs = PUBLIC_RPCS[chainId];
358
+ if (!rpcs?.length) return null;
359
+ return new ethers.JsonRpcProvider(rpcs[0], chainId, { staticNetwork: true });
360
+ }
34
361
  var LZ_TIMEOUTS = {
35
362
  /** Poll interval between balance/event checks */
36
363
  POLL_INTERVAL: 3e4,
@@ -134,6 +461,58 @@ var LZ_ENDPOINT_ABI = [
134
461
  "function composeQueue(address from, address to, bytes32 guid, uint16 index) view returns (bytes32 messageHash)",
135
462
  "function lzCompose(address _from, address _to, bytes32 _guid, uint16 _index, bytes _message, bytes _extraData) payable"
136
463
  ];
464
+ var MULTICALL_ABI = [
465
+ "function submitActions(bytes[] actionsData) returns (uint256 nonce)",
466
+ "function executeActions(uint256 actionsNonce)",
467
+ "function getPendingActions(uint256 actionsNonce) view returns (bytes[] actionsData, uint256 pendingUntil)",
468
+ "function getCurrentNonce() view returns (uint256)",
469
+ "function vetoActions(uint256[] actionsNonces)"
470
+ ];
471
+ var DEX_ABI = [
472
+ "function executeSwap(tuple(address targetContract, address tokenIn, address tokenOut, uint256 maxAmountIn, uint256 minAmountOut, bytes swapCallData) params) returns (uint256 amountOut)",
473
+ "function executeBatchSwap(tuple(tuple(address targetContract, address tokenIn, address tokenOut, uint256 maxAmountIn, uint256 minAmountOut, bytes swapCallData)[] swaps) params) returns (uint256[] amountsOut)"
474
+ ];
475
+ var BRIDGE_FACET_ABI = [
476
+ "function executeBridging(address adapter, address token, uint256 amount, bytes bridgeSpecificParams) payable",
477
+ "function initVaultActionRequest(uint8 actionType, bytes actionCallData, uint256 amountLimit, bytes extraOptions) payable returns (bytes32 guid)",
478
+ "function executeRequest(bytes32 guid)"
479
+ ];
480
+ var ERC7540_FACET_ABI = [
481
+ "function erc7540RequestDeposit(address vault, uint256 assets) returns (uint256 requestId)",
482
+ "function erc7540RequestRedeem(address vault, uint256 shares) returns (uint256 requestId)",
483
+ "function erc7540Deposit(address vault, uint256 assets) returns (uint256 shares)",
484
+ "function erc7540Redeem(address vault, uint256 shares) returns (uint256 assets)"
485
+ ];
486
+ var ERC4626_FACET_ABI = [
487
+ "function erc4626Deposit(address vault, uint256 assets) returns (uint256 shares)",
488
+ "function erc4626Redeem(address vault, uint256 shares) returns (uint256 assets)"
489
+ ];
490
+ var CURATOR_CONFIG_ABI = [
491
+ "function curator() view returns (address)",
492
+ "function timeLockPeriod() view returns (uint256)",
493
+ "function getAvailableAssets() view returns (address[])",
494
+ "function getMaxSlippagePercent() view returns (uint256)",
495
+ "function getCrossChainAccountingManager() view returns (address)",
496
+ "function paused() view returns (bool)"
497
+ ];
498
+ var LZ_ADAPTER_ABI = [
499
+ "function quoteBridgeFee(bytes bridgeSpecificParams) view returns (uint256 nativeFee)",
500
+ "function quoteReadFee(address[] vaults, uint32[] eids, bytes _extraOptions) view returns (tuple(uint256 nativeFee, uint256 lzTokenFee) fee)"
501
+ ];
502
+ var VAULT_ANALYSIS_ABI = [
503
+ "function getAvailableAssets() view returns (address[])",
504
+ "function getDepositableAssets() view returns (address[])",
505
+ "function isAssetAvailable(address asset) view returns (bool)",
506
+ "function isAssetDepositable(address asset) view returns (bool)",
507
+ "function isDepositWhitelistEnabled() view returns (bool)",
508
+ "function getAvailableToDeposit(address depositor) view returns (uint256)",
509
+ "function moreVaultsRegistry() view returns (address)"
510
+ ];
511
+ var REGISTRY_ABI = [
512
+ "function isWhitelisted(address protocol) view returns (bool)",
513
+ "function isBridgeAllowed(address bridge) view returns (bool)",
514
+ "function getAllowedFacets() view returns (address[])"
515
+ ];
137
516
 
138
517
  // src/ethers/errors.ts
139
518
  var MoreVaultsError = class extends Error {
@@ -208,89 +587,9 @@ var WrongChainError = class extends MoreVaultsError {
208
587
  this.name = "WrongChainError";
209
588
  }
210
589
  };
211
- async function preflightAsync(provider, vault, escrow) {
212
- const config = new ethers.Contract(vault, CONFIG_ABI, provider);
213
- const bridge = new ethers.Contract(vault, BRIDGE_ABI, provider);
214
- const [ccManager, registeredEscrow, isHub, oraclesEnabled, isPaused] = await Promise.all([
215
- config.getCrossChainAccountingManager(),
216
- config.getEscrow(),
217
- config.isHub(),
218
- bridge.oraclesCrossChainAccounting(),
219
- config.paused()
220
- ]);
221
- if (ccManager === ethers.ZeroAddress) {
222
- throw new Error(
223
- `[MoreVaults] CCManager not configured on vault ${vault}. Call setCrossChainAccountingManager(ccManagerAddress) as vault owner first.`
224
- );
225
- }
226
- if (registeredEscrow === ethers.ZeroAddress) {
227
- throw new Error(
228
- `[MoreVaults] Escrow not configured for vault ${vault}. The registry must have an escrow set for this vault.`
229
- );
230
- }
231
- if (!isHub) {
232
- throw new Error(
233
- `[MoreVaults] Vault ${vault} is not a hub vault. Async flows (D4/D5/R5) only work on hub vaults.`
234
- );
235
- }
236
- if (oraclesEnabled) {
237
- throw new Error(
238
- `[MoreVaults] Vault ${vault} has oracle-based cross-chain accounting enabled. Use depositSimple/depositCrossChainOracleOn instead of async flows.`
239
- );
240
- }
241
- if (isPaused) {
242
- throw new Error(
243
- `[MoreVaults] Vault ${vault} is paused. Cannot perform any actions.`
244
- );
245
- }
246
- }
247
- async function preflightRedeemLiquidity(provider, vault, shares) {
248
- const config = new ethers.Contract(vault, CONFIG_ABI, provider);
249
- const bridge = new ethers.Contract(vault, BRIDGE_ABI, provider);
250
- const [isHub, oraclesEnabled] = await Promise.all([
251
- config.isHub(),
252
- bridge.oraclesCrossChainAccounting()
253
- ]);
254
- if (!isHub || oraclesEnabled) return;
255
- const vaultContract = new ethers.Contract(vault, VAULT_ABI, provider);
256
- const underlying = await vaultContract.asset();
257
- const underlyingContract = new ethers.Contract(underlying, ERC20_ABI, provider);
258
- const [hubLiquid, assetsNeeded] = await Promise.all([
259
- underlyingContract.balanceOf(vault),
260
- vaultContract.convertToAssets(shares)
261
- ]);
262
- if (hubLiquid < assetsNeeded) {
263
- throw new InsufficientLiquidityError(vault, hubLiquid, assetsNeeded);
264
- }
265
- }
266
- async function preflightSync(provider, vault) {
267
- const config = new ethers.Contract(vault, CONFIG_ABI, provider);
268
- const [isPaused, depositCapResult] = await Promise.all([
269
- config.paused(),
270
- config.maxDeposit(ethers.ZeroAddress).catch(() => null)
271
- ]);
272
- if (isPaused) {
273
- throw new Error(
274
- `[MoreVaults] Vault ${vault} is paused. Cannot perform any actions.`
275
- );
276
- }
277
- if (depositCapResult !== null && depositCapResult === 0n) {
278
- throw new Error(
279
- `[MoreVaults] Vault ${vault} has reached deposit capacity. No more deposits accepted.`
280
- );
281
- }
282
- }
283
-
284
- // src/ethers/chainValidation.ts
285
- async function validateWalletChain(signer, hubChainId) {
286
- if (!hubChainId) return;
287
- const network = await signer.provider?.getNetwork();
288
- if (!network) return;
289
- const current = Number(network.chainId);
290
- if (current !== hubChainId) {
291
- throw new WrongChainError(current, hubChainId);
292
- }
293
- }
590
+ var STARGATE_TYPE_ABI = [
591
+ "function stargateType() view returns (uint8)"
592
+ ];
294
593
  var MULTICALL3_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11";
295
594
  var MULTICALL3_ABI = [
296
595
  "function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)"
@@ -470,8 +769,18 @@ async function getVaultStatus(provider, vault) {
470
769
  issues
471
770
  };
472
771
  }
473
-
474
- // src/ethers/depositFlows.ts
772
+ async function detectStargateOft(provider, oft) {
773
+ try {
774
+ const contract = new ethers.Contract(oft, STARGATE_TYPE_ABI, provider);
775
+ await contract.stargateType();
776
+ return true;
777
+ } catch {
778
+ return false;
779
+ }
780
+ }
781
+ var LZ_ENDPOINT = "0x1a44076050125825900e736c501f859c50fe728c";
782
+ var EMPTY_HASH = "0x0000000000000000000000000000000000000000000000000000000000000000";
783
+ var RECEIVED_HASH = "0x0000000000000000000000000000000000000000000000000000000000000001";
475
784
  async function ensureAllowance2(signer, token, spender, amount) {
476
785
  const owner = await signer.getAddress();
477
786
  const erc20 = new ethers.Contract(token, ERC20_ABI, signer);
@@ -481,176 +790,34 @@ async function ensureAllowance2(signer, token, spender, amount) {
481
790
  await tx.wait();
482
791
  }
483
792
  }
484
- async function depositSimple(signer, addresses, assets, receiver) {
485
- const provider = signer.provider;
486
- await validateWalletChain(signer, addresses.hubChainId);
487
- await preflightSync(provider, addresses.vault);
488
- const vault = new ethers.Contract(addresses.vault, VAULT_ABI, signer);
489
- const underlying = await vault.asset();
490
- await ensureAllowance2(signer, underlying, addresses.vault, assets);
491
- const tx = await vault["deposit(uint256,address)"](assets, receiver);
492
- const receipt = await tx.wait();
493
- let shares = 0n;
494
- for (const log of receipt.logs) {
495
- try {
496
- const parsed = vault.interface.parseLog({
497
- topics: log.topics,
498
- data: log.data
499
- });
500
- if (parsed && parsed.name === "Transfer" && parsed.args[0] === "0x0000000000000000000000000000000000000000") {
501
- shares = parsed.args[2];
502
- break;
503
- }
504
- } catch {
505
- }
506
- }
507
- return { receipt, shares };
508
- }
509
- async function depositMultiAsset(signer, addresses, tokens, amounts, receiver, minShares) {
510
- await validateWalletChain(signer, addresses.hubChainId);
511
- for (let i = 0; i < tokens.length; i++) {
512
- await ensureAllowance2(signer, tokens[i], addresses.vault, amounts[i]);
513
- }
514
- const vault = new ethers.Contract(addresses.vault, VAULT_ABI, signer);
515
- const tx = await vault["deposit(address[],uint256[],address,uint256)"](tokens, amounts, receiver, minShares);
516
- const receipt = await tx.wait();
517
- let shares = 0n;
518
- for (const log of receipt.logs) {
519
- try {
520
- const parsed = vault.interface.parseLog({
521
- topics: log.topics,
522
- data: log.data
523
- });
524
- if (parsed && parsed.name === "Deposit") {
525
- shares = parsed.args[4];
526
- break;
527
- }
528
- } catch {
529
- }
530
- }
531
- return { receipt, shares };
532
- }
533
- var depositCrossChainOracleOn = depositSimple;
534
- async function depositAsync(signer, addresses, assets, receiver, lzFee, extraOptions = "0x") {
535
- const provider = signer.provider;
536
- const escrow = addresses.escrow ?? await new ethers.Contract(addresses.vault, ["function getEscrow() view returns (address)"], provider).getEscrow();
537
- if (escrow === ethers.ZeroAddress) throw new EscrowNotConfiguredError(addresses.vault);
538
- await validateWalletChain(signer, addresses.hubChainId);
539
- await preflightAsync(provider, addresses.vault);
540
- const vault = new ethers.Contract(addresses.vault, VAULT_ABI, signer);
541
- const underlying = await vault.asset();
542
- await ensureAllowance2(signer, underlying, escrow, assets);
793
+ async function depositFromSpoke(signer, spokeOFT, composer, hubEid, spokeEid, amount, receiver, lzFee, minMsgValue = 0n, minSharesOut = 0n, minAmountLD, extraOptions = "0x") {
794
+ await ensureAllowance2(signer, spokeOFT, spokeOFT, amount);
795
+ const oft = new ethers.Contract(spokeOFT, OFT_ABI, signer);
796
+ const refundAddress = await signer.getAddress();
797
+ const receiverBytes32 = ethers.zeroPadValue(receiver, 32);
798
+ const composerBytes32 = ethers.zeroPadValue(composer, 32);
799
+ const hopSendParam = {
800
+ dstEid: spokeEid,
801
+ to: receiverBytes32,
802
+ amountLD: 0n,
803
+ minAmountLD: minSharesOut,
804
+ extraOptions: "0x",
805
+ composeMsg: "0x",
806
+ oftCmd: "0x"
807
+ };
543
808
  const coder = ethers.AbiCoder.defaultAbiCoder();
544
- const actionCallData = coder.encode(
545
- ["uint256", "address"],
546
- [assets, receiver]
809
+ const composeMsg = coder.encode(
810
+ [
811
+ "tuple(uint32 dstEid, bytes32 to, uint256 amountLD, uint256 minAmountLD, bytes extraOptions, bytes composeMsg, bytes oftCmd)",
812
+ "uint256"
813
+ ],
814
+ [hopSendParam, minMsgValue]
547
815
  );
548
- const bridge = new ethers.Contract(addresses.vault, BRIDGE_ABI, signer);
549
- const guid = await bridge.initVaultActionRequest.staticCall(
550
- ActionType.DEPOSIT,
551
- actionCallData,
552
- 0,
553
- extraOptions,
554
- { value: lzFee }
555
- );
556
- const tx = await bridge.initVaultActionRequest(
557
- ActionType.DEPOSIT,
558
- actionCallData,
559
- 0,
560
- // amountLimit = 0 for deposits (minAmountOut handled by cross-chain manager)
561
- extraOptions,
562
- { value: lzFee }
563
- );
564
- const receipt = await tx.wait();
565
- return { receipt, guid };
566
- }
567
- async function mintAsync(signer, addresses, shares, maxAssets, receiver, lzFee, extraOptions = "0x") {
568
- const provider = signer.provider;
569
- const escrow = addresses.escrow ?? await new ethers.Contract(addresses.vault, ["function getEscrow() view returns (address)"], provider).getEscrow();
570
- if (escrow === ethers.ZeroAddress) throw new EscrowNotConfiguredError(addresses.vault);
571
- await validateWalletChain(signer, addresses.hubChainId);
572
- await preflightAsync(provider, addresses.vault);
573
- const vault = new ethers.Contract(addresses.vault, VAULT_ABI, signer);
574
- const underlying = await vault.asset();
575
- await ensureAllowance2(signer, underlying, escrow, maxAssets);
576
- const coder = ethers.AbiCoder.defaultAbiCoder();
577
- const actionCallData = coder.encode(
578
- ["uint256", "address"],
579
- [shares, receiver]
580
- );
581
- const bridge = new ethers.Contract(addresses.vault, BRIDGE_ABI, signer);
582
- const guid = await bridge.initVaultActionRequest.staticCall(
583
- ActionType.MINT,
584
- actionCallData,
585
- maxAssets,
586
- extraOptions,
587
- { value: lzFee }
588
- );
589
- const tx = await bridge.initVaultActionRequest(
590
- ActionType.MINT,
591
- actionCallData,
592
- maxAssets,
593
- extraOptions,
594
- { value: lzFee }
595
- );
596
- const receipt = await tx.wait();
597
- return { receipt, guid };
598
- }
599
- async function smartDeposit(signer, provider, addresses, assets, receiver, extraOptions = "0x") {
600
- const vault = addresses.vault;
601
- const status = await getVaultStatus(provider, vault);
602
- if (status.mode === "paused") {
603
- throw new VaultPausedError(vault);
604
- }
605
- if (status.mode === "full") {
606
- throw new CapacityFullError(vault);
607
- }
608
- if (status.recommendedDepositFlow === "depositAsync") {
609
- const lzFee = await quoteLzFee(provider, vault, extraOptions);
610
- return depositAsync(signer, addresses, assets, receiver, lzFee, extraOptions);
611
- }
612
- return depositSimple(signer, addresses, assets, receiver);
613
- }
614
- var LZ_ENDPOINT = "0x1a44076050125825900e736c501f859c50fe728c";
615
- var EMPTY_HASH = "0x0000000000000000000000000000000000000000000000000000000000000000";
616
- var RECEIVED_HASH = "0x0000000000000000000000000000000000000000000000000000000000000001";
617
- async function ensureAllowance3(signer, token, spender, amount) {
618
- const owner = await signer.getAddress();
619
- const erc20 = new ethers.Contract(token, ERC20_ABI, signer);
620
- const current = await erc20.allowance(owner, spender);
621
- if (current < amount) {
622
- const tx = await erc20.approve(spender, amount);
623
- await tx.wait();
624
- }
625
- }
626
- async function depositFromSpoke(signer, spokeOFT, composer, hubEid, spokeEid, amount, receiver, lzFee, minMsgValue = 0n, minSharesOut = 0n, minAmountLD, extraOptions = "0x") {
627
- await ensureAllowance3(signer, spokeOFT, spokeOFT, amount);
628
- const oft = new ethers.Contract(spokeOFT, OFT_ABI, signer);
629
- const refundAddress = await signer.getAddress();
630
- const receiverBytes32 = ethers.zeroPadValue(receiver, 32);
631
- const composerBytes32 = ethers.zeroPadValue(composer, 32);
632
- const hopSendParam = {
633
- dstEid: spokeEid,
634
- to: receiverBytes32,
635
- amountLD: 0n,
636
- minAmountLD: minSharesOut,
637
- extraOptions: "0x",
638
- composeMsg: "0x",
639
- oftCmd: "0x"
640
- };
641
- const coder = ethers.AbiCoder.defaultAbiCoder();
642
- const composeMsg = coder.encode(
643
- [
644
- "tuple(uint32 dstEid, bytes32 to, uint256 amountLD, uint256 minAmountLD, bytes extraOptions, bytes composeMsg, bytes oftCmd)",
645
- "uint256"
646
- ],
647
- [hopSendParam, minMsgValue]
648
- );
649
- const sendParam = {
650
- dstEid: hubEid,
651
- to: composerBytes32,
652
- amountLD: amount,
653
- minAmountLD: minAmountLD ?? amount,
816
+ const sendParam = {
817
+ dstEid: hubEid,
818
+ to: composerBytes32,
819
+ amountLD: amount,
820
+ minAmountLD: minAmountLD ?? amount,
654
821
  extraOptions,
655
822
  composeMsg,
656
823
  oftCmd: "0x"
@@ -691,68 +858,621 @@ async function quoteDepositFromSpokeFee(provider, spokeOFT, composer, hubEid, sp
691
858
  minMsgValue
692
859
  ]
693
860
  );
694
- const sendParam = {
695
- dstEid: hubEid,
696
- to: composerBytes32,
697
- amountLD: amount,
698
- minAmountLD: minAmountLD ?? amount,
861
+ const sendParam = {
862
+ dstEid: hubEid,
863
+ to: composerBytes32,
864
+ amountLD: amount,
865
+ minAmountLD: minAmountLD ?? amount,
866
+ extraOptions,
867
+ composeMsg: composeMsgBytes,
868
+ oftCmd: "0x"
869
+ };
870
+ const oft = new ethers.Contract(spokeOFT, OFT_ABI, provider);
871
+ const fee = await oft.quoteSend(sendParam, false);
872
+ return fee.nativeFee;
873
+ }
874
+ async function quoteComposeFee(provider, vault, spokeEid, receiver) {
875
+ try {
876
+ const vaultContract = new ethers.Contract(vault, BRIDGE_ABI, provider);
877
+ const readFee = await vaultContract.quoteAccountingFee("0x");
878
+ let shareSendFee = 0n;
879
+ if (spokeEid && receiver) {
880
+ try {
881
+ const COMPOSER_ABI = ["function SHARE_OFT() view returns (address)"];
882
+ const FACTORY_ABI2 = ["function vaultComposer(address _vault) view returns (address)"];
883
+ const factory = new ethers.Contract("0x7bDB8B17604b03125eFAED33cA0c55FBf856BB0C", FACTORY_ABI2, provider);
884
+ const composerAddr = await factory.vaultComposer(vault);
885
+ const composer = new ethers.Contract(composerAddr, COMPOSER_ABI, provider);
886
+ const shareOftAddr = await composer.SHARE_OFT();
887
+ const shareOft = new ethers.Contract(shareOftAddr, OFT_ABI, provider);
888
+ const receiverBytes32 = ethers.zeroPadValue(receiver, 32);
889
+ const fee = await shareOft.quoteSend({
890
+ dstEid: spokeEid,
891
+ to: receiverBytes32,
892
+ amountLD: 1000000n,
893
+ minAmountLD: 0n,
894
+ extraOptions: "0x",
895
+ composeMsg: "0x",
896
+ oftCmd: "0x"
897
+ }, false);
898
+ shareSendFee = fee.nativeFee;
899
+ } catch {
900
+ }
901
+ }
902
+ return (readFee + shareSendFee) * 110n / 100n;
903
+ } catch {
904
+ return 500000000000000n;
905
+ }
906
+ }
907
+ async function executeCompose(signer, from, to, guid, message, fee, index = 0) {
908
+ const endpoint = new ethers.Contract(LZ_ENDPOINT, LZ_ENDPOINT_ABI, signer);
909
+ const hash = await endpoint.composeQueue(from, to, guid, index);
910
+ if (hash === EMPTY_HASH) {
911
+ throw new Error("Compose not found in queue (hash = 0). Never sent or wrong parameters.");
912
+ }
913
+ if (hash === RECEIVED_HASH) {
914
+ throw new Error("Compose already delivered \u2014 no action needed.");
915
+ }
916
+ const tx = await endpoint.lzCompose(from, to, guid, index, message, "0x", {
917
+ value: fee,
918
+ gasLimit: 5000000n
919
+ });
920
+ const receipt = await tx.wait();
921
+ return { receipt };
922
+ }
923
+ async function waitForCompose(hubProvider, composeData, receiver, pollIntervalMs = 2e4, timeoutMs = 18e5) {
924
+ const deadline = Date.now() + timeoutMs;
925
+ const composer = composeData.to.toLowerCase();
926
+ const endpoint = composeData.endpoint;
927
+ const receiverNeedle = receiver.replace(/^0x/, "").toLowerCase();
928
+ const startBlock = composeData.hubBlockStart;
929
+ const hubChainId = composeData.hubChainId;
930
+ const candidateAddresses = [];
931
+ for (const chainMap of Object.values(OFT_ROUTES)) {
932
+ const entry = chainMap[hubChainId];
933
+ if (entry) candidateAddresses.push(entry.oft.toLowerCase());
934
+ }
935
+ const stargateChecks = await Promise.all(
936
+ candidateAddresses.map(async (addr) => ({
937
+ addr,
938
+ isSg: await detectStargateOft(hubProvider, addr)
939
+ }))
940
+ );
941
+ const knownFromAddresses = stargateChecks.filter((c) => c.isSg).map((c) => c.addr);
942
+ const endpointContract = new ethers.Contract(endpoint, LZ_ENDPOINT_ABI, hubProvider);
943
+ const COMPOSE_SENT_TOPIC = "0x0c68e6a0b0fb0f33c52455a8da89b21fc640a3dd4a1b21d9bfcc8aeee4a43e84";
944
+ let attempt = 0;
945
+ let scannedUpTo = startBlock - 1n;
946
+ while (Date.now() < deadline) {
947
+ attempt++;
948
+ const elapsed = Math.round((Date.now() - (deadline - timeoutMs)) / 1e3);
949
+ try {
950
+ const currentBlock = BigInt(await hubProvider.getBlockNumber());
951
+ const chunkSize = 500n;
952
+ let from = scannedUpTo + 1n;
953
+ while (from <= currentBlock) {
954
+ const chunkEnd = from + chunkSize > currentBlock ? currentBlock : from + chunkSize;
955
+ try {
956
+ const logs = await hubProvider.getLogs({
957
+ address: endpoint,
958
+ topics: [COMPOSE_SENT_TOPIC],
959
+ fromBlock: `0x${from.toString(16)}`,
960
+ toBlock: `0x${chunkEnd.toString(16)}`
961
+ });
962
+ for (const log of logs) {
963
+ try {
964
+ const coder = ethers.AbiCoder.defaultAbiCoder();
965
+ const decoded = coder.decode(
966
+ ["address", "address", "bytes32", "uint16", "bytes"],
967
+ log.data
968
+ );
969
+ const logFrom = decoded[0].toLowerCase();
970
+ const logTo = decoded[1].toLowerCase();
971
+ const logGuid = decoded[2];
972
+ const logIndex = Number(decoded[3]);
973
+ const logMessage = decoded[4];
974
+ if (logTo === composer && logMessage.toLowerCase().includes(receiverNeedle)) {
975
+ const hash = await endpointContract.composeQueue(
976
+ logFrom,
977
+ composer,
978
+ logGuid,
979
+ logIndex
980
+ );
981
+ if (hash !== EMPTY_HASH && hash !== RECEIVED_HASH) {
982
+ console.log(`[${elapsed}s] Poll #${attempt} \u2014 compose found! (block ${log.blockNumber})`);
983
+ return {
984
+ ...composeData,
985
+ from: decoded[0],
986
+ to: composeData.to,
987
+ guid: logGuid,
988
+ index: logIndex,
989
+ message: logMessage
990
+ };
991
+ }
992
+ }
993
+ } catch {
994
+ }
995
+ }
996
+ } catch {
997
+ break;
998
+ }
999
+ from = chunkEnd + 1n;
1000
+ }
1001
+ scannedUpTo = currentBlock;
1002
+ } catch {
1003
+ }
1004
+ let guidMatchFound = false;
1005
+ for (const fromAddr of knownFromAddresses) {
1006
+ try {
1007
+ const hash = await endpointContract.composeQueue(
1008
+ fromAddr,
1009
+ composer,
1010
+ composeData.guid,
1011
+ 0
1012
+ );
1013
+ if (hash !== EMPTY_HASH && hash !== RECEIVED_HASH) {
1014
+ console.log(`[${elapsed}s] Poll #${attempt} \u2014 composeQueue confirms pending (GUID match), re-scanning for message...`);
1015
+ scannedUpTo = startBlock - 1n;
1016
+ guidMatchFound = true;
1017
+ }
1018
+ } catch {
1019
+ }
1020
+ }
1021
+ if (!guidMatchFound) {
1022
+ console.log(`[${elapsed}s] Poll #${attempt} \u2014 compose not found yet, waiting ${pollIntervalMs / 1e3}s...`);
1023
+ }
1024
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
1025
+ }
1026
+ throw new Error(
1027
+ `Timeout waiting for compose after ${timeoutMs / 6e4} min. Check LayerZero scan for composer ${composeData.to}.`
1028
+ );
1029
+ }
1030
+
1031
+ // src/ethers/preflight.ts
1032
+ async function preflightAsync(provider, vault, escrow) {
1033
+ const config = new ethers.Contract(vault, CONFIG_ABI, provider);
1034
+ const bridge = new ethers.Contract(vault, BRIDGE_ABI, provider);
1035
+ const [ccManager, registeredEscrow, isHub, oraclesEnabled, isPaused] = await Promise.all([
1036
+ config.getCrossChainAccountingManager(),
1037
+ config.getEscrow(),
1038
+ config.isHub(),
1039
+ bridge.oraclesCrossChainAccounting(),
1040
+ config.paused()
1041
+ ]);
1042
+ if (ccManager === ethers.ZeroAddress) {
1043
+ throw new Error(
1044
+ `[MoreVaults] CCManager not configured on vault ${vault}. Call setCrossChainAccountingManager(ccManagerAddress) as vault owner first.`
1045
+ );
1046
+ }
1047
+ if (registeredEscrow === ethers.ZeroAddress) {
1048
+ throw new Error(
1049
+ `[MoreVaults] Escrow not configured for vault ${vault}. The registry must have an escrow set for this vault.`
1050
+ );
1051
+ }
1052
+ if (!isHub) {
1053
+ throw new Error(
1054
+ `[MoreVaults] Vault ${vault} is not a hub vault. Async flows (D4/D5/R5) only work on hub vaults.`
1055
+ );
1056
+ }
1057
+ if (oraclesEnabled) {
1058
+ throw new Error(
1059
+ `[MoreVaults] Vault ${vault} has oracle-based cross-chain accounting enabled. Use depositSimple/depositCrossChainOracleOn instead of async flows.`
1060
+ );
1061
+ }
1062
+ if (isPaused) {
1063
+ throw new Error(
1064
+ `[MoreVaults] Vault ${vault} is paused. Cannot perform any actions.`
1065
+ );
1066
+ }
1067
+ }
1068
+ async function preflightRedeemLiquidity(provider, vault, shares) {
1069
+ const config = new ethers.Contract(vault, CONFIG_ABI, provider);
1070
+ const bridge = new ethers.Contract(vault, BRIDGE_ABI, provider);
1071
+ const [isHub, oraclesEnabled] = await Promise.all([
1072
+ config.isHub(),
1073
+ bridge.oraclesCrossChainAccounting()
1074
+ ]);
1075
+ if (!isHub || oraclesEnabled) return;
1076
+ const vaultContract = new ethers.Contract(vault, VAULT_ABI, provider);
1077
+ const underlying = await vaultContract.asset();
1078
+ const underlyingContract = new ethers.Contract(underlying, ERC20_ABI, provider);
1079
+ const [hubLiquid, assetsNeeded] = await Promise.all([
1080
+ underlyingContract.balanceOf(vault),
1081
+ vaultContract.convertToAssets(shares)
1082
+ ]);
1083
+ if (hubLiquid < assetsNeeded) {
1084
+ throw new InsufficientLiquidityError(vault, hubLiquid, assetsNeeded);
1085
+ }
1086
+ }
1087
+ async function preflightSync(provider, vault) {
1088
+ const config = new ethers.Contract(vault, CONFIG_ABI, provider);
1089
+ const [isPaused, depositCapResult] = await Promise.all([
1090
+ config.paused(),
1091
+ config.maxDeposit(ethers.ZeroAddress).catch(() => null)
1092
+ ]);
1093
+ if (isPaused) {
1094
+ throw new Error(
1095
+ `[MoreVaults] Vault ${vault} is paused. Cannot perform any actions.`
1096
+ );
1097
+ }
1098
+ if (depositCapResult !== null && depositCapResult === 0n) {
1099
+ throw new Error(
1100
+ `[MoreVaults] Vault ${vault} has reached deposit capacity. No more deposits accepted.`
1101
+ );
1102
+ }
1103
+ }
1104
+ async function preflightSpokeDeposit(spokeProvider, vault, spokeOFT, hubEid, spokeEid, amount, userAddress, lzFee) {
1105
+ const OFT_TOKEN_ABI = ["function token() view returns (address)"];
1106
+ const oftContract = new ethers.Contract(spokeOFT, OFT_TOKEN_ABI, spokeProvider);
1107
+ const spokeToken = await oftContract.token();
1108
+ const tokenContract = new ethers.Contract(spokeToken, ERC20_ABI, spokeProvider);
1109
+ const [spokeTokenBalance, spokeNativeBalance] = await Promise.all([
1110
+ tokenContract.balanceOf(userAddress),
1111
+ spokeProvider.getBalance(userAddress)
1112
+ ]);
1113
+ if (spokeTokenBalance < amount) {
1114
+ throw new Error(
1115
+ `[MoreVaults] Insufficient token balance on spoke chain.
1116
+ Need: ${amount}
1117
+ Have: ${spokeTokenBalance}
1118
+ Token: ${spokeToken}`
1119
+ );
1120
+ }
1121
+ const gasBuffer = 500000000000000n;
1122
+ if (spokeNativeBalance < lzFee + gasBuffer) {
1123
+ throw new Error(
1124
+ `[MoreVaults] Insufficient native gas on spoke chain for TX1.
1125
+ Need: ~${lzFee + gasBuffer} wei (LZ fee + gas)
1126
+ Have: ${spokeNativeBalance} wei`
1127
+ );
1128
+ }
1129
+ const isStargate = await detectStargateOft(spokeProvider, spokeOFT);
1130
+ let hubNativeBalance = 0n;
1131
+ let estimatedComposeFee = 0n;
1132
+ if (isStargate) {
1133
+ const hubChainId = EID_TO_CHAIN_ID[hubEid];
1134
+ const hubProvider = createChainProvider(hubChainId);
1135
+ if (hubProvider) {
1136
+ [hubNativeBalance, estimatedComposeFee] = await Promise.all([
1137
+ hubProvider.getBalance(userAddress),
1138
+ quoteComposeFee(hubProvider, vault, spokeEid, userAddress)
1139
+ ]);
1140
+ const hubGasBuffer = 300000000000000n;
1141
+ const totalNeeded = estimatedComposeFee + hubGasBuffer;
1142
+ if (hubNativeBalance < totalNeeded) {
1143
+ throw new Error(
1144
+ `[MoreVaults] Insufficient ETH on hub chain for TX2 (compose retry).
1145
+ This is a Stargate 2-TX flow \u2014 TX2 requires ETH on the hub chain.
1146
+ Need: ~${totalNeeded} wei (compose fee ${estimatedComposeFee} + gas)
1147
+ Have: ${hubNativeBalance} wei
1148
+ Short: ${totalNeeded - hubNativeBalance} wei
1149
+ Send ETH to ${userAddress} on chainId ${hubChainId} before depositing.`
1150
+ );
1151
+ }
1152
+ }
1153
+ }
1154
+ return {
1155
+ spokeTokenBalance,
1156
+ spokeNativeBalance,
1157
+ hubNativeBalance,
1158
+ estimatedComposeFee,
1159
+ isStargate
1160
+ };
1161
+ }
1162
+ async function preflightSpokeRedeem(route, shares, userAddress, shareBridgeFee) {
1163
+ const spokeProvider = createChainProvider(route.spokeChainId);
1164
+ const hubProvider = createChainProvider(route.hubChainId);
1165
+ if (!spokeProvider) throw new Error(`No public RPC for spoke chainId ${route.spokeChainId}`);
1166
+ if (!hubProvider) throw new Error(`No public RPC for hub chainId ${route.hubChainId}`);
1167
+ const spokeShareContract = new ethers.Contract(route.spokeShareOft, ERC20_ABI, spokeProvider);
1168
+ const [sharesOnSpoke, spokeNativeBalance, hubNativeBalance] = await Promise.all([
1169
+ spokeShareContract.balanceOf(userAddress),
1170
+ spokeProvider.getBalance(userAddress),
1171
+ hubProvider.getBalance(userAddress)
1172
+ ]);
1173
+ if (sharesOnSpoke < shares) {
1174
+ throw new Error(
1175
+ `[MoreVaults] Insufficient shares on spoke chain.
1176
+ Need: ${shares}
1177
+ Have: ${sharesOnSpoke}
1178
+ Token: ${route.spokeShareOft}`
1179
+ );
1180
+ }
1181
+ const spokeGasBuffer = 500000000000000n;
1182
+ if (spokeNativeBalance < shareBridgeFee + spokeGasBuffer) {
1183
+ throw new Error(
1184
+ `[MoreVaults] Insufficient native gas on spoke for TX1 (share bridge).
1185
+ Need: ~${shareBridgeFee + spokeGasBuffer} wei (LZ fee + gas)
1186
+ Have: ${spokeNativeBalance} wei`
1187
+ );
1188
+ }
1189
+ let estimatedAssetBridgeFee = 0n;
1190
+ try {
1191
+ const toBytes32 = `0x${userAddress.replace(/^0x/, "").padStart(64, "0")}`;
1192
+ const dummyAmount = 1000000n;
1193
+ const hubOft = new ethers.Contract(route.hubAssetOft, OFT_ABI, hubProvider);
1194
+ const feeResult = await hubOft.quoteSend({
1195
+ dstEid: route.spokeEid,
1196
+ to: toBytes32,
1197
+ amountLD: dummyAmount,
1198
+ minAmountLD: dummyAmount * 99n / 100n,
1199
+ extraOptions: "0x",
1200
+ composeMsg: "0x",
1201
+ oftCmd: route.isStargate ? "0x01" : "0x"
1202
+ }, false);
1203
+ estimatedAssetBridgeFee = feeResult.nativeFee;
1204
+ } catch {
1205
+ estimatedAssetBridgeFee = 300000000000000n;
1206
+ }
1207
+ const hubGasBuffer = 300000000000000n;
1208
+ const totalHubNeeded = estimatedAssetBridgeFee + hubGasBuffer;
1209
+ if (hubNativeBalance < totalHubNeeded) {
1210
+ throw new Error(
1211
+ `[MoreVaults] Insufficient ETH on hub chain for TX2 (redeem) + TX3 (asset bridge).
1212
+ Need: ~${totalHubNeeded} wei (LZ fee ${estimatedAssetBridgeFee} + gas)
1213
+ Have: ${hubNativeBalance} wei
1214
+ Short: ${totalHubNeeded - hubNativeBalance} wei
1215
+ Send ETH to ${userAddress} on chainId ${route.hubChainId} before redeeming.`
1216
+ );
1217
+ }
1218
+ return {
1219
+ sharesOnSpoke,
1220
+ spokeNativeBalance,
1221
+ hubNativeBalance,
1222
+ estimatedAssetBridgeFee,
1223
+ estimatedAssetsOut: 0n,
1224
+ hubLiquidBalance: 0n
1225
+ };
1226
+ }
1227
+
1228
+ // src/ethers/chainValidation.ts
1229
+ async function validateWalletChain(signer, hubChainId) {
1230
+ if (!hubChainId) return;
1231
+ const network = await signer.provider?.getNetwork();
1232
+ if (!network) return;
1233
+ const current = Number(network.chainId);
1234
+ if (current !== hubChainId) {
1235
+ throw new WrongChainError(current, hubChainId);
1236
+ }
1237
+ }
1238
+
1239
+ // src/ethers/depositFlows.ts
1240
+ async function ensureAllowance3(signer, token, spender, amount) {
1241
+ const owner = await signer.getAddress();
1242
+ const erc20 = new ethers.Contract(token, ERC20_ABI, signer);
1243
+ const current = await erc20.allowance(owner, spender);
1244
+ if (current < amount) {
1245
+ const tx = await erc20.approve(spender, amount);
1246
+ await tx.wait();
1247
+ }
1248
+ }
1249
+ async function depositSimple(signer, addresses, assets, receiver) {
1250
+ const provider = signer.provider;
1251
+ await validateWalletChain(signer, addresses.hubChainId);
1252
+ await preflightSync(provider, addresses.vault);
1253
+ const vault = new ethers.Contract(addresses.vault, VAULT_ABI, signer);
1254
+ const underlying = await vault.asset();
1255
+ await ensureAllowance3(signer, underlying, addresses.vault, assets);
1256
+ const tx = await vault["deposit(uint256,address)"](assets, receiver);
1257
+ const receipt = await tx.wait();
1258
+ let shares = 0n;
1259
+ for (const log of receipt.logs) {
1260
+ try {
1261
+ const parsed = vault.interface.parseLog({
1262
+ topics: log.topics,
1263
+ data: log.data
1264
+ });
1265
+ if (parsed && parsed.name === "Transfer" && parsed.args[0] === "0x0000000000000000000000000000000000000000") {
1266
+ shares = parsed.args[2];
1267
+ break;
1268
+ }
1269
+ } catch {
1270
+ }
1271
+ }
1272
+ return { receipt, shares };
1273
+ }
1274
+ async function depositMultiAsset(signer, addresses, tokens, amounts, receiver, minShares) {
1275
+ await validateWalletChain(signer, addresses.hubChainId);
1276
+ for (let i = 0; i < tokens.length; i++) {
1277
+ await ensureAllowance3(signer, tokens[i], addresses.vault, amounts[i]);
1278
+ }
1279
+ const vault = new ethers.Contract(addresses.vault, VAULT_ABI, signer);
1280
+ const tx = await vault["deposit(address[],uint256[],address,uint256)"](tokens, amounts, receiver, minShares);
1281
+ const receipt = await tx.wait();
1282
+ let shares = 0n;
1283
+ for (const log of receipt.logs) {
1284
+ try {
1285
+ const parsed = vault.interface.parseLog({
1286
+ topics: log.topics,
1287
+ data: log.data
1288
+ });
1289
+ if (parsed && parsed.name === "Deposit") {
1290
+ shares = parsed.args[4];
1291
+ break;
1292
+ }
1293
+ } catch {
1294
+ }
1295
+ }
1296
+ return { receipt, shares };
1297
+ }
1298
+ var depositCrossChainOracleOn = depositSimple;
1299
+ async function depositAsync(signer, addresses, assets, receiver, lzFee, extraOptions = "0x") {
1300
+ const provider = signer.provider;
1301
+ const escrow = addresses.escrow ?? await new ethers.Contract(addresses.vault, ["function getEscrow() view returns (address)"], provider).getEscrow();
1302
+ if (escrow === ethers.ZeroAddress) throw new EscrowNotConfiguredError(addresses.vault);
1303
+ await validateWalletChain(signer, addresses.hubChainId);
1304
+ await preflightAsync(provider, addresses.vault);
1305
+ const vault = new ethers.Contract(addresses.vault, VAULT_ABI, signer);
1306
+ const underlying = await vault.asset();
1307
+ await ensureAllowance3(signer, underlying, escrow, assets);
1308
+ const coder = ethers.AbiCoder.defaultAbiCoder();
1309
+ const actionCallData = coder.encode(
1310
+ ["uint256", "address"],
1311
+ [assets, receiver]
1312
+ );
1313
+ const bridge = new ethers.Contract(addresses.vault, BRIDGE_ABI, signer);
1314
+ const guid = await bridge.initVaultActionRequest.staticCall(
1315
+ ActionType.DEPOSIT,
1316
+ actionCallData,
1317
+ 0,
1318
+ extraOptions,
1319
+ { value: lzFee }
1320
+ );
1321
+ const tx = await bridge.initVaultActionRequest(
1322
+ ActionType.DEPOSIT,
1323
+ actionCallData,
1324
+ 0,
1325
+ // amountLimit = 0 for deposits (minAmountOut handled by cross-chain manager)
1326
+ extraOptions,
1327
+ { value: lzFee }
1328
+ );
1329
+ const receipt = await tx.wait();
1330
+ return { receipt, guid };
1331
+ }
1332
+ async function mintAsync(signer, addresses, shares, maxAssets, receiver, lzFee, extraOptions = "0x") {
1333
+ const provider = signer.provider;
1334
+ const escrow = addresses.escrow ?? await new ethers.Contract(addresses.vault, ["function getEscrow() view returns (address)"], provider).getEscrow();
1335
+ if (escrow === ethers.ZeroAddress) throw new EscrowNotConfiguredError(addresses.vault);
1336
+ await validateWalletChain(signer, addresses.hubChainId);
1337
+ await preflightAsync(provider, addresses.vault);
1338
+ const vault = new ethers.Contract(addresses.vault, VAULT_ABI, signer);
1339
+ const underlying = await vault.asset();
1340
+ await ensureAllowance3(signer, underlying, escrow, maxAssets);
1341
+ const coder = ethers.AbiCoder.defaultAbiCoder();
1342
+ const actionCallData = coder.encode(
1343
+ ["uint256", "address"],
1344
+ [shares, receiver]
1345
+ );
1346
+ const bridge = new ethers.Contract(addresses.vault, BRIDGE_ABI, signer);
1347
+ const guid = await bridge.initVaultActionRequest.staticCall(
1348
+ ActionType.MINT,
1349
+ actionCallData,
1350
+ maxAssets,
1351
+ extraOptions,
1352
+ { value: lzFee }
1353
+ );
1354
+ const tx = await bridge.initVaultActionRequest(
1355
+ ActionType.MINT,
1356
+ actionCallData,
1357
+ maxAssets,
699
1358
  extraOptions,
700
- composeMsg: composeMsgBytes,
701
- oftCmd: "0x"
702
- };
703
- const oft = new ethers.Contract(spokeOFT, OFT_ABI, provider);
704
- const fee = await oft.quoteSend(sendParam, false);
705
- return fee.nativeFee;
1359
+ { value: lzFee }
1360
+ );
1361
+ const receipt = await tx.wait();
1362
+ return { receipt, guid };
706
1363
  }
707
- async function quoteComposeFee(provider, vault, spokeEid, receiver) {
708
- try {
709
- const vaultContract = new ethers.Contract(vault, BRIDGE_ABI, provider);
710
- const readFee = await vaultContract.quoteAccountingFee("0x");
711
- let shareSendFee = 0n;
712
- if (spokeEid && receiver) {
713
- try {
714
- const COMPOSER_ABI = ["function SHARE_OFT() view returns (address)"];
715
- const FACTORY_ABI = ["function vaultComposer(address _vault) view returns (address)"];
716
- const factory = new ethers.Contract("0x7bDB8B17604b03125eFAED33cA0c55FBf856BB0C", FACTORY_ABI, provider);
717
- const composerAddr = await factory.vaultComposer(vault);
718
- const composer = new ethers.Contract(composerAddr, COMPOSER_ABI, provider);
719
- const shareOftAddr = await composer.SHARE_OFT();
720
- const shareOft = new ethers.Contract(shareOftAddr, OFT_ABI, provider);
721
- const receiverBytes32 = ethers.zeroPadValue(receiver, 32);
722
- const fee = await shareOft.quoteSend({
723
- dstEid: spokeEid,
724
- to: receiverBytes32,
725
- amountLD: 1000000n,
726
- minAmountLD: 0n,
727
- extraOptions: "0x",
728
- composeMsg: "0x",
729
- oftCmd: "0x"
730
- }, false);
731
- shareSendFee = fee.nativeFee;
732
- } catch {
733
- }
734
- }
735
- return (readFee + shareSendFee) * 110n / 100n;
736
- } catch {
737
- return 500000000000000n;
1364
+ async function smartDeposit(signer, provider, addresses, assets, receiver, extraOptions = "0x") {
1365
+ const vault = addresses.vault;
1366
+ const status = await getVaultStatus(provider, vault);
1367
+ if (status.mode === "paused") {
1368
+ throw new VaultPausedError(vault);
1369
+ }
1370
+ if (status.mode === "full") {
1371
+ throw new CapacityFullError(vault);
1372
+ }
1373
+ if (status.recommendedDepositFlow === "depositAsync") {
1374
+ const lzFee = await quoteLzFee(provider, vault, extraOptions);
1375
+ return depositAsync(signer, addresses, assets, receiver, lzFee, extraOptions);
738
1376
  }
1377
+ return depositSimple(signer, addresses, assets, receiver);
739
1378
  }
740
- async function executeCompose(signer, from, to, guid, message, fee, index = 0) {
741
- const endpoint = new ethers.Contract(LZ_ENDPOINT, LZ_ENDPOINT_ABI, signer);
742
- const hash = await endpoint.composeQueue(from, to, guid, index);
743
- if (hash === EMPTY_HASH) {
744
- throw new Error("Compose not found in queue (hash = 0). Never sent or wrong parameters.");
1379
+ var OMNI_FACTORY_ADDRESS = "0x7bDB8B17604b03125eFAED33cA0c55FBf856BB0C";
1380
+ var FACTORY_ABI = [
1381
+ "function localEid() view returns (uint32)",
1382
+ "function isCrossChainVault(uint32 __eid, address _vault) view returns (bool)",
1383
+ "function hubToSpokes(uint32 __eid, address _hubVault) view returns (uint32[] eids, address[] vaults)",
1384
+ "function spokeToHub(uint32 __eid, address _spokeVault) view returns (uint32 eid, address vault)"
1385
+ ];
1386
+ var DISCOVERY_CHAIN_IDS = Object.values(CHAIN_IDS).filter(
1387
+ (id) => id !== 545
1388
+ // exclude testnet
1389
+ );
1390
+ async function getVaultTopology(provider, vault, factoryAddress = OMNI_FACTORY_ADDRESS) {
1391
+ const factory = new ethers.Contract(factoryAddress, FACTORY_ABI, provider);
1392
+ const localEid = Number(await factory.localEid());
1393
+ const isHub = await factory.isCrossChainVault(localEid, vault);
1394
+ if (isHub) {
1395
+ const result = await factory.hubToSpokes(localEid, vault);
1396
+ const spokeEids = result[0];
1397
+ const localChainId2 = EID_TO_CHAIN_ID[localEid] ?? 0;
1398
+ const spokeChainIds = spokeEids.map((eid) => EID_TO_CHAIN_ID[Number(eid)]).filter((id) => id !== void 0);
1399
+ return { role: "hub", hubChainId: localChainId2, spokeChainIds };
745
1400
  }
746
- if (hash === RECEIVED_HASH) {
747
- throw new Error("Compose already delivered \u2014 no action needed.");
1401
+ const spokeResult = await factory.spokeToHub(localEid, vault);
1402
+ const hubEid = Number(spokeResult[0]);
1403
+ const hubVault = spokeResult[1];
1404
+ if (hubEid !== 0 && hubVault !== "0x0000000000000000000000000000000000000000") {
1405
+ const hubChainId = EID_TO_CHAIN_ID[hubEid] ?? 0;
1406
+ const spokeChainIds = [];
1407
+ const localChainId2 = EID_TO_CHAIN_ID[localEid];
1408
+ if (localChainId2 !== void 0) spokeChainIds.push(localChainId2);
1409
+ return { role: "spoke", hubChainId, spokeChainIds };
748
1410
  }
749
- const tx = await endpoint.lzCompose(from, to, guid, index, message, "0x", {
750
- value: fee,
751
- gasLimit: 5000000n
752
- });
753
- const receipt = await tx.wait();
754
- return { receipt };
1411
+ const localChainId = EID_TO_CHAIN_ID[localEid] ?? 0;
1412
+ return { role: "local", hubChainId: localChainId, spokeChainIds: [] };
1413
+ }
1414
+ async function getFullVaultTopology(hubChainProvider, vault, factoryAddress = OMNI_FACTORY_ADDRESS) {
1415
+ const topo = await getVaultTopology(hubChainProvider, vault, factoryAddress);
1416
+ if (topo.role !== "hub") {
1417
+ throw new Error(
1418
+ `getFullVaultTopology: provider must be connected to the hub chain (${topo.hubChainId}), but got role="${topo.role}". Connect to chainId ${topo.hubChainId} instead.`
1419
+ );
1420
+ }
1421
+ return topo;
1422
+ }
1423
+ async function discoverVaultTopology(vault, provider, factoryAddress = OMNI_FACTORY_ADDRESS) {
1424
+ let triedChainId;
1425
+ if (provider) {
1426
+ try {
1427
+ const topo = await getVaultTopology(provider, vault, factoryAddress);
1428
+ if (topo.role !== "local") {
1429
+ if (topo.role === "spoke") {
1430
+ const hubProvider = createChainProvider(topo.hubChainId);
1431
+ if (hubProvider) {
1432
+ try {
1433
+ return await getFullVaultTopology(hubProvider, vault, factoryAddress);
1434
+ } catch {
1435
+ }
1436
+ }
1437
+ }
1438
+ return topo;
1439
+ }
1440
+ const network = await provider.getNetwork();
1441
+ triedChainId = Number(network.chainId);
1442
+ } catch {
1443
+ }
1444
+ }
1445
+ for (const chainId of DISCOVERY_CHAIN_IDS) {
1446
+ if (chainId === triedChainId) continue;
1447
+ const chainProvider = createChainProvider(chainId);
1448
+ if (!chainProvider) continue;
1449
+ try {
1450
+ const topo = await getVaultTopology(chainProvider, vault, factoryAddress);
1451
+ if (topo.role === "hub") return topo;
1452
+ if (topo.role === "spoke") {
1453
+ const hubProvider = createChainProvider(topo.hubChainId);
1454
+ if (hubProvider) {
1455
+ try {
1456
+ return await getFullVaultTopology(hubProvider, vault, factoryAddress);
1457
+ } catch {
1458
+ return topo;
1459
+ }
1460
+ }
1461
+ return topo;
1462
+ }
1463
+ } catch {
1464
+ }
1465
+ }
1466
+ return { role: "local", hubChainId: 0, spokeChainIds: [] };
755
1467
  }
1468
+ function isOnHubChain(currentChainId, topology) {
1469
+ return currentChainId === topology.hubChainId;
1470
+ }
1471
+ function getAllVaultChainIds(topology) {
1472
+ return [topology.hubChainId, ...topology.spokeChainIds];
1473
+ }
1474
+
1475
+ // src/ethers/redeemFlows.ts
756
1476
  async function ensureAllowance4(signer, token, spender, amount) {
757
1477
  const owner = await signer.getAddress();
758
1478
  const erc20 = new ethers.Contract(token, ERC20_ABI, signer);
@@ -886,6 +1606,83 @@ async function bridgeAssetsToSpoke(signer, assetOFT, spokeChainEid, amount, rece
886
1606
  const receipt = await tx.wait();
887
1607
  return { receipt };
888
1608
  }
1609
+ var FACTORY_COMPOSER_ABI_RF = [
1610
+ "function vaultComposer(address _vault) view returns (address)"
1611
+ ];
1612
+ var REDEEM_COMPOSER_ABI = [
1613
+ "function SHARE_OFT() view returns (address)"
1614
+ ];
1615
+ var OFT_PEERS_ABI_RF = [
1616
+ "function peers(uint32 eid) view returns (bytes32)"
1617
+ ];
1618
+ async function quoteShareBridgeFee(spokeProvider, shareOFT, hubChainEid, amountLD, receiver) {
1619
+ const toBytes32 = ethers.zeroPadValue(receiver, 32);
1620
+ const sendParam = {
1621
+ dstEid: hubChainEid,
1622
+ to: toBytes32,
1623
+ amountLD,
1624
+ minAmountLD: amountLD,
1625
+ extraOptions: "0x",
1626
+ composeMsg: "0x",
1627
+ oftCmd: "0x"
1628
+ };
1629
+ const oft = new ethers.Contract(shareOFT, OFT_ABI, spokeProvider);
1630
+ const fee = await oft.quoteSend(sendParam, false);
1631
+ return fee.nativeFee;
1632
+ }
1633
+ async function resolveRedeemAddresses(hubProvider, vault, hubChainId, spokeChainId) {
1634
+ const hubEid = CHAIN_ID_TO_EID[hubChainId];
1635
+ const spokeEid = CHAIN_ID_TO_EID[spokeChainId];
1636
+ if (!hubEid || !spokeEid) {
1637
+ throw new Error(`No LZ EID for chainId ${!hubEid ? hubChainId : spokeChainId}`);
1638
+ }
1639
+ const vaultContract = new ethers.Contract(vault, VAULT_ABI, hubProvider);
1640
+ const factory = new ethers.Contract(OMNI_FACTORY_ADDRESS, FACTORY_COMPOSER_ABI_RF, hubProvider);
1641
+ const [hubAsset, composerAddress] = await Promise.all([
1642
+ vaultContract.asset(),
1643
+ factory.vaultComposer(vault)
1644
+ ]);
1645
+ if (composerAddress === ethers.ZeroAddress) {
1646
+ throw new Error(`[MoreVaults] No composer registered for vault ${vault} on hub chain ${hubChainId}`);
1647
+ }
1648
+ const composer = new ethers.Contract(composerAddress, REDEEM_COMPOSER_ABI, hubProvider);
1649
+ const hubShareOft = await composer.SHARE_OFT();
1650
+ const hubShareOftContract = new ethers.Contract(hubShareOft, OFT_PEERS_ABI_RF, hubProvider);
1651
+ const spokeShareOftBytes32 = await hubShareOftContract.peers(spokeEid);
1652
+ const spokeShareOft = `0x${spokeShareOftBytes32.slice(-40)}`;
1653
+ let hubAssetOft = null;
1654
+ let spokeAsset = null;
1655
+ let symbol = "";
1656
+ for (const [sym, chainMap] of Object.entries(OFT_ROUTES)) {
1657
+ const hubEntry = chainMap[hubChainId];
1658
+ const spokeEntry = chainMap[spokeChainId];
1659
+ if (!hubEntry || !spokeEntry) continue;
1660
+ if (hubEntry.token.toLowerCase() === hubAsset.toLowerCase()) {
1661
+ hubAssetOft = hubEntry.oft;
1662
+ spokeAsset = spokeEntry.token;
1663
+ symbol = sym;
1664
+ break;
1665
+ }
1666
+ }
1667
+ if (!hubAssetOft || !spokeAsset) {
1668
+ throw new Error(
1669
+ `[MoreVaults] No OFT route found for vault asset ${hubAsset} between hub chain ${hubChainId} and spoke chain ${spokeChainId}`
1670
+ );
1671
+ }
1672
+ const isStargate = await detectStargateOft(hubProvider, hubAssetOft);
1673
+ return {
1674
+ hubChainId,
1675
+ spokeChainId,
1676
+ hubEid,
1677
+ spokeEid,
1678
+ hubAsset,
1679
+ spokeShareOft,
1680
+ hubAssetOft,
1681
+ spokeAsset,
1682
+ isStargate,
1683
+ symbol
1684
+ };
1685
+ }
889
1686
  var MULTICALL3_ADDRESS2 = "0xcA11bde05977b3631167028862bE2a173976CA11";
890
1687
  var MULTICALL3_ABI2 = [
891
1688
  "function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)"
@@ -955,11 +1752,11 @@ async function canDeposit(provider, vault, user) {
955
1752
  return { allowed: true, reason: "ok" };
956
1753
  }
957
1754
  async function getVaultMetadata(provider, vault) {
958
- const MULTICALL3_ADDRESS3 = "0xcA11bde05977b3631167028862bE2a173976CA11";
959
- const MULTICALL3_ABI3 = [
1755
+ const MULTICALL3_ADDRESS4 = "0xcA11bde05977b3631167028862bE2a173976CA11";
1756
+ const MULTICALL3_ABI4 = [
960
1757
  "function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)"
961
1758
  ];
962
- const mc = new ethers.Contract(MULTICALL3_ADDRESS3, MULTICALL3_ABI3, provider);
1759
+ const mc = new ethers.Contract(MULTICALL3_ADDRESS4, MULTICALL3_ABI4, provider);
963
1760
  const metaIface = new ethers.Interface(METADATA_ABI);
964
1761
  const vaultIface = new ethers.Interface(VAULT_ABI);
965
1762
  const b1Calls = [
@@ -1096,6 +1893,644 @@ async function getVaultSummary(provider, vault) {
1096
1893
  ]);
1097
1894
  return { ...status, ...metadata };
1098
1895
  }
1896
+ var FACTORY_COMPOSER_ABI_UH = [
1897
+ "function vaultComposer(address _vault) view returns (address)"
1898
+ ];
1899
+ var COMPOSER_SHARE_OFT_ABI_UH = [
1900
+ "function SHARE_OFT() view returns (address)"
1901
+ ];
1902
+ var OFT_PEERS_ABI_UH = [
1903
+ "function peers(uint32 eid) view returns (bytes32)"
1904
+ ];
1905
+ async function getUserPositionMultiChain(vault, user) {
1906
+ const topo = await discoverVaultTopology(vault);
1907
+ const hubProvider = createChainProvider(topo.hubChainId);
1908
+ if (!hubProvider) throw new Error(`No public RPC for hub chainId ${topo.hubChainId}`);
1909
+ const mc = new ethers.Contract(MULTICALL3_ADDRESS2, MULTICALL3_ABI2, hubProvider);
1910
+ const vaultIface = new ethers.Interface(VAULT_ABI);
1911
+ const decimalsIface = new ethers.Interface(["function decimals() view returns (uint8)"]);
1912
+ const b1Calls = [
1913
+ { target: vault, allowFailure: false, callData: vaultIface.encodeFunctionData("balanceOf", [user]) },
1914
+ { target: vault, allowFailure: false, callData: decimalsIface.encodeFunctionData("decimals") },
1915
+ { target: vault, allowFailure: false, callData: vaultIface.encodeFunctionData("getWithdrawalRequest", [user]) }
1916
+ ];
1917
+ const [b1Raw, block] = await Promise.all([
1918
+ mc.aggregate3.staticCall(b1Calls),
1919
+ hubProvider.getBlock("latest")
1920
+ ]);
1921
+ const hubShares = vaultIface.decodeFunctionResult("balanceOf", b1Raw[0].returnData)[0];
1922
+ const decimals = Number(decimalsIface.decodeFunctionResult("decimals", b1Raw[1].returnData)[0]);
1923
+ const withdrawalResult = vaultIface.decodeFunctionResult("getWithdrawalRequest", b1Raw[2].returnData);
1924
+ const withdrawShares = withdrawalResult[0];
1925
+ const timelockEndsAt = withdrawalResult[1];
1926
+ const spokeShares = {};
1927
+ const rawSpokeShares = {};
1928
+ if (topo.spokeChainIds.length > 0) {
1929
+ let hubShareOft = null;
1930
+ try {
1931
+ const factory = new ethers.Contract(OMNI_FACTORY_ADDRESS, FACTORY_COMPOSER_ABI_UH, hubProvider);
1932
+ const composerAddress = await factory.vaultComposer(vault);
1933
+ if (composerAddress !== "0x0000000000000000000000000000000000000000") {
1934
+ const composer = new ethers.Contract(composerAddress, COMPOSER_SHARE_OFT_ABI_UH, hubProvider);
1935
+ hubShareOft = await composer.SHARE_OFT();
1936
+ }
1937
+ } catch {
1938
+ }
1939
+ if (hubShareOft) {
1940
+ const hubShareOftContract = new ethers.Contract(hubShareOft, OFT_PEERS_ABI_UH, hubProvider);
1941
+ const spokePromises = topo.spokeChainIds.map(async (spokeChainId) => {
1942
+ try {
1943
+ const spokeEid = CHAIN_ID_TO_EID[spokeChainId];
1944
+ if (!spokeEid) return { chainId: spokeChainId, balance: 0n, rawBalance: 0n };
1945
+ const spokeOftBytes32 = await hubShareOftContract.peers(spokeEid);
1946
+ const spokeOft = `0x${spokeOftBytes32.slice(-40)}`;
1947
+ if (spokeOft === "0x0000000000000000000000000000000000000000") {
1948
+ return { chainId: spokeChainId, balance: 0n, rawBalance: 0n };
1949
+ }
1950
+ const spokeProvider = createChainProvider(spokeChainId);
1951
+ if (!spokeProvider) return { chainId: spokeChainId, balance: 0n, rawBalance: 0n };
1952
+ const spokeMc = new ethers.Contract(MULTICALL3_ADDRESS2, MULTICALL3_ABI2, spokeProvider);
1953
+ const erc20Iface = new ethers.Interface(ERC20_ABI);
1954
+ const spokeDecimalsIface = new ethers.Interface(["function decimals() view returns (uint8)"]);
1955
+ const spokeCalls = [
1956
+ { target: spokeOft, allowFailure: false, callData: erc20Iface.encodeFunctionData("balanceOf", [user]) },
1957
+ { target: spokeOft, allowFailure: false, callData: spokeDecimalsIface.encodeFunctionData("decimals") }
1958
+ ];
1959
+ const spokeRaw = await spokeMc.aggregate3.staticCall(spokeCalls);
1960
+ const rawBalance = erc20Iface.decodeFunctionResult("balanceOf", spokeRaw[0].returnData)[0];
1961
+ const spokeOftDecimals = Number(spokeDecimalsIface.decodeFunctionResult("decimals", spokeRaw[1].returnData)[0]);
1962
+ let balance;
1963
+ if (spokeOftDecimals > decimals) {
1964
+ balance = rawBalance / 10n ** BigInt(spokeOftDecimals - decimals);
1965
+ } else if (spokeOftDecimals < decimals) {
1966
+ balance = rawBalance * 10n ** BigInt(decimals - spokeOftDecimals);
1967
+ } else {
1968
+ balance = rawBalance;
1969
+ }
1970
+ return { chainId: spokeChainId, balance, rawBalance };
1971
+ } catch {
1972
+ return { chainId: spokeChainId, balance: 0n, rawBalance: 0n };
1973
+ }
1974
+ });
1975
+ const results = await Promise.all(spokePromises);
1976
+ for (const { chainId, balance, rawBalance } of results) {
1977
+ spokeShares[chainId] = balance;
1978
+ rawSpokeShares[chainId] = rawBalance;
1979
+ }
1980
+ }
1981
+ }
1982
+ const totalSpokeShares = Object.values(spokeShares).reduce((sum, b) => sum + b, 0n);
1983
+ const totalShares = hubShares + totalSpokeShares;
1984
+ const oneShare = 10n ** BigInt(decimals);
1985
+ const vaultContract = new ethers.Contract(vault, VAULT_ABI, hubProvider);
1986
+ const [estimatedAssets, sharePrice] = await Promise.all([
1987
+ totalShares === 0n ? Promise.resolve(0n) : vaultContract.convertToAssets(totalShares),
1988
+ vaultContract.convertToAssets(oneShare)
1989
+ ]);
1990
+ const currentTimestamp = BigInt(block?.timestamp ?? 0);
1991
+ const pendingWithdrawal = withdrawShares === 0n ? null : {
1992
+ shares: withdrawShares,
1993
+ timelockEndsAt,
1994
+ canRedeemNow: timelockEndsAt === 0n || currentTimestamp >= timelockEndsAt
1995
+ };
1996
+ return {
1997
+ hubShares,
1998
+ spokeShares,
1999
+ rawSpokeShares,
2000
+ totalShares,
2001
+ estimatedAssets,
2002
+ sharePrice,
2003
+ decimals,
2004
+ pendingWithdrawal
2005
+ };
2006
+ }
2007
+ var MULTICALL3_ADDRESS3 = "0xcA11bde05977b3631167028862bE2a173976CA11";
2008
+ var MULTICALL3_ABI3 = [
2009
+ "function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)"
2010
+ ];
2011
+ async function getCuratorVaultStatus(provider, vault) {
2012
+ const mc = new ethers.Contract(MULTICALL3_ADDRESS3, MULTICALL3_ABI3, provider);
2013
+ const curatorConfigIface = new ethers.Interface(CURATOR_CONFIG_ABI);
2014
+ const multicallIface = new ethers.Interface(MULTICALL_ABI);
2015
+ const calls = [
2016
+ { target: vault, allowFailure: false, callData: curatorConfigIface.encodeFunctionData("curator") },
2017
+ { target: vault, allowFailure: false, callData: curatorConfigIface.encodeFunctionData("timeLockPeriod") },
2018
+ { target: vault, allowFailure: false, callData: curatorConfigIface.encodeFunctionData("getMaxSlippagePercent") },
2019
+ { target: vault, allowFailure: false, callData: multicallIface.encodeFunctionData("getCurrentNonce") },
2020
+ { target: vault, allowFailure: false, callData: curatorConfigIface.encodeFunctionData("getAvailableAssets") },
2021
+ { target: vault, allowFailure: false, callData: curatorConfigIface.encodeFunctionData("getCrossChainAccountingManager") },
2022
+ { target: vault, allowFailure: false, callData: curatorConfigIface.encodeFunctionData("paused") }
2023
+ ];
2024
+ const results = await mc.aggregate3.staticCall(calls);
2025
+ const curator = curatorConfigIface.decodeFunctionResult("curator", results[0].returnData)[0];
2026
+ const timeLockPeriod = curatorConfigIface.decodeFunctionResult("timeLockPeriod", results[1].returnData)[0];
2027
+ const maxSlippagePercent = curatorConfigIface.decodeFunctionResult("getMaxSlippagePercent", results[2].returnData)[0];
2028
+ const currentNonce = multicallIface.decodeFunctionResult("getCurrentNonce", results[3].returnData)[0];
2029
+ const availableAssets = curatorConfigIface.decodeFunctionResult("getAvailableAssets", results[4].returnData)[0];
2030
+ const lzAdapter = curatorConfigIface.decodeFunctionResult("getCrossChainAccountingManager", results[5].returnData)[0];
2031
+ const paused = curatorConfigIface.decodeFunctionResult("paused", results[6].returnData)[0];
2032
+ return {
2033
+ curator,
2034
+ timeLockPeriod,
2035
+ maxSlippagePercent,
2036
+ currentNonce,
2037
+ availableAssets,
2038
+ lzAdapter,
2039
+ paused
2040
+ };
2041
+ }
2042
+ async function getPendingActions(provider, vault, nonce) {
2043
+ const multicallContract = new ethers.Contract(vault, MULTICALL_ABI, provider);
2044
+ const [result, block] = await Promise.all([
2045
+ multicallContract.getPendingActions(nonce),
2046
+ provider.getBlock("latest")
2047
+ ]);
2048
+ const [actionsData, pendingUntil] = result;
2049
+ const currentTimestamp = BigInt(block.timestamp);
2050
+ const isExecutable = pendingUntil > 0n && currentTimestamp >= pendingUntil;
2051
+ return {
2052
+ nonce,
2053
+ actionsData,
2054
+ pendingUntil,
2055
+ isExecutable
2056
+ };
2057
+ }
2058
+ async function isCurator(provider, vault, address) {
2059
+ const config = new ethers.Contract(vault, CURATOR_CONFIG_ABI, provider);
2060
+ const curatorAddress = await config.curator();
2061
+ return curatorAddress.toLowerCase() === address.toLowerCase();
2062
+ }
2063
+ async function getVaultAnalysis(provider, vault) {
2064
+ const analysisContract = new ethers.Contract(vault, VAULT_ANALYSIS_ABI, provider);
2065
+ const [availableRaw, depositableRaw, depositWhitelistEnabled, registryResult] = await Promise.all([
2066
+ analysisContract.getAvailableAssets(),
2067
+ analysisContract.getDepositableAssets(),
2068
+ analysisContract.isDepositWhitelistEnabled(),
2069
+ analysisContract.moreVaultsRegistry().catch(() => null)
2070
+ ]);
2071
+ const availableAddresses = availableRaw;
2072
+ const depositableAddresses = depositableRaw;
2073
+ const allAddresses = Array.from(/* @__PURE__ */ new Set([...availableAddresses, ...depositableAddresses]));
2074
+ const assetInfoMap = /* @__PURE__ */ new Map();
2075
+ if (allAddresses.length > 0) {
2076
+ const mc = new ethers.Contract(MULTICALL3_ADDRESS3, MULTICALL3_ABI3, provider);
2077
+ const metaIface = new ethers.Interface(METADATA_ABI);
2078
+ const metadataCalls = allAddresses.flatMap((addr) => [
2079
+ { target: addr, allowFailure: true, callData: metaIface.encodeFunctionData("name") },
2080
+ { target: addr, allowFailure: true, callData: metaIface.encodeFunctionData("symbol") },
2081
+ { target: addr, allowFailure: true, callData: metaIface.encodeFunctionData("decimals") }
2082
+ ]);
2083
+ const metadataResults = await mc.aggregate3.staticCall(metadataCalls);
2084
+ for (let i = 0; i < allAddresses.length; i++) {
2085
+ const addr = allAddresses[i];
2086
+ const nameRes = metadataResults[i * 3];
2087
+ const symbolRes = metadataResults[i * 3 + 1];
2088
+ const decimalsRes = metadataResults[i * 3 + 2];
2089
+ const name = nameRes.success ? metaIface.decodeFunctionResult("name", nameRes.returnData)[0] : "";
2090
+ const symbol = symbolRes.success ? metaIface.decodeFunctionResult("symbol", symbolRes.returnData)[0] : "";
2091
+ const decimals = decimalsRes.success ? Number(metaIface.decodeFunctionResult("decimals", decimalsRes.returnData)[0]) : 18;
2092
+ assetInfoMap.set(addr.toLowerCase(), { address: addr, name, symbol, decimals });
2093
+ }
2094
+ }
2095
+ const registryAddress = registryResult ? registryResult : null;
2096
+ return {
2097
+ availableAssets: availableAddresses.map((a) => assetInfoMap.get(a.toLowerCase())),
2098
+ depositableAssets: depositableAddresses.map((a) => assetInfoMap.get(a.toLowerCase())),
2099
+ depositWhitelistEnabled,
2100
+ registryAddress
2101
+ };
2102
+ }
2103
+ async function checkProtocolWhitelist(provider, vault, protocols) {
2104
+ const analysisContract = new ethers.Contract(vault, VAULT_ANALYSIS_ABI, provider);
2105
+ const registry = await analysisContract.moreVaultsRegistry();
2106
+ if (protocols.length === 0) return {};
2107
+ const mc = new ethers.Contract(MULTICALL3_ADDRESS3, MULTICALL3_ABI3, provider);
2108
+ const registryIface = new ethers.Interface(REGISTRY_ABI);
2109
+ const calls = protocols.map((protocol) => ({
2110
+ target: registry,
2111
+ allowFailure: true,
2112
+ callData: registryIface.encodeFunctionData("isWhitelisted", [protocol])
2113
+ }));
2114
+ const results = await mc.aggregate3.staticCall(calls);
2115
+ const out = {};
2116
+ for (let i = 0; i < protocols.length; i++) {
2117
+ const r = results[i];
2118
+ const whitelisted = r.success ? registryIface.decodeFunctionResult("isWhitelisted", r.returnData)[0] : false;
2119
+ out[protocols[i].toLowerCase()] = whitelisted;
2120
+ }
2121
+ return out;
2122
+ }
2123
+ async function getVaultAssetBreakdown(provider, vault) {
2124
+ const analysisContract = new ethers.Contract(vault, VAULT_ANALYSIS_ABI, provider);
2125
+ const availableRaw = await analysisContract.getAvailableAssets();
2126
+ const addresses = availableRaw;
2127
+ const mc = new ethers.Contract(MULTICALL3_ADDRESS3, MULTICALL3_ABI3, provider);
2128
+ const vaultIface = new ethers.Interface(VAULT_ABI);
2129
+ const metaIface = new ethers.Interface(METADATA_ABI);
2130
+ const erc20Iface = new ethers.Interface(ERC20_ABI);
2131
+ const perAssetCalls = addresses.flatMap((addr) => [
2132
+ { target: addr, allowFailure: true, callData: erc20Iface.encodeFunctionData("balanceOf", [vault]) },
2133
+ { target: addr, allowFailure: true, callData: metaIface.encodeFunctionData("name") },
2134
+ { target: addr, allowFailure: true, callData: metaIface.encodeFunctionData("symbol") },
2135
+ { target: addr, allowFailure: true, callData: metaIface.encodeFunctionData("decimals") }
2136
+ ]);
2137
+ const totalCalls = [
2138
+ ...perAssetCalls,
2139
+ { target: vault, allowFailure: true, callData: vaultIface.encodeFunctionData("totalAssets") },
2140
+ { target: vault, allowFailure: true, callData: vaultIface.encodeFunctionData("totalSupply") },
2141
+ { target: vault, allowFailure: true, callData: metaIface.encodeFunctionData("decimals") }
2142
+ ];
2143
+ const results = await mc.aggregate3.staticCall(totalCalls);
2144
+ const perAssetFields = 4;
2145
+ const assets = addresses.map((addr, i) => {
2146
+ const base = i * perAssetFields;
2147
+ const balance = results[base].success ? erc20Iface.decodeFunctionResult("balanceOf", results[base].returnData)[0] : 0n;
2148
+ const name = results[base + 1].success ? metaIface.decodeFunctionResult("name", results[base + 1].returnData)[0] : "";
2149
+ const symbol = results[base + 2].success ? metaIface.decodeFunctionResult("symbol", results[base + 2].returnData)[0] : "";
2150
+ const decimals = results[base + 3].success ? Number(metaIface.decodeFunctionResult("decimals", results[base + 3].returnData)[0]) : 18;
2151
+ return { address: addr, name, symbol, decimals, balance };
2152
+ });
2153
+ const totalsBase = addresses.length * perAssetFields;
2154
+ const totalAssets = results[totalsBase].success ? vaultIface.decodeFunctionResult("totalAssets", results[totalsBase].returnData)[0] : 0n;
2155
+ const totalSupply = results[totalsBase + 1].success ? vaultIface.decodeFunctionResult("totalSupply", results[totalsBase + 1].returnData)[0] : 0n;
2156
+ const underlyingDecimals = results[totalsBase + 2].success ? Number(metaIface.decodeFunctionResult("decimals", results[totalsBase + 2].returnData)[0]) : 6;
2157
+ return { assets, totalAssets, totalSupply, underlyingDecimals };
2158
+ }
2159
+ function encodeCuratorAction(action) {
2160
+ switch (action.type) {
2161
+ case "swap": {
2162
+ const iface = new ethers.Interface(DEX_ABI);
2163
+ return iface.encodeFunctionData("executeSwap", [
2164
+ {
2165
+ targetContract: action.params.targetContract,
2166
+ tokenIn: action.params.tokenIn,
2167
+ tokenOut: action.params.tokenOut,
2168
+ maxAmountIn: action.params.maxAmountIn,
2169
+ minAmountOut: action.params.minAmountOut,
2170
+ swapCallData: action.params.swapCallData
2171
+ }
2172
+ ]);
2173
+ }
2174
+ case "batchSwap": {
2175
+ const iface = new ethers.Interface(DEX_ABI);
2176
+ return iface.encodeFunctionData("executeBatchSwap", [
2177
+ {
2178
+ swaps: action.params.swaps.map((s) => ({
2179
+ targetContract: s.targetContract,
2180
+ tokenIn: s.tokenIn,
2181
+ tokenOut: s.tokenOut,
2182
+ maxAmountIn: s.maxAmountIn,
2183
+ minAmountOut: s.minAmountOut,
2184
+ swapCallData: s.swapCallData
2185
+ }))
2186
+ }
2187
+ ]);
2188
+ }
2189
+ case "erc4626Deposit": {
2190
+ const iface = new ethers.Interface(ERC4626_FACET_ABI);
2191
+ return iface.encodeFunctionData("erc4626Deposit", [action.vault, action.assets]);
2192
+ }
2193
+ case "erc4626Redeem": {
2194
+ const iface = new ethers.Interface(ERC4626_FACET_ABI);
2195
+ return iface.encodeFunctionData("erc4626Redeem", [action.vault, action.shares]);
2196
+ }
2197
+ case "erc7540RequestDeposit": {
2198
+ const iface = new ethers.Interface(ERC7540_FACET_ABI);
2199
+ return iface.encodeFunctionData("erc7540RequestDeposit", [action.vault, action.assets]);
2200
+ }
2201
+ case "erc7540Deposit": {
2202
+ const iface = new ethers.Interface(ERC7540_FACET_ABI);
2203
+ return iface.encodeFunctionData("erc7540Deposit", [action.vault, action.assets]);
2204
+ }
2205
+ case "erc7540RequestRedeem": {
2206
+ const iface = new ethers.Interface(ERC7540_FACET_ABI);
2207
+ return iface.encodeFunctionData("erc7540RequestRedeem", [action.vault, action.shares]);
2208
+ }
2209
+ case "erc7540Redeem": {
2210
+ const iface = new ethers.Interface(ERC7540_FACET_ABI);
2211
+ return iface.encodeFunctionData("erc7540Redeem", [action.vault, action.shares]);
2212
+ }
2213
+ default: {
2214
+ const _exhaustive = action;
2215
+ throw new Error(`[MoreVaults] Unknown CuratorAction type: ${_exhaustive.type}`);
2216
+ }
2217
+ }
2218
+ }
2219
+ function buildCuratorBatch(actions) {
2220
+ return actions.map(encodeCuratorAction);
2221
+ }
2222
+ async function submitActions(signer, vault, actions) {
2223
+ const multicallContract = new ethers.Contract(vault, MULTICALL_ABI, signer);
2224
+ const tx = await multicallContract.submitActions(actions);
2225
+ const receipt = await tx.wait();
2226
+ const nextNonce = await multicallContract.getCurrentNonce();
2227
+ const nonce = nextNonce - 1n;
2228
+ return { receipt, nonce };
2229
+ }
2230
+ async function executeActions(signer, vault, nonce) {
2231
+ const multicallContract = new ethers.Contract(vault, MULTICALL_ABI, signer);
2232
+ const tx = await multicallContract.executeActions(nonce);
2233
+ return tx.wait();
2234
+ }
2235
+ async function vetoActions(signer, vault, nonces) {
2236
+ const multicallContract = new ethers.Contract(vault, MULTICALL_ABI, signer);
2237
+ const tx = await multicallContract.vetoActions(nonces);
2238
+ return tx.wait();
2239
+ }
2240
+ var UNISWAP_V3_SWAP_ROUTER_ABI = [
2241
+ "function exactInputSingle(tuple(address tokenIn, address tokenOut, uint24 fee, address recipient, uint256 deadline, uint256 amountIn, uint256 amountOutMinimum, uint160 sqrtPriceLimitX96) params) payable returns (uint256 amountOut)"
2242
+ ];
2243
+ var UNISWAP_V3_SWAP_ROUTER02_ABI = [
2244
+ "function exactInputSingle(tuple(address tokenIn, address tokenOut, uint24 fee, address recipient, uint256 amountIn, uint256 amountOutMinimum, uint160 sqrtPriceLimitX96) params) payable returns (uint256 amountOut)"
2245
+ ];
2246
+ var SWAP_ROUTER02_CHAINS = /* @__PURE__ */ new Set([8453]);
2247
+ function encodeUniswapV3SwapCalldata(params) {
2248
+ const { chainId, tokenIn, tokenOut, fee, amountIn, minAmountOut, recipient } = params;
2249
+ const router = UNISWAP_V3_ROUTERS[chainId];
2250
+ if (!router) {
2251
+ throw new Error(
2252
+ `[MoreVaults] No Uniswap V3 router configured for chainId ${chainId}. Supported chains: ${Object.keys(UNISWAP_V3_ROUTERS).join(", ")}`
2253
+ );
2254
+ }
2255
+ let swapCallData;
2256
+ if (SWAP_ROUTER02_CHAINS.has(chainId)) {
2257
+ const iface = new ethers.Interface(UNISWAP_V3_SWAP_ROUTER02_ABI);
2258
+ swapCallData = iface.encodeFunctionData("exactInputSingle", [
2259
+ {
2260
+ tokenIn,
2261
+ tokenOut,
2262
+ fee,
2263
+ recipient,
2264
+ amountIn,
2265
+ amountOutMinimum: minAmountOut,
2266
+ sqrtPriceLimitX96: 0n
2267
+ }
2268
+ ]);
2269
+ } else {
2270
+ const deadline = BigInt(Math.floor(Date.now() / 1e3) + 1200);
2271
+ const iface = new ethers.Interface(UNISWAP_V3_SWAP_ROUTER_ABI);
2272
+ swapCallData = iface.encodeFunctionData("exactInputSingle", [
2273
+ {
2274
+ tokenIn,
2275
+ tokenOut,
2276
+ fee,
2277
+ recipient,
2278
+ deadline,
2279
+ amountIn,
2280
+ amountOutMinimum: minAmountOut,
2281
+ sqrtPriceLimitX96: 0n
2282
+ }
2283
+ ]);
2284
+ }
2285
+ return { targetContract: router, swapCallData };
2286
+ }
2287
+ function buildUniswapV3Swap(params) {
2288
+ const { targetContract, swapCallData } = encodeUniswapV3SwapCalldata(params);
2289
+ return {
2290
+ type: "swap",
2291
+ params: {
2292
+ targetContract,
2293
+ tokenIn: params.tokenIn,
2294
+ tokenOut: params.tokenOut,
2295
+ maxAmountIn: params.amountIn,
2296
+ minAmountOut: params.minAmountOut,
2297
+ swapCallData
2298
+ }
2299
+ };
2300
+ }
2301
+
2302
+ // src/ethers/distribution.ts
2303
+ async function getVaultDistribution(hubProvider, vault, spokeProviders) {
2304
+ const hubStatus = await getVaultStatus(hubProvider, vault);
2305
+ const hubChainId = Number((await hubProvider.getNetwork()).chainId);
2306
+ const hubTotalAssets = hubStatus.totalAssets;
2307
+ const hubLiquidBalance = hubStatus.hubLiquidBalance;
2308
+ const hubStrategyBalance = hubTotalAssets > hubLiquidBalance ? hubTotalAssets - hubLiquidBalance : 0n;
2309
+ const spokeEntries = Object.entries(spokeProviders).map(([chainIdStr, provider]) => ({
2310
+ chainId: Number(chainIdStr),
2311
+ provider
2312
+ }));
2313
+ const spokeBalances = await Promise.all(
2314
+ spokeEntries.map(async ({ chainId, provider }) => {
2315
+ try {
2316
+ const spokeStatus = await getVaultStatus(provider, vault);
2317
+ return { chainId, totalAssets: spokeStatus.totalAssets, isReachable: true };
2318
+ } catch {
2319
+ return { chainId, totalAssets: 0n, isReachable: false };
2320
+ }
2321
+ })
2322
+ );
2323
+ const reachableSpokeSum = spokeBalances.filter((s) => s.isReachable).reduce((acc, s) => acc + s.totalAssets, 0n);
2324
+ const totalActual = hubTotalAssets + reachableSpokeSum;
2325
+ return {
2326
+ hubChainId,
2327
+ hubLiquidBalance,
2328
+ hubStrategyBalance,
2329
+ hubTotalAssets,
2330
+ spokesDeployedBalance: hubStatus.spokesDeployedBalance,
2331
+ spokeBalances,
2332
+ totalActual,
2333
+ oracleAccountingEnabled: hubStatus.oracleAccountingEnabled
2334
+ };
2335
+ }
2336
+ async function getVaultDistributionWithTopology(hubProvider, vault) {
2337
+ const [hubStatus, topology] = await Promise.all([
2338
+ getVaultStatus(hubProvider, vault),
2339
+ getVaultTopology(hubProvider, vault)
2340
+ ]);
2341
+ const hubChainId = Number((await hubProvider.getNetwork()).chainId);
2342
+ const hubTotalAssets = hubStatus.totalAssets;
2343
+ const hubLiquidBalance = hubStatus.hubLiquidBalance;
2344
+ const hubStrategyBalance = hubTotalAssets > hubLiquidBalance ? hubTotalAssets - hubLiquidBalance : 0n;
2345
+ return {
2346
+ hubChainId,
2347
+ hubLiquidBalance,
2348
+ hubStrategyBalance,
2349
+ hubTotalAssets,
2350
+ spokesDeployedBalance: hubStatus.spokesDeployedBalance,
2351
+ spokeBalances: [],
2352
+ totalActual: hubTotalAssets,
2353
+ // hub-only, no spoke data
2354
+ oracleAccountingEnabled: hubStatus.oracleAccountingEnabled,
2355
+ spokeChainIds: topology.spokeChainIds
2356
+ };
2357
+ }
2358
+ var NATIVE_SYMBOL = {
2359
+ 1: "ETH",
2360
+ 10: "ETH",
2361
+ 42161: "ETH",
2362
+ 8453: "ETH",
2363
+ 747: "FLOW",
2364
+ 146: "S",
2365
+ 56: "BNB"
2366
+ };
2367
+ var SYMBOL_ABI = [
2368
+ "function symbol() view returns (string)"
2369
+ ];
2370
+ async function readTokenSymbol(provider, token, fallbackSymbol) {
2371
+ if (!provider) return fallbackSymbol;
2372
+ try {
2373
+ const contract = new ethers.Contract(token, SYMBOL_ABI, provider);
2374
+ return await contract.symbol();
2375
+ } catch {
2376
+ return fallbackSymbol;
2377
+ }
2378
+ }
2379
+ async function getInboundRoutes(hubChainId, vault, vaultAsset, userAddress) {
2380
+ const hubEid = CHAIN_ID_TO_EID[hubChainId];
2381
+ if (!hubEid) throw new Error(`No LZ EID for hub chainId ${hubChainId}`);
2382
+ const hubProvider = createChainProvider(hubChainId);
2383
+ if (!hubProvider) throw new Error(`No public RPC for hub chainId ${hubChainId}`);
2384
+ const topology = await getVaultTopology(hubProvider, vault);
2385
+ const registeredSpokes = new Set(topology.spokeChainIds);
2386
+ const results = [];
2387
+ const vaultAssetNorm = vaultAsset.toLowerCase();
2388
+ for (const [symbol, chainMap] of Object.entries(OFT_ROUTES)) {
2389
+ const hubEntry = chainMap[hubChainId];
2390
+ if (!hubEntry) continue;
2391
+ if (hubEntry.token.toLowerCase() !== vaultAssetNorm) continue;
2392
+ const oftCmd = "0x";
2393
+ const spokesToCheck = Object.keys(chainMap).map(Number).filter((id) => id !== hubChainId && registeredSpokes.has(id));
2394
+ await Promise.allSettled(
2395
+ spokesToCheck.map(async (spokeChainId) => {
2396
+ const spokeEntry = chainMap[spokeChainId];
2397
+ if (!spokeEntry) return;
2398
+ const spokeProvider = createChainProvider(spokeChainId);
2399
+ if (!spokeProvider) return;
2400
+ try {
2401
+ const receiverBytes32 = "0x" + userAddress.replace(/^0x/, "").toLowerCase().padStart(64, "0");
2402
+ const spokeOft = new ethers.Contract(spokeEntry.oft, OFT_ABI, spokeProvider);
2403
+ const [feeResult, sourceTokenSymbol] = await Promise.all([
2404
+ spokeOft.quoteSend(
2405
+ {
2406
+ dstEid: hubEid,
2407
+ to: receiverBytes32,
2408
+ amountLD: 1000000n,
2409
+ minAmountLD: 0n,
2410
+ extraOptions: "0x",
2411
+ composeMsg: "0x",
2412
+ oftCmd
2413
+ },
2414
+ false
2415
+ ),
2416
+ readTokenSymbol(spokeProvider, spokeEntry.token, symbol)
2417
+ ]);
2418
+ results.push({
2419
+ symbol,
2420
+ spokeChainId,
2421
+ depositType: "oft-compose",
2422
+ spokeOft: spokeEntry.oft,
2423
+ spokeToken: spokeEntry.token,
2424
+ sourceTokenSymbol,
2425
+ hubOft: hubEntry.oft,
2426
+ oftCmd,
2427
+ lzFeeEstimate: feeResult.nativeFee,
2428
+ nativeSymbol: NATIVE_SYMBOL[spokeChainId] ?? "ETH"
2429
+ });
2430
+ } catch {
2431
+ }
2432
+ })
2433
+ );
2434
+ }
2435
+ const [asyncMode, ...hubOftEntries] = await Promise.all([
2436
+ isAsyncMode(hubProvider, vault),
2437
+ ...Object.entries(OFT_ROUTES).map(async ([sym, chainMap]) => {
2438
+ const hubEntry = chainMap[hubChainId];
2439
+ if (!hubEntry || hubEntry.token.toLowerCase() !== vaultAssetNorm) return null;
2440
+ return { symbol: sym, hubEntry };
2441
+ })
2442
+ ]);
2443
+ const hubOftEntry = hubOftEntries.find((e) => e !== null) ?? null;
2444
+ if (hubOftEntry) {
2445
+ const { symbol, hubEntry } = hubOftEntry;
2446
+ const [sourceTokenSymbol, lzFeeEstimate] = await Promise.all([
2447
+ readTokenSymbol(hubProvider, hubEntry.token, symbol),
2448
+ asyncMode ? quoteLzFee(hubProvider, vault) : Promise.resolve(0n)
2449
+ ]);
2450
+ results.unshift({
2451
+ symbol,
2452
+ spokeChainId: hubChainId,
2453
+ depositType: asyncMode ? "direct-async" : "direct",
2454
+ spokeOft: null,
2455
+ spokeToken: hubEntry.token,
2456
+ sourceTokenSymbol,
2457
+ hubOft: null,
2458
+ oftCmd: "0x",
2459
+ lzFeeEstimate,
2460
+ nativeSymbol: NATIVE_SYMBOL[hubChainId] ?? "ETH"
2461
+ });
2462
+ }
2463
+ return results;
2464
+ }
2465
+ async function getUserBalancesForRoutes(routes, userAddress) {
2466
+ return Promise.all(
2467
+ routes.map(async (route) => {
2468
+ const provider = createChainProvider(route.spokeChainId);
2469
+ if (!provider) return { ...route, userBalance: 0n };
2470
+ try {
2471
+ let userBalance;
2472
+ if (route.spokeToken.toLowerCase() === ethers.ZeroAddress.toLowerCase()) {
2473
+ userBalance = await provider.getBalance(userAddress);
2474
+ } else {
2475
+ const erc20 = new ethers.Contract(route.spokeToken, ERC20_ABI, provider);
2476
+ userBalance = await erc20.balanceOf(userAddress);
2477
+ }
2478
+ return { ...route, userBalance };
2479
+ } catch {
2480
+ return { ...route, userBalance: 0n };
2481
+ }
2482
+ })
2483
+ );
2484
+ }
2485
+ async function getOutboundRoutes(hubChainId, vault) {
2486
+ const hubEid = CHAIN_ID_TO_EID[hubChainId];
2487
+ if (!hubEid) throw new Error(`No LZ EID for hub chainId ${hubChainId}`);
2488
+ const hubProvider = createChainProvider(hubChainId);
2489
+ if (!hubProvider) throw new Error(`No public RPC for hub chainId ${hubChainId}`);
2490
+ const topology = await getVaultTopology(hubProvider, vault);
2491
+ const routes = [
2492
+ {
2493
+ chainId: hubChainId,
2494
+ routeType: "hub",
2495
+ eid: hubEid,
2496
+ nativeSymbol: NATIVE_SYMBOL[hubChainId] ?? "ETH"
2497
+ }
2498
+ ];
2499
+ for (const spokeChainId of topology.spokeChainIds) {
2500
+ const eid = CHAIN_ID_TO_EID[spokeChainId];
2501
+ if (!eid) continue;
2502
+ routes.push({
2503
+ chainId: spokeChainId,
2504
+ routeType: "spoke",
2505
+ eid,
2506
+ nativeSymbol: NATIVE_SYMBOL[spokeChainId] ?? "ETH"
2507
+ });
2508
+ }
2509
+ return routes;
2510
+ }
2511
+ async function quoteRouteDepositFee(route, hubChainId, amount, userAddress) {
2512
+ if (route.depositType === "direct") return 0n;
2513
+ const hubEid = CHAIN_ID_TO_EID[hubChainId];
2514
+ if (!hubEid) throw new Error(`No LZ EID for hub chainId ${hubChainId}`);
2515
+ if (!route.spokeOft) throw new Error("Route is oft-compose but spokeOft is null");
2516
+ const spokeProvider = createChainProvider(route.spokeChainId);
2517
+ if (!spokeProvider) throw new Error(`No public RPC for spoke chainId ${route.spokeChainId}`);
2518
+ const receiverBytes32 = "0x" + userAddress.replace(/^0x/, "").toLowerCase().padStart(64, "0");
2519
+ const spokeOft = new ethers.Contract(route.spokeOft, OFT_ABI, spokeProvider);
2520
+ const feeResult = await spokeOft.quoteSend(
2521
+ {
2522
+ dstEid: hubEid,
2523
+ to: receiverBytes32,
2524
+ amountLD: amount,
2525
+ minAmountLD: 0n,
2526
+ extraOptions: "0x",
2527
+ composeMsg: "0x",
2528
+ oftCmd: route.oftCmd
2529
+ },
2530
+ false
2531
+ );
2532
+ return feeResult.nativeFee;
2533
+ }
1099
2534
 
1100
2535
  // src/ethers/wagmiCompat.ts
1101
2536
  function asSdkSigner(signer) {
@@ -1105,63 +2540,107 @@ function asSdkSigner(signer) {
1105
2540
 
1106
2541
  exports.ActionType = ActionType;
1107
2542
  exports.BRIDGE_ABI = BRIDGE_ABI;
2543
+ exports.BRIDGE_FACET_ABI = BRIDGE_FACET_ABI;
1108
2544
  exports.CCManagerNotConfiguredError = CCManagerNotConfiguredError;
1109
2545
  exports.CHAIN_IDS = CHAIN_IDS;
1110
2546
  exports.CHAIN_ID_TO_EID = CHAIN_ID_TO_EID;
1111
2547
  exports.CONFIG_ABI = CONFIG_ABI;
2548
+ exports.CURATOR_CONFIG_ABI = CURATOR_CONFIG_ABI;
1112
2549
  exports.CapacityFullError = CapacityFullError;
2550
+ exports.DEX_ABI = DEX_ABI;
1113
2551
  exports.EID_TO_CHAIN_ID = EID_TO_CHAIN_ID;
1114
2552
  exports.ERC20_ABI = ERC20_ABI;
2553
+ exports.ERC4626_FACET_ABI = ERC4626_FACET_ABI;
2554
+ exports.ERC7540_FACET_ABI = ERC7540_FACET_ABI;
1115
2555
  exports.EscrowNotConfiguredError = EscrowNotConfiguredError;
1116
2556
  exports.InsufficientLiquidityError = InsufficientLiquidityError;
2557
+ exports.LZ_ADAPTER_ABI = LZ_ADAPTER_ABI;
1117
2558
  exports.LZ_EIDS = LZ_EIDS;
1118
2559
  exports.LZ_ENDPOINT_ABI = LZ_ENDPOINT_ABI;
1119
2560
  exports.LZ_TIMEOUTS = LZ_TIMEOUTS;
1120
2561
  exports.METADATA_ABI = METADATA_ABI;
2562
+ exports.MULTICALL_ABI = MULTICALL_ABI;
1121
2563
  exports.MissingEscrowAddressError = MissingEscrowAddressError;
1122
2564
  exports.MoreVaultsError = MoreVaultsError;
2565
+ exports.NATIVE_SYMBOL = NATIVE_SYMBOL;
1123
2566
  exports.NotHubVaultError = NotHubVaultError;
1124
2567
  exports.NotWhitelistedError = NotWhitelistedError;
1125
2568
  exports.OFT_ABI = OFT_ABI;
2569
+ exports.OFT_ROUTES = OFT_ROUTES;
2570
+ exports.OMNI_FACTORY_ADDRESS = OMNI_FACTORY_ADDRESS;
2571
+ exports.REGISTRY_ABI = REGISTRY_ABI;
2572
+ exports.UNISWAP_V3_ROUTERS = UNISWAP_V3_ROUTERS;
1126
2573
  exports.VAULT_ABI = VAULT_ABI;
2574
+ exports.VAULT_ANALYSIS_ABI = VAULT_ANALYSIS_ABI;
1127
2575
  exports.VaultPausedError = VaultPausedError;
1128
2576
  exports.WrongChainError = WrongChainError;
1129
2577
  exports.asSdkSigner = asSdkSigner;
1130
2578
  exports.bridgeAssetsToSpoke = bridgeAssetsToSpoke;
1131
2579
  exports.bridgeSharesToHub = bridgeSharesToHub;
2580
+ exports.buildCuratorBatch = buildCuratorBatch;
2581
+ exports.buildUniswapV3Swap = buildUniswapV3Swap;
1132
2582
  exports.canDeposit = canDeposit;
2583
+ exports.checkProtocolWhitelist = checkProtocolWhitelist;
1133
2584
  exports.depositAsync = depositAsync;
1134
2585
  exports.depositCrossChainOracleOn = depositCrossChainOracleOn;
1135
2586
  exports.depositFromSpoke = depositFromSpoke;
1136
2587
  exports.depositFromSpokeAsync = depositFromSpokeAsync;
1137
2588
  exports.depositMultiAsset = depositMultiAsset;
1138
2589
  exports.depositSimple = depositSimple;
2590
+ exports.detectStargateOft = detectStargateOft;
2591
+ exports.discoverVaultTopology = discoverVaultTopology;
2592
+ exports.encodeCuratorAction = encodeCuratorAction;
2593
+ exports.encodeUniswapV3SwapCalldata = encodeUniswapV3SwapCalldata;
1139
2594
  exports.ensureAllowance = ensureAllowance;
2595
+ exports.executeActions = executeActions;
1140
2596
  exports.executeCompose = executeCompose;
2597
+ exports.getAllVaultChainIds = getAllVaultChainIds;
1141
2598
  exports.getAsyncRequestStatus = getAsyncRequestStatus;
1142
2599
  exports.getAsyncRequestStatusLabel = getAsyncRequestStatusLabel;
2600
+ exports.getCuratorVaultStatus = getCuratorVaultStatus;
2601
+ exports.getFullVaultTopology = getFullVaultTopology;
2602
+ exports.getInboundRoutes = getInboundRoutes;
1143
2603
  exports.getMaxWithdrawable = getMaxWithdrawable;
2604
+ exports.getOutboundRoutes = getOutboundRoutes;
2605
+ exports.getPendingActions = getPendingActions;
1144
2606
  exports.getUserBalances = getUserBalances;
2607
+ exports.getUserBalancesForRoutes = getUserBalancesForRoutes;
1145
2608
  exports.getUserPosition = getUserPosition;
2609
+ exports.getUserPositionMultiChain = getUserPositionMultiChain;
2610
+ exports.getVaultAnalysis = getVaultAnalysis;
2611
+ exports.getVaultAssetBreakdown = getVaultAssetBreakdown;
2612
+ exports.getVaultDistribution = getVaultDistribution;
2613
+ exports.getVaultDistributionWithTopology = getVaultDistributionWithTopology;
1146
2614
  exports.getVaultMetadata = getVaultMetadata;
1147
2615
  exports.getVaultStatus = getVaultStatus;
1148
2616
  exports.getVaultSummary = getVaultSummary;
2617
+ exports.getVaultTopology = getVaultTopology;
1149
2618
  exports.getWithdrawalRequest = getWithdrawalRequest;
1150
2619
  exports.isAsyncMode = isAsyncMode;
2620
+ exports.isCurator = isCurator;
2621
+ exports.isOnHubChain = isOnHubChain;
1151
2622
  exports.mintAsync = mintAsync;
1152
2623
  exports.preflightAsync = preflightAsync;
1153
2624
  exports.preflightRedeemLiquidity = preflightRedeemLiquidity;
2625
+ exports.preflightSpokeDeposit = preflightSpokeDeposit;
2626
+ exports.preflightSpokeRedeem = preflightSpokeRedeem;
1154
2627
  exports.preflightSync = preflightSync;
1155
2628
  exports.previewDeposit = previewDeposit;
1156
2629
  exports.previewRedeem = previewRedeem;
1157
2630
  exports.quoteComposeFee = quoteComposeFee;
1158
2631
  exports.quoteDepositFromSpokeFee = quoteDepositFromSpokeFee;
1159
2632
  exports.quoteLzFee = quoteLzFee;
2633
+ exports.quoteRouteDepositFee = quoteRouteDepositFee;
2634
+ exports.quoteShareBridgeFee = quoteShareBridgeFee;
1160
2635
  exports.redeemAsync = redeemAsync;
1161
2636
  exports.redeemShares = redeemShares;
1162
2637
  exports.requestRedeem = requestRedeem;
2638
+ exports.resolveRedeemAddresses = resolveRedeemAddresses;
1163
2639
  exports.smartDeposit = smartDeposit;
1164
2640
  exports.smartRedeem = smartRedeem;
2641
+ exports.submitActions = submitActions;
2642
+ exports.vetoActions = vetoActions;
2643
+ exports.waitForCompose = waitForCompose;
1165
2644
  exports.withdrawAssets = withdrawAssets;
1166
2645
  //# sourceMappingURL=index.cjs.map
1167
2646
  //# sourceMappingURL=index.cjs.map