morpho-blue-py
A typed Python client for the Morpho Blue GraphQL API — lending markets, MetaMorpho vaults, and user positions analytics.
- Sync (
MorphoClient) and async (AsyncMorphoClient) clients built onhttpx. - Fully typed pydantic v2 models (ships
py.typed). - Helper methods: top markets by APY, market/vault lookups, wallet positions.
- Automatic pagination and multi-chain support.
- Optional
pandasexport.
The API is public and read-only — no API key required.
Install
pip install morpho-blue-py
# with pandas export helpers:
pip install "morpho-blue-py[pandas]"
Quickstart — list the largest markets and their supply APY
supply_apy / borrow_apy are returned as decimal fractions (e.g. 0.0366
means 3.66%), so format them with :.2%. We list the biggest Ethereum markets
by deposits and skip ones at 100% utilization — a fully-utilized market reports a
distorted instantaneous rate that can read as thousands of percent.
from morpho_blue import MorphoClient
with MorphoClient() as client:
markets = client.get_markets(
chain_id=1,
first=5,
order_by="supply_assets_usd",
where={"utilization_lte": 0.99},
)
for market in markets:
loan = market.loan_asset.symbol if market.loan_asset else "?"
apy = market.state.supply_apy if market.state else None
print(f"{loan:8} supply APY: {apy:.2%}" if apy is not None else loan)
# USDC supply APY: 3.66%
# USDT supply APY: 3.16%
# WETH supply APY: 1.62%
Markets
from morpho_blue import MorphoClient
with MorphoClient() as client:
# A page of markets on Ethereum (chainId 1), sorted by USD supply.
markets = client.get_markets(chain_id=1, first=20, order_by="supply_assets_usd")
# A single market by its unique key (marketId) — note: the Morpho schema's
# unique key is `marketId`, NOT `uniqueKey`.
market = client.get_market(
"0x8eaf7b29f02ba8d8c1d7aeb587403dcb16e2e943e4e2f5f94b0963c2386406c9",
chain_id=1,
)
# All markets across pages (auto-paginated via skip).
everything = client.iter_markets(chain_id=1, page_size=100)
Vaults (MetaMorpho)
with MorphoClient() as client:
vaults = client.top_vaults_by_apy(chain_id=1, limit=10)
vault = client.get_vault("0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB", chain_id=1)
if vault.state:
print(vault.name, vault.state.net_apy, vault.state.total_assets_usd)
for alloc in vault.state.allocation:
print(alloc.market.market_id, alloc.supply_assets_usd)
Wallet positions
with MorphoClient() as client:
user = client.get_user("0x47E2D28169738039755586743E2dfCF3bd643f86", chain_id=1)
for pos in user.market_positions:
if pos.state:
print(pos.market.market_id, pos.state.supply_assets, pos.state.borrow_assets)
for vpos in user.vault_positions:
print(vpos.vault.symbol, vpos.state.assets if vpos.state else None)
Async
import asyncio
from morpho_blue import AsyncMorphoClient
async def main() -> None:
async with AsyncMorphoClient() as client:
markets = await client.top_markets_by_supply_apy(chain_id=1, limit=5)
print([m.loan_asset.symbol for m in markets if m.loan_asset])
asyncio.run(main())
pandas export
from morpho_blue import MorphoClient
from morpho_blue.export import markets_to_dataframe
with MorphoClient() as client:
df = markets_to_dataframe(client.get_markets(chain_id=1, first=50))
print(df[["loan_asset_symbol", "supply_apy", "supply_assets_usd"]])
Multi-chain
Every method takes an optional chain_id. Supported chains include Ethereum (1),
Base (8453), Arbitrum (42161), Polygon (137), Optimism (10), Unichain (130), and more.
Omit chain_id to query across all chains the API exposes.
Custom endpoint
MorphoClient(endpoint="https://blue-api.morpho.org/graphql") # default
Development
uv venv --python 3.9
uv pip install -e ".[dev]"
ruff check .
mypy
pytest # unit tests (no network)
pytest -m integration # hits the live endpoint
License
MIT