import { type AccrualVaultV2, type MarketParams } from "@morpho-org/blue-sdk"; import { fetchAccrualVaultV2 } from "@morpho-org/blue-sdk-viem"; import { type Address } from "viem"; import type { FetchParameters } from "../../types/data.js"; import { type ActionOutput, type Deallocation, type DepositAmountArgs, type ERC20ApprovalAction, type MorphoClientType, type PermitRequirementSignature, type Requirement, type RequirementSignature, type Transaction, type VaultV2DepositAction, type VaultV2ForceRedeemAction, type VaultV2ForceWithdrawAction, type VaultV2InKindRedeemAction, type VaultV2RedeemAction, type VaultV2WithdrawAction } from "../../types/index.js"; export interface VaultV2Actions { /** * Fetches the latest vault data. * * This function fetches the latest vault data from the blockchain. * @param {FetchParameters} [parameters] - The parameters for the fetch operation. * * @returns {Promise>>} The latest vault data. */ getData: (parameters?: FetchParameters) => Promise>>; /** * Prepares a deposit transaction for the VaultV2 contract. * * This function constructs the transaction data required to deposit a specified amount of assets into the vault. * Uses pre-fetched vault data for accurate calculations of slippage and asset address, * then returns the prepared deposit transaction and a function for retrieving all required approval transactions. * Bundler Integration: This flow uses the bundler to atomically execute the user's asset transfer and vault deposit in a single transaction for slippage protection. * * @param {Object} params - The deposit parameters. * @param {bigint} [params.amount=0n] - Amount of ERC-20 assets to deposit. At least one of amount or nativeAmount must be provided. * @param {Address} params.userAddress - User address initiating the deposit. * @param {AccrualVaultV2} params.vaultData - Pre-fetched vault data with asset address and share conversion. * @param {bigint} [params.slippageTolerance=DEFAULT_SLIPPAGE_TOLERANCE] - Optional slippage tolerance value. Default is 0.03%. Slippage tolerance must be less than 10%. * @param {bigint} [params.nativeAmount] - Amount of native token to wrap into wNative. Vault asset must be wNative. * @returns {Object} The result object. * @returns {Readonly>} returns.tx The prepared deposit transaction. * @returns {Promise<(Readonly> | Requirement)[]>} returns.getRequirements The function for retrieving all required approval transactions. * @throws {UnsupportedBlueMarketIrmError} when an underlying market with positive debt uses an unsupported IRM. */ deposit: (params: { userAddress: Address; vaultData: AccrualVaultV2; slippageTolerance?: bigint; } & DepositAmountArgs) => { buildTx: (signatures?: readonly RequirementSignature[]) => Readonly>; getRequirements: (params?: { useSimplePermit?: boolean; }) => Promise<(Readonly> | Requirement)[]>; }; /** * Prepares a withdraw transaction for the VaultV2 contract. * * This function constructs the transaction data required to withdraw a specified amount of assets from the vault. * * @param {Object} params - The withdraw parameters. * @param {bigint} params.amount - The amount of assets to withdraw. * @param {Address} params.userAddress - User address initiating the withdraw. * @returns {Object} The result object. * @returns {Readonly>} returns.tx The prepared withdraw transaction. */ withdraw: (params: { amount: bigint; userAddress: Address; }) => { buildTx: () => Readonly>; }; /** * Prepares a redeem transaction for the VaultV2 contract. * * This function constructs the transaction data required to redeem a specified amount of shares from the vault. * * @param {Object} params - The redeem parameters. * @param {bigint} params.shares - The amount of shares to redeem. * @param {Address} params.userAddress - User address initiating the redeem. * @returns {Object} The result object. * @returns {Readonly>} returns.tx The prepared redeem transaction. */ redeem: (params: { shares: bigint; userAddress: Address; }) => { buildTx: () => Readonly>; }; /** * Prepares an illiquid Vault V2 exit into idle assets and Morpho Blue supply positions. * * The vault must have exactly one `MorphoMarketV1AdapterV2`. `amount` is penalty-inclusive and * the caller controls market order. Call `getRequirements()` before `buildTx()` so Blue balance, * allowance, and nonce are checked on-chain. Vault gates are enforced by the final transaction * and are not preflighted: receive gates may depend on VaultExitBundlesV1's transient initiator, * while arbitrary send-share gates may depend on intermediate state changed by the exit's * multiple share burns. The SDK intentionally does not validate the user's share balance; size * it so `amount + BigInt(marketParamsList.length) <= vault.previewRedeem(sharesHeld)`. The * per-market term covers V2 withdrawal rounding and is not needed for V1. The share allowance * includes that buffer, the penalty burns, and accrual through the bundle deadline. * * Idle balance, penalty, and adapter positions can drift after the snapshot, so an on-chain * under-coverage panic remains possible if vault state changes between preparation and inclusion. * * @param params - In-kind redemption parameters. * @param params.amount - Penalty-inclusive, asset-denominated amount to exit. * @param params.marketParamsList - Ordered adapter markets consumed greedily after idle assets; * its length is also the V2 share-sufficiency rounding buffer. * @param params.vaultData - Pre-fetched Vault V2 accrual snapshot. * @param params.userAddress - Account that signs and submits the exit. * @param params.adapter - Optional adapter override; defaults to the vault's sole adapter. * @param params.deadline - Optional shared permit/bundle deadline; defaults to two hours from now. * @returns Lazy prerequisite resolution and a synchronous transaction builder. * @throws {ChainIdMismatchError} when the client and entity target different chains. * @throws {UnsupportedBlueMarketIrmError} when an adapter-listed market with positive debt uses an unsupported IRM. * @throws {VaultAddressMismatchError} when `vaultData` belongs to another vault. * @throws {NonPositiveInputError} when `amount` is not positive. * @throws {InKindRedeemZeroDeallocationError} when the vault has no idle assets and the * penalty-adjusted amount rounds to zero deallocated assets. * @throws {EmptyMarketParamsListError} when assets must be deallocated and the market list is empty. * @throws {ExpiredDeadlineError} when `deadline` is not in the future at handle creation or * requirement resolution. * @throws {InKindRedeemRequiresSingleAdapterError} when the vault does not have one adapter. * @throws {AdapterNotPartOfVaultError} when `adapter` is not the vault's adapter. * @throws {UnsupportedInKindAdapterError} when the adapter is not a MorphoMarketV1AdapterV2. * @throws {InKindRedeemCoverageError} when the deduplicated list cannot cover the exit. * @throws {UnsupportedChainIdError} when no address registry exists for the target chain. * @throws {UnknownAddressError} when VaultExitBundlesV1 is not registered on the target chain. * @throws {viem.BaseError} from `getRequirements()` when an RPC or multicall contract read fails. * @throws {InsufficientBlueBalanceForInKindRedeemError} from `getRequirements()` when Blue cannot fund the largest callback. * @throws {AmbiguousRequirementSignaturesError} from `buildTx()` when more than one permit signature is supplied. * @throws {UnexpectedRequirementSignatureError} from `buildTx()` when a non-permit signature is supplied. * @throws {VaultExitBundlesV1PermitMismatchError} from `buildTx()` when the requirement has the wrong permit kind, asset, or signature encoding. * @example * ```ts * import { isRequirementSignature } from "@morpho-org/morpho-sdk"; * * const vault = client.morpho.vaultV2(vaultAddress, 1); * const vaultData = await vault.getData(); * const exit = vault.inKindRedeem({ * amount: 1_000_000n, * marketParamsList, * vaultData, * userAddress, * }); * const signatures = []; * for (const requirement of await exit.getRequirements()) { * if (isRequirementSignature(requirement)) { * signatures.push(await requirement.sign(walletClient, userAddress)); * } else { * const hash = await walletClient.sendTransaction(requirement); * await client.waitForTransactionReceipt({ hash }); * } * } * const tx = exit.buildTx(signatures); * // tx satisfies Readonly> * ``` */ readonly inKindRedeem: (params: { readonly amount: bigint; readonly marketParamsList: readonly MarketParams[]; readonly vaultData: AccrualVaultV2; readonly userAddress: Address; readonly adapter?: Address; readonly deadline?: bigint; }) => ActionOutput; /** * Prepares a force withdraw transaction for the VaultV2 contract using the vault's native multicall. * * This function encodes one or more on-chain forceDeallocate calls followed by a single withdraw, * executed atomically via VaultV2's multicall. This allows a user to free liquidity from multiple * illiquid markets and withdraw the resulting assets in one transaction. * * @param {Object} params - The force withdraw parameters. * @param {readonly Deallocation[]} params.deallocations - The typed list of deallocations to perform. * @param {Object} params.withdraw - The withdraw parameters applied after deallocations. * @param {bigint} params.withdraw.amount - The amount of assets to withdraw. * @param {Address} params.userAddress - User address (penalty source and withdraw recipient). * @returns {Object} The result object. * @returns {Readonly>} returns.buildTx The prepared multicall transaction. */ forceWithdraw: (params: { deallocations: readonly Deallocation[]; withdraw: { amount: bigint; }; userAddress: Address; }) => { buildTx: () => Readonly>; }; /** * Prepares a force redeem transaction for the VaultV2 contract using the vault's native multicall. * * This function encodes one or more on-chain forceDeallocate calls followed by a single redeem, * executed atomically via VaultV2's multicall. This allows a user to free liquidity from multiple * illiquid markets and redeem all their shares in one transaction. * * This is the share-based counterpart to forceWithdraw, useful for maximum withdrawal scenarios * where specifying an exact asset amount is impractical. * * The total assets passed to forceDeallocate calls must be greater than or equal to the * asset-equivalent of the redeemed shares. The caller should apply a buffer on the deallocated * amounts to account for share-price drift between submission and execution. * * @param {Object} params - The force redeem parameters. * @param {readonly Deallocation[]} params.deallocations - The typed list of deallocations to perform. * @param {Object} params.redeem - The redeem parameters applied after deallocations. * @param {bigint} params.redeem.shares - The amount of shares to redeem. * @param {Address} params.userAddress - User address (penalty source and redeem recipient). * @returns {Object} The result object. * @returns {Readonly>} returns.buildTx The prepared multicall transaction. */ forceRedeem: (params: { deallocations: readonly Deallocation[]; redeem: { shares: bigint; }; userAddress: Address; }) => { buildTx: () => Readonly>; }; } export declare class MorphoVaultV2 implements VaultV2Actions { private readonly client; private readonly vault; private readonly chainId; constructor(client: MorphoClientType, vault: Address, chainId: number); getData(parameters?: FetchParameters): Promise; deposit({ amount, userAddress, vaultData, slippageTolerance, nativeAmount, }: { userAddress: Address; vaultData: AccrualVaultV2; slippageTolerance?: bigint; } & DepositAmountArgs): { getRequirements: (params?: { useSimplePermit?: boolean; }) => Promise<(import("../../types/action.js").Bundler3TokenSignatureRequirement | Readonly>)[]>; buildTx: (signatures?: readonly RequirementSignature[]) => Readonly>; }; withdraw({ amount, userAddress }: { amount: bigint; userAddress: Address; }): { buildTx: () => Readonly>; }; redeem({ shares, userAddress }: { shares: bigint; userAddress: Address; }): { buildTx: () => Readonly>; }; /** {@inheritDoc VaultV2Actions.inKindRedeem} */ inKindRedeem({ amount, marketParamsList, vaultData, userAddress, adapter: adapterOverride, deadline: deadlineOverride, }: { readonly amount: bigint; readonly marketParamsList: readonly MarketParams[]; readonly vaultData: AccrualVaultV2; readonly userAddress: Address; readonly adapter?: Address; readonly deadline?: bigint; }): ActionOutput; forceWithdraw({ deallocations, withdraw, userAddress, }: { deallocations: readonly Deallocation[]; withdraw: { amount: bigint; }; userAddress: Address; }): { buildTx: () => Readonly>; }; forceRedeem({ deallocations, redeem, userAddress, }: { deallocations: readonly Deallocation[]; redeem: { shares: bigint; }; userAddress: Address; }): { buildTx: () => Readonly>; }; }