@agether/agether 2.10.1 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@
2
2
  "id": "agether",
3
3
  "name": "Agether Credit",
4
4
  "description": "Onchain credit protocol for AI agents — Morpho-backed overcollateralized credit, ERC-8004 identity, x402 payments. Private key and RPC keys are read from OpenClaw secrets (env vars); no plaintext config needed.",
5
- "version": "2.4.1",
5
+ "version": "2.4.2",
6
6
  "skills": ["skills/agether"],
7
7
  "configSchema": {
8
8
  "type": "object",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agether/agether",
3
- "version": "2.10.1",
3
+ "version": "2.11.0",
4
4
  "description": "OpenClaw plugin for Agether — onchain credit for AI agents on Ethereum & Base",
5
5
  "main": "src/index.ts",
6
6
  "openclaw": {
@@ -9,7 +9,7 @@
9
9
  ]
10
10
  },
11
11
  "dependencies": {
12
- "@agether/sdk": "^2.12.1",
12
+ "@agether/sdk": "^2.13.0",
13
13
  "axios": "^1.6.0",
14
14
  "ethers": "^6.9.0"
15
15
  },
@@ -5,7 +5,7 @@ description: On-chain credit protocol for AI agents. Morpho credit & lending, x4
5
5
 
6
6
  # Agether — On-Chain Credit for AI Agents
7
7
 
8
- You are an AI agent with on-chain financial capabilities on **Ethereum** and **Base** mainnets. You can borrow USDC, earn yield by lending, and pay for APIs autonomously.
8
+ You are an AI agent with on-chain financial capabilities on **Ethereum** and **Base** mainnets. You can borrow any supported loan token (USDC, WETH, etc.), earn yield by lending, and pay for APIs autonomously.
9
9
 
10
10
  ---
11
11
 
@@ -31,14 +31,14 @@ If you don't paste it, the user sees NOTHING. An empty colon ":" with no data af
31
31
  6. **Never ask for private keys** — they come from OpenClaw secrets (AGETHER_PRIVATE_KEY env var).
32
32
  7. **Max LTV is 80%** (125% collateral ratio). To borrow $X, you need $X × 1.25 in collateral value.
33
33
  8. **When user says "register" → ALWAYS call `agether_register`.** But ONLY after chain is set (see MANDATORY BOOT SEQUENCE). A wallet CAN have multiple ERC-8004 identities. The tool handles everything. Never refuse to register because the wallet "already has an identity". Just call the tool.
34
- 9. **Before calling `agether_register`, ASK the user for an agent name.** The name is stored on-chain in the ERC-8004 metadata URI. Ask: "What name would you like for your agent?" Then pass it as `name` parameter. If the user declines or says "skip", call register without a name (default "Unnamed Agent" will be used).
34
+ 9. **If the user asks to register/deploy a new agent but did NOT provide a name — ask them for a name before calling `agether_register`.** The name is stored on-chain in the ERC-8004 metadata URI and cannot be easily changed. Ask: "What name would you like for your agent?" Then pass it as `name` parameter. Only if the user explicitly says "skip" or "no name", call register without a name (default "Unnamed Agent" will be used). **Never register without asking for a name first.**
35
35
  10. **Never guess about blockchain state.** If you're unsure, call the tool. Don't tell the user something is impossible — try it first.
36
36
  11. **Your EOA wallet IS the user's wallet.** Same private key, same address. If the user says "I have WETH", call `agether_balance` — you'll see it in the `collateral` field. You already have access to those tokens.
37
37
  12. **`morpho_deposit` and `morpho_deposit_and_borrow` transfer collateral from your EOA automatically.** You do NOT need anyone to "send you" tokens. If your EOA has WETH, just call the deposit tool directly. The SDK handles EOA→Safe account→Morpho in one flow.
38
38
  13. **To get USDC for x402:** call `morpho_deposit_and_borrow` with collateral from your EOA. Do NOT ask the user to send tokens — check your balance first.
39
39
  14. **Check health before large actions.** Before borrowing, depositing, or withdrawing significant amounts, call `agether_health` to see current LTV and headroom. This prevents failed transactions.
