@agether/sdk 2.4.0 → 2.5.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.
package/dist/cli.js CHANGED
@@ -274,7 +274,7 @@ var MorphoClient_exports = {};
274
274
  __export(MorphoClient_exports, {
275
275
  MorphoClient: () => MorphoClient
276
276
  });
277
- var import_ethers, import_axios, BASE_COLLATERALS, MORPHO_API_URL, MODE_SINGLE, MODE_BATCH, morphoIface, erc20Iface, MorphoClient;
277
+ var import_ethers, import_axios, MORPHO_API_URL, MODE_SINGLE, MODE_BATCH, morphoIface, erc20Iface, MorphoClient;
278
278
  var init_MorphoClient = __esm({
279
279
  "src/clients/MorphoClient.ts"() {
280
280
  "use strict";
@@ -283,11 +283,6 @@ var init_MorphoClient = __esm({
283
283
  init_types();
284
284
  init_abis();
285
285
  init_config();
286
- BASE_COLLATERALS = {
287
- WETH: { address: "0x4200000000000000000000000000000000000006", symbol: "WETH", decimals: 18 },
288
- wstETH: { address: "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452", symbol: "wstETH", decimals: 18 },
289
- cbETH: { address: "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", symbol: "cbETH", decimals: 18 }
290
- };
291
286
  MORPHO_API_URL = "https://api.morpho.org/graphql";
292
287
  MODE_SINGLE = "0x0000000000000000000000000000000000000000000000000000000000000000";
293
288
  MODE_BATCH = "0x0100000000000000000000000000000000000000000000000000000000000000";
@@ -296,6 +291,8 @@ var init_MorphoClient = __esm({
296
291
  MorphoClient = class {
297
292
  constructor(config) {
298
293
  this._marketCache = /* @__PURE__ */ new Map();
294
+ /** Dynamic token registry: symbol (uppercase) → { address, symbol, decimals } */
295
+ this._tokenCache = /* @__PURE__ */ new Map();
299
296
  this._discoveredAt = 0;
300
297
  const chainId = config.chainId ?? 8453 /* Base */;
301
298
  const defaultCfg = getDefaultConfig(chainId);
@@ -482,15 +479,16 @@ var init_MorphoClient = __esm({
482
479
  const usdc = new import_ethers.Contract(this.config.contracts.usdc, ERC20_ABI, this.provider);
483
480
  const ethBal = await this.provider.getBalance(eoaAddr);
484
481
  const usdcBal = await usdc.balanceOf(eoaAddr);
482
+ const discoveredTokens = await this._getDiscoveredTokens();
485
483
  const eoaCollateral = {};
486
- for (const [symbol, info] of Object.entries(BASE_COLLATERALS)) {
484
+ for (const info of discoveredTokens) {
487
485
  try {
488
486
  const token = new import_ethers.Contract(info.address, ERC20_ABI, this.provider);
489
487
  const bal = await token.balanceOf(eoaAddr);
490
- eoaCollateral[symbol] = import_ethers.ethers.formatUnits(bal, info.decimals);
488
+ eoaCollateral[info.symbol] = import_ethers.ethers.formatUnits(bal, info.decimals);
491
489
  } catch (e) {
492
- console.warn(`[agether] EOA collateral fetch failed for ${symbol}:`, e instanceof Error ? e.message : e);
493
- eoaCollateral[symbol] = "0";
490
+ console.warn(`[agether] EOA collateral fetch failed for ${info.symbol}:`, e instanceof Error ? e.message : e);
491
+ eoaCollateral[info.symbol] = "0";
494
492
  }
495
493
  }
496
494
  const result = {
@@ -505,14 +503,14 @@ var init_MorphoClient = __esm({
505
503
  const acctEth = await this.provider.getBalance(acctAddr);
506
504
  const acctUsdc = await usdc.balanceOf(acctAddr);
507
505
  const acctCollateral = {};
508
- for (const [symbol, info] of Object.entries(BASE_COLLATERALS)) {
506
+ for (const info of discoveredTokens) {
509
507
  try {
510
508
  const token = new import_ethers.Contract(info.address, ERC20_ABI, this.provider);
511
509
  const bal = await token.balanceOf(acctAddr);
512
- acctCollateral[symbol] = import_ethers.ethers.formatUnits(bal, info.decimals);
510
+ acctCollateral[info.symbol] = import_ethers.ethers.formatUnits(bal, info.decimals);
513
511
  } catch (e) {
514
- console.warn(`[agether] AgentAccount collateral fetch failed for ${symbol}:`, e instanceof Error ? e.message : e);
515
- acctCollateral[symbol] = "0";
512
+ console.warn(`[agether] AgentAccount collateral fetch failed for ${info.symbol}:`, e instanceof Error ? e.message : e);
513
+ acctCollateral[info.symbol] = "0";
516
514
  }
517
515
  }
518
516
  result.agentAccount = {
@@ -598,6 +596,28 @@ var init_MorphoClient = __esm({
598
596
  irm: mi.irm,
599
597
  lltv: mi.lltv
600
598
  });
599
+ this._tokenCache.set(mi.collateralAsset.symbol.toUpperCase(), {
600
+ address: mi.collateralAsset.address,
601
+ symbol: mi.collateralAsset.symbol,
602
+ decimals: mi.collateralAsset.decimals
603
+ });
604
+ this._tokenCache.set(mi.collateralAsset.address.toLowerCase(), {
605
+ address: mi.collateralAsset.address,
606
+ symbol: mi.collateralAsset.symbol,
607
+ decimals: mi.collateralAsset.decimals
608
+ });
609
+ }
610
+ if (mi.loanAsset.address !== import_ethers.ethers.ZeroAddress) {
611
+ this._tokenCache.set(mi.loanAsset.symbol.toUpperCase(), {
612
+ address: mi.loanAsset.address,
613
+ symbol: mi.loanAsset.symbol,
614
+ decimals: mi.loanAsset.decimals
615
+ });
616
+ this._tokenCache.set(mi.loanAsset.address.toLowerCase(), {
617
+ address: mi.loanAsset.address,
618
+ symbol: mi.loanAsset.symbol,
619
+ decimals: mi.loanAsset.decimals
620
+ });
601
621
  }
602
622
  }
603
623
  return this._discoveredMarkets;
@@ -611,8 +631,17 @@ var init_MorphoClient = __esm({
611
631
  * Tries cache → API → onchain idToMarketParams.
612
632
  */
613
633
  async findMarketForCollateral(collateralSymbolOrAddress) {
614
- const colInfo = BASE_COLLATERALS[collateralSymbolOrAddress];
615
- const colAddr = (colInfo?.address ?? collateralSymbolOrAddress).toLowerCase();
634
+ let colAddr;
635
+ if (collateralSymbolOrAddress.startsWith("0x")) {
636
+ colAddr = collateralSymbolOrAddress.toLowerCase();
637
+ } else {
638
+ try {
639
+ const resolved = await this._resolveToken(collateralSymbolOrAddress);
640
+ colAddr = resolved.address.toLowerCase();
641
+ } catch {
642
+ colAddr = collateralSymbolOrAddress.toLowerCase();
643
+ }
644
+ }
616
645
  const cached = this._marketCache.get(colAddr);
617
646
  if (cached) return cached;
618
647
  await this.getMarkets();
@@ -771,8 +800,17 @@ var init_MorphoClient = __esm({
771
800
  const usdcAddr = this.config.contracts.usdc.toLowerCase();
772
801
  let collateralFilter = "";
773
802
  if (collateralSymbolOrAddress) {
774
- const colInfo = BASE_COLLATERALS[collateralSymbolOrAddress];
775
- const colAddr = (colInfo?.address ?? collateralSymbolOrAddress).toLowerCase();
803
+ let colAddr;
804
+ if (collateralSymbolOrAddress.startsWith("0x")) {
805
+ colAddr = collateralSymbolOrAddress.toLowerCase();
806
+ } else {
807
+ try {
808
+ const resolved = await this._resolveToken(collateralSymbolOrAddress);
809
+ colAddr = resolved.address.toLowerCase();
810
+ } catch {
811
+ colAddr = collateralSymbolOrAddress.toLowerCase();
812
+ }
813
+ }
776
814
  collateralFilter = `, collateralAssetAddress_in: ["${colAddr}"]`;
777
815
  }
778
816
  const query = `{
@@ -831,8 +869,7 @@ var init_MorphoClient = __esm({
831
869
  * @returns Estimated yield in USD for the period
832
870
  */
833
871
  async getYieldEstimate(collateralSymbol, amount, periodDays = 1, ethPriceUsd) {
834
- const colInfo = BASE_COLLATERALS[collateralSymbol];
835
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${collateralSymbol}`, "UNKNOWN_COLLATERAL");
872
+ const colInfo = await this._resolveToken(collateralSymbol);
836
873
  const rates = await this.getMarketRates(collateralSymbol);
837
874
  if (rates.length === 0) {
838
875
  throw new AgetherError(`No market found for ${collateralSymbol}`, "MARKET_NOT_FOUND");
@@ -1134,8 +1171,7 @@ var init_MorphoClient = __esm({
1134
1171
  */
1135
1172
  async supplyCollateral(tokenSymbol, amount, marketParams) {
1136
1173
  const acctAddr = await this.getAccountAddress();
1137
- const colInfo = BASE_COLLATERALS[tokenSymbol];
1138
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
1174
+ const colInfo = await this._resolveToken(tokenSymbol);
1139
1175
  const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
1140
1176
  const weiAmount = import_ethers.ethers.parseUnits(amount, colInfo.decimals);
1141
1177
  const morphoAddr = this.config.contracts.morphoBlue;
@@ -1256,8 +1292,7 @@ var init_MorphoClient = __esm({
1256
1292
  */
1257
1293
  async depositAndBorrow(tokenSymbol, collateralAmount, borrowUsdcAmount, marketParams) {
1258
1294
  const acctAddr = await this.getAccountAddress();
1259
- const colInfo = BASE_COLLATERALS[tokenSymbol];
1260
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
1295
+ const colInfo = await this._resolveToken(tokenSymbol);
1261
1296
  const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
1262
1297
  const colWei = import_ethers.ethers.parseUnits(collateralAmount, colInfo.decimals);
1263
1298
  const borrowWei = import_ethers.ethers.parseUnits(borrowUsdcAmount, 6);
@@ -1425,8 +1460,7 @@ var init_MorphoClient = __esm({
1425
1460
  */
1426
1461
  async withdrawCollateral(tokenSymbol, amount, marketParams, receiver) {
1427
1462
  const acctAddr = await this.getAccountAddress();
1428
- const colInfo = BASE_COLLATERALS[tokenSymbol];
1429
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
1463
+ const colInfo = await this._resolveToken(tokenSymbol);
1430
1464
  const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
1431
1465
  const morphoAddr = this.config.contracts.morphoBlue;
1432
1466
  const usdcAddr = this.config.contracts.usdc;
@@ -1523,8 +1557,7 @@ var init_MorphoClient = __esm({
1523
1557
  * (The agent must then supplyCollateral themselves via their own account.)
1524
1558
  */
1525
1559
  async sponsor(target, tokenSymbol, amount) {
1526
- const colInfo = BASE_COLLATERALS[tokenSymbol];
1527
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
1560
+ const colInfo = await this._resolveToken(tokenSymbol);
1528
1561
  let targetAddr;
1529
1562
  if (target.address) {
1530
1563
  targetAddr = target.address;
@@ -1780,6 +1813,43 @@ var init_MorphoClient = __esm({
1780
1813
  }
1781
1814
  throw new AgetherError("No active supply position found", "NO_SUPPLY");
1782
1815
  }
1816
+ /**
1817
+ * Resolve a token symbol or address to { address, symbol, decimals }.
1818
+ *
1819
+ * Uses the dynamic `_tokenCache` populated by `getMarkets()` from the
1820
+ * Morpho GraphQL API — no hardcoded token list needed.
1821
+ *
1822
+ * @param symbolOrAddress - e.g. 'WETH', 'wstETH', or '0x4200...'
1823
+ */
1824
+ async _resolveToken(symbolOrAddress) {
1825
+ const key = symbolOrAddress.startsWith("0x") ? symbolOrAddress.toLowerCase() : symbolOrAddress.toUpperCase();
1826
+ const cached = this._tokenCache.get(key);
1827
+ if (cached) return cached;
1828
+ await this.getMarkets();
1829
+ const fromApi = this._tokenCache.get(key);
1830
+ if (fromApi) return fromApi;
1831
+ throw new AgetherError(
1832
+ `Unknown token: ${symbolOrAddress}. No Morpho market found with this collateral.`,
1833
+ "UNKNOWN_COLLATERAL"
1834
+ );
1835
+ }
1836
+ /**
1837
+ * Get all discovered collateral tokens (for balance iteration, etc.).
1838
+ * Returns unique tokens from the Morpho API market discovery.
1839
+ */
1840
+ async _getDiscoveredTokens() {
1841
+ await this.getMarkets();
1842
+ const seen = /* @__PURE__ */ new Set();
1843
+ const tokens = [];
1844
+ for (const [key, info] of this._tokenCache) {
1845
+ if (key.startsWith("0x")) continue;
1846
+ if (seen.has(info.address.toLowerCase())) continue;
1847
+ seen.add(info.address.toLowerCase());
1848
+ if (info.symbol === "USDC" || info.symbol === "USDbC") continue;
1849
+ tokens.push(info);
1850
+ }
1851
+ return tokens;
1852
+ }
1783
1853
  /**
1784
1854
  * Compute net deposited amounts per market using Morpho GraphQL API.
1785
1855
  *
package/dist/index.d.mts CHANGED
@@ -394,6 +394,8 @@ declare class MorphoClient {
394
394
  private validationModule;
395
395
  private _accountAddress?;
396
396
  private _marketCache;
397
+ /** Dynamic token registry: symbol (uppercase) → { address, symbol, decimals } */
398
+ private _tokenCache;
397
399
  private _discoveredMarkets?;
398
400
  private _discoveredAt;
399
401
  constructor(config: MorphoClientConfig);
@@ -662,6 +664,20 @@ declare class MorphoClient {
662
664
  private _findActiveMarket;
663
665
  /** Find the first market where the agent has a supply (lending) position. */
664
666
  private _findActiveSupplyMarket;
667
+ /**
668
+ * Resolve a token symbol or address to { address, symbol, decimals }.
669
+ *
670
+ * Uses the dynamic `_tokenCache` populated by `getMarkets()` from the
671
+ * Morpho GraphQL API — no hardcoded token list needed.
672
+ *
673
+ * @param symbolOrAddress - e.g. 'WETH', 'wstETH', or '0x4200...'
674
+ */
675
+ private _resolveToken;
676
+ /**
677
+ * Get all discovered collateral tokens (for balance iteration, etc.).
678
+ * Returns unique tokens from the Morpho API market discovery.
679
+ */
680
+ private _getDiscoveredTokens;
665
681
  /**
666
682
  * Compute net deposited amounts per market using Morpho GraphQL API.
667
683
  *
package/dist/index.d.ts CHANGED
@@ -394,6 +394,8 @@ declare class MorphoClient {
394
394
  private validationModule;
395
395
  private _accountAddress?;
396
396
  private _marketCache;
397
+ /** Dynamic token registry: symbol (uppercase) → { address, symbol, decimals } */
398
+ private _tokenCache;
397
399
  private _discoveredMarkets?;
398
400
  private _discoveredAt;
399
401
  constructor(config: MorphoClientConfig);
@@ -662,6 +664,20 @@ declare class MorphoClient {
662
664
  private _findActiveMarket;
663
665
  /** Find the first market where the agent has a supply (lending) position. */
664
666
  private _findActiveSupplyMarket;
667
+ /**
668
+ * Resolve a token symbol or address to { address, symbol, decimals }.
669
+ *
670
+ * Uses the dynamic `_tokenCache` populated by `getMarkets()` from the
671
+ * Morpho GraphQL API — no hardcoded token list needed.
672
+ *
673
+ * @param symbolOrAddress - e.g. 'WETH', 'wstETH', or '0x4200...'
674
+ */
675
+ private _resolveToken;
676
+ /**
677
+ * Get all discovered collateral tokens (for balance iteration, etc.).
678
+ * Returns unique tokens from the Morpho API market discovery.
679
+ */
680
+ private _getDiscoveredTokens;
665
681
  /**
666
682
  * Compute net deposited amounts per market using Morpho GraphQL API.
667
683
  *
package/dist/index.js CHANGED
@@ -532,11 +532,6 @@ var AgetherClient = class _AgetherClient {
532
532
  // src/clients/MorphoClient.ts
533
533
  var import_ethers2 = require("ethers");
534
534
  var import_axios = __toESM(require("axios"));
535
- var BASE_COLLATERALS = {
536
- WETH: { address: "0x4200000000000000000000000000000000000006", symbol: "WETH", decimals: 18 },
537
- wstETH: { address: "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452", symbol: "wstETH", decimals: 18 },
538
- cbETH: { address: "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", symbol: "cbETH", decimals: 18 }
539
- };
540
535
  var MORPHO_API_URL = "https://api.morpho.org/graphql";
541
536
  var MODE_SINGLE = "0x0000000000000000000000000000000000000000000000000000000000000000";
542
537
  var MODE_BATCH = "0x0100000000000000000000000000000000000000000000000000000000000000";
@@ -545,6 +540,8 @@ var erc20Iface = new import_ethers2.ethers.Interface(ERC20_ABI);
545
540
  var MorphoClient = class {
546
541
  constructor(config) {
547
542
  this._marketCache = /* @__PURE__ */ new Map();
543
+ /** Dynamic token registry: symbol (uppercase) → { address, symbol, decimals } */
544
+ this._tokenCache = /* @__PURE__ */ new Map();
548
545
  this._discoveredAt = 0;
549
546
  const chainId = config.chainId ?? 8453 /* Base */;
550
547
  const defaultCfg = getDefaultConfig(chainId);
@@ -731,15 +728,16 @@ var MorphoClient = class {
731
728
  const usdc = new import_ethers2.Contract(this.config.contracts.usdc, ERC20_ABI, this.provider);
732
729
  const ethBal = await this.provider.getBalance(eoaAddr);
733
730
  const usdcBal = await usdc.balanceOf(eoaAddr);
731
+ const discoveredTokens = await this._getDiscoveredTokens();
734
732
  const eoaCollateral = {};
735
- for (const [symbol, info] of Object.entries(BASE_COLLATERALS)) {
733
+ for (const info of discoveredTokens) {
736
734
  try {
737
735
  const token = new import_ethers2.Contract(info.address, ERC20_ABI, this.provider);
738
736
  const bal = await token.balanceOf(eoaAddr);
739
- eoaCollateral[symbol] = import_ethers2.ethers.formatUnits(bal, info.decimals);
737
+ eoaCollateral[info.symbol] = import_ethers2.ethers.formatUnits(bal, info.decimals);
740
738
  } catch (e) {
741
- console.warn(`[agether] EOA collateral fetch failed for ${symbol}:`, e instanceof Error ? e.message : e);
742
- eoaCollateral[symbol] = "0";
739
+ console.warn(`[agether] EOA collateral fetch failed for ${info.symbol}:`, e instanceof Error ? e.message : e);
740
+ eoaCollateral[info.symbol] = "0";
743
741
  }
744
742
  }
745
743
  const result = {
@@ -754,14 +752,14 @@ var MorphoClient = class {
754
752
  const acctEth = await this.provider.getBalance(acctAddr);
755
753
  const acctUsdc = await usdc.balanceOf(acctAddr);
756
754
  const acctCollateral = {};
757
- for (const [symbol, info] of Object.entries(BASE_COLLATERALS)) {
755
+ for (const info of discoveredTokens) {
758
756
  try {
759
757
  const token = new import_ethers2.Contract(info.address, ERC20_ABI, this.provider);
760
758
  const bal = await token.balanceOf(acctAddr);
761
- acctCollateral[symbol] = import_ethers2.ethers.formatUnits(bal, info.decimals);
759
+ acctCollateral[info.symbol] = import_ethers2.ethers.formatUnits(bal, info.decimals);
762
760
  } catch (e) {
763
- console.warn(`[agether] AgentAccount collateral fetch failed for ${symbol}:`, e instanceof Error ? e.message : e);
764
- acctCollateral[symbol] = "0";
761
+ console.warn(`[agether] AgentAccount collateral fetch failed for ${info.symbol}:`, e instanceof Error ? e.message : e);
762
+ acctCollateral[info.symbol] = "0";
765
763
  }
766
764
  }
767
765
  result.agentAccount = {
@@ -847,6 +845,28 @@ var MorphoClient = class {
847
845
  irm: mi.irm,
848
846
  lltv: mi.lltv
849
847
  });
848
+ this._tokenCache.set(mi.collateralAsset.symbol.toUpperCase(), {
849
+ address: mi.collateralAsset.address,
850
+ symbol: mi.collateralAsset.symbol,
851
+ decimals: mi.collateralAsset.decimals
852
+ });
853
+ this._tokenCache.set(mi.collateralAsset.address.toLowerCase(), {
854
+ address: mi.collateralAsset.address,
855
+ symbol: mi.collateralAsset.symbol,
856
+ decimals: mi.collateralAsset.decimals
857
+ });
858
+ }
859
+ if (mi.loanAsset.address !== import_ethers2.ethers.ZeroAddress) {
860
+ this._tokenCache.set(mi.loanAsset.symbol.toUpperCase(), {
861
+ address: mi.loanAsset.address,
862
+ symbol: mi.loanAsset.symbol,
863
+ decimals: mi.loanAsset.decimals
864
+ });
865
+ this._tokenCache.set(mi.loanAsset.address.toLowerCase(), {
866
+ address: mi.loanAsset.address,
867
+ symbol: mi.loanAsset.symbol,
868
+ decimals: mi.loanAsset.decimals
869
+ });
850
870
  }
851
871
  }
852
872
  return this._discoveredMarkets;
@@ -860,8 +880,17 @@ var MorphoClient = class {
860
880
  * Tries cache → API → onchain idToMarketParams.
861
881
  */
862
882
  async findMarketForCollateral(collateralSymbolOrAddress) {
863
- const colInfo = BASE_COLLATERALS[collateralSymbolOrAddress];
864
- const colAddr = (colInfo?.address ?? collateralSymbolOrAddress).toLowerCase();
883
+ let colAddr;
884
+ if (collateralSymbolOrAddress.startsWith("0x")) {
885
+ colAddr = collateralSymbolOrAddress.toLowerCase();
886
+ } else {
887
+ try {
888
+ const resolved = await this._resolveToken(collateralSymbolOrAddress);
889
+ colAddr = resolved.address.toLowerCase();
890
+ } catch {
891
+ colAddr = collateralSymbolOrAddress.toLowerCase();
892
+ }
893
+ }
865
894
  const cached = this._marketCache.get(colAddr);
866
895
  if (cached) return cached;
867
896
  await this.getMarkets();
@@ -1020,8 +1049,17 @@ var MorphoClient = class {
1020
1049
  const usdcAddr = this.config.contracts.usdc.toLowerCase();
1021
1050
  let collateralFilter = "";
1022
1051
  if (collateralSymbolOrAddress) {
1023
- const colInfo = BASE_COLLATERALS[collateralSymbolOrAddress];
1024
- const colAddr = (colInfo?.address ?? collateralSymbolOrAddress).toLowerCase();
1052
+ let colAddr;
1053
+ if (collateralSymbolOrAddress.startsWith("0x")) {
1054
+ colAddr = collateralSymbolOrAddress.toLowerCase();
1055
+ } else {
1056
+ try {
1057
+ const resolved = await this._resolveToken(collateralSymbolOrAddress);
1058
+ colAddr = resolved.address.toLowerCase();
1059
+ } catch {
1060
+ colAddr = collateralSymbolOrAddress.toLowerCase();
1061
+ }
1062
+ }
1025
1063
  collateralFilter = `, collateralAssetAddress_in: ["${colAddr}"]`;
1026
1064
  }
1027
1065
  const query = `{
@@ -1080,8 +1118,7 @@ var MorphoClient = class {
1080
1118
  * @returns Estimated yield in USD for the period
1081
1119
  */
1082
1120
  async getYieldEstimate(collateralSymbol, amount, periodDays = 1, ethPriceUsd) {
1083
- const colInfo = BASE_COLLATERALS[collateralSymbol];
1084
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${collateralSymbol}`, "UNKNOWN_COLLATERAL");
1121
+ const colInfo = await this._resolveToken(collateralSymbol);
1085
1122
  const rates = await this.getMarketRates(collateralSymbol);
1086
1123
  if (rates.length === 0) {
1087
1124
  throw new AgetherError(`No market found for ${collateralSymbol}`, "MARKET_NOT_FOUND");
@@ -1383,8 +1420,7 @@ var MorphoClient = class {
1383
1420
  */
1384
1421
  async supplyCollateral(tokenSymbol, amount, marketParams) {
1385
1422
  const acctAddr = await this.getAccountAddress();
1386
- const colInfo = BASE_COLLATERALS[tokenSymbol];
1387
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
1423
+ const colInfo = await this._resolveToken(tokenSymbol);
1388
1424
  const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
1389
1425
  const weiAmount = import_ethers2.ethers.parseUnits(amount, colInfo.decimals);
1390
1426
  const morphoAddr = this.config.contracts.morphoBlue;
@@ -1505,8 +1541,7 @@ var MorphoClient = class {
1505
1541
  */
1506
1542
  async depositAndBorrow(tokenSymbol, collateralAmount, borrowUsdcAmount, marketParams) {
1507
1543
  const acctAddr = await this.getAccountAddress();
1508
- const colInfo = BASE_COLLATERALS[tokenSymbol];
1509
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
1544
+ const colInfo = await this._resolveToken(tokenSymbol);
1510
1545
  const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
1511
1546
  const colWei = import_ethers2.ethers.parseUnits(collateralAmount, colInfo.decimals);
1512
1547
  const borrowWei = import_ethers2.ethers.parseUnits(borrowUsdcAmount, 6);
@@ -1674,8 +1709,7 @@ var MorphoClient = class {
1674
1709
  */
1675
1710
  async withdrawCollateral(tokenSymbol, amount, marketParams, receiver) {
1676
1711
  const acctAddr = await this.getAccountAddress();
1677
- const colInfo = BASE_COLLATERALS[tokenSymbol];
1678
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
1712
+ const colInfo = await this._resolveToken(tokenSymbol);
1679
1713
  const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
1680
1714
  const morphoAddr = this.config.contracts.morphoBlue;
1681
1715
  const usdcAddr = this.config.contracts.usdc;
@@ -1772,8 +1806,7 @@ var MorphoClient = class {
1772
1806
  * (The agent must then supplyCollateral themselves via their own account.)
1773
1807
  */
1774
1808
  async sponsor(target, tokenSymbol, amount) {
1775
- const colInfo = BASE_COLLATERALS[tokenSymbol];
1776
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
1809
+ const colInfo = await this._resolveToken(tokenSymbol);
1777
1810
  let targetAddr;
1778
1811
  if (target.address) {
1779
1812
  targetAddr = target.address;
@@ -2029,6 +2062,43 @@ var MorphoClient = class {
2029
2062
  }
2030
2063
  throw new AgetherError("No active supply position found", "NO_SUPPLY");
2031
2064
  }
2065
+ /**
2066
+ * Resolve a token symbol or address to { address, symbol, decimals }.
2067
+ *
2068
+ * Uses the dynamic `_tokenCache` populated by `getMarkets()` from the
2069
+ * Morpho GraphQL API — no hardcoded token list needed.
2070
+ *
2071
+ * @param symbolOrAddress - e.g. 'WETH', 'wstETH', or '0x4200...'
2072
+ */
2073
+ async _resolveToken(symbolOrAddress) {
2074
+ const key = symbolOrAddress.startsWith("0x") ? symbolOrAddress.toLowerCase() : symbolOrAddress.toUpperCase();
2075
+ const cached = this._tokenCache.get(key);
2076
+ if (cached) return cached;
2077
+ await this.getMarkets();
2078
+ const fromApi = this._tokenCache.get(key);
2079
+ if (fromApi) return fromApi;
2080
+ throw new AgetherError(
2081
+ `Unknown token: ${symbolOrAddress}. No Morpho market found with this collateral.`,
2082
+ "UNKNOWN_COLLATERAL"
2083
+ );
2084
+ }
2085
+ /**
2086
+ * Get all discovered collateral tokens (for balance iteration, etc.).
2087
+ * Returns unique tokens from the Morpho API market discovery.
2088
+ */
2089
+ async _getDiscoveredTokens() {
2090
+ await this.getMarkets();
2091
+ const seen = /* @__PURE__ */ new Set();
2092
+ const tokens = [];
2093
+ for (const [key, info] of this._tokenCache) {
2094
+ if (key.startsWith("0x")) continue;
2095
+ if (seen.has(info.address.toLowerCase())) continue;
2096
+ seen.add(info.address.toLowerCase());
2097
+ if (info.symbol === "USDC" || info.symbol === "USDbC") continue;
2098
+ tokens.push(info);
2099
+ }
2100
+ return tokens;
2101
+ }
2032
2102
  /**
2033
2103
  * Compute net deposited amounts per market using Morpho GraphQL API.
2034
2104
  *
package/dist/index.mjs CHANGED
@@ -460,11 +460,6 @@ var AgetherClient = class _AgetherClient {
460
460
  // src/clients/MorphoClient.ts
461
461
  import { ethers as ethers2, Contract as Contract2 } from "ethers";
462
462
  import axios from "axios";
463
- var BASE_COLLATERALS = {
464
- WETH: { address: "0x4200000000000000000000000000000000000006", symbol: "WETH", decimals: 18 },
465
- wstETH: { address: "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452", symbol: "wstETH", decimals: 18 },
466
- cbETH: { address: "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", symbol: "cbETH", decimals: 18 }
467
- };
468
463
  var MORPHO_API_URL = "https://api.morpho.org/graphql";
469
464
  var MODE_SINGLE = "0x0000000000000000000000000000000000000000000000000000000000000000";
470
465
  var MODE_BATCH = "0x0100000000000000000000000000000000000000000000000000000000000000";
@@ -473,6 +468,8 @@ var erc20Iface = new ethers2.Interface(ERC20_ABI);
473
468
  var MorphoClient = class {
474
469
  constructor(config) {
475
470
  this._marketCache = /* @__PURE__ */ new Map();
471
+ /** Dynamic token registry: symbol (uppercase) → { address, symbol, decimals } */
472
+ this._tokenCache = /* @__PURE__ */ new Map();
476
473
  this._discoveredAt = 0;
477
474
  const chainId = config.chainId ?? 8453 /* Base */;
478
475
  const defaultCfg = getDefaultConfig(chainId);
@@ -659,15 +656,16 @@ var MorphoClient = class {
659
656
  const usdc = new Contract2(this.config.contracts.usdc, ERC20_ABI, this.provider);
660
657
  const ethBal = await this.provider.getBalance(eoaAddr);
661
658
  const usdcBal = await usdc.balanceOf(eoaAddr);
659
+ const discoveredTokens = await this._getDiscoveredTokens();
662
660
  const eoaCollateral = {};
663
- for (const [symbol, info] of Object.entries(BASE_COLLATERALS)) {
661
+ for (const info of discoveredTokens) {
664
662
  try {
665
663
  const token = new Contract2(info.address, ERC20_ABI, this.provider);
666
664
  const bal = await token.balanceOf(eoaAddr);
667
- eoaCollateral[symbol] = ethers2.formatUnits(bal, info.decimals);
665
+ eoaCollateral[info.symbol] = ethers2.formatUnits(bal, info.decimals);
668
666
  } catch (e) {
669
- console.warn(`[agether] EOA collateral fetch failed for ${symbol}:`, e instanceof Error ? e.message : e);
670
- eoaCollateral[symbol] = "0";
667
+ console.warn(`[agether] EOA collateral fetch failed for ${info.symbol}:`, e instanceof Error ? e.message : e);
668
+ eoaCollateral[info.symbol] = "0";
671
669
  }
672
670
  }
673
671
  const result = {
@@ -682,14 +680,14 @@ var MorphoClient = class {
682
680
  const acctEth = await this.provider.getBalance(acctAddr);
683
681
  const acctUsdc = await usdc.balanceOf(acctAddr);
684
682
  const acctCollateral = {};
685
- for (const [symbol, info] of Object.entries(BASE_COLLATERALS)) {
683
+ for (const info of discoveredTokens) {
686
684
  try {
687
685
  const token = new Contract2(info.address, ERC20_ABI, this.provider);
688
686
  const bal = await token.balanceOf(acctAddr);
689
- acctCollateral[symbol] = ethers2.formatUnits(bal, info.decimals);
687
+ acctCollateral[info.symbol] = ethers2.formatUnits(bal, info.decimals);
690
688
  } catch (e) {
691
- console.warn(`[agether] AgentAccount collateral fetch failed for ${symbol}:`, e instanceof Error ? e.message : e);
692
- acctCollateral[symbol] = "0";
689
+ console.warn(`[agether] AgentAccount collateral fetch failed for ${info.symbol}:`, e instanceof Error ? e.message : e);
690
+ acctCollateral[info.symbol] = "0";
693
691
  }
694
692
  }
695
693
  result.agentAccount = {
@@ -775,6 +773,28 @@ var MorphoClient = class {
775
773
  irm: mi.irm,
776
774
  lltv: mi.lltv
777
775
  });
776
+ this._tokenCache.set(mi.collateralAsset.symbol.toUpperCase(), {
777
+ address: mi.collateralAsset.address,
778
+ symbol: mi.collateralAsset.symbol,
779
+ decimals: mi.collateralAsset.decimals
780
+ });
781
+ this._tokenCache.set(mi.collateralAsset.address.toLowerCase(), {
782
+ address: mi.collateralAsset.address,
783
+ symbol: mi.collateralAsset.symbol,
784
+ decimals: mi.collateralAsset.decimals
785
+ });
786
+ }
787
+ if (mi.loanAsset.address !== ethers2.ZeroAddress) {
788
+ this._tokenCache.set(mi.loanAsset.symbol.toUpperCase(), {
789
+ address: mi.loanAsset.address,
790
+ symbol: mi.loanAsset.symbol,
791
+ decimals: mi.loanAsset.decimals
792
+ });
793
+ this._tokenCache.set(mi.loanAsset.address.toLowerCase(), {
794
+ address: mi.loanAsset.address,
795
+ symbol: mi.loanAsset.symbol,
796
+ decimals: mi.loanAsset.decimals
797
+ });
778
798
  }
779
799
  }
780
800
  return this._discoveredMarkets;
@@ -788,8 +808,17 @@ var MorphoClient = class {
788
808
  * Tries cache → API → onchain idToMarketParams.
789
809
  */
790
810
  async findMarketForCollateral(collateralSymbolOrAddress) {
791
- const colInfo = BASE_COLLATERALS[collateralSymbolOrAddress];
792
- const colAddr = (colInfo?.address ?? collateralSymbolOrAddress).toLowerCase();
811
+ let colAddr;
812
+ if (collateralSymbolOrAddress.startsWith("0x")) {
813
+ colAddr = collateralSymbolOrAddress.toLowerCase();
814
+ } else {
815
+ try {
816
+ const resolved = await this._resolveToken(collateralSymbolOrAddress);
817
+ colAddr = resolved.address.toLowerCase();
818
+ } catch {
819
+ colAddr = collateralSymbolOrAddress.toLowerCase();
820
+ }
821
+ }
793
822
  const cached = this._marketCache.get(colAddr);
794
823
  if (cached) return cached;
795
824
  await this.getMarkets();
@@ -948,8 +977,17 @@ var MorphoClient = class {
948
977
  const usdcAddr = this.config.contracts.usdc.toLowerCase();
949
978
  let collateralFilter = "";
950
979
  if (collateralSymbolOrAddress) {
951
- const colInfo = BASE_COLLATERALS[collateralSymbolOrAddress];
952
- const colAddr = (colInfo?.address ?? collateralSymbolOrAddress).toLowerCase();
980
+ let colAddr;
981
+ if (collateralSymbolOrAddress.startsWith("0x")) {
982
+ colAddr = collateralSymbolOrAddress.toLowerCase();
983
+ } else {
984
+ try {
985
+ const resolved = await this._resolveToken(collateralSymbolOrAddress);
986
+ colAddr = resolved.address.toLowerCase();
987
+ } catch {
988
+ colAddr = collateralSymbolOrAddress.toLowerCase();
989
+ }
990
+ }
953
991
  collateralFilter = `, collateralAssetAddress_in: ["${colAddr}"]`;
954
992
  }
955
993
  const query = `{
@@ -1008,8 +1046,7 @@ var MorphoClient = class {
1008
1046
  * @returns Estimated yield in USD for the period
1009
1047
  */
1010
1048
  async getYieldEstimate(collateralSymbol, amount, periodDays = 1, ethPriceUsd) {
1011
- const colInfo = BASE_COLLATERALS[collateralSymbol];
1012
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${collateralSymbol}`, "UNKNOWN_COLLATERAL");
1049
+ const colInfo = await this._resolveToken(collateralSymbol);
1013
1050
  const rates = await this.getMarketRates(collateralSymbol);
1014
1051
  if (rates.length === 0) {
1015
1052
  throw new AgetherError(`No market found for ${collateralSymbol}`, "MARKET_NOT_FOUND");
@@ -1311,8 +1348,7 @@ var MorphoClient = class {
1311
1348
  */
1312
1349
  async supplyCollateral(tokenSymbol, amount, marketParams) {
1313
1350
  const acctAddr = await this.getAccountAddress();
1314
- const colInfo = BASE_COLLATERALS[tokenSymbol];
1315
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
1351
+ const colInfo = await this._resolveToken(tokenSymbol);
1316
1352
  const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
1317
1353
  const weiAmount = ethers2.parseUnits(amount, colInfo.decimals);
1318
1354
  const morphoAddr = this.config.contracts.morphoBlue;
@@ -1433,8 +1469,7 @@ var MorphoClient = class {
1433
1469
  */
1434
1470
  async depositAndBorrow(tokenSymbol, collateralAmount, borrowUsdcAmount, marketParams) {
1435
1471
  const acctAddr = await this.getAccountAddress();
1436
- const colInfo = BASE_COLLATERALS[tokenSymbol];
1437
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
1472
+ const colInfo = await this._resolveToken(tokenSymbol);
1438
1473
  const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
1439
1474
  const colWei = ethers2.parseUnits(collateralAmount, colInfo.decimals);
1440
1475
  const borrowWei = ethers2.parseUnits(borrowUsdcAmount, 6);
@@ -1602,8 +1637,7 @@ var MorphoClient = class {
1602
1637
  */
1603
1638
  async withdrawCollateral(tokenSymbol, amount, marketParams, receiver) {
1604
1639
  const acctAddr = await this.getAccountAddress();
1605
- const colInfo = BASE_COLLATERALS[tokenSymbol];
1606
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
1640
+ const colInfo = await this._resolveToken(tokenSymbol);
1607
1641
  const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
1608
1642
  const morphoAddr = this.config.contracts.morphoBlue;
1609
1643
  const usdcAddr = this.config.contracts.usdc;
@@ -1700,8 +1734,7 @@ var MorphoClient = class {
1700
1734
  * (The agent must then supplyCollateral themselves via their own account.)
1701
1735
  */
1702
1736
  async sponsor(target, tokenSymbol, amount) {
1703
- const colInfo = BASE_COLLATERALS[tokenSymbol];
1704
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
1737
+ const colInfo = await this._resolveToken(tokenSymbol);
1705
1738
  let targetAddr;
1706
1739
  if (target.address) {
1707
1740
  targetAddr = target.address;
@@ -1957,6 +1990,43 @@ var MorphoClient = class {
1957
1990
  }
1958
1991
  throw new AgetherError("No active supply position found", "NO_SUPPLY");
1959
1992
  }
1993
+ /**
1994
+ * Resolve a token symbol or address to { address, symbol, decimals }.
1995
+ *
1996
+ * Uses the dynamic `_tokenCache` populated by `getMarkets()` from the
1997
+ * Morpho GraphQL API — no hardcoded token list needed.
1998
+ *
1999
+ * @param symbolOrAddress - e.g. 'WETH', 'wstETH', or '0x4200...'
2000
+ */
2001
+ async _resolveToken(symbolOrAddress) {
2002
+ const key = symbolOrAddress.startsWith("0x") ? symbolOrAddress.toLowerCase() : symbolOrAddress.toUpperCase();
2003
+ const cached = this._tokenCache.get(key);
2004
+ if (cached) return cached;
2005
+ await this.getMarkets();
2006
+ const fromApi = this._tokenCache.get(key);
2007
+ if (fromApi) return fromApi;
2008
+ throw new AgetherError(
2009
+ `Unknown token: ${symbolOrAddress}. No Morpho market found with this collateral.`,
2010
+ "UNKNOWN_COLLATERAL"
2011
+ );
2012
+ }
2013
+ /**
2014
+ * Get all discovered collateral tokens (for balance iteration, etc.).
2015
+ * Returns unique tokens from the Morpho API market discovery.
2016
+ */
2017
+ async _getDiscoveredTokens() {
2018
+ await this.getMarkets();
2019
+ const seen = /* @__PURE__ */ new Set();
2020
+ const tokens = [];
2021
+ for (const [key, info] of this._tokenCache) {
2022
+ if (key.startsWith("0x")) continue;
2023
+ if (seen.has(info.address.toLowerCase())) continue;
2024
+ seen.add(info.address.toLowerCase());
2025
+ if (info.symbol === "USDC" || info.symbol === "USDbC") continue;
2026
+ tokens.push(info);
2027
+ }
2028
+ return tokens;
2029
+ }
1960
2030
  /**
1961
2031
  * Compute net deposited amounts per market using Morpho GraphQL API.
1962
2032
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agether/sdk",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "TypeScript SDK for Agether - autonomous credit for AI agents on Base",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",