import { type RoundingDirection } from "../math/index.js"; import type { BigIntish } from "../types.js"; import { type CapacityLimit } from "../utils.js"; import { type IMarketParams, MarketParams } from "./MarketParams.js"; /** Options for max borrow capacity calculations. */ export interface MaxBorrowOptions { maxLtv?: bigint; } /** Options for max withdraw collateral capacity calculations. */ export interface MaxWithdrawCollateralOptions { maxLtv?: bigint; } /** Capacity limits for each market operation available to a position. */ export interface MaxPositionCapacities { supply: CapacityLimit; withdraw: CapacityLimit; borrow: CapacityLimit | undefined; repay: CapacityLimit; supplyCollateral: CapacityLimit; withdrawCollateral: CapacityLimit | undefined; } /** Plain input shape for a Morpho Blue market. */ export interface IMarket { params: IMarketParams; totalSupplyAssets: bigint; totalBorrowAssets: bigint; totalSupplyShares: bigint; totalBorrowShares: bigint; lastUpdate: bigint; fee: bigint; price?: bigint; rateAtTarget?: bigint; } /** * Represents a lending market on Morpho Blue. */ export declare class Market implements IMarket { /** * The market's params. */ readonly params: MarketParams; /** * The amount of loan assets supplied in total on the market. */ totalSupplyAssets: bigint; /** * The amount of loan assets supplied in total on the market. */ totalBorrowAssets: bigint; /** * The amount of loan assets supplied in total on the market. */ totalSupplyShares: bigint; /** * The amount of loan assets supplied in total on the market. */ totalBorrowShares: bigint; /** * The block timestamp (in __seconds__) when the interest was last accrued. */ lastUpdate: bigint; /** * The fee percentage of the market, scaled by WAD. */ fee: bigint; /** * The price as returned by the market's oracle. * `undefined` if the oracle is undefined or reverts. */ price?: bigint; /** * If the market uses the Adaptive Curve IRM, the rate at target utilization. * Undefined otherwise. */ rateAtTarget?: bigint; constructor({ params, totalSupplyAssets, totalBorrowAssets, totalSupplyShares, totalBorrowShares, lastUpdate, fee, price, rateAtTarget, }: IMarket); /** * The market's hex-encoded id, defined as the hash of the market params. */ get id(): import("../types.js").MarketId; /** * Whether the market satisfies the canonical definition of an idle market (i.e. collateral token is the zero address). */ get isIdle(): boolean; /** * @warning Cannot be used to calculate the liquidity available inside a callback, * because the balance of Blue may be lower than the market's liquidity due to assets being transferred out prior to the callback. */ get liquidity(): bigint; /** * The market's utilization rate (scaled by WAD). */ get utilization(): bigint; /** * The market's Annual Percentage Yield (APY) at the IRM's target utilization rate, if applicable. */ get apyAtTarget(): number | undefined; /** * Returns the instantaneous rate at which interest accrues for borrowers of this market, * if `accrueInterest` was called immediately onchain (scaled by WAD). * * Even if `accrueInterest` is called immediately onchain, * the instantaneous rate only corresponds to an intermediary value used to calculate * the actual average rate experienced by borrowers of this market. * * If interested in the instantaneous rate experienced by existing market actors at a specific timestamp, * use `getEndBorrowRate(timestamp)`, `getBorrowApy(timestamp)`, or `getSupplyApy(timestamp)` instead. * @throws {UnsupportedMarketIrmError} when the market uses a nonzero unsupported IRM. */ get endBorrowRate(): bigint; /** * Returns the average rate at which interest _would_ accrue from `lastUpdate` * till now, if `accrueInterest` was called immediately onchain (scaled by WAD). * If `accrueInterest` was just called, the average rate equals the instantaneous rate, * so it is equivalent to `getBorrowRate(lastUpdate)`. * * In most cases, `accrueInterest` will not be called immediately onchain, * so the average rate is only an intermediary value. * * If interested in the average rate experienced by existing market actors at a specific timestamp, * use `getAvgBorrowRate(timestamp)`, `getAvgBorrowApy(timestamp)`, or `getAvgSupplyApy(timestamp)` instead. * @throws {UnsupportedMarketIrmError} when the market uses a nonzero unsupported IRM. */ get avgBorrowRate(): bigint; /** * The market's current, instantaneous supply-side Annual Percentage Yield (APY). * If interested in the APY at a specific timestamp, use `getSupplyApy(timestamp)` instead. * @throws {UnsupportedMarketIrmError} when positive debt uses a nonzero unsupported IRM. */ get supplyApy(): number; /** * The market's current, instantaneous borrow-side Annual Percentage Yield (APY). * If interested in the APY at a specific timestamp, use `getBorrowApy(timestamp)` instead. * @throws {UnsupportedMarketIrmError} when the market uses a nonzero unsupported IRM. */ get borrowApy(): number; /** * Returns the instantaneous rate at which interest accrues for borrowers of this market, * at the given timestamp, if the state remains unchanged (not accrued) (scaled by WAD). * It is fundamentally different from the rate at which interest is paid by borrowers to lenders in the case of an interest accrual, * as in the case of the AdaptiveCurveIRM, the (approximated) average rate since the last update is used instead. * @param timestamp The timestamp at which to calculate the borrow rate. * Earlier timestamps are treated as `lastUpdate`. * Defaults to `Time.timestamp()` (returns the current borrow rate). * @throws {UnsupportedMarketIrmError} when the market uses a nonzero unsupported IRM. */ getEndBorrowRate(timestamp?: BigIntish): bigint; /** * Returns the average rate at which interest _would_ accrue for borrowers of this market, * if `accrueInterest` was called at the given timestamp (scaled by WAD). * @param timestamp The timestamp at which to calculate the average borrow rate. * Earlier timestamps are treated as `lastUpdate`. * Defaults to `Time.timestamp()` (returns the current average borrow rate). * @throws {UnsupportedMarketIrmError} when the market uses a nonzero unsupported IRM. */ getAvgBorrowRate(timestamp?: BigIntish): bigint; /** * Returns the rates that _would_ apply to interest accrual for borrowers of this market, * if `accrueInterest` was called at the given timestamp (scaled by WAD). * @param timestamp The timestamp at which to calculate the accrual borrow rate. * Earlier timestamps are treated as `lastUpdate`. * Defaults to `Time.timestamp()` (returns the current accrual borrow rate). */ protected getAccrualBorrowRates(timestamp?: BigIntish): { elapsed: bigint; avgBorrowRate: bigint; endBorrowRate: bigint; endRateAtTarget?: bigint; }; /** * The market's instantaneous borrow-side Annual Percentage Yield (APY) at the given timestamp, * if the state remains unchanged (not accrued). * @param timestamp The timestamp at which to calculate the borrow APY. * Earlier timestamps are treated as `lastUpdate`. * Defaults to `Time.timestamp()` (returns the current borrow APY). * @throws {UnsupportedMarketIrmError} when the market uses a nonzero unsupported IRM. */ getBorrowApy(timestamp?: BigIntish): number; /** * The market's instantaneous supply-side Annual Percentage Yield (APY) at the given timestamp, * if the state remains unchanged (not accrued). * @param timestamp The timestamp at which to calculate the supply APY. * Earlier timestamps are treated as `lastUpdate`. * Defaults to `Time.timestamp()` (returns the current supply APY). * @throws {UnsupportedMarketIrmError} when positive debt uses a nonzero unsupported IRM. */ getSupplyApy(timestamp?: BigIntish): number; /** * The market's experienced borrow-side Annual Percentage Yield (APY), * if interest was to be accrued at the given timestamp. * @param timestamp The timestamp at which to calculate the borrow APY. * Earlier timestamps are treated as `lastUpdate`. * Defaults to `Time.timestamp()` (returns the current borrow APY). * @throws {UnsupportedMarketIrmError} when the market uses a nonzero unsupported IRM. */ getAvgBorrowApy(timestamp?: BigIntish): number; /** * Returns the average rate at which interest _would_ accrue for suppliers of this market, * if `accrueInterest` was called at the given timestamp (scaled by WAD). * @param timestamp The timestamp at which to calculate the average supply rate. * Earlier timestamps are treated as `lastUpdate`. * Defaults to `Time.timestamp()` (returns the current average supply rate). * @throws {UnsupportedMarketIrmError} when positive debt uses a nonzero unsupported IRM. */ getAvgSupplyRate(timestamp?: BigIntish): bigint; /** * The market's experienced supply-side Annual Percentage Yield (APY), * if interest was to be accrued at the given timestamp. * @param timestamp The timestamp at which to calculate the supply APY. * Earlier timestamps are treated as `lastUpdate`. * Defaults to `Time.timestamp()` (returns the current supply APY). * @throws {UnsupportedMarketIrmError} when positive debt uses a nonzero unsupported IRM. */ getAvgSupplyApy(timestamp?: BigIntish): number; /** * Returns a new market derived from this market, whose interest has been accrued up to the given timestamp. * @param timestamp The timestamp at which to accrue interest. * Earlier timestamps are treated as `lastUpdate`. * Defaults to `lastUpdate`. At or before `lastUpdate`, returns an unchanged copy without projecting interest or rewinding the timestamp. * @returns A new `Market`, unchanged for past or equal timestamps; otherwise with accrued asset totals and fee shares, updated `lastUpdate`, and projected `rateAtTarget`. * @throws {UnsupportedMarketIrmError} when projection requires a nonzero unsupported IRM. * @example * ```ts * import { ChainId, getChainAddress, Market, MarketParams } from "@morpho-org/blue-sdk"; * * const market = new Market({ * params: MarketParams.idle(getChainAddress(ChainId.EthMainnet, "usdc")), * totalSupplyAssets: 1_000_000n, * totalBorrowAssets: 0n, * totalSupplyShares: 1_000_000_000_000n, * totalBorrowShares: 0n, * lastUpdate: 1_700_000_000n, * fee: 0n, * }); * const accrued = market.accrueInterest(1_699_999_999n); * // accrued satisfies Market * // accrued.lastUpdate === 1_700_000_000n; accrued.totalSupplyAssets === 1_000_000n * // market.lastUpdate === 1_700_000_000n * ``` */ accrueInterest(timestamp?: BigIntish): Market; /** * Applies a supply to an interest-accrued copy of this market. * @param assets Loan assets to supply, or zero when `shares` is provided. * @param shares Supply shares to mint, or zero when `assets` is provided. * @param timestamp Optional accrual timestamp. Defaults to `lastUpdate`; earlier timestamps skip interest accrual while still applying the operation. * @returns The updated market and normalized asset and share amounts. * @throws {BlueErrors.InconsistentInput} when both or neither of `assets` and `shares` are nonzero. * @throws {UnsupportedMarketIrmError} when positive debt requires an unsupported IRM projection. * @example * ```ts * import { ChainId, getChainAddress, Market, MarketParams } from "@morpho-org/blue-sdk"; * * const market = new Market({ * params: MarketParams.idle(getChainAddress(ChainId.EthMainnet, "usdc")), * totalSupplyAssets: 0n, * totalBorrowAssets: 0n, * totalSupplyShares: 0n, * totalBorrowShares: 0n, * lastUpdate: 1_700_000_000n, * fee: 0n, * }); * const result = market.supply(1_000_000n, 0n); * // result satisfies { market: Market; assets: bigint; shares: bigint } * // result.assets === 1_000_000n; result.shares === 1_000_000_000_000n * ``` */ supply(assets: bigint, shares: bigint, timestamp?: BigIntish): { market: Market; assets: bigint; shares: bigint; }; /** * Applies a withdrawal to an interest-accrued copy of this market. * @param assets Loan assets to withdraw, or zero when `shares` is provided. * @param shares Supply shares to burn, or zero when `assets` is provided. * @param timestamp Optional accrual timestamp. Defaults to `lastUpdate`; earlier timestamps skip interest accrual while still applying the operation. * @returns The updated market and normalized asset and share amounts. * @throws {BlueErrors.InconsistentInput} when both or neither of `assets` and `shares` are nonzero. * @throws {UnsupportedMarketIrmError} when positive debt requires an unsupported IRM projection. * @throws {BlueErrors.InsufficientLiquidity} when the withdrawal exceeds the accrued market's liquidity. * @example * ```ts * import { ChainId, getChainAddress, Market, MarketParams } from "@morpho-org/blue-sdk"; * * const market = new Market({ * params: MarketParams.idle(getChainAddress(ChainId.EthMainnet, "usdc")), * totalSupplyAssets: 1_000_000n, * totalBorrowAssets: 0n, * totalSupplyShares: 1_000_000_000_000n, * totalBorrowShares: 0n, * lastUpdate: 1_700_000_000n, * fee: 0n, * }); * const result = market.withdraw(500_000n, 0n); * // result satisfies { market: Market; assets: bigint; shares: bigint } * // result.assets === 500_000n; result.shares === 500_000_000_000n * ``` */ withdraw(assets: bigint, shares: bigint, timestamp?: BigIntish): { market: Market; assets: bigint; shares: bigint; }; /** * Applies a borrow to an interest-accrued copy of this market. * @param assets Loan assets to borrow, or zero when `shares` is provided. * @param shares Borrow shares to mint, or zero when `assets` is provided. * @param timestamp Optional accrual timestamp. Defaults to `lastUpdate`; earlier timestamps skip interest accrual while still applying the operation. * @returns The updated market and normalized asset and share amounts. * @throws {BlueErrors.InconsistentInput} when both or neither of `assets` and `shares` are nonzero. * @throws {UnsupportedMarketIrmError} when positive debt requires an unsupported IRM projection. * @throws {BlueErrors.InsufficientLiquidity} when the borrow exceeds the accrued market's liquidity. * @example * ```ts * import { ChainId, Market } from "@morpho-org/blue-sdk"; * import { markets } from "@morpho-org/morpho-test"; * * const market = new Market({ * params: markets[ChainId.EthMainnet].eth_wstEth, * totalSupplyAssets: 10n ** 18n, * totalBorrowAssets: 0n, * totalSupplyShares: 10n ** 24n, * totalBorrowShares: 0n, * lastUpdate: 1_700_000_000n, * fee: 0n, * }); * const result = market.borrow(10n ** 17n, 0n); * // result satisfies { market: Market; assets: bigint; shares: bigint } * // result.assets === 10n ** 17n; result.shares === 10n ** 23n * ``` */ borrow(assets: bigint, shares: bigint, timestamp?: BigIntish): { market: Market; assets: bigint; shares: bigint; }; /** * Simulates a repayment on this market and returns the resulting market state. * Exactly one of `assets` or `shares` must be non-zero. * When repaying by shares, the repaid `assets` are rounded up and may exceed * `totalBorrowAssets`; the market total is then floored at zero, mirroring `Morpho.repay`. * @param assets The amount of loan assets to repay (`0n` when repaying by shares). * @param shares The amount of borrow shares to repay (`0n` when repaying by assets). * @param timestamp The timestamp at which to accrue interest before repaying. Defaults to `lastUpdate`; earlier timestamps skip interest accrual while still repaying. * @returns The accrued market after repayment, along with the resolved `assets` and `shares` repaid. * @throws {BlueErrors.InconsistentInput} If both or neither of `assets` and `shares` are non-zero. * @throws {UnsupportedMarketIrmError} when positive debt requires an unsupported IRM projection. * @example * ```ts * const { market: after, assets } = market.repay(0n, position.borrowShares); * ``` */ repay(assets: bigint, shares: bigint, timestamp?: BigIntish): { market: Market; assets: bigint; shares: bigint; }; /** * Converts a given amount of supply shares into supply loan assets. * @param shares The amount of shares to convert. * @param rounding The rounding direction to use (defaults to "Down"). */ toSupplyAssets(shares: bigint, rounding?: RoundingDirection): bigint; /** * Converts a given amount of supply loan assets into supply shares. * @param shares The amount of assets to convert. * @param rounding The rounding direction to use (defaults to "Up"). */ toSupplyShares(assets: bigint, rounding?: RoundingDirection): bigint; /** * Converts a given amount of borrow shares into borrow loan assets. * @param shares The amount of shares to convert. * @param rounding The rounding direction to use (defaults to "Up"). */ toBorrowAssets(shares: bigint, rounding?: RoundingDirection): bigint; /** * Converts a given amount of borrow loan assets into borrow shares. * @param shares The amount of assets to convert. * @param rounding The rounding direction to use (defaults to "Down"). */ toBorrowShares(assets: bigint, rounding?: RoundingDirection): bigint; /** * Returns the smallest volume to supply until the market gets the closest to the given utilization rate. * @param utilization The target utilization rate (scaled by WAD). */ getSupplyToUtilization(utilization: bigint): bigint; /** * Returns the liquidity available to withdraw until the market gets the closest to the given utilization rate. * @param utilization The target utilization rate (scaled by WAD). */ getWithdrawToUtilization(utilization: bigint): bigint; /** * Returns the liquidity available to borrow until the market gets the closest to the given utilization rate. * @param utilization The target utilization rate (scaled by WAD). */ getBorrowToUtilization(utilization: bigint): bigint; /** * Returns the smallest volume to repay until the market gets the closest to the given utilization rate. * @param utilization The target utilization rate (scaled by WAD). */ getRepayToUtilization(utilization: bigint): bigint; /** * Returns the value of a given amount of collateral quoted in loan assets. * `undefined` iff the market's oracle is undefined or reverts. * @param collateral The amount of collateral to quote. */ getCollateralValue(collateral: bigint): bigint | undefined; /** * Returns the maximum debt allowed given a certain amount of collateral. * `undefined` iff the market's oracle is undefined or reverts. * To calculate the amount of loan assets that can be borrowed, use `getMaxBorrowableAssets`. * @param collateral The amount of collateral to consider. */ getMaxBorrowAssets(collateral: bigint, { maxLtv }?: MaxBorrowOptions): bigint | undefined; /** * Returns the maximum amount of loan assets that can be borrowed given a certain borrow position. * `undefined` iff the market's oracle is undefined or reverts. * @param position The borrow position to consider. */ getMaxBorrowableAssets(position: { collateral: bigint; borrowShares: bigint; }): bigint | undefined; /** * Returns the amount of collateral that would be seized in a liquidation given a certain amount of repaid shares. * `undefined` iff the market's oracle is undefined or reverts. * @param repaidShares The amount of shares hypothetically repaid. */ getLiquidationSeizedAssets(repaidShares: bigint): bigint | undefined; /** * Returns the amount of borrow shares that would be repaid in a liquidation given a certain amount of seized collateral. * `undefined` iff the market's oracle is undefined or reverts. * @param seizedAssets The amount of collateral hypothetically seized. */ getLiquidationRepaidShares(seizedAssets: bigint): bigint | undefined; /** * Returns the maximum amount of collateral that is worth being seized in a liquidation given a certain borrow position. * `undefined` iff the market's oracle is undefined or reverts. * @param position The borrow position to consider. */ getSeizableCollateral(position: { collateral: bigint; borrowShares: bigint; }): bigint | undefined; /** * Returns the amount of collateral that can be withdrawn given a certain borrow position. * `undefined` iff the market's oracle is undefined or reverts. * @param position The borrow position to consider. */ getWithdrawableCollateral(position: { collateral: bigint; borrowShares: bigint; }, { maxLtv }?: MaxWithdrawCollateralOptions): bigint | undefined; /** * Returns whether a given borrow position is healthy. * `undefined` iff the market's oracle is undefined or reverts. * @param position The borrow position to check. */ isHealthy(position: { collateral: bigint; borrowShares: bigint; }): boolean | undefined; /** * Returns the liquidation price of a given borrow position. * @param position The borrow position to consider. */ getLiquidationPrice(position: { collateral: bigint; borrowShares: bigint; }): bigint | null; /** * Returns the price variation required for the given position to reach its liquidation threshold (scaled by WAD). * Negative when healthy (the price needs to drop x%), positive when unhealthy (the price needs to soar x%). * Returns `undefined` iff the market's price is undefined. * Returns null if the position is not a borrow. * @param position The borrow position to consider. */ getPriceVariationToLiquidationPrice(position: { collateral: bigint; borrowShares: bigint; }): bigint | null | undefined; /** * Returns the health factor of a given borrow position (scaled by WAD). * @param position The borrow position to consider. */ getHealthFactor(position: { collateral: bigint; borrowShares: bigint; }): bigint | undefined; /** * Returns the loan-to-value ratio of a given borrow position (scaled by WAD). * @param position The borrow position to consider. */ getLtv(position: { collateral: bigint; borrowShares: bigint; }): bigint | null | undefined; /** * Returns the usage ratio of the maximum borrow capacity given a certain borrow position (scaled by WAD). * @param position The borrow position to consider. */ getBorrowCapacityUsage(position: { collateral: bigint; borrowShares: bigint; }): bigint | undefined; /** * Returns the maximum amount of loan assets that can be borrowed given a certain borrow position * and the reason for the limit. * Returns `undefined` iff the market's price is undefined. * @param position The borrow position to consider. */ getBorrowCapacityLimit({ collateral, borrowShares, }: { collateral: bigint; borrowShares?: bigint; }, options?: MaxBorrowOptions): CapacityLimit | undefined; /** * Returns the maximum amount of loan assets that can be repaid given a certain borrow position * and a balance of loan assets, and the reason for the limit. * @param position The borrow position to consider. */ getRepayCapacityLimit(borrowShares: bigint, loanTokenBalance: bigint): CapacityLimit; /** * Returns the maximum amount of loan assets that can be withdrawn given a certain supply position * and a balance of loan assets, and the reason for the limit. * @param position The supply position to consider. */ getWithdrawCapacityLimit({ supplyShares, }: { supplyShares: bigint; }): CapacityLimit; /** * Returns the maximum amount of collateral assets that can be withdrawn given a certain borrow position * and the reason for the limit. * Returns `undefined` iff the market's price is undefined. * @param position The borrow position to consider. */ getWithdrawCollateralCapacityLimit(position: { collateral: bigint; borrowShares: bigint; }, options?: MaxWithdrawCollateralOptions): CapacityLimit | undefined; /** * Returns the maximum capacity for all interactions with Morpho Blue given a certain position * and loan and collateral balances. * @param position The position to consider. * @param loanTokenBalance The balance of loan assets. * @param collateralTokenBalance The balance of collateral assets. */ getMaxCapacities(position: { collateral: bigint; supplyShares: bigint; borrowShares: bigint; }, loanTokenBalance: bigint, collateralTokenBalance: bigint, options?: { borrow?: MaxBorrowOptions; withdrawCollateral?: MaxWithdrawCollateralOptions; }): MaxPositionCapacities; }