@oydual31/more-vaults-sdk 0.4.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +94 -0
  2. package/dist/{spokeRoutes-B8Lnk-t4.d.cts → curatorBridge-CNs59kT9.d.cts} +222 -1
  3. package/dist/{spokeRoutes-B8Lnk-t4.d.ts → curatorBridge-CNs59kT9.d.ts} +222 -1
  4. package/dist/ethers/index.cjs +328 -3
  5. package/dist/ethers/index.cjs.map +1 -1
  6. package/dist/ethers/index.d.cts +279 -1
  7. package/dist/ethers/index.d.ts +279 -1
  8. package/dist/ethers/index.js +318 -5
  9. package/dist/ethers/index.js.map +1 -1
  10. package/dist/react/index.cjs +375 -0
  11. package/dist/react/index.cjs.map +1 -1
  12. package/dist/react/index.d.cts +266 -2
  13. package/dist/react/index.d.ts +266 -2
  14. package/dist/react/index.js +372 -2
  15. package/dist/react/index.js.map +1 -1
  16. package/dist/viem/index.cjs +377 -0
  17. package/dist/viem/index.cjs.map +1 -1
  18. package/dist/viem/index.d.cts +261 -3
  19. package/dist/viem/index.d.ts +261 -3
  20. package/dist/viem/index.js +367 -2
  21. package/dist/viem/index.js.map +1 -1
  22. package/package.json +1 -1
  23. package/src/ethers/abis.ts +24 -0
  24. package/src/ethers/curatorBridge.ts +235 -0
  25. package/src/ethers/curatorSubVaults.ts +443 -0
  26. package/src/ethers/index.ts +26 -0
  27. package/src/ethers/types.ts +99 -0
  28. package/src/react/index.ts +14 -0
  29. package/src/react/useCuratorBridgeQuote.ts +43 -0
  30. package/src/react/useERC7540RequestStatus.ts +43 -0
  31. package/src/react/useExecuteBridge.ts +50 -0
  32. package/src/react/useSubVaultPositions.ts +35 -0
  33. package/src/react/useVaultPortfolio.ts +35 -0
  34. package/src/viem/abis.ts +24 -0
  35. package/src/viem/curatorBridge.ts +288 -0
  36. package/src/viem/curatorSubVaults.ts +514 -0
  37. package/src/viem/index.ts +23 -0
  38. package/src/viem/types.ts +100 -0
package/README.md CHANGED
@@ -173,6 +173,12 @@ All three modules expose the same logical features. Choose based on your stack.
173
173
  | `executeActions` | Yes | Yes | `useExecuteActions` |
174
174
  | `vetoActions` | Yes | Yes | `useVetoActions` |
175
175
  | `buildUniswapV3Swap`, `encodeUniswapV3SwapCalldata` | Yes | Yes | — |
176
+ | `quoteCuratorBridgeFee`, `executeCuratorBridge` | Yes | Yes | `useCuratorBridgeQuote`, `useExecuteBridge` |
177
+ | `findBridgeRoute`, `encodeBridgeParams` | Yes | Yes | — |
178
+ | `getSubVaultPositions`, `getVaultPortfolio` | Yes | Yes | `useSubVaultPositions`, `useVaultPortfolio` |
179
+ | `getSubVaultInfo`, `detectSubVaultType` | Yes | Yes | — |
180
+ | `getERC7540RequestStatus` | Yes | Yes | `useERC7540RequestStatus` |
181
+ | `previewSubVaultDeposit`, `previewSubVaultRedeem` | Yes | Yes | — |
176
182
  | `detectStargateOft` | Yes | Yes | — |
177
183
  | `preflightSync`, `preflightAsync` | Yes | Yes | — |
178
184
  | `preflightSpokeDeposit`, `preflightSpokeRedeem` | Yes | Yes | — |
@@ -675,6 +681,89 @@ const { targetContract, swapCallData } = encodeUniswapV3SwapCalldata({
675
681
  })
