/** * Cross-Chain Vault Type Definitions * * Defines all request/response interfaces for LayerZero OVault cross-chain * vault operations. These types are generic and not tied to any specific * vault configuration — SDK consumers provide their own config. * * @module evm/types/crossChain */ import type { IAddress } from '../../types'; /** * Injected dependency for the `@layerzerolabs/ovault-evm` SDK. * * Because the `@layerzerolabs/ovault-evm` package has broken ESM exports * (bare directory imports in a `"type": "module"` package), the SDK cannot * `require()` it internally. Instead, the consuming application imports it * in its own bundler context and passes it to SDK functions via this type. * * @example * ```ts * import { OVaultSyncMessageBuilder, OVaultSyncOperations } from '@layerzerolabs/ovault-evm'; * * await buildCrossChainVaultTx({ * ovaultSdk: { OVaultSyncMessageBuilder, OVaultSyncOperations }, * // ...other params * }); * ``` */ export interface IOVaultSdkDependency { OVaultSyncMessageBuilder: { generateOVaultInputs: (input: unknown) => Promise; [key: string]: unknown; }; OVaultSyncOperations: { DEPOSIT: string; REDEEM: string; }; } /** * Cross-chain vault configuration provided by SDK consumers. * * Each vault deployment requires 5 contract types: * 1. AssetOFT — OFT wrapper for the underlying asset (e.g., USDC) on hub + spoke chains * 2. ERC4626 Vault — The actual vault contract on the hub chain * 3. ShareOFTAdapter — Wraps vault shares for cross-chain transport (hub chain) * 4. ComposerSync — Orchestrates cross-chain operations (hub chain) * 5. ShareOFT — Share token representation on spoke chains */ export interface ICrossChainVaultConfig { /** Human-readable vault name */ vaultName: string; /** Vault receipt token symbol */ vaultSymbol: string; /** Chain ID where the ERC4626 vault lives */ hubChainId: number; /** Address of the ERC4626 vault on the hub chain */ vaultAddress: IAddress; /** Chain IDs where users can deposit from (spoke chains) */ spokeChainIds: number[]; /** Contract addresses for the OVault deployment */ contracts: { /** Underlying asset token addresses per chain (e.g., native USDC) */ assetToken: Record; /** AssetOFT (OFT wrapper for the asset) addresses per chain */ assetOFT: Record; /** ShareOFTAdapter address on the hub chain */ shareOFTAdapter: IAddress; /** VaultComposerSync address on the hub chain */ composerSync: IAddress; /** ShareOFT addresses on spoke chains */ shareOFT: Record; }; /** LayerZero Endpoint IDs (NOT chain IDs) */ layerZeroEids: { /** Hub chain LayerZero EID */ hub: number; /** Spoke chain LayerZero EIDs keyed by chain ID */ spokes: Record; }; /** * Multi-asset vault support. * When set, the vault uses `previewDeposit(address, uint256)` instead of * the standard ERC4626 `previewDeposit(uint256)`. */ multiAsset?: { /** Asset address on hub chain used for previewDeposit calls */ hubAssetAddress: IAddress; }; /** * When `true`, the vault's receipt token cannot leave the hub chain: there * is no OFT/bridge for it, so minting shares on a spoke would strand the * user. Withdraw UIs must offer the hub chain only. Defaults * to `false` when omitted. Drives `getWithdrawDestinationChains`. */ hubOnlyReceipt?: boolean; } /** Operation type for cross-chain vault transactions */ export type CrossChainOperation = 'DEPOSIT' | 'REDEEM'; /** * Parameters for building a cross-chain vault transaction. * Used internally by `buildCrossChainVaultTx`. */ export interface ICrossChainBuildRequest { /** Injected `@layerzerolabs/ovault-evm` SDK dependency */ ovaultSdk: IOVaultSdkDependency; /** Cross-chain vault configuration */ config: ICrossChainVaultConfig; /** Operation to perform */ operation: CrossChainOperation; /** Amount to deposit/redeem (human-readable string, raw bigint, or number) */ amount: string | number | bigint; /** Decimals of the token being deposited/redeemed */ decimals: number; /** Chain ID the user is currently on */ userChainId: number; /** User's wallet address */ walletAddress: IAddress; /** Chain to receive shares (deposit) or assets (redeem). Defaults to user's chain */ destinationChainId?: number; /** Recipient address. Defaults to walletAddress */ recipientAddress?: IAddress; /** Slippage tolerance in basis points (default: 100 = 1%) */ slippageBps?: number; /** * viem Chain object for the hub chain (with RPC URLs configured). * Required for SDK to create a public client for on-chain reads. */ hubChain: unknown; /** * viem Chain object for the user's source chain (with RPC URLs configured). */ sourceChain: unknown; /** Fee buffer percentage applied to LZ native fees (default: 50) */ feeBufferPercent?: number; /** Gas limit for lzCompose on hub chain (default: 2_000_000n) */ hubLzComposeGasLimit?: bigint; } /** * Result from building a cross-chain vault transaction. */ export interface ICrossChainBuildResult { success: boolean; data?: { /** Contract address to call */ contractAddress: IAddress; /** Function name to call on the contract */ contractFunctionName: string; /** ABI for the contract call */ abi: readonly unknown[]; /** Arguments for the contract function */ txArgs: readonly unknown[]; /** Native value to send with the transaction (includes LZ fees) */ messageValue: bigint; /** LayerZero messaging fee breakdown */ messageFee: { nativeFee: bigint; lzTokenFee: bigint; }; /** Expected output amount on destination */ dstAmount: bigint; /** Minimum output amount (after slippage) */ minDstAmount: bigint; /** Approval info if token approval is required */ approval?: { tokenAddress: IAddress; spender: IAddress; amount: bigint; }; }; error?: string; } /** * Request parameters for executing a cross-chain deposit. */ export interface ICrossChainDepositRequest { /** Injected `@layerzerolabs/ovault-evm` SDK dependency */ ovaultSdk: IOVaultSdkDependency; /** Cross-chain vault configuration */ config: ICrossChainVaultConfig; /** Amount to deposit (human-readable) */ amount: string; /** Decimals of the deposit token */ decimals: number; /** Chain ID the user is depositing from */ userChainId: number; /** User's wallet address */ walletAddress: IAddress; /** viem WalletClient for signing transactions */ walletClient: unknown; /** viem PublicClient for reading chain state */ publicClient: unknown; /** viem Chain object for the hub chain (with RPC URLs) */ hubChain: unknown; /** viem Chain object for the source chain (with RPC URLs) */ sourceChain: unknown; /** Chain to receive shares on. Defaults to user's chain */ destinationChainId?: number; /** Skip the internal approval check (set true when caller handles approval) */ skipApprovalCheck?: boolean; /** Slippage tolerance in basis points (default: 100 = 1%) */ slippageBps?: number; /** Fee buffer percentage (default: 50) */ feeBufferPercent?: number; /** Gas buffer multiplier as percentage (default: 150 = 1.5x) */ gasBufferPercent?: number; } /** * Result from a cross-chain deposit execution. */ export interface ICrossChainDepositResult { /** Transaction hash */ transactionHash: string; /** Whether the on-chain receipt shows success */ success: boolean; } /** * Request parameters for executing a cross-chain redemption. */ export interface ICrossChainRedeemRequest { /** Injected `@layerzerolabs/ovault-evm` SDK dependency */ ovaultSdk: IOVaultSdkDependency; /** Cross-chain vault configuration */ config: ICrossChainVaultConfig; /** Amount of shares to redeem (human-readable) */ amount: string; /** Decimals of the share token */ decimals: number; /** Chain ID the user is on (must be hub chain) */ userChainId: number; /** User's wallet address */ walletAddress: IAddress; /** viem WalletClient for signing transactions */ walletClient: unknown; /** viem PublicClient for reading chain state */ publicClient: unknown; /** viem Chain object for the hub chain (with RPC URLs) */ hubChain: unknown; /** viem Chain object for the source chain (with RPC URLs) */ sourceChain: unknown; /** Chain to receive assets on. Defaults to user's chain */ destinationChainId?: number; /** Skip the internal approval check (set true when caller handles approval) */ skipApprovalCheck?: boolean; /** Slippage tolerance in basis points (default: 100 = 1%) */ slippageBps?: number; /** Fee buffer percentage (default: 50) */ feeBufferPercent?: number; /** Gas buffer multiplier as percentage (default: 200 = 2x) */ gasBufferPercent?: number; /** Minimum gas limit for redeem operations (default: 5_000_000n) */ minGasLimit?: bigint; } /** * Result from a cross-chain redeem execution. */ export interface ICrossChainRedeemResult { /** Transaction hash */ transactionHash: string; /** Whether the on-chain receipt shows success */ success: boolean; } /** * Request parameters for quoting a cross-chain deposit. */ export interface IQuoteCrossChainDepositRequest { /** Injected `@layerzerolabs/ovault-evm` SDK dependency */ ovaultSdk: IOVaultSdkDependency; /** Cross-chain vault configuration */ config: ICrossChainVaultConfig; /** Amount to deposit (human-readable) */ amount: string; /** Decimals of the deposit token */ decimals: number; /** Chain ID the user would deposit from */ userChainId: number; /** User's wallet address */ walletAddress: IAddress; /** viem Chain object for the hub chain (with RPC URLs) */ hubChain: unknown; /** viem Chain object for the source chain (with RPC URLs) */ sourceChain: unknown; /** Destination chain for shares */ destinationChainId?: number; /** Slippage tolerance in basis points (default: 100 = 1%) */ slippageBps?: number; /** Fee buffer percentage (default: 50) */ feeBufferPercent?: number; } /** * Request parameters for quoting a cross-chain redeem. */ export interface IQuoteCrossChainRedeemRequest { /** Injected `@layerzerolabs/ovault-evm` SDK dependency */ ovaultSdk: IOVaultSdkDependency; /** Cross-chain vault configuration */ config: ICrossChainVaultConfig; /** Amount of shares to redeem (human-readable) */ amount: string; /** Decimals of the share token */ decimals: number; /** User's wallet address */ walletAddress: IAddress; /** viem Chain object for the hub chain (with RPC URLs) */ hubChain: unknown; /** viem Chain object for the source chain (with RPC URLs) */ sourceChain: unknown; /** Destination chain for assets */ destinationChainId?: number; /** Slippage tolerance in basis points (default: 100 = 1%) */ slippageBps?: number; /** Fee buffer percentage (default: 50) */ feeBufferPercent?: number; } /** * Result from a cross-chain fee/output quote. */ export interface IQuoteCrossChainResult { /** Native fee in wei (includes buffer) */ nativeFee: bigint; /** Expected output amount on destination */ dstAmount: bigint; /** Minimum output amount (after slippage) */ minDstAmount: bigint; /** Unix epoch (ms) when this quote was generated. */ quotedAt: number; /** Unix epoch (ms) after which this quote is stale. */ expiresAt: number; } /** Default validity window for a cross-chain quote (30s). */ export declare const CROSS_CHAIN_QUOTE_TTL_MS = 30000; /** Returns `true` when the quote should be refreshed before submitting. */ export declare function isQuoteStale(quote: Pick, now?: number): boolean; /** * Cross-chain operation status for tracking LayerZero messages. */ export interface ICrossChainOperationStatus { /** Source chain transaction hash */ srcTxHash: string; /** Current status of the cross-chain message */ status: 'PENDING' | 'INFLIGHT' | 'DELIVERED' | 'FAILED'; /** Source chain ID */ srcChainId: number; /** Destination chain ID */ dstChainId: number; } /** * Refund status for failed cross-chain operations. * LayerZero may refund assets if delivery fails. */ export interface IRefundStatus { /** Whether a refund has been initiated */ refunded: boolean; /** Refund transaction hash (if available) */ refundTxHash?: string; /** Amount refunded in the source token's smallest unit */ refundAmount?: bigint; /** Chain ID where the refund was issued */ refundChainId?: number; } /** * Error classification for cross-chain operations. */ export type CrossChainErrorType = 'max-deposit' | 'nonce' | 'no-peer' | 'bridge-fee' | 'insufficient-balance' | 'user-rejected' | 'gas' | 'network' | 'unknown';