40
40
  15. **Batch awareness:** `morpho_deposit_and_borrow` is a batched operation (deposit + borrow in one tx). Always prefer it over separate `morpho_deposit` then `morpho_borrow` when doing both — it saves gas and is atomic.
41
- 16. **Collateral tokens are dynamic.** Don't hardcode "WETH/wstETH/cbETH". Call `morpho_markets` to discover which tokens are available. The SDK auto-discovers tokens from Morpho GraphQL API.
41
+ 16. **Collateral and loan tokens are dynamic.** Don't hardcode tokens. Call `morpho_markets` to discover which collateral/loan token pairs are available. The SDK auto-discovers from Morpho GraphQL API.
42
42
  17. **Withdrawals stay in AgentAccount by default.** `morpho_withdraw` and `morpho_withdraw_supply` keep funds in the Safe account unless `toEoa: true` is passed. Use `wallet_withdraw_token` / `wallet_withdraw_eth` to move any token or ETH from AgentAccount to EOA.
43
43
  18. **Always show Health Factor when reporting positions.** HF = LLTV / LTV. HF > 1.15 = safe 🟢, HF 1.0–1.15 = warning 🟡, HF ≤ 1.0 = liquidation 🔴. `morpho_status` returns HF per position. Always paste it so the user understands their risk.
44
44
 
@@ -134,21 +134,21 @@ Both `agether_set_agent` and `agether_register` save the agentId to config perma
134
134
  | Tool | Params | What it does |
135
135
  |------|--------|-------------|
136
136
  | `morpho_status` | none | Show all Morpho positions — collateral, debt, LTV, **Health Factor** (HF), headroom, risk level per market |
137
- | `morpho_markets` | `token?` | List Morpho Blue USDC markets — supply/borrow APY, utilization, LLTV, liquidity. Optional token filter. |
138
- | `morpho_max_borrowable` | none | Calculate max additional USDC borrowable given current collateral/debt |
137
+ | `morpho_markets` | `token?`, `loanToken?` | List all Morpho Blue markets — supply/borrow APY, utilization, LLTV, liquidity. Optional collateral or loan token filter. |
138
+ | `morpho_max_borrowable` | none | Calculate max additional loan token borrowable given current collateral/debt across all markets |
139
139
  | `morpho_deposit` | `amount`, `token` | Deposit collateral from EOA → Morpho (no borrow). Token auto-discovered. |
140
- | `morpho_deposit_and_borrow` | `collateralAmount`, `token`, `borrowAmount` | **PREFERRED** — Deposit + borrow in one batched tx (ERC-7579 batch mode). Best for first-time setup. |
141
- | `morpho_borrow` | `amount`, `token?` | Borrow USDC against existing collateral → lands in AgentAccount. Token auto-detected. |
142
- | `morpho_repay` | `amount`, `token?` | Repay USDC debt. Use `amount: "all"` to clear dust shares. |
140
+ | `morpho_deposit_and_borrow` | `collateralAmount`, `token`, `borrowAmount`, `loanToken?` | **PREFERRED** — Deposit + borrow in one batched tx (ERC-7579 batch mode). Supports any loan token. Best for first-time setup. |
141
+ | `morpho_borrow` | `amount`, `token?`, `loanToken?` | Borrow loan token (USDC, WETH, etc.) against existing collateral → lands in AgentAccount. Token auto-detected. |
142
+ | `morpho_repay` | `amount`, `token?`, `loanToken?` | Repay loan token debt. Use `amount: "all"` to clear dust shares. |
143
143
  | `morpho_withdraw` | `amount`, `token`, `toEoa?` | Withdraw collateral from Morpho. Default: stays in AgentAccount. `toEoa: true` → send to EOA wallet. |
144
144
  | `morpho_sponsor` | `agentId`/`agentAddress`, `amount`, `token` | Transfer collateral to another agent's AgentAccount. |
145
145
 
146
146
  ### Morpho Lending (Supply-side — earn yield)
147
147
  | Tool | Params | What it does |
148
148
  |------|--------|-------------|
