@morpho-org/blue-sdk
v7.1.0
Published
Framework-agnostic package that defines Morpho-related entity classes (such as `Market`, `Token`, `Vault`).
Keywords
Readme
@morpho-org/blue-sdk
Overview
Framework-agnostic package that defines Morpho-related entity classes:
MarketParams: represents the immutable configuration of a market on MorphoMarket: represents the state of a market on MorphoToken: represents a ERC20 tokenUser: represents a user of MorphoVaultConfig: represents the configuration of a Morpho VaultVault: represents the state of a Morpho VaultVaultUser: represents the state of a user on a Morpho VaultVaultMarketAllocation: represents the allocation (and configuration) of a Morpho Vault on a Morpho market
Upgrading from v6? Read the v6 → v7 migration guide.
Installation
npm install @morpho-org/blue-sdkyarn add @morpho-org/blue-sdkUsage
Instance of the immutable configuration of a specific market
Leverage the MarketParams class to manipulate a given market's immutable configuration:
import { MarketParams } from "@morpho-org/blue-sdk";
const config = new MarketParams({
loanToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
collateralToken: "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", // wstETH
oracle: "0x2a01EB9496094dA03c4E364Def50f5aD1280AD72",
irm: "0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC", // AdaptiveCurveIrm
lltv: 94_5000000000000000n, // 94.5%
});
config.liquidationIncentiveFactor; // e.g. 1_090000000000000000n (109%).Instance of a specific market
Leverage the Market class to manipulate a specific market:
import { Market, MarketParams } from "@morpho-org/blue-sdk";
import { Time } from "@morpho-org/morpho-ts";
const market = new Market({
config: new MarketParams({
loanToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
collateralToken: "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", // wstETH
oracle: "0x2a01EB9496094dA03c4E364Def50f5aD1280AD72",
irm: "0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC", // AdaptiveCurveIrm
lltv: 94_5000000000000000n, // 94.5%
}),
totalSupplyAssets: 1000_000000000000000000n,
totalBorrowAssets: 920_000000000000000000n,
totalSupplyShares: 1000_000000000000000000000000n,
totalBorrowShares: 920_000000000000000000000000n,
lastUpdate: 1721000000n,
fee: 0n,
price: 1_100000000000000000000000000000000000n,
rateAtTarget: 94850992095n,
});
market.utilization; // e.g. 92_0000000000000000n (92%).
market.liquidity; // e.g. 80_000000000000000000n (in loan assets).
market.apyAtTarget; // e.g. 3_0000000000000000n (3%).
const accruedMarket = market.accrueInterest(Time.timestamp()); // Accrue interest to the latest's timestamp.
accruedMarket.toSupplyAssets(shares); // Convert supply shares to assets.Accrual never throws solely because the requested timestamp is in the past.
Market.accrueInterest and position accrual return unchanged copies when the
timestamp is at or before the market's lastUpdate, without projecting the IRM
or rewinding state. Rate helpers evaluate earlier timestamps at lastUpdate;
requesting an unsupported IRM's rate still throws UnsupportedMarketIrmError.
AccrualVaultV2.accrueInterest likewise returns an unchanged vault copy and zero
fee shares at or before the vault's own lastUpdate. Forward vault accrual also
accrues contributing nested adapters, markets, and positions to the same
timestamp; newer nested markets, zero-share or zero-allocation nested state, and
adapters without accrueInterest keep their snapshots. The liquidity adapter
reuses the accrued registered adapter instance and is never accrued
independently; an unregistered liquidity adapter keeps its snapshot. Vault V1 has no
vault-wide timestamp: it still reconciles losses and fees using its nested snapshots, including any
that need no interest accrual.
Instance of the position of a specific user on a specific market
Leverage the Position class to manipulate the position of a user on a given market:
import { Position } from "@morpho-org/blue-sdk";
import { Time } from "@morpho-org/morpho-ts";
const position = new AccrualPosition(
new Position({
user,
marketId: market.id,
supplyShares: 0n,
borrowShares: 20_000000000000000000000000n,
collateral: 27_000000000000000000n,
}),
market
);
position.borrowAssets; // e.g. 20_000000000000000000n (in loan assets).
position.isHealthy; // e.g. true.
position.maxBorrowableAssets; // e.g. 2100_000000000000000000n (in loan assets).
const accruedPosition = position.accrueInterest(Time.timestamp()); // Accrue interest to the latest's timestamp.
position.borrowAssets; // e.g. 20_400000000000000000n (in loan assets).Addresses customization
registerCustomAddresses
Extends the default address registry and unwrapped token mapping for known or custom chains. Useful for testing or adding support for new networks.
[!Note]
- Custom addresses should be registered statically, at the root level.
- Custom addresses can't be removed nor changed.
✅ Use Cases
- Injecting additional or missing contract addresses on known chains.
- Providing a full set of addresses for an unknown (custom) chain.
- Registering mappings of wrapped → unwrapped tokens per chain (e.g., WETH → ETH).
Function Signature
registerCustomAddresses(options?: {
addresses?: Record<number, ChainAddresses>; // Can be a subset of ChainAddresses if chain is known
unwrappedTokens?: Record<number, Record<Address, Address>>;
}): voidParameters
addresses(optional)
A map ofchainId → ChainAddresses.- For known chains, partial overrides are allowed (e.g., add a missing adapter).
- For unknown chains, a complete
ChainAddressesobject with required addresses must be provided. - Throws an error if you attempt to override an existing address.
unwrappedTokens(optional)
A map ofchainId → { wrapped → unwrapped }.- Throws an error if you attempt to override an existing mapping.
Behavior
- Merges user-provided addresses and unwrapped tokens into the internal registries.
- Uses a deep merge with custom logic to prevent overwriting existing values.
- Updates internal constants:
addressesRegistry,addresses, andunwrappedTokensMapping. - Applies
Object.freeze()to ensure immutability.
Example
registerCustomAddresses({
addresses: {
8453: { stEth: "0xabc..." }, // provide stEth address on base
31337: {
blue: "0x123...",
...
}, // registers a new local test chain
},
unwrappedTokens: {
31337: {
"0xWrapped": "0xUnwrapped" // e.g., WETH → ETH
}
}
});Development
Contribute from the monorepo root. See CONTRIBUTING.md for setup, checks, and package workflow. Report vulnerabilities through SECURITY.md.
License
MIT. See LICENSE.
