import { type AccrualVault, type AccrualVaultV2, type MarketParams } from "@morpho-org/blue-sdk"; import { fetchAccrualVault } from "@morpho-org/blue-sdk-viem"; import { type Address } from "viem"; import type { FetchParameters } from "../../types/data.js"; import { type ActionOutput, type DepositAmountArgs, type ERC20ApprovalAction, type MorphoClientType, type PermitRequirementSignature, type Requirement, type RequirementSignature, type Transaction, type VaultV1DepositAction, type VaultV1InKindRedeemAction, type VaultV1MigrateToV2Action, type VaultV1RedeemAction, type VaultV1WithdrawAction } from "../../types/index.js"; export interface VaultV1Actions { /** * Fetches direct onchain vault and allocation state without applying virtual interest. * * @param {FetchParameters} [parameters] - Optional fetch parameters (block number, state overrides, etc.). * @returns {Promise>>} The requested vault state. */ getData: (parameters?: FetchParameters) => Promise>>; /** * Prepares a deposit into a VaultV1 (MetaMorpho) contract. * * Uses pre-fetched vault data to compute `maxSharePrice` with slippage tolerance, * then returns `buildTx` and `getRequirements` for lazy evaluation. * * @param {Object} params - The deposit parameters. * @param {bigint} params.amount - Amount of assets to deposit. * @param {Address} params.userAddress - User address initiating the deposit. * @param {AccrualVault} params.vaultData - Pre-fetched vault data with asset address and share conversion. * @param {bigint} [params.slippageTolerance=DEFAULT_SLIPPAGE_TOLERANCE] - Slippage tolerance (default 0.03%, max 10%). * @param {bigint} [params.nativeAmount] - Amount of native ETH to wrap into WETH. Vault asset must be wNative. * @returns {Object} Object with `buildTx` and `getRequirements`. */ deposit: (params: { userAddress: Address; vaultData: AccrualVault; slippageTolerance?: bigint; } & DepositAmountArgs) => { buildTx: (signatures?: readonly RequirementSignature[]) => Readonly>; getRequirements: (params?: { useSimplePermit?: boolean; }) => Promise<(Readonly> | Requirement)[]>; }; /** * Prepares a withdraw from a VaultV1 (MetaMorpho) contract. * * @param {Object} params - The withdraw parameters. * @param {bigint} params.amount - Amount of assets to withdraw. * @param {Address} params.userAddress - User address initiating the withdraw. * @returns {Object} Object with `buildTx`. */ withdraw: (params: { amount: bigint; userAddress: Address; }) => { buildTx: () => Readonly>; }; /** * Prepares a redeem from a VaultV1 (MetaMorpho) contract. * * @param {Object} params - The redeem parameters. * @param {bigint} params.shares - Amount of shares to redeem. * @param {Address} params.userAddress - User address initiating the redeem. * @returns {Object} Object with `buildTx`. */ redeem: (params: { shares: bigint; userAddress: Address; }) => { buildTx: () => Readonly>; }; /** * Prepares an illiquid Vault V1 exit into the vault's Morpho Blue supply positions. * * The caller controls market order and must call `getRequirements()` before `buildTx()` so the * RPC-backed Blue-balance and Morpho-deployment checks run. The SDK validates market coverage but * intentionally does not validate the user's share balance; size `amount` in asset terms against * `previewRedeem(sharesHeld)`. The share allowance first accrues pending performance-fee shares, * then uses the current rounded-up share preview; future interest can only reduce the required * burn. * * Snapshot state can drift before inclusion, so a later reallocation may still make the on-chain * loop under-cover even after pre-flight succeeds. * * @param params - In-kind redemption parameters. * @param params.amount - Asset-denominated amount to exit. * @param params.marketParamsList - Ordered vault markets consumed greedily by the contract; * repeated entries cannot draw from the same vault position twice. * @param params.vaultData - Pre-fetched Vault V1 accrual snapshot. * @param params.userAddress - Account that signs and submits the exit. * @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 allocated market with positive debt uses an unsupported IRM. * @throws {VaultAddressMismatchError} when `vaultData` belongs to another vault. * @throws {NonPositiveInputError} when `amount` is not positive. * @throws {EmptyMarketParamsListError} when the market list is empty. * @throws {ExpiredDeadlineError} when `deadline` is not in the future at handle creation or * requirement resolution. * @throws {InKindRedeemCoverageError} when the ordered list cannot cover `amount` without * assigning more than the vault owns in a repeated market. * @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 {VaultMorphoMismatchError} from `getRequirements()` when the vault uses another Morpho deployment. * @throws {VaultIsBlueFeeRecipientError} from `getRequirements()` when Morpho Blue accrues protocol fees to the vault. * @throws {InsufficientBlueBalanceForInKindRedeemError} from `getRequirements()` when Blue cannot fund the flash loan. * @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.vaultV1(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: AccrualVault; readonly userAddress: Address; readonly deadline?: bigint; }) => ActionOutput; /** * Prepares an atomic migration of Vault V1 shares to Vault V2 through bundler3. * * Accrues the source snapshot before converting V1 shares to assets so pending Vault V1 * performance-fee shares are reflected in both migration bounds. Projects the target Vault V2 * two hours forward when computing the deposit-leg maximum share price. * * @param params - Migration parameters. * @param params.userAddress - Account whose Vault V1 shares are migrated and that receives Vault * V2 shares. * @param params.sourceVault - Pre-fetched Vault V1 state with market allocations for local accrual. * @param params.targetVault - Pre-fetched Vault V2 accrual snapshot with the same underlying * asset. * @param params.shares - Positive number of Vault V1 shares to migrate. * @param params.slippageTolerance - Optional WAD-scaled tolerance; defaults to * `DEFAULT_SLIPPAGE_TOLERANCE` and cannot exceed 10%. * @returns Lazy approval or permit resolution through `getRequirements()` and a synchronous * `buildTx()` returning a deep-frozen `Transaction`. * @throws {ChainIdMismatchError} when the client and entity target different chains. * @throws {UnsupportedBlueMarketIrmError} when an allocated source or target market with positive debt uses an unsupported IRM. * @throws {VaultAddressMismatchError} when `sourceVault` belongs to another vault. * @throws {VaultAssetMismatchError} when the source and target assets differ. * @throws {NonPositiveInputError} when `shares` is not positive or the target projection yields * no shares. * @throws {NegativeInputError} when `slippageTolerance` is negative. * @throws {ExcessiveSlippageToleranceError} when `slippageTolerance` exceeds the SDK maximum. * @throws {UnknownBlueMarketAllocationError} when `sourceVault.withdrawQueue` references a market * absent from `sourceVault.allocations`. * @throws {UnsupportedChainIdError} from `getRequirements()` or `buildTx()` when the chain has no * address registry. * @throws {viem.BaseError} from `getRequirements()` when an RPC contract read fails. * @throws {UnexpectedRequirementSignatureError} from `buildTx()` when a non-permit signature is * supplied. * @throws {AmbiguousRequirementSignaturesError} from `buildTx()` when several permit signatures * are supplied. * @throws {DepositAssetMismatchError} from `buildTx()` when a supplied permit targets another * token. * @throws {DepositAmountMismatchError} from `buildTx()` when a supplied permit covers another * amount. * @throws {Permit2ExpirationMissingError} from `buildTx()` when a Permit2 signature lacks an * expiration. * @example * ```ts * import { * morphoViemExtension, * type Transaction, * type VaultV1MigrateToV2Action, * } from "@morpho-org/morpho-sdk"; * import { createPublicClient, http } from "viem"; * import { mainnet } from "viem/chains"; * * const client = createPublicClient({ chain: mainnet, transport: http() }).extend( * morphoViemExtension(), * ); * const sourceVaultAddress = "0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB"; * const targetVaultAddress = "0x04422053aDDbc9bB2759b248B574e3FCA76Bc145"; * const userAddress = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"; * const source = client.morpho.vaultV1(sourceVaultAddress, mainnet.id); * const [sourceVault, targetVault] = await Promise.all([ * source.getData(), * client.morpho.vaultV2(targetVaultAddress, mainnet.id).getData(), * ]); * const { buildTx } = source.migrateToV2({ * userAddress, * sourceVault, * targetVault, * shares: 1_000_000n, * }); * const tx: Readonly> = buildTx(); * ``` */ migrateToV2: (params: { userAddress: Address; sourceVault: AccrualVault; targetVault: AccrualVaultV2; shares: bigint; slippageTolerance?: bigint; }) => { buildTx: (signatures?: readonly RequirementSignature[]) => Readonly>; getRequirements: () => Promise<(Readonly> | Requirement)[]>; }; } export declare class MorphoVaultV1 implements VaultV1Actions { 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: AccrualVault; 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 VaultV1Actions.inKindRedeem} */ inKindRedeem({ amount, marketParamsList, vaultData, userAddress, deadline: deadlineOverride, }: { readonly amount: bigint; readonly marketParamsList: readonly MarketParams[]; readonly vaultData: AccrualVault; readonly userAddress: Address; readonly deadline?: bigint; }): ActionOutput; /** {@inheritDoc VaultV1Actions.migrateToV2} */ migrateToV2({ userAddress, sourceVault, targetVault, shares, slippageTolerance, }: { userAddress: Address; sourceVault: AccrualVault; targetVault: AccrualVaultV2; shares: bigint; slippageTolerance?: bigint; }): { getRequirements: () => Promise<(import("../../types/action.js").Bundler3TokenSignatureRequirement | Readonly>)[]>; buildTx: (signatures?: readonly RequirementSignature[]) => Readonly>; }; }