149
- | `morpho_supply` | `amount`, `market?` | Supply USDC as a LENDER to earn yield from borrowers. Auto-picks highest APY market if no market specified. |
150
- | `morpho_supply_status` | `market?` | Show supply (lending) positions with earned yield. Tracks yield on-chain — no database needed. |
151
- | `morpho_withdraw_supply` | `amount`, `market?`, `toEoa?` | Withdraw supplied USDC (principal + earned interest). Default: stays in AgentAccount. `toEoa: true` → send to EOA. |
149
+ | `morpho_supply` | `amount`, `market?`, `loanToken?` | Supply a loan token (USDC, WETH, etc.) as a LENDER to earn yield from borrowers. Auto-picks highest APY market if no market specified. |
150
+ | `morpho_supply_status` | `market?` | Show supply (lending) positions with earned yield per loan token. Tracks yield on-chain — no database needed. |
151
+ | `morpho_withdraw_supply` | `amount`, `market?`, `toEoa?` | Withdraw supplied tokens (principal + earned interest). Default: stays in AgentAccount. `toEoa: true` → send to EOA. |
152
152
 
153
153
  ### x402 Payments
154
154
  | Tool | Params | What it does |
@@ -231,24 +231,24 @@ IF no auto-funding configured:
231
231
  → Call morpho_markets to show which tokens are accepted
232
232
  ```
233
233
 
234
- ### User wants to borrow USDC via Morpho
234
+ ### User wants to borrow via Morpho
235
235
  ```
236
236
  1. agether_health ← check collateral, headroom, current LTV
237
237
  2. IF headroom allows the borrow amount AND collateral already in Morpho:
238
- → morpho_borrow(amount)
238
+ → morpho_borrow(amount, loanToken?) ← defaults to most liquid market
239
239
  3. IF EOA has collateral but nothing in Morpho yet:
240
- → morpho_deposit_and_borrow(collateralAmount, token, borrowAmount)
240
+ → morpho_deposit_and_borrow(collateralAmount, token, borrowAmount, loanToken?)
241
241
  4. agether_balance ← show the result with balance changes
242
- 5. Show: tx hash, collateral deposited, USDC borrowed, new balances, new LTV
242
+ 5. Show: tx hash, collateral deposited, amount borrowed, loan token, new balances, new LTV
243
243
  ```
244
244
 
245
245
  ### User wants to earn yield (supply-side lending)
246
246
  ```
247
- 1. Check USDC availability:
248
- - agether_health for AgentAccount USDC
249
- - If no USDC in AgentAccount but exists in EOA → wallet_fund first
247
+ 1. Check token availability:
248
+ - agether_health for AgentAccount balances
249
+ - If no tokens in AgentAccount but exists in EOA → wallet_fund first
250
250
  2. morpho_markets ← show supply APYs to pick best market
251
- 3. morpho_supply(amount, market?) ← supply USDC to earn yield
251
+ 3. morpho_supply(amount, market?, loanToken?) ← supply tokens to earn yield
252
252
  4. Later: morpho_supply_status ← check earned yield
253
253
  5. To exit: morpho_withdraw_supply("all") ← principal + earned interest
254
254
  ```
@@ -256,7 +256,7 @@ IF no auto-funding configured:
256
256
  ### User wants to repay + withdraw
257
257
  ```
258
258
  1. agether_health ← check current debt, collateral, LTV
259
- 2. morpho_repay(amount or "all") ← repay USDC
259
+ 2. morpho_repay(amount or "all", loanToken?) ← repay loan token
260
260
  3. morpho_withdraw("all", token, toEoa: true) ← get collateral back to EOA
261
261
  4. agether_balance ← show final balances
262
262
  ```
@@ -272,7 +272,7 @@ For ETH:
272
272
  For Morpho collateral:
273
273
  → morpho_withdraw(amount, token, toEoa: true) ← must use toEoa flag
274
274
 
275
- For supply positions (lent USDC):
275
+ For supply positions (lent tokens):
276
276
  → morpho_withdraw_supply(amount, market?, toEoa: true) ← must use toEoa flag
277
277
  ```
278
278
 
@@ -344,13 +344,13 @@ You MUST format every on-chain action reply like this. Do NOT skip any field.
344
344
 
345
345
  Example after repay:
