The MorphoClient provides direct access to Morpho Blue lending markets. It handles registration, market discovery, collateral management, borrowing, USDC supply (lending to earn yield), repayment, and position tracking — all through a Safe account using ERC-4337 UserOps.
MorphoClient submits all state-changing operations as ERC-4337 UserOps: EOA signs UserOp → EntryPoint → Safe7579 → execute(MODE_BATCH, ...). Multiple operations (e.g., deposit + borrow) are combined into a single atomic transaction. If any step fails, the entire transaction reverts.
Constructor
Private Key
External Signer
import { MorphoClient } from '@agether/sdk';
const morpho = new MorphoClient({
privateKey: process.env.AGENT_PRIVATE_KEY!,
rpcUrl: 'https://base-rpc.publicnode.com',
agentId: '42', // Your ERC-8004 agent ID (optional for first-time registration)
chainId: 8453, // Base mainnet (default)
});
import { MorphoClient } from '@agether/sdk';
// Works with Bankr, Privy, Turnkey, MetaMask, or any ethers.AbstractSigner
const morpho = new MorphoClient({
signer: externalSigner,
rpcUrl: 'https://base-rpc.publicnode.com',
agentId: '42',
});
Configuration
| Parameter | Type | Required | Description |
|---|
privateKey | string | Either this or signer | Agent wallet private key |
signer | ethers.AbstractSigner | Either this or privateKey | External signer (Bankr, Privy, Turnkey, etc.) |
rpcUrl | string | Yes | Base RPC endpoint |
agentId | string | No | ERC-8004 agent ID (set after registration if not known) |
chainId | number | No | Chain ID (default: 8453 for Base) |
contracts | object | No | Override contract addresses |
Registration
register(name?)
Register an ERC-8004 identity and create a Safe-based agent account in one call. If already registered, returns existing state.
const result = await morpho.register();
console.log('Agent ID:', result.agentId);
console.log('Account:', result.agentAccount);
console.log('Already existed:', result.alreadyRegistered);
console.log('KYA Required:', result.kyaRequired);
Return type:
interface RegisterResult {
agentId: string;
address: string; // EOA wallet
agentAccount: string; // Safe account address
alreadyRegistered: boolean;
kyaRequired: boolean;
tx?: string; // TX hash (only if newly created)
}
Market Discovery
getMarkets(forceRefresh?)
Fetch available Morpho Blue USDC markets on Base. Returns all markets (49+) — not limited to specific collateral types. Results are cached for 5 minutes unless forceRefresh is true.
const markets = await morpho.getMarkets();
for (const market of markets) {
console.log(`${market.collateralAsset.symbol}:`);
console.log(` LLTV: ${Number(market.lltv) / 1e16}%`);
console.log(` Utilization: ${(market.utilization * 100).toFixed(1)}%`);
console.log(` Market Key: ${market.uniqueKey}`);
}
Markets are fetched from the Morpho GraphQL API, filtered for USDC loan markets on Base.
getMarketRates(collateralSymbolOrAddress?)
Get current supply/borrow APY and utilization for markets.
// All markets
const allRates = await morpho.getMarketRates();
// Specific collateral
const wethRates = await morpho.getMarketRates('WETH');
for (const r of wethRates) {
console.log('Borrow APY:', (r.borrowApy * 100).toFixed(2) + '%');
console.log('Supply APY:', (r.supplyApy * 100).toFixed(2) + '%');
console.log('Utilization:', (r.utilization * 100).toFixed(1) + '%');
}
Borrowing Operations
depositAndBorrow(token, collateralAmount, borrowAmount)
The primary borrowing operation — deposit collateral and borrow USDC in a single atomic transaction.
const result = await morpho.depositAndBorrow('WETH', '0.1', '100');
console.log('TX:', result.tx);
console.log('Collateral:', result.collateralAmount, result.collateralToken);
console.log('Borrowed:', result.borrowAmount, 'USDC');
Under the hood, this executes as an ERC-4337 UserOp with a batched execution:
- EOA transfer: Collateral tokens are transferred from EOA → Safe account
- Safe batch (ERC-7579
execute(MODE_BATCH, ...)):
collateral.approve(MorphoBlue, amount)
Morpho.supplyCollateral(marketParams, amount, account, "")
Morpho.borrow(marketParams, borrowAmount, 0, account, account)
supplyCollateral(token, amount)
Deposit collateral without borrowing.
const result = await morpho.supplyCollateral('WETH', '0.5');
console.log('TX:', result.tx);
borrow(amount, token?)
Borrow USDC against existing collateral. If token is specified, borrows from that market. Otherwise auto-detects the first market with collateral.
const result = await morpho.borrow('200');
console.log('TX:', result.tx);
console.log('Borrowed:', result.amount, 'USDC');
// From specific market
const result2 = await morpho.borrow('100', 'wstETH');
repay(amount, token?)
Repay borrowed USDC. Pass "all" to repay the full debt using share-based repayment (no dust left).
// Partial repay
const result = await morpho.repay('50');
console.log('TX:', result.tx);
console.log('Remaining debt:', result.remainingDebt);
// Full repay
const result2 = await morpho.repay('all');
When repaying "all", the SDK uses share-based repayment to ensure zero dust borrow shares remain. If the Safe account doesn’t have enough USDC, the SDK automatically transfers the shortfall from the EOA.
withdrawCollateral(token, amount, marketParams?, receiver?)
Withdraw collateral from Morpho. Pass "all" for full withdrawal. By default, collateral is sent to the EOA wallet.
await morpho.withdrawCollateral('WETH', '0.05');
await morpho.withdrawCollateral('WETH', 'all'); // After repaying all debt
Withdrawing collateral reduces your Health Factor. If it drops below 1.0, your position can be liquidated. If dust borrow shares remain, the SDK auto-repays them before withdrawing.
Supply Operations (Earn Yield)
These methods let your agent supply USDC as a lender to Morpho Blue markets to earn yield from borrowers. This is separate from depositing collateral — you’re lending USDC to earn interest.
supplyAsset(usdcAmount, collateralSymbol?)
Supply USDC to a Morpho Blue market as a lender to earn yield.
// Supply to highest-APY market (auto-selected)
const result = await morpho.supplyAsset('500');
console.log('TX:', result.tx);
// Supply to specific market
const result2 = await morpho.supplyAsset('100', 'WETH');
console.log('Supplied $100 to WETH/USDC market');
If the Safe account doesn’t have enough USDC, the SDK automatically transfers the needed amount from the EOA wallet.
withdrawSupply(usdcAmount, collateralSymbol?, receiver?)
Withdraw supplied USDC (principal + earned interest) from a Morpho Blue lending position. Pass "all" to withdraw the entire position.
// Partial withdrawal
const result = await morpho.withdrawSupply('100');
console.log('TX:', result.tx);
// Full withdrawal (all principal + earned yield)
const result2 = await morpho.withdrawSupply('all', 'WETH');
// Withdraw to a specific address
await morpho.withdrawSupply('all', 'WETH', '0xReceiverAddress');
getSupplyPositions(collateralSymbol?)
Get all supply (lending) positions with earned yield. Reads Morpho events directly from blockchain — no database needed.
// All supply positions
const positions = await morpho.getSupplyPositions();
for (const pos of positions) {
console.log(`${pos.market}:`);
console.log(` Supplied: $${pos.currentValue}`);
console.log(` Net Deposited: $${pos.netDeposited}`);
console.log(` Earned Yield: $${pos.earnedYield}`);
console.log(` APY: ${pos.supplyApy}%`);
}
// Filter by market
const wethPositions = await morpho.getSupplyPositions('WETH');
Position Management
getStatus()
Returns all borrow positions across all discovered markets.
const status = await morpho.getStatus();
console.log('Agent:', status.agentId);
console.log('Account:', status.agentAccount);
console.log('Total Debt:', status.totalDebt, 'USDC');
for (const pos of status.positions) {
console.log(`${pos.collateralToken}/USDC:`);
console.log(` Collateral: ${pos.collateral}`);
console.log(` Debt: ${pos.debt} USDC`);
console.log(` Borrow Shares: ${pos.borrowShares}`);
}
getBalances()
Get token balances for both the EOA and Safe account, including collateral tokens.
const balances = await morpho.getBalances();
console.log('Agent ID:', balances.agentId);
console.log('EOA ETH:', balances.eth);
console.log('EOA USDC:', balances.usdc);
if (balances.agentAccount) {
console.log('Account:', balances.agentAccount.address);
console.log('Account USDC:', balances.agentAccount.usdc);
}
getMaxBorrowable()
Calculate maximum additional USDC that can be borrowed given current collateral and debt.
const result = await morpho.getMaxBorrowable();
console.log('Total additional borrowable:', result.total.toString(), 'USDC (raw)');
for (const market of result.byMarket) {
console.log(`${market.collateralToken}:`);
console.log(` Max additional: ${market.maxAdditional.toString()}`);
}
Reputation
getCreditScore()
Read the agent’s credit score from the Agether8004Scorer contract.
const score = await morpho.getCreditScore();
console.log('Score:', score.toString());
isEligible(minScore?)
Check if the agent meets a minimum score threshold.
const { eligible, currentScore } = await morpho.isEligible(500n);
isScoreFresh()
Check if the score is within the valid attestation window.
const { fresh, age } = await morpho.isScoreFresh();
Agent-to-Agent
Send collateral tokens to another agent’s account.
const result = await morpho.sponsor(
{ agentId: '42' }, // or { address: '0x...' }
'WETH',
'0.1'
);
console.log('TX:', result.tx);
console.log('Target account:', result.targetAccount);
fundAccount(usdcAmount)
Transfer USDC from EOA to Safe account.
const result = await morpho.fundAccount('500');
console.log('TX:', result.tx);
console.log('Amount:', result.amount, 'USDC');
Complete Example
import { MorphoClient } from '@agether/sdk';
async function main() {
const morpho = new MorphoClient({
privateKey: process.env.AGENT_PRIVATE_KEY!,
rpcUrl: 'https://base-rpc.publicnode.com',
});
// Register
const { agentId, agentAccount } = await morpho.register();
console.log('Agent registered:', agentId, '→', agentAccount);
// Check available markets (49+ on Base)
const markets = await morpho.getMarkets();
console.log('Available markets:', markets.length);
// === Borrowing ===
// Deposit 0.1 WETH and borrow 100 USDC
await morpho.depositAndBorrow('WETH', '0.1', '100');
// === Earning Yield ===
// Supply $50 USDC to earn interest from borrowers
await morpho.supplyAsset('50', 'WETH');
// Check supply position
const positions = await morpho.getSupplyPositions();
console.log('Supply positions:', positions);
// === Cleanup ===
await morpho.withdrawSupply('all', 'WETH');
await morpho.repay('all');
await morpho.withdrawCollateral('WETH', 'all');
console.log('Done — all positions closed');
}
main().catch(console.error);