@agether/sdk 2.13.0 → 2.14.1

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.
package/dist/index.js CHANGED
@@ -1155,7 +1155,7 @@ var MorphoClient = class {
1155
1155
  const chainId = this.config.chainId;
1156
1156
  const query = `{
1157
1157
  markets(
1158
- first: 50
1158
+ first: 500
1159
1159
  orderBy: SupplyAssetsUsd
1160
1160
  orderDirection: Desc
1161
1161
  where: { chainId_in: [${chainId}] }
@@ -1261,7 +1261,7 @@ var MorphoClient = class {
1261
1261
  const resolved = await this._resolveToken(loanTokenSymbolOrAddress);
1262
1262
  loanAddr = resolved.address.toLowerCase();
1263
1263
  } catch {
1264
- loanAddr = loanTokenSymbolOrAddress.toLowerCase();
1264
+ loanAddr = void 0;
1265
1265
  }
1266
1266
  }
1267
1267
  }
@@ -1269,6 +1269,7 @@ var MorphoClient = class {
1269
1269
  for (const m of this._discoveredMarkets ?? []) {
1270
1270
  if (m.collateralAsset.address.toLowerCase() !== colAddr) continue;
1271
1271
  if (loanAddr && m.loanAsset.address.toLowerCase() !== loanAddr) continue;
1272
+ if (!loanAddr && loanTokenSymbolOrAddress && m.loanAsset.symbol.toUpperCase() !== loanTokenSymbolOrAddress.toUpperCase()) continue;
1272
1273
  return {
1273
1274
  loanToken: m.loanAsset.address,
1274
1275
  collateralToken: m.collateralAsset.address,
@@ -1277,6 +1278,27 @@ var MorphoClient = class {
1277
1278
  lltv: m.lltv
1278
1279
  };
1279
1280
  }
1281
+ if (!collateralSymbolOrAddress.startsWith("0x")) {
1282
+ const searched = await this.searchMarkets(collateralSymbolOrAddress, { asCollateral: true });
1283
+ const allResults = [...searched];
1284
+ if (loanTokenSymbolOrAddress && !loanTokenSymbolOrAddress.startsWith("0x")) {
1285
+ const loanSearched = await this.searchMarkets(loanTokenSymbolOrAddress, { asLoanToken: true });
1286
+ const seen = new Set(allResults.map((r) => r.marketId));
1287
+ for (const m of loanSearched) {
1288
+ if (!seen.has(m.marketId)) allResults.push(m);
1289
+ }
1290
+ }
1291
+ for (const m of allResults) {
1292
+ if (colAddr.startsWith("0x") && m.collateralAddress.toLowerCase() !== colAddr) {
1293
+ if (m.collateralToken.toUpperCase() !== collateralSymbolOrAddress.toUpperCase()) continue;
1294
+ } else if (m.collateralToken.toUpperCase() !== collateralSymbolOrAddress.toUpperCase()) {
1295
+ continue;
1296
+ }
1297
+ if (loanAddr && m.loanAddress.toLowerCase() !== loanAddr) continue;
1298
+ if (!loanAddr && loanTokenSymbolOrAddress && m.loanToken.toUpperCase() !== loanTokenSymbolOrAddress.toUpperCase()) continue;
1299
+ return this.getMarketParams(m.marketId);
1300
+ }
1301
+ }
1280
1302
  throw new AgetherError(
1281
1303
  `No Morpho market found for collateral ${collateralSymbolOrAddress}` + (loanTokenSymbolOrAddress ? ` with loan token ${loanTokenSymbolOrAddress}` : ""),
1282
1304
  "MARKET_NOT_FOUND"
@@ -1307,26 +1329,54 @@ var MorphoClient = class {
1307
1329
  };
1308
1330
  }
1309
1331
  /**
1310
- * Full status: positions across all discovered markets.
1332
+ * Full status: positions across all markets the user has interacted with.
1333
+ *
1334
+ * Uses Morpho GraphQL `marketPositions` to find ALL positions (not limited
1335
+ * to the top-500 markets), then reads onchain data for accurate debt.
1311
1336
  */
1312
1337
  async getStatus() {
1313
1338
  const acctAddr = await this.getAccountAddress();
1314
- const markets = await this.getMarkets();
1339
+ const chainId = this.config.chainId;
1315
1340
  const positions = [];
1316
1341
  let totalDebtFloat = 0;
1317
- for (const m of markets) {
1318
- if (!m.collateralAsset || m.collateralAsset.address === import_ethers2.ethers.ZeroAddress) continue;
1319
- try {
1320
- const pos = await this.morphoBlue.position(m.uniqueKey, acctAddr);
1321
- if (pos.collateral === 0n && pos.borrowShares === 0n && pos.supplyShares === 0n) continue;
1342
+ try {
1343
+ const posQuery = `{
1344
+ marketPositions(
1345
+ where: {
1346
+ userAddress_in: ["${acctAddr}"]
1347
+ chainId_in: [${chainId}]
1348
+ }
1349
+ first: 100
1350
+ ) {
1351
+ items {
1352
+ supplyShares
1353
+ borrowShares
1354
+ collateral
1355
+ market {
1356
+ uniqueKey
1357
+ loanAsset { symbol address decimals }
1358
+ collateralAsset { symbol address decimals }
1359
+ }
1360
+ }
1361
+ }
1362
+ }`;
1363
+ const resp = await import_axios.default.post(MORPHO_API_URL, { query: posQuery }, { timeout: 15e3 });
1364
+ const items = resp.data?.data?.marketPositions?.items ?? [];
1365
+ for (const item of items) {
1366
+ const supplyShares = BigInt(item.supplyShares ?? "0");
1367
+ const borrowShares = BigInt(item.borrowShares ?? "0");
1368
+ const collateral = BigInt(item.collateral ?? "0");
1369
+ if (collateral === 0n && borrowShares === 0n && supplyShares === 0n) continue;
1370
+ const m = item.market;
1371
+ if (!m?.collateralAsset || !m?.loanAsset) continue;
1322
1372
  const loanDecimals = m.loanAsset.decimals;
1323
1373
  let debt = 0n;
1324
- if (pos.borrowShares > 0n) {
1374
+ if (borrowShares > 0n) {
1325
1375
  try {
1326
1376
  const mkt = await this.morphoBlue.market(m.uniqueKey);
1327
1377
  const totalBorrowShares = BigInt(mkt.totalBorrowShares);
1328
1378
  const totalBorrowAssets = BigInt(mkt.totalBorrowAssets);
1329
- debt = totalBorrowShares > 0n ? (BigInt(pos.borrowShares) * totalBorrowAssets + totalBorrowShares - 1n) / totalBorrowShares : 0n;
1379
+ debt = totalBorrowShares > 0n ? (borrowShares * totalBorrowAssets + totalBorrowShares - 1n) / totalBorrowShares : 0n;
1330
1380
  totalDebtFloat += parseFloat(import_ethers2.ethers.formatUnits(debt, loanDecimals));
1331
1381
  } catch (e) {
1332
1382
  console.warn(`[agether] debt calc failed for market ${m.uniqueKey}:`, e instanceof Error ? e.message : e);
@@ -1336,14 +1386,46 @@ var MorphoClient = class {
1336
1386
  marketId: m.uniqueKey,
1337
1387
  collateralToken: m.collateralAsset.symbol,
1338
1388
  loanToken: m.loanAsset.symbol,
1339
- collateral: import_ethers2.ethers.formatUnits(pos.collateral, m.collateralAsset.decimals),
1340
- borrowShares: pos.borrowShares.toString(),
1341
- supplyShares: pos.supplyShares.toString(),
1389
+ collateral: import_ethers2.ethers.formatUnits(collateral, m.collateralAsset.decimals),
1390
+ borrowShares: borrowShares.toString(),
1391
+ supplyShares: supplyShares.toString(),
1342
1392
  debt: import_ethers2.ethers.formatUnits(debt, loanDecimals)
1343
1393
  });
1344
- } catch (e) {
1345
- console.warn(`[agether] position read failed for market:`, e instanceof Error ? e.message : e);
1346
- continue;
1394
+ }
1395
+ } catch (e) {
1396
+ console.warn("[agether] marketPositions API failed, falling back to market scan:", e instanceof Error ? e.message : e);
1397
+ const markets = await this.getMarkets();
1398
+ for (const m of markets) {
1399
+ if (!m.collateralAsset || m.collateralAsset.address === import_ethers2.ethers.ZeroAddress) continue;
1400
+ try {
1401
+ const pos = await this.morphoBlue.position(m.uniqueKey, acctAddr);
1402
+ if (pos.collateral === 0n && pos.borrowShares === 0n && pos.supplyShares === 0n) continue;
1403
+ const loanDecimals = m.loanAsset.decimals;
1404
+ let debt = 0n;
1405
+ if (pos.borrowShares > 0n) {
1406
+ try {
1407
+ const mkt = await this.morphoBlue.market(m.uniqueKey);
1408
+ const totalBorrowShares = BigInt(mkt.totalBorrowShares);
1409
+ const totalBorrowAssets = BigInt(mkt.totalBorrowAssets);
1410
+ debt = totalBorrowShares > 0n ? (BigInt(pos.borrowShares) * totalBorrowAssets + totalBorrowShares - 1n) / totalBorrowShares : 0n;
1411
+ totalDebtFloat += parseFloat(import_ethers2.ethers.formatUnits(debt, loanDecimals));
1412
+ } catch (e2) {
1413
+ console.warn(`[agether] debt calc failed:`, e2 instanceof Error ? e2.message : e2);
1414
+ }
1415
+ }
1416
+ positions.push({
1417
+ marketId: m.uniqueKey,
1418
+ collateralToken: m.collateralAsset.symbol,
1419
+ loanToken: m.loanAsset.symbol,
1420
+ collateral: import_ethers2.ethers.formatUnits(pos.collateral, m.collateralAsset.decimals),
1421
+ borrowShares: pos.borrowShares.toString(),
1422
+ supplyShares: pos.supplyShares.toString(),
1423
+ debt: import_ethers2.ethers.formatUnits(debt, loanDecimals)
1424
+ });
1425
+ } catch (e2) {
1426
+ console.warn(`[agether] position read failed:`, e2 instanceof Error ? e2.message : e2);
1427
+ continue;
1428
+ }
1347
1429
  }
1348
1430
  }
1349
1431
  return {
@@ -1447,41 +1529,39 @@ var MorphoClient = class {
1447
1529
  async getMarketRates(collateralSymbolOrAddress, loanTokenSymbolOrAddress) {
1448
1530
  const chainId = this.config.chainId;
1449
1531
  let collateralFilter = "";
1532
+ let loanFilter = "";
1533
+ let searchTerm = "";
1450
1534
  if (collateralSymbolOrAddress) {
1451
- let colAddr;
1452
1535
  if (collateralSymbolOrAddress.startsWith("0x")) {
1453
- colAddr = collateralSymbolOrAddress.toLowerCase();
1536
+ collateralFilter = `, collateralAssetAddress_in: ["${collateralSymbolOrAddress.toLowerCase()}"]`;
1454
1537
  } else {
1455
- try {
1456
- const resolved = await this._resolveToken(collateralSymbolOrAddress);
1457
- colAddr = resolved.address.toLowerCase();
1458
- } catch {
1459
- colAddr = collateralSymbolOrAddress.toLowerCase();
1538
+ const cached = this._tokenCache.get(collateralSymbolOrAddress.toUpperCase());
1539
+ if (cached) {
1540
+ collateralFilter = `, collateralAssetAddress_in: ["${cached.address.toLowerCase()}"]`;
1541
+ } else {
1542
+ searchTerm = collateralSymbolOrAddress;
1460
1543
  }
1461
1544
  }
1462
- collateralFilter = `, collateralAssetAddress_in: ["${colAddr}"]`;
1463
1545
  }
1464
- let loanFilter = "";
1465
1546
  if (loanTokenSymbolOrAddress) {
1466
- let loanAddr;
1467
1547
  if (loanTokenSymbolOrAddress.startsWith("0x")) {
1468
- loanAddr = loanTokenSymbolOrAddress.toLowerCase();
1548
+ loanFilter = `, loanAssetAddress_in: ["${loanTokenSymbolOrAddress.toLowerCase()}"]`;
1469
1549
  } else {
1470
- try {
1471
- const resolved = await this._resolveToken(loanTokenSymbolOrAddress);
1472
- loanAddr = resolved.address.toLowerCase();
1473
- } catch {
1474
- loanAddr = loanTokenSymbolOrAddress.toLowerCase();
1550
+ const cached = this._tokenCache.get(loanTokenSymbolOrAddress.toUpperCase());
1551
+ if (cached) {
1552
+ loanFilter = `, loanAssetAddress_in: ["${cached.address.toLowerCase()}"]`;
1553
+ } else {
1554
+ searchTerm = searchTerm || loanTokenSymbolOrAddress;
1475
1555
  }
1476
1556
  }
1477
- loanFilter = `, loanAssetAddress_in: ["${loanAddr}"]`;
1478
1557
  }
1558
+ const searchClause = searchTerm ? `, search: "${searchTerm}"` : "";
1479
1559
  const query = `{
1480
1560
  markets(
1481
- first: 50
1561
+ first: 100
1482
1562
  orderBy: SupplyAssetsUsd
1483
1563
  orderDirection: Desc
1484
- where: { chainId_in: [${chainId}]${loanFilter}${collateralFilter} }
1564
+ where: { chainId_in: [${chainId}]${loanFilter}${collateralFilter}${searchClause} }
1485
1565
  ) {
1486
1566
  items {
1487
1567
  uniqueKey
@@ -1500,7 +1580,15 @@ var MorphoClient = class {
1500
1580
  }`;
1501
1581
  try {
1502
1582
  const resp = await import_axios.default.post(MORPHO_API_URL, { query }, { timeout: 1e4 });
1503
- const items = resp.data?.data?.markets?.items ?? [];
1583
+ let items = resp.data?.data?.markets?.items ?? [];
1584
+ if (searchTerm && collateralSymbolOrAddress && !collateralSymbolOrAddress.startsWith("0x")) {
1585
+ const sym = collateralSymbolOrAddress.toUpperCase();
1586
+ items = items.filter((m) => m.collateralAsset?.symbol?.toUpperCase() === sym);
1587
+ }
1588
+ if (searchTerm && loanTokenSymbolOrAddress && !loanTokenSymbolOrAddress.startsWith("0x")) {
1589
+ const sym = loanTokenSymbolOrAddress.toUpperCase();
1590
+ items = items.filter((m) => m.loanAsset?.symbol?.toUpperCase() === sym);
1591
+ }
1504
1592
  return items.filter((m) => m.collateralAsset?.address && m.collateralAsset.address !== import_ethers2.ethers.ZeroAddress).map((m) => {
1505
1593
  const loanDecimals = m.loanAsset?.decimals ?? 18;
1506
1594
  return {
@@ -1521,6 +1609,205 @@ var MorphoClient = class {
1521
1609
  return [];
1522
1610
  }
1523
1611
  }
1612
+ // ════════════════════════════════════════════════════════
1613
+ // Market Search & Wallet Discovery
1614
+ // ════════════════════════════════════════════════════════
1615
+ /**
1616
+ * Search Morpho markets by token name using the Morpho GraphQL API `search` field.
1617
+ * No hardcoded token lists — uses Morpho's built-in fuzzy search.
1618
+ *
1619
+ * @param search - token name or symbol (e.g. 'WETH', 'staked ETH', 'ezETH')
1620
+ * @param options.asCollateral - only return markets where the searched token is collateral
1621
+ * @param options.asLoanToken - only return markets where the searched token is the loan asset
1622
+ */
1623
+ async searchMarkets(search, options) {
1624
+ const chainId = this.config.chainId;
1625
+ const query = `{
1626
+ markets(
1627
+ first: 100
1628
+ orderBy: SupplyAssetsUsd
1629
+ orderDirection: Desc
1630
+ where: { chainId_in: [${chainId}], search: "${search}" }
1631
+ ) {
1632
+ items {
1633
+ uniqueKey
1634
+ lltv
1635
+ loanAsset { address symbol decimals }
1636
+ collateralAsset { address symbol decimals }
1637
+ state {
1638
+ borrowAssets
1639
+ supplyAssets
1640
+ utilization
1641
+ supplyApy
1642
+ borrowApy
1643
+ }
1644
+ }
1645
+ }
1646
+ }`;
1647
+ try {
1648
+ const resp = await import_axios.default.post(MORPHO_API_URL, { query }, { timeout: 1e4 });
1649
+ let items = resp.data?.data?.markets?.items ?? [];
1650
+ items = items.filter((m) => m.collateralAsset?.address && m.collateralAsset.address !== import_ethers2.ethers.ZeroAddress);
1651
+ const searchUpper = search.toUpperCase();
1652
+ if (options?.asCollateral) {
1653
+ items = items.filter((m) => m.collateralAsset?.symbol?.toUpperCase() === searchUpper);
1654
+ }
1655
+ if (options?.asLoanToken) {
1656
+ items = items.filter((m) => m.loanAsset?.symbol?.toUpperCase() === searchUpper);
1657
+ }
1658
+ return items.map((m) => {
1659
+ const loanDecimals = m.loanAsset?.decimals ?? 18;
1660
+ const collateralDecimals = m.collateralAsset?.decimals ?? 18;
1661
+ return {
1662
+ collateralToken: m.collateralAsset.symbol,
1663
+ loanToken: m.loanAsset.symbol,
1664
+ loanDecimals,
1665
+ collateralDecimals,
1666
+ supplyApy: m.state?.supplyApy ? Number(m.state.supplyApy) : 0,
1667
+ borrowApy: m.state?.borrowApy ? Number(m.state.borrowApy) : 0,
1668
+ utilization: m.state?.utilization ? Number(m.state.utilization) : 0,
1669
+ totalSupplyUsd: m.state?.supplyAssets ? Number(m.state.supplyAssets) / 10 ** loanDecimals : 0,
1670
+ totalBorrowUsd: m.state?.borrowAssets ? Number(m.state.borrowAssets) / 10 ** loanDecimals : 0,
1671
+ lltv: `${(Number(m.lltv) / 1e16).toFixed(0)}%`,
1672
+ marketId: m.uniqueKey,
1673
+ collateralAddress: m.collateralAsset.address,
1674
+ loanAddress: m.loanAsset.address
1675
+ };
1676
+ });
1677
+ } catch (e) {
1678
+ console.warn("[agether] searchMarkets failed:", e instanceof Error ? e.message : e);
1679
+ return [];
1680
+ }
1681
+ }
1682
+ /**
1683
+ * Scan the AgentAccount wallet for all ERC-20 tokens that appear in Morpho
1684
+ * markets on the current chain. Returns tokens where balance > 0.
1685
+ *
1686
+ * Uses the full market list (500 markets) to discover all relevant tokens,
1687
+ * then checks on-chain balance for each unique token address.
1688
+ *
1689
+ * @returns Array of tokens with non-zero balance, sorted by balance descending.
1690
+ */
1691
+ async getWalletTokenBalances() {
1692
+ const acctAddr = await this.getAccountAddress();
1693
+ await this.getMarkets();
1694
+ const uniqueTokens = /* @__PURE__ */ new Map();
1695
+ for (const [key, info] of this._tokenCache.entries()) {
1696
+ if (key.startsWith("0x") && !uniqueTokens.has(key)) {
1697
+ uniqueTokens.set(key, info);
1698
+ }
1699
+ }
1700
+ const results = [];
1701
+ try {
1702
+ const ethBalance = await this.provider.getBalance(acctAddr);
1703
+ if (ethBalance > 0n) {
1704
+ results.push({
1705
+ symbol: "ETH",
1706
+ address: import_ethers2.ethers.ZeroAddress,
1707
+ decimals: 18,
1708
+ balance: ethBalance,
1709
+ balanceFormatted: import_ethers2.ethers.formatEther(ethBalance)
1710
+ });
1711
+ }
1712
+ } catch {
1713
+ }
1714
+ const tokenEntries = Array.from(uniqueTokens.values());
1715
+ const batchSize = 20;
1716
+ for (let i = 0; i < tokenEntries.length; i += batchSize) {
1717
+ const batch = tokenEntries.slice(i, i + batchSize);
1718
+ const checks = batch.map(async (info) => {
1719
+ try {
1720
+ const token = new import_ethers2.Contract(info.address, ERC20_ABI, this.provider);
1721
+ const balance = await token.balanceOf(acctAddr);
1722
+ if (balance > 0n) {
1723
+ return {
1724
+ symbol: info.symbol,
1725
+ address: info.address,
1726
+ decimals: info.decimals,
1727
+ balance,
1728
+ balanceFormatted: import_ethers2.ethers.formatUnits(balance, info.decimals)
1729
+ };
1730
+ }
1731
+ } catch {
1732
+ }
1733
+ return null;
1734
+ });
1735
+ const batchResults = await Promise.all(checks);
1736
+ for (const r of batchResults) {
1737
+ if (r) results.push(r);
1738
+ }
1739
+ }
1740
+ results.sort((a, b) => b.balance > a.balance ? 1 : b.balance < a.balance ? -1 : 0);
1741
+ return results;
1742
+ }
1743
+ /**
1744
+ * Find borrowing opportunities for the agent.
1745
+ *
1746
+ * - If `collateralSymbol` is provided: find all markets where that token is collateral.
1747
+ * - If omitted: scan wallet balances and find markets for each token the agent holds.
1748
+ *
1749
+ * Returns markets grouped by collateral token with APY, liquidity, and balance info.
1750
+ *
1751
+ * @param collateralSymbol - optional, e.g. 'WETH'. If omitted, scans wallet.
1752
+ */
1753
+ async findBorrowingOptions(collateralSymbol) {
1754
+ let tokensToCheck;
1755
+ if (collateralSymbol) {
1756
+ tokensToCheck = [{ symbol: collateralSymbol, balanceFormatted: "N/A" }];
1757
+ try {
1758
+ const balance = await this.getTokenBalance(collateralSymbol);
1759
+ const info = await this._resolveToken(collateralSymbol);
1760
+ tokensToCheck = [{ symbol: collateralSymbol, balanceFormatted: import_ethers2.ethers.formatUnits(balance, info.decimals) }];
1761
+ } catch {
1762
+ }
1763
+ } else {
1764
+ const walletTokens = await this.getWalletTokenBalances();
1765
+ tokensToCheck = walletTokens.filter((t) => t.symbol !== "ETH").map((t) => ({ symbol: t.symbol, balanceFormatted: t.balanceFormatted }));
1766
+ if (tokensToCheck.length === 0) {
1767
+ return [];
1768
+ }
1769
+ }
1770
+ const results = [];
1771
+ for (const token of tokensToCheck) {
1772
+ const markets = await this.searchMarkets(token.symbol, { asCollateral: true });
1773
+ if (markets.length === 0) continue;
1774
+ results.push({
1775
+ collateralToken: token.symbol,
1776
+ collateralBalance: token.balanceFormatted,
1777
+ markets: markets.map((m) => ({
1778
+ loanToken: m.loanToken,
1779
+ borrowApy: `${(m.borrowApy * 100).toFixed(2)}%`,
1780
+ supplyApy: `${(m.supplyApy * 100).toFixed(2)}%`,
1781
+ lltv: m.lltv,
1782
+ utilization: `${(m.utilization * 100).toFixed(1)}%`,
1783
+ availableLiquidity: `$${(m.totalSupplyUsd - m.totalBorrowUsd).toFixed(0)}`,
1784
+ marketId: m.marketId
1785
+ }))
1786
+ });
1787
+ }
1788
+ return results;
1789
+ }
1790
+ /**
1791
+ * Find supply/lending opportunities for a specific loan token.
1792
+ *
1793
+ * "What can I supply to earn WETH?" → shows all markets where WETH is the loan token
1794
+ * (user supplies WETH to earn yield from borrowers).
1795
+ *
1796
+ * @param loanTokenSymbol - e.g. 'USDC', 'WETH'
1797
+ */
1798
+ async findSupplyOptions(loanTokenSymbol) {
1799
+ const markets = await this.searchMarkets(loanTokenSymbol, { asLoanToken: true });
1800
+ return markets.map((m) => ({
1801
+ collateralToken: m.collateralToken,
1802
+ loanToken: m.loanToken,
1803
+ supplyApy: `${(m.supplyApy * 100).toFixed(2)}%`,
1804
+ borrowApy: `${(m.borrowApy * 100).toFixed(2)}%`,
1805
+ lltv: m.lltv,
1806
+ utilization: `${(m.utilization * 100).toFixed(1)}%`,
1807
+ totalSupply: `$${m.totalSupplyUsd.toFixed(0)}`,
1808
+ marketId: m.marketId
1809
+ }));
1810
+ }
1524
1811
  /**
1525
1812
  * Estimate theoretical yield for a given collateral amount over a period.
1526
1813
  *
@@ -2425,6 +2712,46 @@ var MorphoClient = class {
2425
2712
  /** Find the first market where the agent has collateral deposited. */
2426
2713
  async _findActiveMarket() {
2427
2714
  const acctAddr = await this.getAccountAddress();
2715
+ const chainId = this.config.chainId;
2716
+ try {
2717
+ const posQuery = `{
2718
+ marketPositions(
2719
+ where: { userAddress_in: ["${acctAddr}"], chainId_in: [${chainId}] }
2720
+ first: 50
2721
+ ) {
2722
+ items {
2723
+ collateral
2724
+ market {
2725
+ uniqueKey
2726
+ oracleAddress
2727
+ irmAddress
2728
+ lltv
2729
+ loanAsset { address symbol decimals }
2730
+ collateralAsset { address symbol decimals }
2731
+ }
2732
+ }
2733
+ }
2734
+ }`;
2735
+ const resp = await import_axios.default.post(MORPHO_API_URL, { query: posQuery }, { timeout: 1e4 });
2736
+ const items = resp.data?.data?.marketPositions?.items ?? [];
2737
+ for (const item of items) {
2738
+ if (BigInt(item.collateral ?? "0") > 0n && item.market?.collateralAsset) {
2739
+ const m = item.market;
2740
+ return {
2741
+ params: {
2742
+ loanToken: m.loanAsset.address,
2743
+ collateralToken: m.collateralAsset.address,
2744
+ oracle: m.oracleAddress,
2745
+ irm: m.irmAddress,
2746
+ lltv: BigInt(m.lltv)
2747
+ },
2748
+ symbol: m.collateralAsset.symbol
2749
+ };
2750
+ }
2751
+ }
2752
+ } catch (e) {
2753
+ console.warn("[agether] _findActiveMarket GraphQL failed, falling back:", e instanceof Error ? e.message : e);
2754
+ }
2428
2755
  const markets = await this.getMarkets();
2429
2756
  for (const m of markets) {
2430
2757
  if (!m.collateralAsset || m.collateralAsset.address === import_ethers2.ethers.ZeroAddress) continue;
@@ -2453,6 +2780,46 @@ var MorphoClient = class {
2453
2780
  /** Find the first market where the agent has a supply (lending) position. */
2454
2781
  async _findActiveSupplyMarket() {
2455
2782
  const acctAddr = await this.getAccountAddress();
2783
+ const chainId = this.config.chainId;
2784
+ try {
2785
+ const posQuery = `{
2786
+ marketPositions(
2787
+ where: { userAddress_in: ["${acctAddr}"], chainId_in: [${chainId}] }
2788
+ first: 50
2789
+ ) {
2790
+ items {
2791
+ supplyShares
2792
+ market {
2793
+ uniqueKey
2794
+ oracleAddress
2795
+ irmAddress
2796
+ lltv
2797
+ loanAsset { address symbol decimals }
2798
+ collateralAsset { address symbol decimals }
2799
+ }
2800
+ }
2801
+ }
2802
+ }`;
2803
+ const resp = await import_axios.default.post(MORPHO_API_URL, { query: posQuery }, { timeout: 1e4 });
2804
+ const items = resp.data?.data?.marketPositions?.items ?? [];
2805
+ for (const item of items) {
2806
+ if (BigInt(item.supplyShares ?? "0") > 0n && item.market?.collateralAsset) {
2807
+ const m = item.market;
2808
+ return {
2809
+ params: {
2810
+ loanToken: m.loanAsset.address,
2811
+ collateralToken: m.collateralAsset.address,
2812
+ oracle: m.oracleAddress,
2813
+ irm: m.irmAddress,
2814
+ lltv: BigInt(m.lltv)
2815
+ },
2816
+ symbol: m.collateralAsset.symbol
2817
+ };
2818
+ }
2819
+ }
2820
+ } catch (e) {
2821
+ console.warn("[agether] _findActiveSupplyMarket GraphQL failed, falling back:", e instanceof Error ? e.message : e);
2822
+ }
2456
2823
  const markets = await this.getMarkets();
2457
2824
  for (const m of markets) {
2458
2825
  if (!m.collateralAsset || m.collateralAsset.address === import_ethers2.ethers.ZeroAddress) continue;
@@ -2523,6 +2890,24 @@ var MorphoClient = class {
2523
2890
  await this.getMarkets();
2524
2891
  const fromApi = this._tokenCache.get(key);
2525
2892
  if (fromApi) return fromApi;
2893
+ if (!symbolOrAddress.startsWith("0x")) {
2894
+ const searchResults = await this.searchMarkets(symbolOrAddress);
2895
+ const sym = symbolOrAddress.toUpperCase();
2896
+ for (const m of searchResults) {
2897
+ if (m.collateralToken.toUpperCase() === sym) {
2898
+ const info = { address: m.collateralAddress, symbol: m.collateralToken, decimals: m.collateralDecimals };
2899
+ this._tokenCache.set(sym, info);
2900
+ this._tokenCache.set(m.collateralAddress.toLowerCase(), info);
2901
+ return info;
2902
+ }
2903
+ if (m.loanToken.toUpperCase() === sym) {
2904
+ const info = { address: m.loanAddress, symbol: m.loanToken, decimals: m.loanDecimals };
2905
+ this._tokenCache.set(sym, info);
2906
+ this._tokenCache.set(m.loanAddress.toLowerCase(), info);
2907
+ return info;
2908
+ }
2909
+ }
2910
+ }
2526
2911
  throw new AgetherError(
2527
2912
  `Unknown token: ${symbolOrAddress}. No Morpho market found with this token.`,
2528
2913
  "UNKNOWN_TOKEN"