346
346
  ```
347
- ✅ Repaid $1.50 USDC
347
+ ✅ Repaid 1.50 USDC
348
348
 
349
349
  🔗 Tx: https://basescan.org/tx/0xabc123def456...
350
350
  💰 Balances:
351
351
  EOA: 0.05 ETH, 0 USDC
352
- AgentAccount: 0 ETH, $3.50 USDC
353
- 📊 Debt remaining: $0.00
352
+ AgentAccount: 0 ETH, 3.50 USDC
353
+ 📊 Debt remaining: 0.00 USDC
354
354
  ```
355
355
 
356
356
  Example after register:
@@ -365,11 +365,11 @@ Example after register:
365
365
 
366
366
  Example after supply (lending):
367
367
  ```
368
- ✅ Supplied $500 USDC to WETH/USDC market
368
+ ✅ Supplied 500 USDC to WETH/USDC market
369
369
 
370
370
  🔗 Tx: https://basescan.org/tx/0x789abc...
371
371
  📈 Earning ~3.2% APY from borrowers
372
- 💰 AgentAccount: $50 USDC remaining
372
+ 💰 AgentAccount: 50 USDC remaining
373
373
  ```
374
374
 
375
375
  If something **fails**:
@@ -385,7 +385,7 @@ If something **fails**:
385
385
  | Parameter | Value |
386
386
  |-----------|-------|
387
387
  | Chains | Ethereum mainnet (1) or Base mainnet (8453) — set via `agether_set_chain` |
388
- | Currency | USDC (6 decimals) |
388
+ | Currency | Any supported loan token — USDC (6 decimals), WETH (18 decimals), etc. Dynamically discovered from Morpho markets. |
389
389
  | Max LTV | 80% (= 125% collateral ratio) |
390
390
  | Collateral tokens | Dynamically discovered from Morpho markets (call `morpho_markets`) |
391
391
  | x402 cost | ~$0.001 per API call (WeatherXM) |
@@ -402,7 +402,7 @@ If something **fails**:
402
402
  | `Payment rejected (402)` | No USDC for x402 payment | Borrow USDC first, or enable autoDraw/autoYield in config |
403
403
  | `No collateral deposited` | Trying to borrow without collateral | `morpho_deposit` first |
404
404
  | `Insufficient collateral` | EOA doesn't have enough of that token | Tell user to send collateral to EOA address |
405
- | `Insufficient USDC in AgentAccount` | Not enough USDC for repay/pay | Fund via borrow, yield withdrawal, or `wallet_fund` |
405
+ | `Insufficient USDC in AgentAccount` | Not enough loan token for repay/pay | Fund via borrow, yield withdrawal, or `wallet_fund` |
406
406
  | `ExecutionFailed` | Smart contract call reverted | Check inner error, usually LTV or approval issue |
407
407
  | `PositionNotActive` | No collateral deposited for this token | Deposit collateral with `morpho_deposit` first |
408
408
 
@@ -437,12 +437,12 @@ EOA Wallet (private key from AGETHER_PRIVATE_KEY)
437
437
  Morpho Blue (direct lending, overcollateralized 125%)
438
438
  ├── BORROWER side:
439
439
  │ ├── supplyCollateral() → collateral into Morpho Blue market
440
- │ ├── borrow() → USDC from Morpho Blue → AgentAccount
441
- │ ├── repay() → USDC from AgentAccount → Morpho Blue
440
+ │ ├── borrow() → loan token (USDC, WETH, etc.) from Morpho Blue → AgentAccount
441
+ │ ├── repay() → loan token from AgentAccount → Morpho Blue
442
442
  │ └── withdrawCollateral() → collateral back (to AgentAccount or EOA)
443
443
  └── LENDER side:
444
- ├── supply() → USDC into Morpho Blue market (earn yield)
445
- ├── withdraw() → USDC + earned interest back (to AgentAccount or EOA)
444
+ ├── supply() → loan token into Morpho Blue market (earn yield)
445
+ ├── withdraw() → loan token + earned interest back (to AgentAccount or EOA)
446
446
  └── Yield tracked via Morpho GraphQL API (no database needed)
447
447
 
448
448
  Wallet transfers:
