@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.
- package/README.md +94 -0
- package/dist/{spokeRoutes-B8Lnk-t4.d.cts → curatorBridge-CNs59kT9.d.cts} +222 -1
- package/dist/{spokeRoutes-B8Lnk-t4.d.ts → curatorBridge-CNs59kT9.d.ts} +222 -1
- package/dist/ethers/index.cjs +328 -3
- package/dist/ethers/index.cjs.map +1 -1
- package/dist/ethers/index.d.cts +279 -1
- package/dist/ethers/index.d.ts +279 -1
- package/dist/ethers/index.js +318 -5
- package/dist/ethers/index.js.map +1 -1
- package/dist/react/index.cjs +375 -0
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +266 -2
- package/dist/react/index.d.ts +266 -2
- package/dist/react/index.js +372 -2
- package/dist/react/index.js.map +1 -1
- package/dist/viem/index.cjs +377 -0
- package/dist/viem/index.cjs.map +1 -1
- package/dist/viem/index.d.cts +261 -3
- package/dist/viem/index.d.ts +261 -3
- package/dist/viem/index.js +367 -2
- package/dist/viem/index.js.map +1 -1
- package/package.json +1 -1
- package/src/ethers/abis.ts +24 -0
- package/src/ethers/curatorBridge.ts +235 -0
- package/src/ethers/curatorSubVaults.ts +443 -0
- package/src/ethers/index.ts +26 -0
- package/src/ethers/types.ts +99 -0
- package/src/react/index.ts +14 -0
- package/src/react/useCuratorBridgeQuote.ts +43 -0
- package/src/react/useERC7540RequestStatus.ts +43 -0
- package/src/react/useExecuteBridge.ts +50 -0
- package/src/react/useSubVaultPositions.ts +35 -0
- package/src/react/useVaultPortfolio.ts +35 -0
- package/src/viem/abis.ts +24 -0
- package/src/viem/curatorBridge.ts +288 -0
- package/src/viem/curatorSubVaults.ts +514 -0
- package/src/viem/index.ts +23 -0
- 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
|
-
|
|
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
|
-
|
|
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 };
|