676
682
  ```
677
683
 
684
+ ### Bridge operations
685
+
686
+ Curators can bridge assets between hub and spoke vaults via LayerZero. This is a direct curator call (not via multicall) — the vault pauses during bridging for security.
687
+
688
+ ```ts
689
+ import {
690
+ quoteCuratorBridgeFee,
691
+ executeCuratorBridge,
692
+ findBridgeRoute,
693
+ } from '@oydual31/more-vaults-sdk/viem'
694
+
695
+ // Find the OFT route for USDC between Base and Arbitrum
696
+ const route = findBridgeRoute(8453, 42161, USDC_ADDRESS)
697
+ // route.oftSrc — OFT on source chain (Stargate USDC on Base)
698
+ // route.oftDst — OFT on destination chain
699
+ // route.symbol — 'stgUSDC'
700
+
701
+ // Quote the LayerZero fee
702
+ const fee = await quoteCuratorBridgeFee(publicClient, VAULT, {
703
+ oftToken: route.oftSrc,
704
+ dstEid: 30110, // Arbitrum LZ EID
705
+ amount: parseUnits('1000', 6), // 1000 USDC
706
+ dstVault: SPOKE_VAULT_ADDRESS,
707
+ refundAddress: curatorAddress,
708
+ })
709
+
710
+ // Execute the bridge (curator only)
711
+ const txHash = await executeCuratorBridge(
712
+ walletClient, publicClient, VAULT,
713
+ USDC_ADDRESS, // underlying ERC-20 token
714
+ {
715
+ oftToken: route.oftSrc,
716
+ dstEid: 30110,
717
+ amount: parseUnits('1000', 6),
718
+ dstVault: SPOKE_VAULT_ADDRESS,
719
+ refundAddress: curatorAddress,
720
+ },
721
+ )
722
+ ```
723
+
724
+ ### Sub-vault operations
725
+
726
+ Curators invest vault assets into ERC4626/ERC7540 sub-vaults (Aave, Morpho, etc.) to generate yield.
727
+
728
+ ```ts
729
+ import {
730
+ getSubVaultPositions,
731
+ getVaultPortfolio,
732
+ getSubVaultInfo,
733
+ detectSubVaultType,
734
+ getERC7540RequestStatus,
735
+ previewSubVaultDeposit,
736
+ } from '@oydual31/more-vaults-sdk/viem'
737
+
738
+ // Full portfolio: liquid assets + sub-vault positions
739
+ const portfolio = await getVaultPortfolio(publicClient, VAULT)
740
+ // portfolio.liquidAssets — AssetBalance[] (tokens held directly)
741
+ // portfolio.subVaultPositions — SubVaultPosition[] (shares + underlying value)
742
+ // portfolio.totalValue — total in vault underlying units
743
+ // portfolio.lockedAssets — locked in pending ERC7540 requests
744
+
745
+ // Active sub-vault positions with current values
746
+ const positions = await getSubVaultPositions(publicClient, VAULT)
747
+ for (const p of positions) {
748
+ console.log(`${p.symbol}: ${p.sharesBalance} shares = ${p.underlyingValue} ${p.underlyingSymbol}`)
749
+ }
750
+
751
+ // Analyze a target sub-vault before investing
752
+ const info = await getSubVaultInfo(publicClient, VAULT, MORPHO_VAULT)
753
+ // info.type — 'erc4626' or 'erc7540'
754
+ // info.maxDeposit — capacity remaining
755
+ // info.isWhitelisted — must be true to invest
756
+
757
+ // Preview: how many shares would a 1000 USDC deposit yield?
758
+ const shares = await previewSubVaultDeposit(publicClient, MORPHO_VAULT, parseUnits('1000', 6))
759
+
760
+ // For ERC7540 async sub-vaults: check if requests are ready
761
+ const status = await getERC7540RequestStatus(publicClient, VAULT, ASYNC_VAULT)
762
+ if (status.canFinalizeDeposit) {
763
+ // Curator can now call erc7540Deposit via submitActions
764
+ }
765
+ ```
766
+
678
767
  ---
679
768
 
680
769
  ## Vault topology & distribution
@@ -849,6 +938,11 @@ Import from `@oydual31/more-vaults-sdk/react`. Requires wagmi v2 + @tanstack/rea
849
938
  | `useSubmitActions()` | Submit a batch of curator actions |
850
939
  | `useExecuteActions()` | Execute queued actions after timelock |
851
940
  | `useVetoActions()` | Guardian: cancel pending actions |
941
+ | `useCuratorBridgeQuote()` | Quote LayerZero fee for curator bridge |
942
+ | `useExecuteBridge()` | Execute curator bridge operation |
943
+ | `useSubVaultPositions()` | Active sub-vault positions with values |
944
+ | `useVaultPortfolio()` | Full portfolio: liquid + deployed + locked |
945
+ | `useERC7540RequestStatus()` | Pending/claimable ERC7540 request status |
852
946
 
853
947
  ### React example
854
948
 
@@ -188,6 +188,98 @@ interface VaultAssetBreakdown {
188
188
  /** Vault underlying token decimals */
189
189
  underlyingDecimals: number;
190
190
  }
191
+ /**
192
+ * A single active sub-vault position held by the curator vault.
193
+ * Covers both ERC4626 (synchronous) and ERC7540 (asynchronous) sub-vaults.
194
+ */
195
+ interface SubVaultPosition {
196
+ /** Sub-vault contract address */
197
+ address: Address;
198
+ /** Protocol type of the sub-vault */
199
+ type: 'erc4626' | 'erc7540';
200
+ /** Name of the sub-vault share token */
201
+ name: string;
202
+ /** Symbol of the sub-vault share token */
203
+ symbol: string;
204
+ /** Decimals of the sub-vault share token */
205
+ decimals: number;
206
+ /** Shares of the sub-vault held by the curator vault */
207
+ sharesBalance: bigint;
208
+ /** Current value of the shares in terms of the sub-vault's underlying asset */
209
+ underlyingValue: bigint;
210
+ /** Underlying asset address of the sub-vault */
211
+ underlyingAsset: Address;
212
+ /** Symbol of the sub-vault's underlying asset */
213
+ underlyingSymbol: string;
214
+ /** Decimals of the sub-vault's underlying asset */
215
+ underlyingDecimals: number;
216
+ }
217
+ /**
218
+ * Metadata and capability snapshot for a potential sub-vault investment target.
219
+ */
220
+ interface SubVaultInfo {
221
+ /** Sub-vault contract address */
222
+ address: Address;
223
+ /** Protocol type: ERC4626 (sync) or ERC7540 (async) */
224
+ type: 'erc4626' | 'erc7540';
225
+ /** Sub-vault share token name */
226
+ name: string;
227
+ /** Sub-vault share token symbol */
228
+ symbol: string;
229
+ /** Sub-vault share token decimals */
230
+ decimals: number;
231
+ /** Underlying asset address */
232
+ underlyingAsset: Address;
233
+ /** Underlying asset symbol */
234
+ underlyingSymbol: string;
235
+ /** Underlying asset decimals */
236
+ underlyingDecimals: number;
237
+ /** Maximum amount the curator vault can deposit (from maxDeposit(vault)) */
238
+ maxDeposit: bigint;
239
+ /** Whether the sub-vault is whitelisted in the global MoreVaults registry */
240
+ isWhitelisted: boolean;
241
+ }
242
+ /**
243
+ * Status of pending and claimable ERC7540 async requests for a sub-vault.
244
+ * Uses requestId = 0 (the standard default for non-batch ERC7540 vaults).
245
+ */
246
+ interface ERC7540RequestStatus {
247
+ /** Sub-vault address these statuses belong to */
248
+ subVault: Address;
249
+ /** Assets in a pending deposit request (not yet claimable) */
250
+ pendingDeposit: bigint;
251
+ /** Assets ready to be claimed/finalized as shares */
252
+ claimableDeposit: bigint;
253
+ /** Shares in a pending redeem request (not yet claimable) */
254
+ pendingRedeem: bigint;
255
+ /** Assets ready to be claimed after redeem fulfillment */
256
+ claimableRedeem: bigint;
257
+ /** True if claimableDeposit > 0 — vault can call erc7540Deposit to finalize */
258
+ canFinalizeDeposit: boolean;
259
+ /** True if claimableRedeem > 0 — vault can call erc7540Redeem to finalize */
260
+ canFinalizeRedeem: boolean;
261
+ }
262
+ /**
263
+ * Full portfolio view for a curator vault combining liquid and invested assets.
264
+ */
265
+ interface VaultPortfolio {
266
+ /** Liquid ERC20 asset balances held directly by the vault (excludes sub-vault share tokens) */
267
+ liquidAssets: AssetBalance[];
268
+ /** Active positions in ERC4626/ERC7540 sub-vaults */
269
+ subVaultPositions: SubVaultPosition[];
270
+ /**
271
+ * Approximate total value in underlying terms:
272
+ * liquid underlying balance + sum of sub-vault convertToAssets values.
273
+ * For the authoritative total, use `totalAssets` from the vault contract.
274
+ */
275
+ totalValue: bigint;
276
+ /** totalAssets() from the vault — authoritative AUM figure */
277
+ totalAssets: bigint;
278
+ /** totalSupply() of vault shares */
279
+ totalSupply: bigint;
280
+ /** Assets locked in pending ERC7540 requests (lockedTokensAmountOfAsset) */
281
+ lockedAssets: bigint;
282
+ }
191
283
 
192
284
  /**
193
285
  * Wait for a transaction receipt with generous timeout and retry logic.
@@ -818,4 +910,133 @@ declare function getOutboundRoutes(hubChainId: number, vault: Address): Promise<
818
910
  */
819
911
  declare function quoteRouteDepositFee(route: InboundRoute, hubChainId: number, amount: bigint, userAddress: Address): Promise<bigint>;
820
912
 
821
- export { getUserBalancesForRoutes as $, type AsyncRequestResult as A, type BatchSwapParams as B, type ComposeData as C, type DepositResult as D, type VaultSummary as E, type VaultTopology as F, canDeposit as G, detectStargateOft as H, type InboundRoute as I, discoverVaultTopology as J, ensureAllowance as K, getAllVaultChainIds as L, type MaxWithdrawable as M, NATIVE_SYMBOL as N, OMNI_FACTORY_ADDRESS as O, type PendingAction as P, getAsyncRequestStatus as Q, type RedeemResult as R, type SpokeDepositResult as S, getAsyncRequestStatusLabel as T, type UserBalances as U, type VaultAddresses as V, getFullVaultTopology as W, getInboundRoutes as X, getMaxWithdrawable as Y, getOutboundRoutes as Z, getUserBalances as _, type CuratorVaultStatus as a, getUserPosition as a0, getUserPositionMultiChain as a1, getVaultDistribution as a2, getVaultDistributionWithTopology as a3, getVaultMetadata as a4, getVaultStatus as a5, getVaultSummary as a6, getVaultTopology as a7, isAsyncMode as a8, isOnHubChain as a9, previewDeposit as aa, previewRedeem as ab, quoteLzFee as ac, quoteRouteDepositFee as ad, waitForAsyncRequest as ae, waitForTx as af, type VaultAnalysis as b, type VaultAssetBreakdown as c, type CuratorAction as d, type SubmitActionsResult as e, ActionType as f, type ActionTypeValue as g, type AssetBalance as h, type AssetInfo as i, type AsyncRequestFinalResult as j, type AsyncRequestStatus as k, type AsyncRequestStatusInfo as l, type BridgeParams as m, type CrossChainRequestInfo as n, type DepositBlockReason as o, type DepositEligibility as p, type InboundRouteWithBalance as q, type MultiChainUserPosition as r, type OutboundRoute as s, type SpokeBalance as t, type SwapParams as u, type UserPosition as v, type VaultDistribution as w, type VaultMetadata as x, type VaultMode as y, type VaultStatus as z };
913
+ /**
914
+ * Curator BridgeFacet helpers for the MoreVaults SDK.
915
+ *
916
+ * Provides typed helpers to quote and execute cross-chain asset bridging
917
+ * via BridgeFacet.executeBridging on any MoreVaults diamond.
918
+ *
919
+ * Key flows:
920
+ * 1. `quoteCuratorBridgeFee` — read-only fee estimation via LzAdapter
921
+ * 2. `executeCuratorBridge` — send bridging transaction (curator only)
922
+ * 3. `encodeBridgeParams` — encode the 5-field bridgeSpecificParams bytes
923
+ * 4. `findBridgeRoute` — resolve OFT route for a token on given chains
924
+ *
925
+ * Bridge call flow:
926
+ * curator → vault.executeBridging(adapter, token, amount, bridgeSpecificParams)
927
+ * bridgeSpecificParams = abi.encode(oftToken, dstEid, amount, dstVault, refundAddress)
928
+ *
929
+ * Quote call flow:
930
+ * publicClient → lzAdapter.quoteBridgeFee(encode(oftToken, dstEid, amount, dstVault))
931
+ *
932
+ * @module curatorBridge
933
+ */
934
+
935
+ /**
936
+ * Parameters for a curator bridge operation.
937
+ * Used in both quoting (4-field) and execution (5-field with refundAddress).
938
+ */
939
+ interface CuratorBridgeParams {
940
+ /** OFT contract address on the source chain (from OFT_ROUTES[symbol][chainId].oft) */
941
+ oftToken: Address;
942
+ /** LayerZero endpoint ID of the destination chain */
943
+ dstEid: number;
944
+ /** Amount to bridge (in token's native units) */
945
+ amount: bigint;
946
+ /** Vault address on the destination chain (hub or spoke) */
947
+ dstVault: Address;
948
+ /** Address where excess LayerZero gas refunds are sent (usually the curator wallet) */
949
+ refundAddress: Address;
950
+ }
951
+ /**
952
+ * Encode the 5-field bridgeSpecificParams for use in `executeBridging`.
953
+ *
954
+ * Encodes: (oftToken, dstEid, amount, dstVault, refundAddress)
955
+ * Types: (address, uint32, uint256, address, address)
956
+ *
957
+ * @param params Full bridge parameters including refundAddress
958
+ * @returns ABI-encoded bytes (`0x`-prefixed hex string)
959
+ */
960
+ declare function encodeBridgeParams(params: CuratorBridgeParams): `0x${string}`;
961
+ /**
962
+ * Find the OFT bridge route for a given token address on the source chain.
963
+ *
964
+ * Searches OFT_ROUTES for an asset whose `token` or `oft` field matches
965
+ * the provided address on the given source chainId.
966
+ *
967
+ * @param srcChainId EVM chain ID of the source chain (where the vault holds the token)
968
+ * @param dstChainId EVM chain ID of the destination chain
969
+ * @param tokenAddress ERC-20 token address on the source chain
970
+ * @returns Route info or null if no matching route exists
971
+ *
972
+ * @example
973
+ * ```typescript
974
+ * const route = findBridgeRoute(8453, 1, '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913')
975
+ * // → { symbol: 'stgUSDC', oftHub: '0x27a1...', oftSpoke: '0xc026...' }
976
+ * ```
977
+ */
978
+ declare function findBridgeRoute(srcChainId: number, dstChainId: number, tokenAddress: Address): {
979
+ oftSrc: Address;
980
+ oftDst: Address;
981
+ symbol: string;
982
+ } | null;
983
+ /**
984
+ * Quote the native fee required to bridge assets via the vault's LzAdapter.
985
+ *
986
+ * Calls `lzAdapter.quoteBridgeFee(bridgeSpecificParams)` using a 4-field
987
+ * encoding (no refundAddress). The returned fee must be sent as `msg.value`
988
+ * when calling `executeBridging`.
989
+ *
990
+ * @param publicClient Viem public client (must be on the vault's chain)
991
+ * @param vault Hub vault address (diamond proxy)
992
+ * @param params Bridge parameters (refundAddress is optional here)
993
+ * @returns Native fee in wei
994
+ *
995
+ * @example
996
+ * ```typescript
997
+ * const fee = await quoteCuratorBridgeFee(publicClient, VAULT, {
998
+ * oftToken: '0x27a16dc786820B16E5c9028b75B99F6f604b5d26', // stgUSDC on Base
999
+ * dstEid: 30101, // Ethereum EID
1000
+ * amount: 1_000_000n, // 1 USDC
1001
+ * dstVault: '0xSpokeVault...',
1002
+ * refundAddress: '0xCurator...',
1003
+ * })
1004
+ * console.log('Fee:', formatEther(fee), 'ETH')
1005
+ * ```
1006
+ */
1007
+ declare function quoteCuratorBridgeFee(publicClient: PublicClient, vault: Address, params: CuratorBridgeParams): Promise<bigint>;
1008
+ /**
1009
+ * Execute a curator bridge operation via `BridgeFacet.executeBridging`.
1010
+ *
1011
+ * This is a direct curator call (NOT via multicall). The vault pauses during
1012
+ * bridging for security. The `token` passed to executeBridging is the underlying
1013
+ * ERC-20, NOT the OFT address.
1014
+ *
1015
+ * Steps:
1016
+ * 1. Get lzAdapter from `getCuratorVaultStatus`
1017
+ * 2. Quote the native bridge fee
1018
+ * 3. Encode 5-field bridgeSpecificParams
1019
+ * 4. Call `vault.executeBridging(adapter, token, amount, bridgeSpecificParams)` with fee as value
1020
+ *
1021
+ * @param walletClient Wallet client with curator account attached
1022
+ * @param publicClient Public client for reads and fee quoting
1023
+ * @param vault Hub vault address (diamond proxy)
1024
+ * @param token Underlying ERC-20 token address (NOT the OFT address)
1025
+ * @param params Full bridge parameters including refundAddress
1026
+ * @returns Transaction hash
1027
+ * @throws If caller is not curator, vault is paused, or bridge fails
1028
+ *
1029
+ * @example
1030
+ * ```typescript
1031
+ * const txHash = await executeCuratorBridge(walletClient, publicClient, VAULT, USDC_ADDRESS, {
1032
+ * oftToken: '0x27a16dc786820B16E5c9028b75B99F6f604b5d26',
1033
+ * dstEid: 30101,
1034
+ * amount: 1_000_000n,
1035
+ * dstVault: '0xSpokeVault...',
1036
+ * refundAddress: curatorAddress,
1037
+ * })
1038
+ * ```
1039
+ */
1040
+ declare function executeCuratorBridge(walletClient: WalletClient, publicClient: PublicClient, vault: Address, token: Address, params: CuratorBridgeParams): Promise<Hash>;
1041
+
1042
+ export { getAllVaultChainIds as $, type AsyncRequestResult as A, type BatchSwapParams as B, type ComposeData as C, type DepositResult as D, type ERC7540RequestStatus as E, type VaultDistribution as F, type VaultMetadata as G, type VaultMode as H, type InboundRoute as I, type VaultStatus as J, type VaultSummary as K, type VaultTopology as L, type MaxWithdrawable as M, NATIVE_SYMBOL as N, OMNI_FACTORY_ADDRESS as O, type PendingAction as P, canDeposit as Q, type RedeemResult as R, type SpokeDepositResult as S, detectStargateOft as T, type UserBalances as U, type VaultAddresses as V, discoverVaultTopology as W, encodeBridgeParams as X, ensureAllowance as Y, executeCuratorBridge as Z, findBridgeRoute as _, type CuratorVaultStatus as a, getAsyncRequestStatus as a0, getAsyncRequestStatusLabel as a1, getFullVaultTopology as a2, getInboundRoutes as a3, getMaxWithdrawable as a4, getOutboundRoutes as a5, getUserBalances as a6, getUserBalancesForRoutes as a7, getUserPosition as a8, getUserPositionMultiChain as a9, getVaultDistribution as aa, getVaultDistributionWithTopology as ab, getVaultMetadata as ac, getVaultStatus as ad, getVaultSummary as ae, getVaultTopology as af, isAsyncMode as ag, isOnHubChain as ah, previewDeposit as ai, previewRedeem as aj, quoteCuratorBridgeFee as ak, quoteLzFee as al, quoteRouteDepositFee as am, waitForAsyncRequest as an, waitForTx as ao, type VaultAnalysis as b, type VaultAssetBreakdown as c, type CuratorAction as d, type SubmitActionsResult as e, type SubVaultInfo as f, type SubVaultPosition as g, type VaultPortfolio as h, ActionType as i, type ActionTypeValue as j, type AssetBalance as k, type AssetInfo as l, type AsyncRequestFinalResult as m, type AsyncRequestStatus as n, type AsyncRequestStatusInfo as o, type BridgeParams as p, type CrossChainRequestInfo as q, type CuratorBridgeParams as r, type DepositBlockReason as s, type DepositEligibility as t, type InboundRouteWithBalance as u, type MultiChainUserPosition as v, type OutboundRoute as w, type SpokeBalance as x, type SwapParams as y, type UserPosition as z };
@@ -188,6 +188,98 @@ interface VaultAssetBreakdown {
188
188
  /** Vault underlying token decimals */
189
189
  underlyingDecimals: number;
190
190
  }
191
+ /**
192
+ * A single active sub-vault position held by the curator vault.
193
+ * Covers both ERC4626 (synchronous) and ERC7540 (asynchronous) sub-vaults.
194
+ */
195
+ interface SubVaultPosition {
196
+ /** Sub-vault contract address */
197
+ address: Address;
198
+ /** Protocol type of the sub-vault */
199
+ type: 'erc4626' | 'erc7540';
200
+ /** Name of the sub-vault share token */
201
+ name: string;
202
+ /** Symbol of the sub-vault share token */
203
+ symbol: string;
204
+ /** Decimals of the sub-vault share token */
205
+ decimals: number;
206
+ /** Shares of the sub-vault held by the curator vault */
207
+ sharesBalance: bigint;
208
+ /** Current value of the shares in terms of the sub-vault's underlying asset */
209
+ underlyingValue: bigint;
210
+ /** Underlying asset address of the sub-vault */
211
+ underlyingAsset: Address;
212
+ /** Symbol of the sub-vault's underlying asset */
213
+ underlyingSymbol: string;
214
+ /** Decimals of the sub-vault's underlying asset */
215
+ underlyingDecimals: number;
216
+ }
217
+ /**
218
+ * Metadata and capability snapshot for a potential sub-vault investment target.
219
+ */
220
+ interface SubVaultInfo {
221
+ /** Sub-vault contract address */
222
+ address: Address;
223
+ /** Protocol type: ERC4626 (sync) or ERC7540 (async) */
224
+ type: 'erc4626' | 'erc7540';
225
+ /** Sub-vault share token name */
226
+ name: string;
227
+ /** Sub-vault share token symbol */
228
+ symbol: string;
229
+ /** Sub-vault share token decimals */
230
+ decimals: number;
231
+ /** Underlying asset address */
232
+ underlyingAsset: Address;
233
+ /** Underlying asset symbol */
234
+ underlyingSymbol: string;
235
+ /** Underlying asset decimals */
236
+ underlyingDecimals: number;
237
+ /** Maximum amount the curator vault can deposit (from maxDeposit(vault)) */
238
+ maxDeposit: bigint;
239
+ /** Whether the sub-vault is whitelisted in the global MoreVaults registry */
240
+ isWhitelisted: boolean;
241
+ }
242
+ /**
243
+ * Status of pending and claimable ERC7540 async requests for a sub-vault.
244
+ * Uses requestId = 0 (the standard default for non-batch ERC7540 vaults).
245
+ */
246
+ interface ERC7540RequestStatus {
247
+ /** Sub-vault address these statuses belong to */
248
+ subVault: Address;
249
+ /** Assets in a pending deposit request (not yet claimable) */
250
+ pendingDeposit: bigint;
251
+ /** Assets ready to be claimed/finalized as shares */
252
+ claimableDeposit: bigint;
253
+ /** Shares in a pending redeem request (not yet claimable) */
254
+ pendingRedeem: bigint;
255
+ /** Assets ready to be claimed after redeem fulfillment */
256
+ claimableRedeem: bigint;
257
+ /** True if claimableDeposit > 0 — vault can call erc7540Deposit to finalize */
258
+ canFinalizeDeposit: boolean;
259
+ /** True if claimableRedeem > 0 — vault can call erc7540Redeem to finalize */
260
+ canFinalizeRedeem: boolean;
261
+ }
262
+ /**
263
+ * Full portfolio view for a curator vault combining liquid and invested assets.
264
+ */
265
+ interface VaultPortfolio {
266
+ /** Liquid ERC20 asset balances held directly by the vault (excludes sub-vault share tokens) */
267
+ liquidAssets: AssetBalance[];
268
+ /** Active positions in ERC4626/ERC7540 sub-vaults */
269
+ subVaultPositions: SubVaultPosition[];
270
+ /**
271
+ * Approximate total value in underlying terms:
272
+ * liquid underlying balance + sum of sub-vault convertToAssets values.
273
+ * For the authoritative total, use `totalAssets` from the vault contract.
274
+ */
275
+ totalValue: bigint;
276
+ /** totalAssets() from the vault — authoritative AUM figure */
277
+ totalAssets: bigint;
278
+ /** totalSupply() of vault shares */
279
+ totalSupply: bigint;
280
+ /** Assets locked in pending ERC7540 requests (lockedTokensAmountOfAsset) */
281
+ lockedAssets: bigint;
282
+ }
191
283
 
192
284
  /**
193
285
  * Wait for a transaction receipt with generous timeout and retry logic.
@@ -818,4 +910,133 @@ declare function getOutboundRoutes(hubChainId: number, vault: Address): Promise<
818
910
  */
819
911
  declare function quoteRouteDepositFee(route: InboundRoute, hubChainId: number, amount: bigint, userAddress: Address): Promise<bigint>;
820
912
 
821
- export { getUserBalancesForRoutes as $, type AsyncRequestResult as A, type BatchSwapParams as B, type ComposeData as C, type DepositResult as D, type VaultSummary as E, type VaultTopology as F, canDeposit as G, detectStargateOft as H, type InboundRoute as I, discoverVaultTopology as J, ensureAllowance as K, getAllVaultChainIds as L, type MaxWithdrawable as M, NATIVE_SYMBOL as N, OMNI_FACTORY_ADDRESS as O, type PendingAction as P, getAsyncRequestStatus as Q, type RedeemResult as R, type SpokeDepositResult as S, getAsyncRequestStatusLabel as T, type UserBalances as U, type VaultAddresses as V, getFullVaultTopology as W, getInboundRoutes as X, getMaxWithdrawable as Y, getOutboundRoutes as Z, getUserBalances as _, type CuratorVaultStatus as a, getUserPosition as a0, getUserPositionMultiChain as a1, getVaultDistribution as a2, getVaultDistributionWithTopology as a3, getVaultMetadata as a4, getVaultStatus as a5, getVaultSummary as a6, getVaultTopology as a7, isAsyncMode as a8, isOnHubChain as a9, previewDeposit as aa, previewRedeem as ab, quoteLzFee as ac, quoteRouteDepositFee as ad, waitForAsyncRequest as ae, waitForTx as af, type VaultAnalysis as b, type VaultAssetBreakdown as c, type CuratorAction as d, type SubmitActionsResult as e, ActionType as f, type ActionTypeValue as g, type AssetBalance as h, type AssetInfo as i, type AsyncRequestFinalResult as j, type AsyncRequestStatus as k, type AsyncRequestStatusInfo as l, type BridgeParams as m, type CrossChainRequestInfo as n, type DepositBlockReason as o, type DepositEligibility as p, type InboundRouteWithBalance as q, type MultiChainUserPosition as r, type OutboundRoute as s, type SpokeBalance as t, type SwapParams as u, type UserPosition as v, type VaultDistribution as w, type VaultMetadata as x, type VaultMode as y, type VaultStatus as z };
913
+ /**
914
+ * Curator BridgeFacet helpers for the MoreVaults SDK.
915
+ *
916
+ * Provides typed helpers to quote and execute cross-chain asset bridging
917
+ * via BridgeFacet.executeBridging on any MoreVaults diamond.
918
+ *
919
+ * Key flows:
920
+ * 1. `quoteCuratorBridgeFee` — read-only fee estimation via LzAdapter
921
+ * 2. `executeCuratorBridge` — send bridging transaction (curator only)
922
+ * 3. `encodeBridgeParams` — encode the 5-field bridgeSpecificParams bytes
923
+ * 4. `findBridgeRoute` — resolve OFT route for a token on given chains
924
+ *
925
+ * Bridge call flow:
926
+ * curator → vault.executeBridging(adapter, token, amount, bridgeSpecificParams)
927
+ * bridgeSpecificParams = abi.encode(oftToken, dstEid, amount, dstVault, refundAddress)
928
+ *
929
+ * Quote call flow:
930
+ * publicClient → lzAdapter.quoteBridgeFee(encode(oftToken, dstEid, amount, dstVault))
931
+ *
932
+ * @module curatorBridge
933
+ */
934
+
935
+ /**
936
+ * Parameters for a curator bridge operation.
937
+ * Used in both quoting (4-field) and execution (5-field with refundAddress).
938
+ */
939
+ interface CuratorBridgeParams {
940
+ /** OFT contract address on the source chain (from OFT_ROUTES[symbol][chainId].oft) */
941
+ oftToken: Address;
942
+ /** LayerZero endpoint ID of the destination chain */
943
+ dstEid: number;
944
+ /** Amount to bridge (in token's native units) */
945
+ amount: bigint;
946
+ /** Vault address on the destination chain (hub or spoke) */
947
+ dstVault: Address;
948
+ /** Address where excess LayerZero gas refunds are sent (usually the curator wallet) */
949
+ refundAddress: Address;
950
+ }
951
+ /**
952
+ * Encode the 5-field bridgeSpecificParams for use in `executeBridging`.
953
+ *
954
+ * Encodes: (oftToken, dstEid, amount, dstVault, refundAddress)
955
+ * Types: (address, uint32, uint256, address, address)
956
+ *
957
+ * @param params Full bridge parameters including refundAddress
958
+ * @returns ABI-encoded bytes (`0x`-prefixed hex string)
959
+ */
960
+ declare function encodeBridgeParams(params: CuratorBridgeParams): `0x${string}`;
961
+ /**
962
+ * Find the OFT bridge route for a given token address on the source chain.
963
+ *
964
+ * Searches OFT_ROUTES for an asset whose `token` or `oft` field matches
965
+ * the provided address on the given source chainId.
966
+ *
967
+ * @param srcChainId EVM chain ID of the source chain (where the vault holds the token)
968
+ * @param dstChainId EVM chain ID of the destination chain
969
+ * @param tokenAddress ERC-20 token address on the source chain
970
+ * @returns Route info or null if no matching route exists
971
+ *
972
+ * @example
973
+ * ```typescript
974
+ * const route = findBridgeRoute(8453, 1, '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913')
975
+ * // → { symbol: 'stgUSDC', oftHub: '0x27a1...', oftSpoke: '0xc026...' }
976
+ * ```
977
+ */
978
+ declare function findBridgeRoute(srcChainId: number, dstChainId: number, tokenAddress: Address): {
979
+ oftSrc: Address;
980
+ oftDst: Address;
981
+ symbol: string;
982
+ } | null;
983
+ /**
984
+ * Quote the native fee required to bridge assets via the vault's LzAdapter.
985
+ *
986
+ * Calls `lzAdapter.quoteBridgeFee(bridgeSpecificParams)` using a 4-field
987
+ * encoding (no refundAddress). The returned fee must be sent as `msg.value`
988
+ * when calling `executeBridging`.
989
+ *
990
+ * @param publicClient Viem public client (must be on the vault's chain)
991
+ * @param vault Hub vault address (diamond proxy)
992
+ * @param params Bridge parameters (refundAddress is optional here)
993
+ * @returns Native fee in wei
994
+ *
995
+ * @example
996
+ * ```typescript
997
+ * const fee = await quoteCuratorBridgeFee(publicClient, VAULT, {
998
+ * oftToken: '0x27a16dc786820B16E5c9028b75B99F6f604b5d26', // stgUSDC on Base
999
+ * dstEid: 30101, // Ethereum EID
1000
+ * amount: 1_000_000n, // 1 USDC
1001
+ * dstVault: '0xSpokeVault...',
1002
+ * refundAddress: '0xCurator...',
1003
+ * })
1004
+ * console.log('Fee:', formatEther(fee), 'ETH')
1005
+ * ```
1006
+ */
1007
+ declare function quoteCuratorBridgeFee(publicClient: PublicClient, vault: Address, params: CuratorBridgeParams): Promise<bigint>;
1008
+ /**
1009
+ * Execute a curator bridge operation via `BridgeFacet.executeBridging`.
1010
+ *
1011
+ * This is a direct curator call (NOT via multicall). The vault pauses during
1012
+ * bridging for security. The `token` passed to executeBridging is the underlying
1013
+ * ERC-20, NOT the OFT address.
1014
+ *
1015
+ * Steps:
1016
+ * 1. Get lzAdapter from `getCuratorVaultStatus`
1017
+ * 2. Quote the native bridge fee
1018
+ * 3. Encode 5-field bridgeSpecificParams
1019
+ * 4. Call `vault.executeBridging(adapter, token, amount, bridgeSpecificParams)` with fee as value
1020
+ *
1021
+ * @param walletClient Wallet client with curator account attached
1022
+ * @param publicClient Public client for reads and fee quoting
1023
+ * @param vault Hub vault address (diamond proxy)
1024
+ * @param token Underlying ERC-20 token address (NOT the OFT address)
1025
+ * @param params Full bridge parameters including refundAddress
1026
+ * @returns Transaction hash
1027
+ * @throws If caller is not curator, vault is paused, or bridge fails
1028
+ *
1029
+ * @example
1030
+ * ```typescript
1031
+ * const txHash = await executeCuratorBridge(walletClient, publicClient, VAULT, USDC_ADDRESS, {
1032
+ * oftToken: '0x27a16dc786820B16E5c9028b75B99F6f604b5d26',
1033
+ * dstEid: 30101,
1034
+ * amount: 1_000_000n,
1035
+ * dstVault: '0xSpokeVault...',
1036
+ * refundAddress: curatorAddress,
1037
+ * })
1038
+ * ```
1039
+ */
1040
+ declare function executeCuratorBridge(walletClient: WalletClient, publicClient: PublicClient, vault: Address, token: Address, params: CuratorBridgeParams): Promise<Hash>;
1041
+
1042
+ export { getAllVaultChainIds as $, type AsyncRequestResult as A, type BatchSwapParams as B, type ComposeData as C, type DepositResult as D, type ERC7540RequestStatus as E, type VaultDistribution as F, type VaultMetadata as G, type VaultMode as H, type InboundRoute as I, type VaultStatus as J, type VaultSummary as K, type VaultTopology as L, type MaxWithdrawable as M, NATIVE_SYMBOL as N, OMNI_FACTORY_ADDRESS as O, type PendingAction as P, canDeposit as Q, type RedeemResult as R, type SpokeDepositResult as S, detectStargateOft as T, type UserBalances as U, type VaultAddresses as V, discoverVaultTopology as W, encodeBridgeParams as X, ensureAllowance as Y, executeCuratorBridge as Z, findBridgeRoute as _, type CuratorVaultStatus as a, getAsyncRequestStatus as a0, getAsyncRequestStatusLabel as a1, getFullVaultTopology as a2, getInboundRoutes as a3, getMaxWithdrawable as a4, getOutboundRoutes as a5, getUserBalances as a6, getUserBalancesForRoutes as a7, getUserPosition as a8, getUserPositionMultiChain as a9, getVaultDistribution as aa, getVaultDistributionWithTopology as ab, getVaultMetadata as ac, getVaultStatus as ad, getVaultSummary as ae, getVaultTopology as af, isAsyncMode as ag, isOnHubChain as ah, previewDeposit as ai, previewRedeem as aj, quoteCuratorBridgeFee as ak, quoteLzFee as al, quoteRouteDepositFee as am, waitForAsyncRequest as an, waitForTx as ao, type VaultAnalysis as b, type VaultAssetBreakdown as c, type CuratorAction as d, type SubmitActionsResult as e, type SubVaultInfo as f, type SubVaultPosition as g, type VaultPortfolio as h, ActionType as i, type ActionTypeValue as j, type AssetBalance as k, type AssetInfo as l, type AsyncRequestFinalResult as m, type AsyncRequestStatus as n, type AsyncRequestStatusInfo as o, type BridgeParams as p, type CrossChainRequestInfo as q, type CuratorBridgeParams as r, type DepositBlockReason as s, type DepositEligibility as t, type InboundRouteWithBalance as u, type MultiChainUserPosition as v, type OutboundRoute as w, type SpokeBalance as x, type SwapParams as y, type UserPosition as z };