@1delta/margin-fetcher 5.0.100 → 5.0.102

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
@@ -7186,10 +7186,7 @@ var calculateRateForCompoundType = (n, chainId, scale3 = 1 /* SECOND */, unitSec
7186
7186
  const perUnit = unitSeconds && unitSeconds > 0 ? unitSeconds : scale3 === 0 /* BLOCK */ ? Number(BLOCK_TIMES[chainId] ?? 1) : 1;
7187
7187
  return (Math.pow(rate * 60 * 60 * 24 / perUnit + 1, 365) - 1) * 100;
7188
7188
  };
7189
- var formatAaveRawApyToApr = (raw) => {
7190
- const apy = formatAaveYieldToNumber(raw);
7191
- return apyToApr(apy / 100) * 100;
7192
- };
7189
+ var formatAaveRayToApr = (raw) => formatAaveYieldToNumber(raw);
7193
7190
  var convertRateToApr = (ratePerSecond) => {
7194
7191
  const rps = Number(ratePerSecond);
7195
7192
  if (isNaN(rps)) return 0;
@@ -7277,13 +7274,13 @@ var getAaveV2ReservesDataConverter = (lender, chainId, prices, additionalYields,
7277
7274
  reserveData?.[8 /* variableBorrowIndex */]
7278
7275
  ),
7279
7276
  // rates
7280
- depositRate: formatAaveRawApyToApr(
7277
+ depositRate: formatAaveRayToApr(
7281
7278
  reserveData?.[3 /* liquidityRate */]?.toString()
7282
7279
  ),
7283
- variableBorrowRate: formatAaveRawApyToApr(
7280
+ variableBorrowRate: formatAaveRayToApr(
7284
7281
  reserveData?.[4 /* variableBorrowRate */]?.toString()
7285
7282
  ),
7286
- stableBorrowRate: formatAaveRawApyToApr(
7283
+ stableBorrowRate: formatAaveRayToApr(
7287
7284
  reserveData?.[5 /* stableBorrowRate */]?.toString()
7288
7285
  ),
7289
7286
  intrinsicYield: additionalYields?.intrinsicYields?.[oracleKey] ?? 0,
@@ -7504,13 +7501,13 @@ var getAaveV3ReservesDataConverter = (lender, chainId, prices, additionalYields,
7504
7501
  reserveData?.[10 /* variableBorrowIndex */]
7505
7502
  ),
7506
7503
  // rates
7507
- depositRate: formatAaveRawApyToApr(
7504
+ depositRate: formatAaveRayToApr(
7508
7505
  reserveData?.[5 /* liquidityRate */]?.toString()
7509
7506
  ),
7510
- variableBorrowRate: formatAaveRawApyToApr(
7507
+ variableBorrowRate: formatAaveRayToApr(
7511
7508
  reserveData?.[6 /* variableBorrowRate */]?.toString()
7512
7509
  ),
7513
- stableBorrowRate: formatAaveRawApyToApr(
7510
+ stableBorrowRate: formatAaveRayToApr(
7514
7511
  reserveData?.[7 /* stableBorrowRate */]?.toString()
7515
7512
  ),
7516
7513
  intrinsicYield: additionalYields?.intrinsicYields?.[toOracleKey(assetMeta?.assetGroup)] ?? 0,
@@ -7766,10 +7763,10 @@ function parseYLDRCall(chainId, lender, additionalYields, prices, tokenList) {
7766
7763
  reserveData?.[6 /* variableBorrowIndex */]
7767
7764
  ),
7768
7765
  // rates
7769
- depositRate: formatAaveRawApyToApr(
7766
+ depositRate: formatAaveRayToApr(
7770
7767
  reserveData?.[3 /* liquidityRate */]?.toString()
7771
7768
  ),
7772
- variableBorrowRate: formatAaveRawApyToApr(
7769
+ variableBorrowRate: formatAaveRayToApr(
7773
7770
  reserveData?.[4 /* variableBorrowRate */]?.toString()
7774
7771
  ),
7775
7772
  stableBorrowRate: 0,
@@ -7941,13 +7938,13 @@ function parseAave32(chainId, lender, prices, additionalYields, tokenList) {
7941
7938
  reserveData?.[10 /* variableBorrowIndex */]
7942
7939
  ),
7943
7940
  // rates
7944
- depositRate: formatAaveRawApyToApr(
7941
+ depositRate: formatAaveRayToApr(
7945
7942
  reserveData?.[5 /* liquidityRate */]?.toString()
7946
7943
  ),
7947
- variableBorrowRate: formatAaveRawApyToApr(
7944
+ variableBorrowRate: formatAaveRayToApr(
7948
7945
  reserveData?.[6 /* variableBorrowRate */]?.toString()
7949
7946
  ),
7950
- stableBorrowRate: formatAaveRawApyToApr(
7947
+ stableBorrowRate: formatAaveRayToApr(
7951
7948
  reserveData?.[7 /* stableBorrowRate */]?.toString()
7952
7949
  ),
7953
7950
  intrinsicYield: additionalYields?.intrinsicYields?.[toOracleKey(assetMeta?.assetGroup)] ?? 0,
@@ -10732,11 +10729,11 @@ async function resolveListaBrokers(chainId, marketKeys, getClient = getEvmClient
10732
10729
  const moolah = morphoPools()?.LISTA_DAO?.[chainId];
10733
10730
  const out = {};
10734
10731
  if (!moolah || marketKeys.length === 0) return out;
10735
- const cache6 = BROKER_CACHE[chainId] ??= {};
10732
+ const cache7 = BROKER_CACHE[chainId] ??= {};
10736
10733
  const missing = [];
10737
10734
  for (const key3 of marketKeys) {
10738
10735
  const id = toBytes32MarketId(key3);
10739
- if (cache6[id] === void 0) missing.push(id);
10736
+ if (cache7[id] === void 0) missing.push(id);
10740
10737
  }
10741
10738
  if (missing.length > 0) {
10742
10739
  try {
@@ -10752,7 +10749,7 @@ async function resolveListaBrokers(chainId, marketKeys, getClient = getEvmClient
10752
10749
  );
10753
10750
  results.forEach((addr4, i) => {
10754
10751
  if (addr4 === void 0) return;
10755
- cache6[missing[i]] = addr4.toLowerCase();
10752
+ cache7[missing[i]] = addr4.toLowerCase();
10756
10753
  });
10757
10754
  } catch (e) {
10758
10755
  console.warn(
@@ -10763,7 +10760,7 @@ async function resolveListaBrokers(chainId, marketKeys, getClient = getEvmClient
10763
10760
  }
10764
10761
  for (const key3 of marketKeys) {
10765
10762
  const id = toBytes32MarketId(key3);
10766
- const broker = cache6[id];
10763
+ const broker = cache7[id];
10767
10764
  if (broker && broker !== zeroAddress) out[id] = broker;
10768
10765
  }
10769
10766
  return out;
@@ -10791,7 +10788,7 @@ async function fetchListaFixedTerms(chainId, marketKeys, multicallRetry) {
10791
10788
  })),
10792
10789
  multicallRetry
10793
10790
  );
10794
- const cache6 = FIXED_TERMS_CACHE[chainId] ??= {};
10791
+ const cache7 = FIXED_TERMS_CACHE[chainId] ??= {};
10795
10792
  results.forEach((raw, i) => {
10796
10793
  if (!raw) return;
10797
10794
  const id = ids[i];
@@ -10805,7 +10802,7 @@ async function fetchListaFixedTerms(chainId, marketKeys, multicallRetry) {
10805
10802
  };
10806
10803
  });
10807
10804
  out[id] = terms;
10808
- cache6[id] = terms;
10805
+ cache7[id] = terms;
10809
10806
  });
10810
10807
  } catch (e) {
10811
10808
  console.warn(
@@ -12310,6 +12307,39 @@ function formatNr(n, d) {
12310
12307
  return Number(formatUnits(BigInt(n ?? 0), d));
12311
12308
  }
12312
12309
 
12310
+ // src/lending/public-data/morpho/unlisted.ts
12311
+ var MORPHO_UNLISTED_CHAINS = /* @__PURE__ */ new Set([
12312
+ // Robinhood Chain. 189 of its 194 markets are unlisted and essentially all of
12313
+ // them are Longbow — a curated Morpho Blue deployment (tokenized equities and
12314
+ // RWAs against USDG) that Morpho's own frontend does not carry, so `listed`
12315
+ // here says nothing about the market's quality. Enabled 2026-09-08 together
12316
+ // with the three things a chain needs before it can be:
12317
+ // 1. its collateral tokens in `token-lists` (wsNET was the last gap — the
12318
+ // collateral of the chain's LARGEST market), or the rows price at $0,
12319
+ // 2. `lender-metadata`'s `SERVES_UNLISTED_CHAINS` carrying the same chain
12320
+ // id, so the markets get a NAME and an oracle roster (5 -> 188 rows),
12321
+ // 3. a look at what the unlisted book actually holds — here 56 real
12322
+ // markets, $524k supplied / $351k borrowed, no runaway rates (the
12323
+ // highest borrow APR on the chain is 21.9 %).
12324
+ // See LONGBOW.md.
12325
+ "4663",
12326
+ // World Chain. blue-api indexes it, but 0 of its 30 markets are listed —
12327
+ // Morpho's frontend simply does not carry the chain, so `listed` says
12328
+ // nothing about the book (the Longbow shape again). Looked at 2026-09-16:
12329
+ // $59.5M supplied / $45.0M borrowed, of which the real two-sided markets are
12330
+ // USDC/WBTC $3.9M, USDC/WETH $3.6M, WETH/WBTC $2.1M, USDC/WLD $1.6M and
12331
+ // WETH/ezETH $1.1M at 0.1–4.6 % borrow APY; the $35.8M USDC/sdeUSD market is
12332
+ // pinned at 100 % utilization (297,994 % APY, $0 liquid) and is exactly what
12333
+ // `earn/rateSanity.ts` exists to drop. Token-list gaps on 480 at enablement:
12334
+ // sdeUSD and ezETH (collateral of two markets) — those rows price at $0 with
12335
+ // a blank LTV until token-lists carries them. `lender-metadata`'s
12336
+ // `SERVES_UNLISTED_CHAINS` was updated in the same change.
12337
+ "480"
12338
+ ]);
12339
+ function morphoIncludesUnlisted(chainId) {
12340
+ return MORPHO_UNLISTED_CHAINS.has(chainId);
12341
+ }
12342
+
12313
12343
  // src/lending/public-data/morpho/convertPublic.ts
12314
12344
  function convertMarketsToMorphoResponse(response, chainId, additionalYields = {
12315
12345
  intrinsicYields: {},
@@ -12319,6 +12349,7 @@ function convertMarketsToMorphoResponse(response, chainId, additionalYields = {
12319
12349
  const data = {};
12320
12350
  const items = response?.markets?.items;
12321
12351
  if (!items) return data;
12352
+ const listedFlagMeaningful = !morphoIncludesUnlisted(chainId);
12322
12353
  items.forEach((market) => {
12323
12354
  const {
12324
12355
  uniqueKey,
@@ -12483,7 +12514,7 @@ function convertMarketsToMorphoResponse(response, chainId, additionalYields = {
12483
12514
  irm: irmAddress,
12484
12515
  collateralAddress: collateralAssetAddress,
12485
12516
  loanAddress: loanAssetAddress,
12486
- isListed: whitelisted,
12517
+ isListed: whitelisted || listedFlagMeaningful ? whitelisted : void 0,
12487
12518
  fee: state.fee,
12488
12519
  rateAtTarget: state?.rateAtTarget?.toString()
12489
12520
  }
@@ -12493,18 +12524,220 @@ function convertMarketsToMorphoResponse(response, chainId, additionalYields = {
12493
12524
  });
12494
12525
  return data;
12495
12526
  }
12496
- var query = (first, skip, chainId, includeUnlisted = false) => `
12527
+
12528
+ // src/lending/public-data/morpho/vaultFunded.ts
12529
+ var MORPHO_VAULT_FUNDED_MIN_USD = 1e4;
12530
+ var MORPHO_VAULT_FUNDED_MIN_VAULT_USD = 1e3;
12531
+ var BASE_URL = "https://blue-api.morpho.org/graphql";
12532
+ var V1_PAGE = 100;
12533
+ var V2_PAGE = 50;
12534
+ var MAX_PAGES = 20;
12535
+ var CACHE_TTL_MS = 15 * 6e4;
12536
+ var FAIL_TTL_MS = 6e4;
12537
+ var V1_VAULT_ALLOCATIONS_QUERY = (first, skip, chainId) => `
12538
+ query VaultFundedV1 {
12539
+ vaults(first: ${first}, skip: ${skip}, where: {
12540
+ chainId_in: [${chainId}],
12541
+ totalAssetsUsd_gte: ${MORPHO_VAULT_FUNDED_MIN_VAULT_USD}
12542
+ }) {
12543
+ items {
12544
+ address
12545
+ state {
12546
+ allocation {
12547
+ supplyAssetsUsd
12548
+ market { marketId listed collateralAsset { address } }
12549
+ }
12550
+ }
12551
+ }
12552
+ }
12553
+ }
12554
+ `;
12555
+ var V2_VAULT_CAPS_QUERY = (first, skip, chainId) => `
12556
+ query VaultFundedV2 {
12557
+ vaultV2s(first: ${first}, skip: ${skip}, where: {
12558
+ chainId_in: [${chainId}],
12559
+ totalAssetsUsd_gte: ${MORPHO_VAULT_FUNDED_MIN_VAULT_USD}
12560
+ }) {
12561
+ items {
12562
+ address
12563
+ totalAssets
12564
+ totalAssetsUsd
12565
+ asset { decimals price { usd } }
12566
+ caps {
12567
+ items {
12568
+ type
12569
+ allocation
12570
+ data {
12571
+ __typename
12572
+ ... on MarketV1CapData {
12573
+ market { marketId listed collateralAsset { address } }
12574
+ }
12575
+ }
12576
+ }
12577
+ }
12578
+ }
12579
+ }
12580
+ }
12581
+ `;
12582
+ var ZERO = "0x0000000000000000000000000000000000000000";
12583
+ var isUnlistedLendable = (m) => {
12584
+ if (m?.listed !== false) return false;
12585
+ const coll = m.collateralAsset?.address?.toLowerCase();
12586
+ return !!coll && coll !== ZERO;
12587
+ };
12588
+ function sumVaultFundedUnlisted(v1Vaults, v2Vaults, minUsd = MORPHO_VAULT_FUNDED_MIN_USD) {
12589
+ const byMarket = /* @__PURE__ */ new Map();
12590
+ const add = (marketId, usd) => {
12591
+ if (!marketId || usd == null || !Number.isFinite(usd) || usd <= 0) return;
12592
+ const k = marketId.toLowerCase();
12593
+ byMarket.set(k, (byMarket.get(k) ?? 0) + usd);
12594
+ };
12595
+ for (const v of v1Vaults) {
12596
+ for (const a of v?.state?.allocation ?? []) {
12597
+ if (!isUnlistedLendable(a?.market)) continue;
12598
+ add(a.market.marketId, typeof a.supplyAssetsUsd === "number" ? a.supplyAssetsUsd : null);
12599
+ }
12600
+ }
12601
+ for (const v of v2Vaults) {
12602
+ const decimals = typeof v?.asset?.decimals === "number" ? v.asset.decimals : null;
12603
+ let price2 = typeof v?.asset?.price?.usd === "number" ? v.asset.price.usd : null;
12604
+ const total = Number(v?.totalAssets ?? 0);
12605
+ if (price2 == null && decimals != null && total > 0 && typeof v?.totalAssetsUsd === "number")
12606
+ price2 = v.totalAssetsUsd / (total / 10 ** decimals);
12607
+ for (const c of v?.caps?.items ?? []) {
12608
+ if (c?.type !== "MarketV1") continue;
12609
+ const m = c.data?.market;
12610
+ if (!isUnlistedLendable(m)) continue;
12611
+ const raw = Number(c.allocation ?? 0);
12612
+ add(m.marketId, price2 != null && decimals != null ? raw / 10 ** decimals * price2 : null);
12613
+ }
12614
+ }
12615
+ return [...byMarket].filter(([, usd]) => usd >= minUsd).map(([marketId, vaultUsd]) => ({ marketId, vaultUsd })).sort((a, b) => b.vaultUsd - a.vaultUsd || a.marketId.localeCompare(b.marketId));
12616
+ }
12617
+ async function post(query3) {
12618
+ const res = await fetch(BASE_URL, {
12619
+ method: "POST",
12620
+ headers: { "Content-Type": "application/json" },
12621
+ body: JSON.stringify({ query: query3 })
12622
+ });
12623
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
12624
+ const json = await res.json();
12625
+ if (json?.errors?.length)
12626
+ throw new Error(json.errors.map((e) => e?.message).join("; "));
12627
+ return json.data;
12628
+ }
12629
+ async function pageAll(build6, field13, pageSize) {
12630
+ const out = [];
12631
+ for (let page = 0; page < MAX_PAGES; page++) {
12632
+ const items = (await post(build6(pageSize, page * pageSize)))?.[field13]?.items;
12633
+ if (!Array.isArray(items)) throw new Error(`unexpected ${field13} shape`);
12634
+ out.push(...items);
12635
+ if (items.length < pageSize) return out;
12636
+ }
12637
+ console.warn(`[morpho-vault-funded] ${field13}: hit MAX_PAGES, result truncated`);
12638
+ return out;
12639
+ }
12640
+ async function discover(chainId) {
12641
+ const [v1, v2] = await Promise.all([
12642
+ pageAll((f, s) => V1_VAULT_ALLOCATIONS_QUERY(f, s, chainId), "vaults", V1_PAGE),
12643
+ pageAll((f, s) => V2_VAULT_CAPS_QUERY(f, s, chainId), "vaultV2s", V2_PAGE)
12644
+ ]);
12645
+ return sumVaultFundedUnlisted(v1, v2);
12646
+ }
12647
+ var cache = /* @__PURE__ */ new Map();
12648
+ function morphoVaultFundedUnlistedMarkets(chainId) {
12649
+ if (morphoIncludesUnlisted(chainId)) return Promise.resolve([]);
12650
+ const now = Date.now();
12651
+ const hit = cache.get(chainId);
12652
+ if (hit && now - hit.at < hit.ttl) return hit.promise;
12653
+ const entry = { at: now, ttl: CACHE_TTL_MS, promise: Promise.resolve([]) };
12654
+ entry.promise = discover(chainId).catch((e) => {
12655
+ entry.ttl = FAIL_TTL_MS;
12656
+ console.warn(
12657
+ `[morpho-vault-funded] chain ${chainId}: discovery failed, serving listed markets only:`,
12658
+ e?.message ?? e
12659
+ );
12660
+ return [];
12661
+ });
12662
+ cache.set(chainId, entry);
12663
+ return entry.promise;
12664
+ }
12665
+ async function morphoVaultFundedUnlistedMarketIds(chainId) {
12666
+ return (await morphoVaultFundedUnlistedMarkets(chainId)).map((m) => m.marketId);
12667
+ }
12668
+ var uniqueKeyInFilter = (keys) => `uniqueKey_in: [${keys.map((k) => JSON.stringify(k.toLowerCase())).join(", ")}]`;
12669
+ function mergeMarketItemsByKey(base, extra) {
12670
+ const have = new Set(base.map((m) => m?.uniqueKey?.toLowerCase()));
12671
+ const out = [...base];
12672
+ for (const m of extra) {
12673
+ const k = m?.uniqueKey?.toLowerCase();
12674
+ if (!k || have.has(k)) continue;
12675
+ have.add(k);
12676
+ out.push(m);
12677
+ }
12678
+ return out;
12679
+ }
12680
+ var BY_KEY_CHUNK = 100;
12681
+ async function appendVaultFundedMarkets(chainId, base, buildByKeys) {
12682
+ const ids = await morphoVaultFundedUnlistedMarketIds(chainId);
12683
+ if (ids.length === 0) return base;
12684
+ const have = new Set(base.map((m) => m?.uniqueKey?.toLowerCase()));
12685
+ const missing = ids.filter((id) => !have.has(id));
12686
+ if (missing.length === 0) return base;
12687
+ try {
12688
+ const extra = [];
12689
+ for (let i = 0; i < missing.length; i += BY_KEY_CHUNK) {
12690
+ const items = (await post(buildByKeys(missing.slice(i, i + BY_KEY_CHUNK))))?.markets?.items;
12691
+ if (!Array.isArray(items)) throw new Error("unexpected markets shape");
12692
+ extra.push(...items);
12693
+ }
12694
+ return mergeMarketItemsByKey(base, extra);
12695
+ } catch (e) {
12696
+ console.warn(
12697
+ `[morpho-vault-funded] chain ${chainId}: by-key fetch of ${missing.length} markets failed:`,
12698
+ e?.message ?? e
12699
+ );
12700
+ return base;
12701
+ }
12702
+ }
12703
+
12704
+ // src/lending/public-data/morpho/apiFields.ts
12705
+ function normalizeMorphoApiMarket(item) {
12706
+ if (!item || typeof item !== "object") return item;
12707
+ const out = { ...item };
12708
+ if ("oracle" in out) {
12709
+ out.oracleAddress = out.oracle?.address ?? void 0;
12710
+ delete out.oracle;
12711
+ }
12712
+ for (const side of ["loanAsset", "collateralAsset"]) {
12713
+ const a = out[side];
12714
+ if (a && typeof a === "object" && "price" in a) {
12715
+ const { price: price2, ...rest } = a;
12716
+ out[side] = { ...rest, priceUsd: price2?.usd ?? null };
12717
+ }
12718
+ }
12719
+ return out;
12720
+ }
12721
+ function normalizeMorphoApiMarkets(items) {
12722
+ return items.map(normalizeMorphoApiMarket);
12723
+ }
12724
+
12725
+ // src/lending/public-data/morpho/fetchPublic.ts
12726
+ var query = (first, skip, chainId, includeUnlisted = false, uniqueKeys) => `
12497
12727
  query GetMarkets {
12498
12728
  markets(first: ${first}, skip: ${skip}, where: {
12499
- chainId_in: [${chainId}]${includeUnlisted ? "" : ",\n listed: true"}
12729
+ chainId_in: [${chainId}]${uniqueKeys ? `,
12730
+ ${uniqueKeyInFilter(uniqueKeys)}` : includeUnlisted ? "" : ",\n listed: true"}
12500
12731
  },
12501
- orderBy: SupplyAssetsUsd,
12732
+ orderBy: ${uniqueKeys ? "UniqueKey" : "SupplyAssetsUsd"},
12502
12733
  orderDirection: Desc
12503
12734
  ) {
12504
12735
  items {
12505
12736
  uniqueKey: marketId
12506
12737
  irmAddress
12507
- oracleAddress
12738
+ oracle {
12739
+ address
12740
+ }
12508
12741
  lltv
12509
12742
  whitelisted: listed
12510
12743
  loanAsset {
@@ -12512,14 +12745,18 @@ query GetMarkets {
12512
12745
  name
12513
12746
  symbol
12514
12747
  decimals
12515
- priceUsd
12748
+ price {
12749
+ usd
12750
+ }
12516
12751
  }
12517
12752
  collateralAsset {
12518
12753
  address
12519
12754
  name
12520
12755
  symbol
12521
12756
  decimals
12522
- priceUsd
12757
+ price {
12758
+ usd
12759
+ }
12523
12760
  }
12524
12761
  state {
12525
12762
  borrowApy
@@ -12547,7 +12784,7 @@ query GetMarkets {
12547
12784
  }
12548
12785
  }
12549
12786
  `;
12550
- var BASE_URL = "https://blue-api.morpho.org/graphql";
12787
+ var BASE_URL2 = "https://blue-api.morpho.org/graphql";
12551
12788
  function assertNoGraphQLErrors(json) {
12552
12789
  if (json?.errors?.length) {
12553
12790
  throw new Error(
@@ -12556,12 +12793,25 @@ function assertNoGraphQLErrors(json) {
12556
12793
  }
12557
12794
  }
12558
12795
  async function fetchMorphoMarkets(chainId, includeUnlisted = false) {
12796
+ const data = await fetchMorphoMarketsBase(chainId, includeUnlisted);
12797
+ if (!Array.isArray(data?.markets?.items)) return data;
12798
+ const items = includeUnlisted ? data.markets.items : await appendVaultFundedMarkets(
12799
+ chainId,
12800
+ data.markets.items,
12801
+ (keys) => query(keys.length, 0, chainId, false, keys)
12802
+ );
12803
+ return {
12804
+ ...data,
12805
+ markets: { ...data.markets, items: normalizeMorphoApiMarkets(items) }
12806
+ };
12807
+ }
12808
+ async function fetchMorphoMarketsBase(chainId, includeUnlisted) {
12559
12809
  if (chainId !== Chain.ETHEREUM_MAINNET) {
12560
12810
  const requestBody = {
12561
12811
  query: query(200, 0, chainId, includeUnlisted),
12562
12812
  variables: {}
12563
12813
  };
12564
- const response = await fetch(BASE_URL, {
12814
+ const response = await fetch(BASE_URL2, {
12565
12815
  method: "POST",
12566
12816
  headers: {
12567
12817
  "Content-Type": "application/json"
@@ -12586,14 +12836,14 @@ async function fetchMorphoMarkets(chainId, includeUnlisted = false) {
12586
12836
  variables: {}
12587
12837
  };
12588
12838
  const [data0, data1] = await Promise.all([
12589
- fetch(BASE_URL, {
12839
+ fetch(BASE_URL2, {
12590
12840
  method: "POST",
12591
12841
  headers: {
12592
12842
  "Content-Type": "application/json"
12593
12843
  },
12594
12844
  body: JSON.stringify(requestBody0)
12595
12845
  }).then((x) => x.json()),
12596
- fetch(BASE_URL, {
12846
+ fetch(BASE_URL2, {
12597
12847
  method: "POST",
12598
12848
  headers: {
12599
12849
  "Content-Type": "application/json"
@@ -20184,7 +20434,7 @@ var FLUID_API_BASE = "https://api.fluid.instadapp.io/v2";
20184
20434
  var SUPPORTED_CHAINS = /* @__PURE__ */ new Set(["1", "56", "137", "8453", "9745", "42161"]);
20185
20435
  var TTL_MS2 = 6e4;
20186
20436
  var ZERO_ADDRESS4 = "0x0000000000000000000000000000000000000000";
20187
- var cache = {};
20437
+ var cache2 = {};
20188
20438
  var inflight = /* @__PURE__ */ new Map();
20189
20439
  var isRealDex = (d) => !!d && String(d.id ?? "0") !== "0" && String(d.address ?? ZERO_ADDRESS4).toLowerCase() !== ZERO_ADDRESS4;
20190
20440
  var toBigInt7 = (v) => {
@@ -20229,7 +20479,7 @@ var parseChainPayload = (raw) => {
20229
20479
  };
20230
20480
  var fetchFluidApiData = async (chainId) => {
20231
20481
  if (!SUPPORTED_CHAINS.has(chainId)) return void 0;
20232
- const hit = cache[chainId];
20482
+ const hit = cache2[chainId];
20233
20483
  if (hit && Date.now() - hit.at < TTL_MS2) return hit.data;
20234
20484
  const pending = inflight.get(chainId);
20235
20485
  if (pending) return pending;
@@ -20240,11 +20490,11 @@ var fetchFluidApiData = async (chainId) => {
20240
20490
  const json = await res.json();
20241
20491
  if (!Array.isArray(json)) throw new Error("unexpected payload");
20242
20492
  const data = parseChainPayload(json);
20243
- cache[chainId] = { at: Date.now(), data };
20493
+ cache2[chainId] = { at: Date.now(), data };
20244
20494
  return data;
20245
20495
  } catch {
20246
- const prev = cache[chainId]?.data;
20247
- cache[chainId] = { at: Date.now(), data: prev };
20496
+ const prev = cache2[chainId]?.data;
20497
+ cache2[chainId] = { at: Date.now(), data: prev };
20248
20498
  return prev;
20249
20499
  } finally {
20250
20500
  inflight.delete(chainId);
@@ -20253,7 +20503,7 @@ var fetchFluidApiData = async (chainId) => {
20253
20503
  inflight.set(chainId, run);
20254
20504
  return run;
20255
20505
  };
20256
- var getCachedFluidApiData = (chainId) => cache[chainId]?.data;
20506
+ var getCachedFluidApiData = (chainId) => cache2[chainId]?.data;
20257
20507
  var DEX_RESOLVER_FALLBACK = {
20258
20508
  "1": "0x11D80CfF056Cef4F9E6d23da8672fE9873e5cC07",
20259
20509
  "137": "0x11D80CfF056Cef4F9E6d23da8672fE9873e5cC07",
@@ -20265,12 +20515,12 @@ var DEX_RESOLVER_FALLBACK = {
20265
20515
  var dexResolverFor = (chainId) => fluidResolvers()?.[chainId]?.dexResolver ?? DEX_RESOLVER_FALLBACK[chainId];
20266
20516
  var ZERO_ADDRESS5 = "0x0000000000000000000000000000000000000000";
20267
20517
  var TTL_MS3 = 6e4;
20268
- var cache2 = {};
20518
+ var cache3 = {};
20269
20519
  var inflight2 = /* @__PURE__ */ new Map();
20270
20520
  var fetchFluidDexState = async (chainId, multicallRetry, extraDexAddresses = []) => {
20271
20521
  const resolver = dexResolverFor(chainId);
20272
20522
  if (!resolver) return void 0;
20273
- const hit = cache2[chainId];
20523
+ const hit = cache3[chainId];
20274
20524
  if (hit && Date.now() - hit.at < TTL_MS3) return hit.data;
20275
20525
  const pending = inflight2.get(chainId);
20276
20526
  if (pending) return pending;
@@ -20310,11 +20560,11 @@ var fetchFluidDexState = async (chainId, multicallRetry, extraDexAddresses = [])
20310
20560
  totalBorrowShares: BigInt(s.totalBorrowShares ?? 0)
20311
20561
  };
20312
20562
  }
20313
- cache2[chainId] = { at: Date.now(), data };
20563
+ cache3[chainId] = { at: Date.now(), data };
20314
20564
  return data;
20315
20565
  } catch {
20316
- const prev = cache2[chainId]?.data;
20317
- cache2[chainId] = { at: Date.now(), data: prev };
20566
+ const prev = cache3[chainId]?.data;
20567
+ cache3[chainId] = { at: Date.now(), data: prev };
20318
20568
  return prev;
20319
20569
  } finally {
20320
20570
  inflight2.delete(chainId);
@@ -20323,7 +20573,7 @@ var fetchFluidDexState = async (chainId, multicallRetry, extraDexAddresses = [])
20323
20573
  inflight2.set(chainId, run);
20324
20574
  return run;
20325
20575
  };
20326
- var getCachedFluidDexState = (chainId) => cache2[chainId]?.data;
20576
+ var getCachedFluidDexState = (chainId) => cache3[chainId]?.data;
20327
20577
 
20328
20578
  // src/lending/public-data/fluid/publicCallParse.ts
20329
20579
  var FLUID_EEE_LOWER = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
@@ -25520,7 +25770,7 @@ var LLAMALEND_READ_ABI = [
25520
25770
  ...LlamaLendAmmAbi,
25521
25771
  ...Erc20Abi
25522
25772
  ];
25523
- var ZERO = "0x0000000000000000000000000000000000000000";
25773
+ var ZERO2 = "0x0000000000000000000000000000000000000000";
25524
25774
  var WAD8 = 10n ** 18n;
25525
25775
  var CALLS_PER_MARKET = 6;
25526
25776
  var fetchJson2 = async (url, timeoutMs = 8e3) => {
@@ -25569,7 +25819,7 @@ async function fetchChainExtras(chainId, markets) {
25569
25819
  { address: m.amm, name: "price_oracle", params: [] },
25570
25820
  { address: m.amm, name: "active_band", params: [] },
25571
25821
  { address: m.controller, name: "n_loans", params: [] },
25572
- { address: m.vault, name: "maxDeposit", params: [ZERO] },
25822
+ { address: m.vault, name: "maxDeposit", params: [ZERO2] },
25573
25823
  // v1 controllers have no `borrow_cap`; allowFailure turns that into a
25574
25824
  // null rather than sinking the whole batch.
25575
25825
  { address: m.controller, name: "borrow_cap", params: [] },
@@ -29342,7 +29592,7 @@ function convertFrankencoinMarketsToResponse(raw, chainId, prices = {}, _additio
29342
29592
  }
29343
29593
 
29344
29594
  // src/lending/public-data/silo-v2/fetchPublic.ts
29345
- var BASE_URL2 = "https://api-v3.silo.finance";
29595
+ var BASE_URL3 = "https://api-v3.silo.finance";
29346
29596
  var SILO_API_SUPPORTED_CHAIN_IDS = /* @__PURE__ */ new Set([
29347
29597
  "1",
29348
29598
  // Ethereum
@@ -29485,7 +29735,7 @@ query GetSilosLite {
29485
29735
  async function fetchSiloMarketsLite(chainId, options) {
29486
29736
  if (!SILO_API_SUPPORTED_CHAIN_IDS.has(chainId)) return [];
29487
29737
  const limit = options?.limit ?? 500;
29488
- const response = await fetch(BASE_URL2, {
29738
+ const response = await fetch(BASE_URL3, {
29489
29739
  method: "POST",
29490
29740
  headers: { "Content-Type": "application/json" },
29491
29741
  body: JSON.stringify({ query: liteQuery(chainId, limit) })
@@ -29510,7 +29760,7 @@ async function fetchSiloMarketsLite(chainId, options) {
29510
29760
  async function fetchSiloMarkets(chainId, options) {
29511
29761
  if (!SILO_API_SUPPORTED_CHAIN_IDS.has(chainId)) return [];
29512
29762
  const limit = options?.limit ?? 500;
29513
- const response = await fetch(BASE_URL2, {
29763
+ const response = await fetch(BASE_URL3, {
29514
29764
  method: "POST",
29515
29765
  headers: { "Content-Type": "application/json" },
29516
29766
  body: JSON.stringify({ query: query2(chainId, limit) })
@@ -30291,39 +30541,6 @@ var getLenderPublicDataViaApi = async (chainId, lenders, prices, additionalYield
30291
30541
  }
30292
30542
  return lenderData;
30293
30543
  };
30294
-
30295
- // src/lending/public-data/morpho/unlisted.ts
30296
- var MORPHO_UNLISTED_CHAINS = /* @__PURE__ */ new Set([
30297
- // Robinhood Chain. 189 of its 194 markets are unlisted and essentially all of
30298
- // them are Longbow — a curated Morpho Blue deployment (tokenized equities and
30299
- // RWAs against USDG) that Morpho's own frontend does not carry, so `listed`
30300
- // here says nothing about the market's quality. Enabled 2026-09-08 together
30301
- // with the three things a chain needs before it can be:
30302
- // 1. its collateral tokens in `token-lists` (wsNET was the last gap — the
30303
- // collateral of the chain's LARGEST market), or the rows price at $0,
30304
- // 2. `lender-metadata`'s `SERVES_UNLISTED_CHAINS` carrying the same chain
30305
- // id, so the markets get a NAME and an oracle roster (5 -> 188 rows),
30306
- // 3. a look at what the unlisted book actually holds — here 56 real
30307
- // markets, $524k supplied / $351k borrowed, no runaway rates (the
30308
- // highest borrow APR on the chain is 21.9 %).
30309
- // See LONGBOW.md.
30310
- "4663",
30311
- // World Chain. blue-api indexes it, but 0 of its 30 markets are listed —
30312
- // Morpho's frontend simply does not carry the chain, so `listed` says
30313
- // nothing about the book (the Longbow shape again). Looked at 2026-09-16:
30314
- // $59.5M supplied / $45.0M borrowed, of which the real two-sided markets are
30315
- // USDC/WBTC $3.9M, USDC/WETH $3.6M, WETH/WBTC $2.1M, USDC/WLD $1.6M and
30316
- // WETH/ezETH $1.1M at 0.1–4.6 % borrow APY; the $35.8M USDC/sdeUSD market is
30317
- // pinned at 100 % utilization (297,994 % APY, $0 liquid) and is exactly what
30318
- // `earn/rateSanity.ts` exists to drop. Token-list gaps on 480 at enablement:
30319
- // sdeUSD and ezETH (collateral of two markets) — those rows price at $0 with
30320
- // a blank LTV until token-lists carries them. `lender-metadata`'s
30321
- // `SERVES_UNLISTED_CHAINS` was updated in the same change.
30322
- "480"
30323
- ]);
30324
- function morphoIncludesUnlisted(chainId) {
30325
- return MORPHO_UNLISTED_CHAINS.has(chainId);
30326
- }
30327
30544
  var ERC20_BALANCE_OF_ABI2 = [
30328
30545
  {
30329
30546
  inputs: [{ name: "account", type: "address" }],
@@ -30946,7 +31163,7 @@ function decodeVariableLensRows(blob, fixedWords, headerBytes = 0) {
30946
31163
  }
30947
31164
 
30948
31165
  // src/lending/user-data/aave-v3-type/lens.ts
30949
- var ZERO2 = "0x0000000000000000000000000000000000000000";
31166
+ var ZERO3 = "0x0000000000000000000000000000000000000000";
30950
31167
  var AAVE_LENS_HEADER_BYTES = 3;
30951
31168
  var HEADER_EMODE_OK = 1;
30952
31169
  var HEADER_CONFIG_OK = 2;
@@ -30954,7 +31171,7 @@ var AAVE_LENS_WORDS = 7;
30954
31171
  var reserveTuple = (tokens, asset) => {
30955
31172
  const t = tokens?.[asset.toLowerCase()];
30956
31173
  if (!t?.aToken || !t?.vToken) return void 0;
30957
- return [asset, t.aToken, t.vToken, t.sToken ?? ZERO2];
31174
+ return [asset, t.aToken, t.vToken, t.sToken ?? ZERO3];
30958
31175
  };
30959
31176
  var usesAaveLens = (chainId, lender) => {
30960
31177
  if (getPositionLensFor(chainId, LENS_FAMILY.AAVE) === void 0) return false;
@@ -30984,7 +31201,7 @@ var buildAaveLensCall = (chainId, lender, account, assetsToQuery, withEMode) =>
30984
31201
  getAaveTypePoolDataProviderAddress(chainId, lender),
30985
31202
  // A zero pool disables the e-mode read, which is exactly what YLDR wants:
30986
31203
  // it has no `getUserEMode` and the walk omits that call for it too.
30987
- withEMode ? getAaveTypePoolAddress(chainId, lender) : ZERO2
31204
+ withEMode ? getAaveTypePoolAddress(chainId, lender) : ZERO3
30988
31205
  ]
30989
31206
  );
30990
31207
  return [
@@ -32064,7 +32281,7 @@ var buildExactlyUserCall = (chainId, _lender, account) => {
32064
32281
  return [{ address: cfg.previewer, name: "exactly", params: [account] }];
32065
32282
  };
32066
32283
  var OWNER_INDEX_PROBE_COUNT = 8;
32067
- var CACHE_TTL_MS = 5 * 6e4;
32284
+ var CACHE_TTL_MS2 = 5 * 6e4;
32068
32285
  var discoveryCache = /* @__PURE__ */ new Map();
32069
32286
  async function discoverViaLens(chainId, branches, zappers, account, opts) {
32070
32287
  const lens = getPositionLensFor(chainId, LENS_FAMILY.LIQUITY);
@@ -32133,7 +32350,7 @@ var getCachedLiquityTroves = (chainId, lender, account, opts) => {
32133
32350
  const hit = discoveryCache.get(
32134
32351
  cacheKey(chainId, lender, account, blockKey(opts))
32135
32352
  );
32136
- if (!hit || Date.now() - hit.at > CACHE_TTL_MS) return void 0;
32353
+ if (!hit || Date.now() - hit.at > CACHE_TTL_MS2) return void 0;
32137
32354
  return hit;
32138
32355
  };
32139
32356
  var ADDRESS_ADDRESS_UINT = [
@@ -32353,7 +32570,7 @@ var buildRiverUserCall = (chainId, lender, account) => {
32353
32570
  });
32354
32571
  return calls;
32355
32572
  };
32356
- var ZERO3 = "0x0000000000000000000000000000000000000000";
32573
+ var ZERO4 = "0x0000000000000000000000000000000000000000";
32357
32574
  var LLAMALEND_LENS_WORDS = 12;
32358
32575
  var LLAMALEND_CALLS_PER_MARKET = 8;
32359
32576
  var usesLlamaLendLens = (chainId) => getPositionLensFor(chainId, LENS_FAMILY.LLAMALEND) !== void 0;
@@ -32367,7 +32584,7 @@ var buildLlamaLendLensCall = (chainId, markets, account, delegate) => {
32367
32584
  m.controller,
32368
32585
  m.amm,
32369
32586
  m.vault,
32370
- m.gauge ?? ZERO3
32587
+ m.gauge ?? ZERO4
32371
32588
  ]),
32372
32589
  delegate
32373
32590
  ]
@@ -32916,7 +33133,7 @@ function getCachedTwyneDiscovery(chainId, lender, account, opts) {
32916
33133
  }
32917
33134
  var lower2 = (a) => String(a).toLowerCase();
32918
33135
  var isAddress4 = (v) => typeof v === "string" && /^0x[0-9a-fA-F]{40}$/.test(v);
32919
- async function discover(chainId, lender, account, opts) {
33136
+ async function discover2(chainId, lender, account, opts) {
32920
33137
  const key3 = discoveryKey3(chainId, lender, account, blockKey(opts));
32921
33138
  const cached = discoveryCache4.get(key3);
32922
33139
  if (cached && Date.now() - cached.at < DISCOVERY_TTL_MS3) return cached;
@@ -33018,7 +33235,7 @@ async function discover(chainId, lender, account, opts) {
33018
33235
  return result;
33019
33236
  }
33020
33237
  async function buildTwyneUserCall(chainId, lender, account, opts) {
33021
- const { vaults } = await discover(chainId, lender, account, opts);
33238
+ const { vaults } = await discover2(chainId, lender, account, opts);
33022
33239
  if (vaults.length === 0) return [];
33023
33240
  return vaults.flatMap(({ vault }) => [
33024
33241
  { address: vault, name: "totalAssetsDepositedOrReserved", args: [] },
@@ -33032,14 +33249,14 @@ async function buildTwyneUserCall(chainId, lender, account, opts) {
33032
33249
  }
33033
33250
  var DSS_CALLS_PER_CDP = 1;
33034
33251
  var MAX_CDP_WALK = 64;
33035
- var CACHE_TTL_MS2 = 5 * 6e4;
33252
+ var CACHE_TTL_MS3 = 5 * 6e4;
33036
33253
  var discoveryCache5 = /* @__PURE__ */ new Map();
33037
33254
  var cacheKey2 = (lender, chainId, account, block = "head") => `${lender}:${chainId}:${account.toLowerCase()}:${block}`;
33038
33255
  var getCachedDssCdps = (lender, chainId, account, opts) => {
33039
33256
  const hit = discoveryCache5.get(
33040
33257
  cacheKey2(lender, chainId, account, blockKey(opts))
33041
33258
  );
33042
- if (!hit || Date.now() - hit.at > CACHE_TTL_MS2) return void 0;
33259
+ if (!hit || Date.now() - hit.at > CACHE_TTL_MS3) return void 0;
33043
33260
  return hit;
33044
33261
  };
33045
33262
  var big7 = (v) => {
@@ -33282,12 +33499,12 @@ async function discoverTellerBidsViaLens(chainId, tellerV2, account, opts) {
33282
33499
 
33283
33500
  // src/lending/user-data/teller/userCallBuild.ts
33284
33501
  var TELLER_CALLS_PER_BID = 4;
33285
- var CACHE_TTL_MS3 = 5 * 6e4;
33502
+ var CACHE_TTL_MS4 = 5 * 6e4;
33286
33503
  var discoveryCache7 = /* @__PURE__ */ new Map();
33287
33504
  var cacheKey4 = (chainId, account, block = "head") => `${chainId}:${account.toLowerCase()}:${block}`;
33288
33505
  var getCachedTellerBids = (chainId, account, opts) => {
33289
33506
  const hit = discoveryCache7.get(cacheKey4(chainId, account, blockKey(opts)));
33290
- if (!hit || Date.now() - hit.at > CACHE_TTL_MS3) return void 0;
33507
+ if (!hit || Date.now() - hit.at > CACHE_TTL_MS4) return void 0;
33291
33508
  return hit;
33292
33509
  };
33293
33510
  var nowSec5 = () => Math.floor(Date.now() / 1e3);
@@ -33424,12 +33641,12 @@ var buildFlyingTulipUserCall = (chainId, lender, account) => {
33424
33641
  ];
33425
33642
  };
33426
33643
  var TERMMAX_MARKETS_PER_CALL = 180;
33427
- var CACHE_TTL_MS4 = 5 * 6e4;
33644
+ var CACHE_TTL_MS5 = 5 * 6e4;
33428
33645
  var discoveryCache8 = /* @__PURE__ */ new Map();
33429
33646
  var cacheKey5 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
33430
33647
  var getCachedTermMaxDiscovery = (chainId, account) => {
33431
33648
  const hit = discoveryCache8.get(cacheKey5(chainId, account));
33432
- if (!hit || Date.now() - hit.at > CACHE_TTL_MS4) return void 0;
33649
+ if (!hit || Date.now() - hit.at > CACHE_TTL_MS5) return void 0;
33433
33650
  return hit;
33434
33651
  };
33435
33652
  var buildTermMaxUserCall = async (chainId, _lender, account) => {
@@ -43709,7 +43926,7 @@ var MORPHO_API_CHAIN_IDS = {
43709
43926
  [Chain.UNICHAIN]: 130
43710
43927
  };
43711
43928
  var FETCH_TIMEOUT_MS = 3e3;
43712
- var CACHE_TTL_MS5 = 2e3;
43929
+ var CACHE_TTL_MS6 = 2e3;
43713
43930
  var buildSubgraphQuery = (account) => `
43714
43931
  {
43715
43932
  account(id: "${account.toLowerCase()}") {
@@ -43777,7 +43994,7 @@ async function dedupedFetch(chainId, account, loader) {
43777
43994
  const existing = inflight3.get(key3);
43778
43995
  if (existing) return existing;
43779
43996
  const promise = loader().then((value) => {
43780
- resolved.set(key3, { value, expiresAt: Date.now() + CACHE_TTL_MS5 });
43997
+ resolved.set(key3, { value, expiresAt: Date.now() + CACHE_TTL_MS6 });
43781
43998
  return value;
43782
43999
  }).finally(() => {
43783
44000
  inflight3.delete(key3);
@@ -56754,7 +56971,7 @@ var dtrinityRebateRewardFetcher = {
56754
56971
  };
56755
56972
  var SECONDS_PER_YEAR15 = 31536e3;
56756
56973
  var WAD16 = 10n ** 18n;
56757
- var ZERO4 = "0x0000000000000000000000000000000000000000";
56974
+ var ZERO5 = "0x0000000000000000000000000000000000000000";
56758
56975
  var UNBOOSTED_FACTOR = 0.4;
56759
56976
  var MAX_BOOST = 2.5;
56760
56977
  var GAUGE_CONTROLLER = "0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB";
@@ -56950,7 +57167,7 @@ async function fetchPrices(keys) {
56950
57167
  var priceOf = (prices, chainId, address) => prices[`${LLAMA_CHAIN_SLUG[chainId]}:${address.toLowerCase()}`] ?? 0;
56951
57168
  function rosterFor(chainId) {
56952
57169
  const markets = llamaLendChainData(Lender.LLAMALEND, chainId)?.markets ?? [];
56953
- return markets.filter((m) => m.gauge && m.gauge !== ZERO4).map((m) => ({
57170
+ return markets.filter((m) => m.gauge && m.gauge !== ZERO5).map((m) => ({
56954
57171
  controller: m.controller,
56955
57172
  vault: m.vault,
56956
57173
  gauge: m.gauge,
@@ -57027,7 +57244,7 @@ async function fetchForChain(chainId, nowSeconds) {
57027
57244
  }) : [];
57028
57245
  let cursor = 0;
57029
57246
  const withTokens = state.map((s) => {
57030
- const tokens = r2.slice(cursor, cursor + s.rewardCount).filter((t) => typeof t === "string" && t !== ZERO4);
57247
+ const tokens = r2.slice(cursor, cursor + s.rewardCount).filter((t) => typeof t === "string" && t !== ZERO5);
57031
57248
  cursor += s.rewardCount;
57032
57249
  return { ...s, tokens };
57033
57250
  });
@@ -57622,26 +57839,32 @@ function getMorphoAbi() {
57622
57839
  var MORPHO_GRAPHQL_URL = "https://blue-api.morpho.org/graphql";
57623
57840
  var MAX_UNLISTED_PRICE_PAGES = 10;
57624
57841
  var PRICE_PAGE_SIZE = 200;
57625
- var PRICE_QUERY = (first, skip, chainId, includeUnlisted) => `
57842
+ var PRICE_QUERY = (first, skip, chainId, includeUnlisted, uniqueKeys) => `
57626
57843
  query GetMarketPrices {
57627
57844
  markets(first: ${first}, skip: ${skip}, where: {
57628
- chainId_in: [${chainId}]${!includeUnlisted && chainId != Chain.ETHEREUM_MAINNET ? `,listed: true` : ""}
57845
+ chainId_in: [${chainId}]${uniqueKeys ? `,${uniqueKeyInFilter(uniqueKeys)}` : !includeUnlisted && chainId != Chain.ETHEREUM_MAINNET ? `,listed: true` : ""}
57629
57846
  },
57630
- orderBy: SupplyAssetsUsd,
57847
+ orderBy: ${uniqueKeys ? "UniqueKey" : "SupplyAssetsUsd"},
57631
57848
  orderDirection: Desc
57632
57849
  ) {
57633
57850
  items {
57634
57851
  uniqueKey: marketId
57635
- oracleAddress
57852
+ oracle {
57853
+ address
57854
+ }
57636
57855
  loanAsset {
57637
57856
  address
57638
57857
  decimals
57639
- priceUsd
57858
+ price {
57859
+ usd
57860
+ }
57640
57861
  }
57641
57862
  collateralAsset {
57642
57863
  address
57643
57864
  decimals
57644
- priceUsd
57865
+ price {
57866
+ usd
57867
+ }
57645
57868
  }
57646
57869
  state {
57647
57870
  price
@@ -57652,7 +57875,7 @@ query GetMarketPrices {
57652
57875
  `;
57653
57876
  async function fetchMorphoGraphQLPrices(chainId, includeUnlisted = false) {
57654
57877
  if (!morphoApiAvailable(chainId)) return null;
57655
- const post = (skip) => fetch(MORPHO_GRAPHQL_URL, {
57878
+ const post2 = (skip) => fetch(MORPHO_GRAPHQL_URL, {
57656
57879
  method: "POST",
57657
57880
  headers: { "Content-Type": "application/json" },
57658
57881
  body: JSON.stringify({
@@ -57673,7 +57896,7 @@ async function fetchMorphoGraphQLPrices(chainId, includeUnlisted = false) {
57673
57896
  const allMarkets = [];
57674
57897
  if (includeUnlisted) {
57675
57898
  for (let page = 0; page < MAX_UNLISTED_PRICE_PAGES; page++) {
57676
- const items = readItems(await post(page * PRICE_PAGE_SIZE));
57899
+ const items = readItems(await post2(page * PRICE_PAGE_SIZE));
57677
57900
  if (!items) return null;
57678
57901
  allMarkets.push(...items);
57679
57902
  if (items.length < PRICE_PAGE_SIZE) break;
@@ -57685,14 +57908,23 @@ async function fetchMorphoGraphQLPrices(chainId, includeUnlisted = false) {
57685
57908
  }
57686
57909
  } else {
57687
57910
  const skips = chainId === Chain.ETHEREUM_MAINNET ? [0, PRICE_PAGE_SIZE] : [0];
57688
- const results = await Promise.all(skips.map(post));
57911
+ const results = await Promise.all(skips.map(post2));
57689
57912
  for (const result of results) {
57690
57913
  const items = readItems(result);
57691
57914
  if (!items) return null;
57692
57915
  allMarkets.push(...items);
57693
57916
  }
57694
57917
  }
57695
- return processMarketsToEntries(chainId, allMarkets, "morpho-gql");
57918
+ const priced = includeUnlisted ? allMarkets : await appendVaultFundedMarkets(
57919
+ chainId,
57920
+ allMarkets,
57921
+ (keys) => PRICE_QUERY(keys.length, 0, chainId, false, keys)
57922
+ );
57923
+ return processMarketsToEntries(
57924
+ chainId,
57925
+ normalizeMorphoApiMarkets(priced),
57926
+ "morpho-gql"
57927
+ );
57696
57928
  } catch (err) {
57697
57929
  console.warn(
57698
57930
  `[morpho-gql] chain ${chainId}: API error, falling back to on-chain`,
@@ -64297,7 +64529,7 @@ var fetchSiloVaults = async (chainId, prices = {}, tokenList = {}, options) => {
64297
64529
  // src/vaults/euler-earn/entityLabels.ts
64298
64530
  var LABELS_BASE = "https://raw.githubusercontent.com/euler-xyz/euler-labels/master";
64299
64531
  var TTL_MS4 = 30 * 60 * 1e3;
64300
- var cache3 = /* @__PURE__ */ new Map();
64532
+ var cache4 = /* @__PURE__ */ new Map();
64301
64533
  var inflight4 = /* @__PURE__ */ new Map();
64302
64534
  async function fetchChainEntities(chainId) {
64303
64535
  const res = await fetch(`${LABELS_BASE}/${chainId}/entities.json`);
@@ -64321,12 +64553,12 @@ async function fetchChainEntities(chainId) {
64321
64553
  return map;
64322
64554
  }
64323
64555
  async function fetchEulerEntityNames(chainId) {
64324
- const hit = cache3.get(chainId);
64556
+ const hit = cache4.get(chainId);
64325
64557
  if (hit && Date.now() - hit.at <= TTL_MS4) return hit.map;
64326
64558
  const running = inflight4.get(chainId);
64327
64559
  if (running) return running;
64328
64560
  const p = fetchChainEntities(chainId).then((map) => {
64329
- cache3.set(chainId, { at: Date.now(), map });
64561
+ cache4.set(chainId, { at: Date.now(), map });
64330
64562
  return map;
64331
64563
  }).catch(() => {
64332
64564
  return hit?.map ?? /* @__PURE__ */ new Map();
@@ -64423,7 +64655,7 @@ query EvkByAssets($assets: [Bytes!]!) {
64423
64655
  }
64424
64656
  }
64425
64657
  `;
64426
- var ZERO5 = 0n;
64658
+ var ZERO6 = 0n;
64427
64659
  var RAY_TO_PERCENT3 = 1e25;
64428
64660
  function readAddress2(field13) {
64429
64661
  if (!field13) return void 0;
@@ -64438,28 +64670,28 @@ function parseVaultFee(v) {
64438
64670
  return n;
64439
64671
  }
64440
64672
  function safeBigInt(v) {
64441
- if (v == null || v === "") return ZERO5;
64673
+ if (v == null || v === "") return ZERO6;
64442
64674
  try {
64443
64675
  return BigInt(v);
64444
64676
  } catch {
64445
- return ZERO5;
64677
+ return ZERO6;
64446
64678
  }
64447
64679
  }
64448
64680
  function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent2, evkIndex) {
64449
64681
  if (!strategies?.length) return 0;
64450
64682
  const totalAssets = safeBigInt(totalAssetsRaw);
64451
- if (totalAssets === ZERO5) return 0;
64452
- let weightedRay = ZERO5;
64683
+ if (totalAssets === ZERO6) return 0;
64684
+ let weightedRay = ZERO6;
64453
64685
  for (const s of strategies) {
64454
64686
  const evk = s.strategy?.toLowerCase();
64455
64687
  if (!evk) continue;
64456
64688
  const apyRay = evkIndex.bySupplyApyRay.get(evk);
64457
64689
  if (apyRay == null) continue;
64458
64690
  const allocated = safeBigInt(s.allocatedAssets);
64459
- if (allocated === ZERO5) continue;
64691
+ if (allocated === ZERO6) continue;
64460
64692
  weightedRay += allocated * apyRay;
64461
64693
  }
64462
- if (weightedRay === ZERO5) return 0;
64694
+ if (weightedRay === ZERO6) return 0;
64463
64695
  const apyRayPerAsset = weightedRay / totalAssets;
64464
64696
  const grossPercent = apyToAprPercent(Number(apyRayPerAsset) / RAY_TO_PERCENT3);
64465
64697
  const netPercent = grossPercent * (1 - feePercent2 / 100);
@@ -64467,24 +64699,24 @@ function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent2, evkIn
64467
64699
  }
64468
64700
  function computeRealLiquidity(strategies, totalAssetsRaw, evkIndex) {
64469
64701
  const totalAssets = safeBigInt(totalAssetsRaw);
64470
- if (totalAssets === ZERO5) return ZERO5;
64702
+ if (totalAssets === ZERO6) return ZERO6;
64471
64703
  if (evkIndex.byCash.size === 0 && evkIndex.bySupplyApyRay.size === 0) {
64472
64704
  return totalAssets;
64473
64705
  }
64474
64706
  if (!strategies?.length) {
64475
64707
  return totalAssets;
64476
64708
  }
64477
- let allocSum = ZERO5;
64478
- let withdrawable = ZERO5;
64709
+ let allocSum = ZERO6;
64710
+ let withdrawable = ZERO6;
64479
64711
  for (const s of strategies) {
64480
64712
  const alloc = safeBigInt(s.allocatedAssets);
64481
- if (alloc === ZERO5) continue;
64713
+ if (alloc === ZERO6) continue;
64482
64714
  allocSum += alloc;
64483
64715
  const evk = s.strategy?.toLowerCase();
64484
64716
  const cash = evk ? evkIndex.byCash.get(evk) : void 0;
64485
64717
  withdrawable += cash == null ? alloc : alloc < cash ? alloc : cash;
64486
64718
  }
64487
- const idle = totalAssets > allocSum ? totalAssets - allocSum : ZERO5;
64719
+ const idle = totalAssets > allocSum ? totalAssets - allocSum : ZERO6;
64488
64720
  const result = idle + withdrawable;
64489
64721
  return result > totalAssets ? totalAssets : result;
64490
64722
  }
@@ -75061,7 +75293,7 @@ function isLiveMarket(market, nowSecs = Math.floor(Date.now() / 1e3)) {
75061
75293
  if (expiry === void 0) return false;
75062
75294
  return expiry > nowSecs;
75063
75295
  }
75064
- var CACHE_TTL_MS6 = 6e4;
75296
+ var CACHE_TTL_MS7 = 6e4;
75065
75297
  var marketsCache;
75066
75298
  var assetsCache;
75067
75299
  function clearPendleMarketsCache() {
@@ -75077,9 +75309,9 @@ async function getJson4(url, label) {
75077
75309
  }
75078
75310
  return response.json();
75079
75311
  }
75080
- function cache4(slot, build6, store) {
75312
+ function cache5(slot, build6, store) {
75081
75313
  const now = Date.now();
75082
- if (slot && now - slot.at < CACHE_TTL_MS6) return slot.promise;
75314
+ if (slot && now - slot.at < CACHE_TTL_MS7) return slot.promise;
75083
75315
  const promise = build6();
75084
75316
  const entry = { at: now, promise };
75085
75317
  store(entry);
@@ -75087,7 +75319,7 @@ function cache4(slot, build6, store) {
75087
75319
  return promise;
75088
75320
  }
75089
75321
  function fetchPendleApiMarkets() {
75090
- return cache4(
75322
+ return cache5(
75091
75323
  marketsCache,
75092
75324
  async () => (await getJson4(PENDLE_MARKETS_URL, "markets"))?.markets ?? [],
75093
75325
  (c) => {
@@ -75097,7 +75329,7 @@ function fetchPendleApiMarkets() {
75097
75329
  }
75098
75330
  var assetKey = (chainId, address) => `${chainId}-${address.toLowerCase()}`;
75099
75331
  function fetchPendleApiAssets() {
75100
- return cache4(
75332
+ return cache5(
75101
75333
  assetsCache,
75102
75334
  async () => {
75103
75335
  const json = await getJson4(PENDLE_ASSETS_URL, "assets");
@@ -75348,17 +75580,17 @@ function parsePtRate(raw) {
75348
75580
  if (!Number.isFinite(n) || n < 0 || n > 1.000001) return void 0;
75349
75581
  return n;
75350
75582
  }
75351
- var CACHE_TTL_MS7 = 6e4;
75352
- var cache5 = /* @__PURE__ */ new Map();
75583
+ var CACHE_TTL_MS8 = 6e4;
75584
+ var cache6 = /* @__PURE__ */ new Map();
75353
75585
  function clearSpectraMarketsCache() {
75354
- cache5.clear();
75586
+ cache6.clear();
75355
75587
  }
75356
75588
  function fetchSpectraApiMarkets(chainId) {
75357
75589
  const network = spectraNetwork(chainId);
75358
75590
  if (!network) return Promise.resolve([]);
75359
75591
  const now = Date.now();
75360
- const hit = cache5.get(network);
75361
- if (hit && now - hit.at < CACHE_TTL_MS7) return hit.promise;
75592
+ const hit = cache6.get(network);
75593
+ if (hit && now - hit.at < CACHE_TTL_MS8) return hit.promise;
75362
75594
  const promise = (async () => {
75363
75595
  const response = await fetch(spectraPoolsUrl(network), {
75364
75596
  headers: { Accept: "application/json" }
@@ -75371,9 +75603,9 @@ function fetchSpectraApiMarkets(chainId) {
75371
75603
  const json = await response.json();
75372
75604
  return Array.isArray(json) ? json : [];
75373
75605
  })();
75374
- cache5.set(network, { at: now, promise });
75606
+ cache6.set(network, { at: now, promise });
75375
75607
  promise.catch(() => {
75376
- if (cache5.get(network)?.promise === promise) cache5.delete(network);
75608
+ if (cache6.get(network)?.promise === promise) cache6.delete(network);
75377
75609
  });
75378
75610
  return promise;
75379
75611
  }