package/src/index.ts CHANGED
@@ -59,7 +59,7 @@ const SPEND_CACHE_FILE = path.join(
59
59
 
60
60
  interface SpendCacheData {
61
61
  date: string; // YYYY-MM-DD
62
- totalBorrowed: string; // raw bigint string (6-decimal USDC units)
62
+ totalBorrowed: string; // raw bigint string (loan token native units)
63
63
  }
64
64
 
65
65
  function loadSpendCache(): SpendCacheData | undefined {
@@ -519,14 +519,17 @@ export default function register(api: any) {
519
519
  ]);
520
520
 
521
521
  const positions = status.positions.map((p: any) => {
522
- const mm = maxBorrow.byMarket.find((m: any) => m.collateralToken === p.collateralToken);
523
- const collateralValueUsd = mm ? Number(mm.collateralValue) / 1e6 : 0;
522
+ const mm = maxBorrow.byMarket.find((m: any) => m.collateralToken === p.collateralToken && m.loanToken === p.loanToken);
523
+ const loanDecimals = mm ? mm.loanDecimals : 6;
524
+ const divisor = 10 ** loanDecimals;
525
+ const collateralValue = mm ? Number(mm.collateralValue) / divisor : 0;
524
526
  const debt = parseFloat(p.debt);
525
527
  const lltv = 0.80; // Morpho LLTV
526
- const ltv = collateralValueUsd > 0 ? debt / collateralValueUsd : 0;
528
+ const ltv = collateralValue > 0 ? debt / collateralValue : 0;
527
529
  // HF = LLTV / LTV — >1 is safe, <1 is liquidatable
528
530
  const hf = ltv > 0 ? lltv / ltv : Infinity;
529
- const headroom = mm ? Number(mm.maxAdditional) / 1e6 : 0;
531
+ const headroom = mm ? Number(mm.maxAdditional) / divisor : 0;
532
+ const loanSymbol = p.loanToken || 'USDC';
530
533
 
531
534
  let risk: string;
532
535
  if (debt === 0) risk = "🟢 no debt";
@@ -536,19 +539,20 @@ export default function register(api: any) {
536
539
 
537
540
  return {
538
541
  collateralToken: p.collateralToken,
542
+ loanToken: loanSymbol,
539
543
  collateral: p.collateral,
540
- collateralValueUsd: `$${collateralValueUsd.toFixed(2)}`,
541
- debt: `$${debt.toFixed(2)}`,
544
+ collateralValue: `${collateralValue.toFixed(4)} ${loanSymbol}`,
545
+ debt: `${debt.toFixed(4)} ${loanSymbol}`,
542
546
  ltv: `${(ltv * 100).toFixed(1)}%`,
543
547
  healthFactor: debt === 0 ? "∞" : hf.toFixed(2),
544
- headroom: `$${headroom.toFixed(2)}`,
548
+ headroom: `${headroom.toFixed(4)} ${loanSymbol}`,
545
549
  risk,
546
550
  };
547
551
  });
548
552
 
549
553
  return ok(JSON.stringify({
550
554
  agentAccount: status.agentAccount,
551
- totalDebt: `$${status.totalDebt}`,
555
+ totalDebt: status.totalDebt,
552
556
  positions,
553
557
  }, null, 2));
554
558
  } catch (e) { return fail(e); }
@@ -561,7 +565,7 @@ export default function register(api: any) {
561
565
  api.registerTool({
562
566
  name: "morpho_deposit",
563
567
  description:
564
- "Deposit collateral into Morpho Blue via AgentAccount. Enables borrowing USDC. Token is auto-discovered from available markets.",
568
+ "Deposit collateral into Morpho Blue via AgentAccount. Enables borrowing against it. Token is auto-discovered from available markets.",
565
569
  parameters: {
566
570
  type: "object",
567
571
  properties: {
@@ -592,18 +596,20 @@ export default function register(api: any) {
592
596
  api.registerTool({
593
597
  name: "morpho_deposit_and_borrow",
594
598
  description:
595
- "Deposit collateral AND borrow USDC in one batched transaction via AgentAccount (ERC-7579 batch mode). " +
596
- "Deposits collateral from EOA into Morpho, then borrows USDC. All in one tx.",
599
+ "Deposit collateral AND borrow in one batched transaction via AgentAccount (ERC-7579 batch mode). " +
600
+ "Deposits collateral from EOA into Morpho, then borrows loan token. All in one tx. " +
601
+ "Supports any loan token (USDC, WETH, etc.).",
597
602
  parameters: {
598
603
  type: "object",
599
604
  properties: {
600
605
  collateralAmount: { type: "string", description: "Amount of collateral (e.g. '0.05')" },
601
606
  token: { type: "string", description: "Collateral token" },
602
- borrowAmount: { type: "string", description: "USDC amount to borrow (e.g. '50')" },
607
+ borrowAmount: { type: "string", description: "Amount to borrow (e.g. '50')" },
608
+ loanToken: { type: "string", description: "Loan token to borrow (e.g. 'USDC', 'WETH'). Optional — defaults to most liquid market." },
603
609
  },
604
610
  required: ["collateralAmount", "token", "borrowAmount"],
605
611
  },
606
- async execute(_id: string, params: { collateralAmount: string; token: string; borrowAmount: string }) {
612
+ async execute(_id: string, params: { collateralAmount: string; token: string; borrowAmount: string; loanToken?: string }) {
607
613
  try {
608
614
  const cfg = getConfig(api);
609
615
  requireChain(cfg);
@@ -612,11 +618,13 @@ export default function register(api: any) {
612
618
  params.token,
613
619
  params.collateralAmount,
614
620
  params.borrowAmount,
621
+ undefined,
622
+ params.loanToken,
615
623
  );
616
624
  return ok(JSON.stringify({
617
625
  status: "deposited_and_borrowed",
618
626
  collateral: `${params.collateralAmount} ${params.token}`,
619
- borrowed: `$${params.borrowAmount}`,
627
+ borrowed: `${params.borrowAmount}`,
620
628
  agentAccount: result.agentAccount,
621
629
  tx: txLink(result.tx),
622
630
  }));
@@ -671,25 +679,27 @@ export default function register(api: any) {
671
679
  api.registerTool({
672
680
  name: "morpho_borrow",
673
681
  description:
674
- "Borrow USDC against deposited collateral via Morpho Blue. " +
675
- "USDC lands in AgentAccount. Requires collateral deposited first.",
682
+ "Borrow loan token against deposited collateral via Morpho Blue. " +
683
+ "Borrowed tokens land in AgentAccount. Requires collateral deposited first. " +
684
+ "Supports any loan token (USDC, WETH, etc.).",
676
685
  parameters: {
677
686
  type: "object",
678
687
  properties: {
679
- amount: { type: "string", description: "Amount in USD to borrow (e.g. '100')" },
688
+ amount: { type: "string", description: "Amount to borrow (e.g. '100')" },
680
689
  token: { type: "string", description: "Collateral token (optional, auto-detected)" },
690
+ loanToken: { type: "string", description: "Loan token to borrow (e.g. 'USDC', 'WETH'). Optional — defaults to most liquid market." },
681
691
  },
682
692
  required: ["amount"],
683
693
  },
684
- async execute(_id: string, params: { amount: string; token?: string }) {
694
+ async execute(_id: string, params: { amount: string; token?: string; loanToken?: string }) {
685
695
  try {
686
696
  const cfg = getConfig(api);
687
697
  requireChain(cfg);
688
698
  const client = createMorphoClient(cfg);
689
- const result = await client.borrow(params.amount, params.token);
699
+ const result = await client.borrow(params.amount, params.token, undefined, params.loanToken);
690
700
  return ok(JSON.stringify({
691
701
  status: "borrowed",
692
- amount: `$${params.amount}`,
702
+ amount: params.amount,
693
703
  collateral: result.collateralToken,
694
704
  agentAccount: result.agentAccount,
695
705
  tx: txLink(result.tx),
@@ -704,25 +714,27 @@ export default function register(api: any) {
704
714
  api.registerTool({
705
715
  name: "morpho_repay",
706
716
  description:
707
- "Repay borrowed USDC back to Morpho Blue from AgentAccount. Reduces debt. " +
708
- "Use amount 'all' to repay full debt and clear dust shares.",
717
+ "Repay borrowed loan token back to Morpho Blue from AgentAccount. Reduces debt. " +
718
+ "Use amount 'all' to repay full debt and clear dust shares. " +
719
+ "Supports any loan token (USDC, WETH, etc.).",
709
720
  parameters: {
710
721
  type: "object",
711
722
  properties: {
712
- amount: { type: "string", description: "Amount in USD to repay (e.g. '50' or 'all' for full repayment)" },
723
+ amount: { type: "string", description: "Amount to repay (e.g. '50' or 'all' for full repayment)" },
713
724
  token: { type: "string", description: "Collateral token (optional, auto-detected)" },
725
+ loanToken: { type: "string", description: "Loan token to repay (e.g. 'USDC', 'WETH'). Optional — auto-detected." },
714
726
  },
715
727
  required: ["amount"],
716
728
  },
717
- async execute(_id: string, params: { amount: string; token?: string }) {
729
+ async execute(_id: string, params: { amount: string; token?: string; loanToken?: string }) {
718
730
  try {
719
731
  const cfg = getConfig(api);
720
732
  requireChain(cfg);
721
733
  const client = createMorphoClient(cfg);
722
- const result = await client.repay(params.amount, params.token);
734
+ const result = await client.repay(params.amount, params.token, undefined, params.loanToken);
723
735
  return ok(JSON.stringify({
724
736
  status: "repaid",
725
- amount: `$${params.amount}`,
737
+ amount: params.amount,
726
738
  remainingDebt: result.remainingDebt,
727
739
  tx: txLink(result.tx),
728
740
  }));
@@ -774,33 +786,38 @@ export default function register(api: any) {
774
786
  api.registerTool({
775
787
  name: "morpho_supply",
776
788
  description:
777
- "Supply USDC to a Morpho Blue market as a LENDER to earn yield. " +
778
- "This is the lending side — your USDC earns interest from borrowers. " +
779
- "Unlike morpho_deposit (collateral for borrowing), this puts USDC to work earning APY.",
789
+ "Supply a loan token (USDC, WETH, etc.) to a Morpho Blue market as a LENDER to earn yield. " +
790
+ "This is the lending side — your tokens earn interest from borrowers. " +
791
+ "Unlike morpho_deposit (collateral for borrowing), this puts tokens to work earning APY.",
780
792
  parameters: {
781
793
  type: "object",
782
794
  properties: {
783
- amount: { type: "string", description: "USDC amount to supply (e.g. '500')" },
795
+ amount: { type: "string", description: "Amount to supply (e.g. '500')" },
784
796
  market: {
785
797
  type: "string",
786
798
 
787
799
  description: "Which market to supply to, identified by collateral token (optional — auto-picks highest APY)",
788
800
  },
801
+ loanToken: {
802
+ type: "string",
803
+ description: "Loan token to supply (e.g. 'USDC', 'WETH'). Optional — defaults to USDC.",
804
+ },
789
805
  },
790
806
  required: ["amount"],
791
807
  },
792
- async execute(_id: string, params: { amount: string; market?: string }) {
808
+ async execute(_id: string, params: { amount: string; market?: string; loanToken?: string }) {
793
809
  try {
794
810
  const cfg = getConfig(api);
795
811
  requireChain(cfg);
796
812
  const client = createMorphoClient(cfg);
797
- const result = await client.supplyAsset(params.amount, params.market);
813
+ const result = await client.supplyAsset(params.amount, params.market, params.loanToken);
814
+ const tokenLabel = params.loanToken || 'USDC';
798
815
  return ok(JSON.stringify({
799
816
  status: "supplied",
800
- amount: `$${params.amount} USDC`,
817
+ amount: `${params.amount} ${tokenLabel}`,
801
818
  market: result.collateralToken,
802
819
  agentAccount: result.agentAccount,
803
- note: "USDC is now earning yield from borrowers in this market",
820
+ note: `${tokenLabel} is now earning yield from borrowers in this market`,
804
821
  tx: txLink(result.tx),
805
822
  }));
806
823
  } catch (e) { return fail(e); }
@@ -839,9 +856,9 @@ export default function register(api: any) {
839
856
 
840
857
  const formatted = positions.map((p: any) => ({
841
858
  market: `${p.collateralToken}/${p.loanToken}`,
842
- suppliedAssets: `$${p.suppliedAssets} USDC`,
843
- netDeposited: `$${p.netDeposited} USDC`,
844
- earnedYield: `$${p.earnedYield} USDC`,
859
+ suppliedAssets: `${p.suppliedAssets} ${p.loanToken}`,
860
+ netDeposited: `${p.netDeposited} ${p.loanToken}`,
861
+ earnedYield: `${p.earnedYield} ${p.loanToken}`,
845
862
  supplyApy: `${(p.supplyApy * 100).toFixed(2)}%`,
846
863
  marketId: p.marketId.slice(0, 18) + "…",
847
864
  }));
@@ -852,8 +869,8 @@ export default function register(api: any) {
852
869
  return ok(JSON.stringify({
853
870
  positions: formatted,
854
871
  totals: {
855
- totalSupplied: `$${totalSupplied.toFixed(2)} USDC`,
856
- totalYield: `$${totalYield.toFixed(6)} USDC`,
872
+ totalSupplied: `${totalSupplied.toFixed(2)}`,
873
+ totalYield: `${totalYield.toFixed(6)}`,
857
874
  },
858
875
  }, null, 2));
859
876
  } catch (e) { return fail(e); }
@@ -861,18 +878,18 @@ export default function register(api: any) {
861
878
  });
862
879
 
863
880
  // ═══════════════════════════════════════════════════════
864
- // TOOL: morpho_withdraw_supply (withdraw lent USDC)
881
+ // TOOL: morpho_withdraw_supply (withdraw lent tokens)
865
882
  // ═══════════════════════════════════════════════════════
866
883
  api.registerTool({
867
884
  name: "morpho_withdraw_supply",
868
885
  description:
869
- "Withdraw supplied USDC (principal + earned interest) from a Morpho Blue lending position. " +
870
- "By default keeps USDC in AgentAccount. Set toEoa=true to send to EOA wallet. " +
886
+ "Withdraw supplied tokens (principal + earned interest) from a Morpho Blue lending position. " +
887
+ "By default keeps tokens in AgentAccount. Set toEoa=true to send to EOA wallet. " +
871
888
  "Use amount 'all' to withdraw the full position. Different from morpho_withdraw which withdraws collateral.",
872
889
  parameters: {
873
890
  type: "object",
874
891
  properties: {
875
- amount: { type: "string", description: "USDC amount to withdraw (e.g. '100' or 'all')" },
892
+ amount: { type: "string", description: "Amount to withdraw (e.g. '100' or 'all')" },
876
893
  market: {
877
894
  type: "string",
878
895
 
@@ -892,8 +909,8 @@ export default function register(api: any) {
892
909
  const result = await client.withdrawSupply(params.amount, params.market, receiver);
893
910
  return ok(JSON.stringify({
894
911
  status: "withdrawn",
895
- amount: params.amount === "all" ? "all (full position)" : `$${params.amount} USDC`,
896
- remainingSupply: `$${result.remainingSupply} USDC`,
912
+ amount: params.amount === "all" ? "all (full position)" : params.amount,
913
+ remainingSupply: result.remainingSupply,
897
914
  destination: result.destination,
898
915
  tx: txLink(result.tx),
899
916
  }));
@@ -907,20 +924,21 @@ export default function register(api: any) {
907
924
  api.registerTool({
908
925
  name: "morpho_markets",
909
926
  description:
910
- "List available Morpho Blue USDC markets — liquidity, supply/borrow APY, utilization, LLTV. " +
911
- "Optionally filter by collateral token.",
927
+ "List available Morpho Blue markets — liquidity, supply/borrow APY, utilization, LLTV. " +
928
+ "Supports all loan tokens (USDC, WETH, etc.). Optionally filter by collateral or loan token.",
912
929
  parameters: {
913
930
  type: "object",
914
931
  properties: {
915
932
  token: { type: "string", description: "Filter by collateral token (optional)" },
933
+ loanToken: { type: "string", description: "Filter by loan token (e.g. 'USDC', 'WETH'). Optional — shows all." },
916
934
  },
917
935
  required: [],
918
936
  },
919
- async execute(_id: string, params: { token?: string }) {
937
+ async execute(_id: string, params: { token?: string; loanToken?: string }) {
920
938
  try {
921
939
  const cfg = getConfig(api);
922
940
  const client = createMorphoClient(cfg);
923
- const rates = await client.getMarketRates(params.token);
941
+ const rates = await client.getMarketRates(params.token, params.loanToken);
924
942
 
925
943
  if (rates.length === 0) return ok("No markets found.");
926
944