@1delta/margin-fetcher 5.0.101 → 5.0.103

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
@@ -10217,7 +10217,6 @@ var ARBITRUM_ONE_MULTICALL_ADDRESS = "0xadF885960B47eA2CD9B55E6DAc6B42b7Cb2806dB
10217
10217
  var LINEA_MULTICALL_ADDRESS = "0xac1cE734566f390A94b00eb9bf561c2625BF44ea";
10218
10218
  var AVALANCHE_MULTICALL_ADDRESS = "0x0139141Cd4Ee88dF3Cdb65881D411bAE271Ef0C2";
10219
10219
  var BASE_MULTICALL_ADDRESS = "0x091e99cb1C49331a94dD62755D168E941AbD0693";
10220
- var BLAST_MULTICALL_ADDRESS = "0xdC7f370de7631cE9e2c2e1DCDA6B3B5744Cf4705";
10221
10220
  var TAIKO_MULTICALL_ADDRESS = "0x8E24CfC19c6C00c524353CB8816f5f1c2F33c201";
10222
10221
  var HEMI_MULTICALL_ADDRESS = "0x352A86168e6988A1aDF9A15Cb00017AAd3B67155";
10223
10222
  var GNOSIS_MULTICALL_ADDRESS = "0x4dfa9a980efE4802E969AC33968E3d6E59B8a19e";
@@ -10252,7 +10251,6 @@ var MULTICALL_ADDRESS = {
10252
10251
  [Chain.CELO_MAINNET]: CELO_MULTICALL_ADDRESS,
10253
10252
  [Chain.BNB_SMART_CHAIN_MAINNET]: BNB_MULTICALL_ADDRESS,
10254
10253
  [Chain.MANTLE]: MANTLE_MULTICALL_ADDRESS,
10255
- [Chain.BLAST]: BLAST_MULTICALL_ADDRESS,
10256
10254
  [Chain.LINEA]: LINEA_MULTICALL_ADDRESS,
10257
10255
  [Chain.AVALANCHE_C_CHAIN]: AVALANCHE_MULTICALL_ADDRESS,
10258
10256
  [Chain.TAIKO_ALETHIA]: TAIKO_MULTICALL_ADDRESS,
@@ -10729,11 +10727,11 @@ async function resolveListaBrokers(chainId, marketKeys, getClient = getEvmClient
10729
10727
  const moolah = morphoPools()?.LISTA_DAO?.[chainId];
10730
10728
  const out = {};
10731
10729
  if (!moolah || marketKeys.length === 0) return out;
10732
- const cache6 = BROKER_CACHE[chainId] ??= {};
10730
+ const cache7 = BROKER_CACHE[chainId] ??= {};
10733
10731
  const missing = [];
10734
10732
  for (const key3 of marketKeys) {
10735
10733
  const id = toBytes32MarketId(key3);
10736
- if (cache6[id] === void 0) missing.push(id);
10734
+ if (cache7[id] === void 0) missing.push(id);
10737
10735
  }
10738
10736
  if (missing.length > 0) {
10739
10737
  try {
@@ -10749,7 +10747,7 @@ async function resolveListaBrokers(chainId, marketKeys, getClient = getEvmClient
10749
10747
  );
10750
10748
  results.forEach((addr4, i) => {
10751
10749
  if (addr4 === void 0) return;
10752
- cache6[missing[i]] = addr4.toLowerCase();
10750
+ cache7[missing[i]] = addr4.toLowerCase();
10753
10751
  });
10754
10752
  } catch (e) {
10755
10753
  console.warn(
@@ -10760,7 +10758,7 @@ async function resolveListaBrokers(chainId, marketKeys, getClient = getEvmClient
10760
10758
  }
10761
10759
  for (const key3 of marketKeys) {
10762
10760
  const id = toBytes32MarketId(key3);
10763
- const broker = cache6[id];
10761
+ const broker = cache7[id];
10764
10762
  if (broker && broker !== zeroAddress) out[id] = broker;
10765
10763
  }
10766
10764
  return out;
@@ -10788,7 +10786,7 @@ async function fetchListaFixedTerms(chainId, marketKeys, multicallRetry) {
10788
10786
  })),
10789
10787
  multicallRetry
10790
10788
  );
10791
- const cache6 = FIXED_TERMS_CACHE[chainId] ??= {};
10789
+ const cache7 = FIXED_TERMS_CACHE[chainId] ??= {};
10792
10790
  results.forEach((raw, i) => {
10793
10791
  if (!raw) return;
10794
10792
  const id = ids[i];
@@ -10802,7 +10800,7 @@ async function fetchListaFixedTerms(chainId, marketKeys, multicallRetry) {
10802
10800
  };
10803
10801
  });
10804
10802
  out[id] = terms;
10805
- cache6[id] = terms;
10803
+ cache7[id] = terms;
10806
10804
  });
10807
10805
  } catch (e) {
10808
10806
  console.warn(
@@ -12307,6 +12305,39 @@ function formatNr(n, d) {
12307
12305
  return Number(formatUnits(BigInt(n ?? 0), d));
12308
12306
  }
12309
12307
 
12308
+ // src/lending/public-data/morpho/unlisted.ts
12309
+ var MORPHO_UNLISTED_CHAINS = /* @__PURE__ */ new Set([
12310
+ // Robinhood Chain. 189 of its 194 markets are unlisted and essentially all of
12311
+ // them are Longbow — a curated Morpho Blue deployment (tokenized equities and
12312
+ // RWAs against USDG) that Morpho's own frontend does not carry, so `listed`
12313
+ // here says nothing about the market's quality. Enabled 2026-09-08 together
12314
+ // with the three things a chain needs before it can be:
12315
+ // 1. its collateral tokens in `token-lists` (wsNET was the last gap — the
12316
+ // collateral of the chain's LARGEST market), or the rows price at $0,
12317
+ // 2. `lender-metadata`'s `SERVES_UNLISTED_CHAINS` carrying the same chain
12318
+ // id, so the markets get a NAME and an oracle roster (5 -> 188 rows),
12319
+ // 3. a look at what the unlisted book actually holds — here 56 real
12320
+ // markets, $524k supplied / $351k borrowed, no runaway rates (the
12321
+ // highest borrow APR on the chain is 21.9 %).
12322
+ // See LONGBOW.md.
12323
+ "4663",
12324
+ // World Chain. blue-api indexes it, but 0 of its 30 markets are listed —
12325
+ // Morpho's frontend simply does not carry the chain, so `listed` says
12326
+ // nothing about the book (the Longbow shape again). Looked at 2026-09-16:
12327
+ // $59.5M supplied / $45.0M borrowed, of which the real two-sided markets are
12328
+ // USDC/WBTC $3.9M, USDC/WETH $3.6M, WETH/WBTC $2.1M, USDC/WLD $1.6M and
12329
+ // WETH/ezETH $1.1M at 0.1–4.6 % borrow APY; the $35.8M USDC/sdeUSD market is
12330
+ // pinned at 100 % utilization (297,994 % APY, $0 liquid) and is exactly what
12331
+ // `earn/rateSanity.ts` exists to drop. Token-list gaps on 480 at enablement:
12332
+ // sdeUSD and ezETH (collateral of two markets) — those rows price at $0 with
12333
+ // a blank LTV until token-lists carries them. `lender-metadata`'s
12334
+ // `SERVES_UNLISTED_CHAINS` was updated in the same change.
12335
+ "480"
12336
+ ]);
12337
+ function morphoIncludesUnlisted(chainId) {
12338
+ return MORPHO_UNLISTED_CHAINS.has(chainId);
12339
+ }
12340
+
12310
12341
  // src/lending/public-data/morpho/convertPublic.ts
12311
12342
  function convertMarketsToMorphoResponse(response, chainId, additionalYields = {
12312
12343
  intrinsicYields: {},
@@ -12316,6 +12347,7 @@ function convertMarketsToMorphoResponse(response, chainId, additionalYields = {
12316
12347
  const data = {};
12317
12348
  const items = response?.markets?.items;
12318
12349
  if (!items) return data;
12350
+ const listedFlagMeaningful = !morphoIncludesUnlisted(chainId);
12319
12351
  items.forEach((market) => {
12320
12352
  const {
12321
12353
  uniqueKey,
@@ -12480,7 +12512,7 @@ function convertMarketsToMorphoResponse(response, chainId, additionalYields = {
12480
12512
  irm: irmAddress,
12481
12513
  collateralAddress: collateralAssetAddress,
12482
12514
  loanAddress: loanAssetAddress,
12483
- isListed: whitelisted,
12515
+ isListed: whitelisted || listedFlagMeaningful ? whitelisted : void 0,
12484
12516
  fee: state.fee,
12485
12517
  rateAtTarget: state?.rateAtTarget?.toString()
12486
12518
  }
@@ -12490,18 +12522,220 @@ function convertMarketsToMorphoResponse(response, chainId, additionalYields = {
12490
12522
  });
12491
12523
  return data;
12492
12524
  }
12493
- var query = (first, skip, chainId, includeUnlisted = false) => `
12525
+
12526
+ // src/lending/public-data/morpho/vaultFunded.ts
12527
+ var MORPHO_VAULT_FUNDED_MIN_USD = 1e4;
12528
+ var MORPHO_VAULT_FUNDED_MIN_VAULT_USD = 1e3;
12529
+ var BASE_URL = "https://blue-api.morpho.org/graphql";
12530
+ var V1_PAGE = 100;
12531
+ var V2_PAGE = 50;
12532
+ var MAX_PAGES = 20;
12533
+ var CACHE_TTL_MS = 15 * 6e4;
12534
+ var FAIL_TTL_MS = 6e4;
12535
+ var V1_VAULT_ALLOCATIONS_QUERY = (first, skip, chainId) => `
12536
+ query VaultFundedV1 {
12537
+ vaults(first: ${first}, skip: ${skip}, where: {
12538
+ chainId_in: [${chainId}],
12539
+ totalAssetsUsd_gte: ${MORPHO_VAULT_FUNDED_MIN_VAULT_USD}
12540
+ }) {
12541
+ items {
12542
+ address
12543
+ state {
12544
+ allocation {
12545
+ supplyAssetsUsd
12546
+ market { marketId listed collateralAsset { address } }
12547
+ }
12548
+ }
12549
+ }
12550
+ }
12551
+ }
12552
+ `;
12553
+ var V2_VAULT_CAPS_QUERY = (first, skip, chainId) => `
12554
+ query VaultFundedV2 {
12555
+ vaultV2s(first: ${first}, skip: ${skip}, where: {
12556
+ chainId_in: [${chainId}],
12557
+ totalAssetsUsd_gte: ${MORPHO_VAULT_FUNDED_MIN_VAULT_USD}
12558
+ }) {
12559
+ items {
12560
+ address
12561
+ totalAssets
12562
+ totalAssetsUsd
12563
+ asset { decimals price { usd } }
12564
+ caps {
12565
+ items {
12566
+ type
12567
+ allocation
12568
+ data {
12569
+ __typename
12570
+ ... on MarketV1CapData {
12571
+ market { marketId listed collateralAsset { address } }
12572
+ }
12573
+ }
12574
+ }
12575
+ }
12576
+ }
12577
+ }
12578
+ }
12579
+ `;
12580
+ var ZERO = "0x0000000000000000000000000000000000000000";
12581
+ var isUnlistedLendable = (m) => {
12582
+ if (m?.listed !== false) return false;
12583
+ const coll = m.collateralAsset?.address?.toLowerCase();
12584
+ return !!coll && coll !== ZERO;
12585
+ };
12586
+ function sumVaultFundedUnlisted(v1Vaults, v2Vaults, minUsd = MORPHO_VAULT_FUNDED_MIN_USD) {
12587
+ const byMarket = /* @__PURE__ */ new Map();
12588
+ const add = (marketId, usd) => {
12589
+ if (!marketId || usd == null || !Number.isFinite(usd) || usd <= 0) return;
12590
+ const k = marketId.toLowerCase();
12591
+ byMarket.set(k, (byMarket.get(k) ?? 0) + usd);
12592
+ };
12593
+ for (const v of v1Vaults) {
12594
+ for (const a of v?.state?.allocation ?? []) {
12595
+ if (!isUnlistedLendable(a?.market)) continue;
12596
+ add(a.market.marketId, typeof a.supplyAssetsUsd === "number" ? a.supplyAssetsUsd : null);
12597
+ }
12598
+ }
12599
+ for (const v of v2Vaults) {
12600
+ const decimals = typeof v?.asset?.decimals === "number" ? v.asset.decimals : null;
12601
+ let price2 = typeof v?.asset?.price?.usd === "number" ? v.asset.price.usd : null;
12602
+ const total = Number(v?.totalAssets ?? 0);
12603
+ if (price2 == null && decimals != null && total > 0 && typeof v?.totalAssetsUsd === "number")
12604
+ price2 = v.totalAssetsUsd / (total / 10 ** decimals);
12605
+ for (const c of v?.caps?.items ?? []) {
12606
+ if (c?.type !== "MarketV1") continue;
12607
+ const m = c.data?.market;
12608
+ if (!isUnlistedLendable(m)) continue;
12609
+ const raw = Number(c.allocation ?? 0);
12610
+ add(m.marketId, price2 != null && decimals != null ? raw / 10 ** decimals * price2 : null);
12611
+ }
12612
+ }
12613
+ return [...byMarket].filter(([, usd]) => usd >= minUsd).map(([marketId, vaultUsd]) => ({ marketId, vaultUsd })).sort((a, b) => b.vaultUsd - a.vaultUsd || a.marketId.localeCompare(b.marketId));
12614
+ }
12615
+ async function post(query3) {
12616
+ const res = await fetch(BASE_URL, {
12617
+ method: "POST",
12618
+ headers: { "Content-Type": "application/json" },
12619
+ body: JSON.stringify({ query: query3 })
12620
+ });
12621
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
12622
+ const json = await res.json();
12623
+ if (json?.errors?.length)
12624
+ throw new Error(json.errors.map((e) => e?.message).join("; "));
12625
+ return json.data;
12626
+ }
12627
+ async function pageAll(build6, field13, pageSize) {
12628
+ const out = [];
12629
+ for (let page = 0; page < MAX_PAGES; page++) {
12630
+ const items = (await post(build6(pageSize, page * pageSize)))?.[field13]?.items;
12631
+ if (!Array.isArray(items)) throw new Error(`unexpected ${field13} shape`);
12632
+ out.push(...items);
12633
+ if (items.length < pageSize) return out;
12634
+ }
12635
+ console.warn(`[morpho-vault-funded] ${field13}: hit MAX_PAGES, result truncated`);
12636
+ return out;
12637
+ }
12638
+ async function discover(chainId) {
12639
+ const [v1, v2] = await Promise.all([
12640
+ pageAll((f, s) => V1_VAULT_ALLOCATIONS_QUERY(f, s, chainId), "vaults", V1_PAGE),
12641
+ pageAll((f, s) => V2_VAULT_CAPS_QUERY(f, s, chainId), "vaultV2s", V2_PAGE)
12642
+ ]);
12643
+ return sumVaultFundedUnlisted(v1, v2);
12644
+ }
12645
+ var cache = /* @__PURE__ */ new Map();
12646
+ function morphoVaultFundedUnlistedMarkets(chainId) {
12647
+ if (morphoIncludesUnlisted(chainId)) return Promise.resolve([]);
12648
+ const now = Date.now();
12649
+ const hit = cache.get(chainId);
12650
+ if (hit && now - hit.at < hit.ttl) return hit.promise;
12651
+ const entry = { at: now, ttl: CACHE_TTL_MS, promise: Promise.resolve([]) };
12652
+ entry.promise = discover(chainId).catch((e) => {
12653
+ entry.ttl = FAIL_TTL_MS;
12654
+ console.warn(
12655
+ `[morpho-vault-funded] chain ${chainId}: discovery failed, serving listed markets only:`,
12656
+ e?.message ?? e
12657
+ );
12658
+ return [];
12659
+ });
12660
+ cache.set(chainId, entry);
12661
+ return entry.promise;
12662
+ }
12663
+ async function morphoVaultFundedUnlistedMarketIds(chainId) {
12664
+ return (await morphoVaultFundedUnlistedMarkets(chainId)).map((m) => m.marketId);
12665
+ }
12666
+ var uniqueKeyInFilter = (keys) => `uniqueKey_in: [${keys.map((k) => JSON.stringify(k.toLowerCase())).join(", ")}]`;
12667
+ function mergeMarketItemsByKey(base, extra) {
12668
+ const have = new Set(base.map((m) => m?.uniqueKey?.toLowerCase()));
12669
+ const out = [...base];
12670
+ for (const m of extra) {
12671
+ const k = m?.uniqueKey?.toLowerCase();
12672
+ if (!k || have.has(k)) continue;
12673
+ have.add(k);
12674
+ out.push(m);
12675
+ }
12676
+ return out;
12677
+ }
12678
+ var BY_KEY_CHUNK = 100;
12679
+ async function appendVaultFundedMarkets(chainId, base, buildByKeys) {
12680
+ const ids = await morphoVaultFundedUnlistedMarketIds(chainId);
12681
+ if (ids.length === 0) return base;
12682
+ const have = new Set(base.map((m) => m?.uniqueKey?.toLowerCase()));
12683
+ const missing = ids.filter((id) => !have.has(id));
12684
+ if (missing.length === 0) return base;
12685
+ try {
12686
+ const extra = [];
12687
+ for (let i = 0; i < missing.length; i += BY_KEY_CHUNK) {
12688
+ const items = (await post(buildByKeys(missing.slice(i, i + BY_KEY_CHUNK))))?.markets?.items;
12689
+ if (!Array.isArray(items)) throw new Error("unexpected markets shape");
12690
+ extra.push(...items);
12691
+ }
12692
+ return mergeMarketItemsByKey(base, extra);
12693
+ } catch (e) {
12694
+ console.warn(
12695
+ `[morpho-vault-funded] chain ${chainId}: by-key fetch of ${missing.length} markets failed:`,
12696
+ e?.message ?? e
12697
+ );
12698
+ return base;
12699
+ }
12700
+ }
12701
+
12702
+ // src/lending/public-data/morpho/apiFields.ts
12703
+ function normalizeMorphoApiMarket(item) {
12704
+ if (!item || typeof item !== "object") return item;
12705
+ const out = { ...item };
12706
+ if ("oracle" in out) {
12707
+ out.oracleAddress = out.oracle?.address ?? void 0;
12708
+ delete out.oracle;
12709
+ }
12710
+ for (const side of ["loanAsset", "collateralAsset"]) {
12711
+ const a = out[side];
12712
+ if (a && typeof a === "object" && "price" in a) {
12713
+ const { price: price2, ...rest } = a;
12714
+ out[side] = { ...rest, priceUsd: price2?.usd ?? null };
12715
+ }
12716
+ }
12717
+ return out;
12718
+ }
12719
+ function normalizeMorphoApiMarkets(items) {
12720
+ return items.map(normalizeMorphoApiMarket);
12721
+ }
12722
+
12723
+ // src/lending/public-data/morpho/fetchPublic.ts
12724
+ var query = (first, skip, chainId, includeUnlisted = false, uniqueKeys) => `
12494
12725
  query GetMarkets {
12495
12726
  markets(first: ${first}, skip: ${skip}, where: {
12496
- chainId_in: [${chainId}]${includeUnlisted ? "" : ",\n listed: true"}
12727
+ chainId_in: [${chainId}]${uniqueKeys ? `,
12728
+ ${uniqueKeyInFilter(uniqueKeys)}` : includeUnlisted ? "" : ",\n listed: true"}
12497
12729
  },
12498
- orderBy: SupplyAssetsUsd,
12730
+ orderBy: ${uniqueKeys ? "UniqueKey" : "SupplyAssetsUsd"},
12499
12731
  orderDirection: Desc
12500
12732
  ) {
12501
12733
  items {
12502
12734
  uniqueKey: marketId
12503
12735
  irmAddress
12504
- oracleAddress
12736
+ oracle {
12737
+ address
12738
+ }
12505
12739
  lltv
12506
12740
  whitelisted: listed
12507
12741
  loanAsset {
@@ -12509,14 +12743,18 @@ query GetMarkets {
12509
12743
  name
12510
12744
  symbol
12511
12745
  decimals
12512
- priceUsd
12746
+ price {
12747
+ usd
12748
+ }
12513
12749
  }
12514
12750
  collateralAsset {
12515
12751
  address
12516
12752
  name
12517
12753
  symbol
12518
12754
  decimals
12519
- priceUsd
12755
+ price {
12756
+ usd
12757
+ }
12520
12758
  }
12521
12759
  state {
12522
12760
  borrowApy
@@ -12544,7 +12782,7 @@ query GetMarkets {
12544
12782
  }
12545
12783
  }
12546
12784
  `;
12547
- var BASE_URL = "https://blue-api.morpho.org/graphql";
12785
+ var BASE_URL2 = "https://blue-api.morpho.org/graphql";
12548
12786
  function assertNoGraphQLErrors(json) {
12549
12787
  if (json?.errors?.length) {
12550
12788
  throw new Error(
@@ -12553,12 +12791,25 @@ function assertNoGraphQLErrors(json) {
12553
12791
  }
12554
12792
  }
12555
12793
  async function fetchMorphoMarkets(chainId, includeUnlisted = false) {
12794
+ const data = await fetchMorphoMarketsBase(chainId, includeUnlisted);
12795
+ if (!Array.isArray(data?.markets?.items)) return data;
12796
+ const items = includeUnlisted ? data.markets.items : await appendVaultFundedMarkets(
12797
+ chainId,
12798
+ data.markets.items,
12799
+ (keys) => query(keys.length, 0, chainId, false, keys)
12800
+ );
12801
+ return {
12802
+ ...data,
12803
+ markets: { ...data.markets, items: normalizeMorphoApiMarkets(items) }
12804
+ };
12805
+ }
12806
+ async function fetchMorphoMarketsBase(chainId, includeUnlisted) {
12556
12807
  if (chainId !== Chain.ETHEREUM_MAINNET) {
12557
12808
  const requestBody = {
12558
12809
  query: query(200, 0, chainId, includeUnlisted),
12559
12810
  variables: {}
12560
12811
  };
12561
- const response = await fetch(BASE_URL, {
12812
+ const response = await fetch(BASE_URL2, {
12562
12813
  method: "POST",
12563
12814
  headers: {
12564
12815
  "Content-Type": "application/json"
@@ -12583,14 +12834,14 @@ async function fetchMorphoMarkets(chainId, includeUnlisted = false) {
12583
12834
  variables: {}
12584
12835
  };
12585
12836
  const [data0, data1] = await Promise.all([
12586
- fetch(BASE_URL, {
12837
+ fetch(BASE_URL2, {
12587
12838
  method: "POST",
12588
12839
  headers: {
12589
12840
  "Content-Type": "application/json"
12590
12841
  },
12591
12842
  body: JSON.stringify(requestBody0)
12592
12843
  }).then((x) => x.json()),
12593
- fetch(BASE_URL, {
12844
+ fetch(BASE_URL2, {
12594
12845
  method: "POST",
12595
12846
  headers: {
12596
12847
  "Content-Type": "application/json"
@@ -13603,7 +13854,6 @@ var MARKET_LENS = {
13603
13854
  [Chain.AVALANCHE_C_CHAIN]: COMPOUND_V2_MARKET_LENS,
13604
13855
  [Chain.INK]: COMPOUND_V2_MARKET_LENS,
13605
13856
  [Chain.LINEA]: COMPOUND_V2_MARKET_LENS,
13606
- [Chain.BLAST]: COMPOUND_V2_MARKET_LENS,
13607
13857
  [Chain.MANTA_PACIFIC_MAINNET]: COMPOUND_V2_MARKET_LENS,
13608
13858
  /**
13609
13859
  * zkSync Era is the one chain where the address differs. zk-stack chains
@@ -20181,7 +20431,7 @@ var FLUID_API_BASE = "https://api.fluid.instadapp.io/v2";
20181
20431
  var SUPPORTED_CHAINS = /* @__PURE__ */ new Set(["1", "56", "137", "8453", "9745", "42161"]);
20182
20432
  var TTL_MS2 = 6e4;
20183
20433
  var ZERO_ADDRESS4 = "0x0000000000000000000000000000000000000000";
20184
- var cache = {};
20434
+ var cache2 = {};
20185
20435
  var inflight = /* @__PURE__ */ new Map();
20186
20436
  var isRealDex = (d) => !!d && String(d.id ?? "0") !== "0" && String(d.address ?? ZERO_ADDRESS4).toLowerCase() !== ZERO_ADDRESS4;
20187
20437
  var toBigInt7 = (v) => {
@@ -20226,7 +20476,7 @@ var parseChainPayload = (raw) => {
20226
20476
  };
20227
20477
  var fetchFluidApiData = async (chainId) => {
20228
20478
  if (!SUPPORTED_CHAINS.has(chainId)) return void 0;
20229
- const hit = cache[chainId];
20479
+ const hit = cache2[chainId];
20230
20480
  if (hit && Date.now() - hit.at < TTL_MS2) return hit.data;
20231
20481
  const pending = inflight.get(chainId);
20232
20482
  if (pending) return pending;
@@ -20237,11 +20487,11 @@ var fetchFluidApiData = async (chainId) => {
20237
20487
  const json = await res.json();
20238
20488
  if (!Array.isArray(json)) throw new Error("unexpected payload");
20239
20489
  const data = parseChainPayload(json);
20240
- cache[chainId] = { at: Date.now(), data };
20490
+ cache2[chainId] = { at: Date.now(), data };
20241
20491
  return data;
20242
20492
  } catch {
20243
- const prev = cache[chainId]?.data;
20244
- cache[chainId] = { at: Date.now(), data: prev };
20493
+ const prev = cache2[chainId]?.data;
20494
+ cache2[chainId] = { at: Date.now(), data: prev };
20245
20495
  return prev;
20246
20496
  } finally {
20247
20497
  inflight.delete(chainId);
@@ -20250,7 +20500,7 @@ var fetchFluidApiData = async (chainId) => {
20250
20500
  inflight.set(chainId, run);
20251
20501
  return run;
20252
20502
  };
20253
- var getCachedFluidApiData = (chainId) => cache[chainId]?.data;
20503
+ var getCachedFluidApiData = (chainId) => cache2[chainId]?.data;
20254
20504
  var DEX_RESOLVER_FALLBACK = {
20255
20505
  "1": "0x11D80CfF056Cef4F9E6d23da8672fE9873e5cC07",
20256
20506
  "137": "0x11D80CfF056Cef4F9E6d23da8672fE9873e5cC07",
@@ -20262,12 +20512,12 @@ var DEX_RESOLVER_FALLBACK = {
20262
20512
  var dexResolverFor = (chainId) => fluidResolvers()?.[chainId]?.dexResolver ?? DEX_RESOLVER_FALLBACK[chainId];
20263
20513
  var ZERO_ADDRESS5 = "0x0000000000000000000000000000000000000000";
20264
20514
  var TTL_MS3 = 6e4;
20265
- var cache2 = {};
20515
+ var cache3 = {};
20266
20516
  var inflight2 = /* @__PURE__ */ new Map();
20267
20517
  var fetchFluidDexState = async (chainId, multicallRetry, extraDexAddresses = []) => {
20268
20518
  const resolver = dexResolverFor(chainId);
20269
20519
  if (!resolver) return void 0;
20270
- const hit = cache2[chainId];
20520
+ const hit = cache3[chainId];
20271
20521
  if (hit && Date.now() - hit.at < TTL_MS3) return hit.data;
20272
20522
  const pending = inflight2.get(chainId);
20273
20523
  if (pending) return pending;
@@ -20307,11 +20557,11 @@ var fetchFluidDexState = async (chainId, multicallRetry, extraDexAddresses = [])
20307
20557
  totalBorrowShares: BigInt(s.totalBorrowShares ?? 0)
20308
20558
  };
20309
20559
  }
20310
- cache2[chainId] = { at: Date.now(), data };
20560
+ cache3[chainId] = { at: Date.now(), data };
20311
20561
  return data;
20312
20562
  } catch {
20313
- const prev = cache2[chainId]?.data;
20314
- cache2[chainId] = { at: Date.now(), data: prev };
20563
+ const prev = cache3[chainId]?.data;
20564
+ cache3[chainId] = { at: Date.now(), data: prev };
20315
20565
  return prev;
20316
20566
  } finally {
20317
20567
  inflight2.delete(chainId);
@@ -20320,7 +20570,7 @@ var fetchFluidDexState = async (chainId, multicallRetry, extraDexAddresses = [])
20320
20570
  inflight2.set(chainId, run);
20321
20571
  return run;
20322
20572
  };
20323
- var getCachedFluidDexState = (chainId) => cache2[chainId]?.data;
20573
+ var getCachedFluidDexState = (chainId) => cache3[chainId]?.data;
20324
20574
 
20325
20575
  // src/lending/public-data/fluid/publicCallParse.ts
20326
20576
  var FLUID_EEE_LOWER = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
@@ -25517,7 +25767,7 @@ var LLAMALEND_READ_ABI = [
25517
25767
  ...LlamaLendAmmAbi,
25518
25768
  ...Erc20Abi
25519
25769
  ];
25520
- var ZERO = "0x0000000000000000000000000000000000000000";
25770
+ var ZERO2 = "0x0000000000000000000000000000000000000000";
25521
25771
  var WAD8 = 10n ** 18n;
25522
25772
  var CALLS_PER_MARKET = 6;
25523
25773
  var fetchJson2 = async (url, timeoutMs = 8e3) => {
@@ -25566,7 +25816,7 @@ async function fetchChainExtras(chainId, markets) {
25566
25816
  { address: m.amm, name: "price_oracle", params: [] },
25567
25817
  { address: m.amm, name: "active_band", params: [] },
25568
25818
  { address: m.controller, name: "n_loans", params: [] },
25569
- { address: m.vault, name: "maxDeposit", params: [ZERO] },
25819
+ { address: m.vault, name: "maxDeposit", params: [ZERO2] },
25570
25820
  // v1 controllers have no `borrow_cap`; allowFailure turns that into a
25571
25821
  // null rather than sinking the whole batch.
25572
25822
  { address: m.controller, name: "borrow_cap", params: [] },
@@ -29339,7 +29589,7 @@ function convertFrankencoinMarketsToResponse(raw, chainId, prices = {}, _additio
29339
29589
  }
29340
29590
 
29341
29591
  // src/lending/public-data/silo-v2/fetchPublic.ts
29342
- var BASE_URL2 = "https://api-v3.silo.finance";
29592
+ var BASE_URL3 = "https://api-v3.silo.finance";
29343
29593
  var SILO_API_SUPPORTED_CHAIN_IDS = /* @__PURE__ */ new Set([
29344
29594
  "1",
29345
29595
  // Ethereum
@@ -29482,7 +29732,7 @@ query GetSilosLite {
29482
29732
  async function fetchSiloMarketsLite(chainId, options) {
29483
29733
  if (!SILO_API_SUPPORTED_CHAIN_IDS.has(chainId)) return [];
29484
29734
  const limit = options?.limit ?? 500;
29485
- const response = await fetch(BASE_URL2, {
29735
+ const response = await fetch(BASE_URL3, {
29486
29736
  method: "POST",
29487
29737
  headers: { "Content-Type": "application/json" },
29488
29738
  body: JSON.stringify({ query: liteQuery(chainId, limit) })
@@ -29507,7 +29757,7 @@ async function fetchSiloMarketsLite(chainId, options) {
29507
29757
  async function fetchSiloMarkets(chainId, options) {
29508
29758
  if (!SILO_API_SUPPORTED_CHAIN_IDS.has(chainId)) return [];
29509
29759
  const limit = options?.limit ?? 500;
29510
- const response = await fetch(BASE_URL2, {
29760
+ const response = await fetch(BASE_URL3, {
29511
29761
  method: "POST",
29512
29762
  headers: { "Content-Type": "application/json" },
29513
29763
  body: JSON.stringify({ query: query2(chainId, limit) })
@@ -30288,39 +30538,6 @@ var getLenderPublicDataViaApi = async (chainId, lenders, prices, additionalYield
30288
30538
  }
30289
30539
  return lenderData;
30290
30540
  };
30291
-
30292
- // src/lending/public-data/morpho/unlisted.ts
30293
- var MORPHO_UNLISTED_CHAINS = /* @__PURE__ */ new Set([
30294
- // Robinhood Chain. 189 of its 194 markets are unlisted and essentially all of
30295
- // them are Longbow — a curated Morpho Blue deployment (tokenized equities and
30296
- // RWAs against USDG) that Morpho's own frontend does not carry, so `listed`
30297
- // here says nothing about the market's quality. Enabled 2026-09-08 together
30298
- // with the three things a chain needs before it can be:
30299
- // 1. its collateral tokens in `token-lists` (wsNET was the last gap — the
30300
- // collateral of the chain's LARGEST market), or the rows price at $0,
30301
- // 2. `lender-metadata`'s `SERVES_UNLISTED_CHAINS` carrying the same chain
30302
- // id, so the markets get a NAME and an oracle roster (5 -> 188 rows),
30303
- // 3. a look at what the unlisted book actually holds — here 56 real
30304
- // markets, $524k supplied / $351k borrowed, no runaway rates (the
30305
- // highest borrow APR on the chain is 21.9 %).
30306
- // See LONGBOW.md.
30307
- "4663",
30308
- // World Chain. blue-api indexes it, but 0 of its 30 markets are listed —
30309
- // Morpho's frontend simply does not carry the chain, so `listed` says
30310
- // nothing about the book (the Longbow shape again). Looked at 2026-09-16:
30311
- // $59.5M supplied / $45.0M borrowed, of which the real two-sided markets are
30312
- // USDC/WBTC $3.9M, USDC/WETH $3.6M, WETH/WBTC $2.1M, USDC/WLD $1.6M and
30313
- // WETH/ezETH $1.1M at 0.1–4.6 % borrow APY; the $35.8M USDC/sdeUSD market is
30314
- // pinned at 100 % utilization (297,994 % APY, $0 liquid) and is exactly what
30315
- // `earn/rateSanity.ts` exists to drop. Token-list gaps on 480 at enablement:
30316
- // sdeUSD and ezETH (collateral of two markets) — those rows price at $0 with
30317
- // a blank LTV until token-lists carries them. `lender-metadata`'s
30318
- // `SERVES_UNLISTED_CHAINS` was updated in the same change.
30319
- "480"
30320
- ]);
30321
- function morphoIncludesUnlisted(chainId) {
30322
- return MORPHO_UNLISTED_CHAINS.has(chainId);
30323
- }
30324
30541
  var ERC20_BALANCE_OF_ABI2 = [
30325
30542
  {
30326
30543
  inputs: [{ name: "account", type: "address" }],
@@ -30943,7 +31160,7 @@ function decodeVariableLensRows(blob, fixedWords, headerBytes = 0) {
30943
31160
  }
30944
31161
 
30945
31162
  // src/lending/user-data/aave-v3-type/lens.ts
30946
- var ZERO2 = "0x0000000000000000000000000000000000000000";
31163
+ var ZERO3 = "0x0000000000000000000000000000000000000000";
30947
31164
  var AAVE_LENS_HEADER_BYTES = 3;
30948
31165
  var HEADER_EMODE_OK = 1;
30949
31166
  var HEADER_CONFIG_OK = 2;
@@ -30951,7 +31168,7 @@ var AAVE_LENS_WORDS = 7;
30951
31168
  var reserveTuple = (tokens, asset) => {
30952
31169
  const t = tokens?.[asset.toLowerCase()];
30953
31170
  if (!t?.aToken || !t?.vToken) return void 0;
30954
- return [asset, t.aToken, t.vToken, t.sToken ?? ZERO2];
31171
+ return [asset, t.aToken, t.vToken, t.sToken ?? ZERO3];
30955
31172
  };
30956
31173
  var usesAaveLens = (chainId, lender) => {
30957
31174
  if (getPositionLensFor(chainId, LENS_FAMILY.AAVE) === void 0) return false;
@@ -30981,7 +31198,7 @@ var buildAaveLensCall = (chainId, lender, account, assetsToQuery, withEMode) =>
30981
31198
  getAaveTypePoolDataProviderAddress(chainId, lender),
30982
31199
  // A zero pool disables the e-mode read, which is exactly what YLDR wants:
30983
31200
  // it has no `getUserEMode` and the walk omits that call for it too.
30984
- withEMode ? getAaveTypePoolAddress(chainId, lender) : ZERO2
31201
+ withEMode ? getAaveTypePoolAddress(chainId, lender) : ZERO3
30985
31202
  ]
30986
31203
  );
30987
31204
  return [
@@ -32061,7 +32278,7 @@ var buildExactlyUserCall = (chainId, _lender, account) => {
32061
32278
  return [{ address: cfg.previewer, name: "exactly", params: [account] }];
32062
32279
  };
32063
32280
  var OWNER_INDEX_PROBE_COUNT = 8;
32064
- var CACHE_TTL_MS = 5 * 6e4;
32281
+ var CACHE_TTL_MS2 = 5 * 6e4;
32065
32282
  var discoveryCache = /* @__PURE__ */ new Map();
32066
32283
  async function discoverViaLens(chainId, branches, zappers, account, opts) {
32067
32284
  const lens = getPositionLensFor(chainId, LENS_FAMILY.LIQUITY);
@@ -32130,7 +32347,7 @@ var getCachedLiquityTroves = (chainId, lender, account, opts) => {
32130
32347
  const hit = discoveryCache.get(
32131
32348
  cacheKey(chainId, lender, account, blockKey(opts))
32132
32349
  );
32133
- if (!hit || Date.now() - hit.at > CACHE_TTL_MS) return void 0;
32350
+ if (!hit || Date.now() - hit.at > CACHE_TTL_MS2) return void 0;
32134
32351
  return hit;
32135
32352
  };
32136
32353
  var ADDRESS_ADDRESS_UINT = [
@@ -32350,7 +32567,7 @@ var buildRiverUserCall = (chainId, lender, account) => {
32350
32567
  });
32351
32568
  return calls;
32352
32569
  };
32353
- var ZERO3 = "0x0000000000000000000000000000000000000000";
32570
+ var ZERO4 = "0x0000000000000000000000000000000000000000";
32354
32571
  var LLAMALEND_LENS_WORDS = 12;
32355
32572
  var LLAMALEND_CALLS_PER_MARKET = 8;
32356
32573
  var usesLlamaLendLens = (chainId) => getPositionLensFor(chainId, LENS_FAMILY.LLAMALEND) !== void 0;
@@ -32364,7 +32581,7 @@ var buildLlamaLendLensCall = (chainId, markets, account, delegate) => {
32364
32581
  m.controller,
32365
32582
  m.amm,
32366
32583
  m.vault,
32367
- m.gauge ?? ZERO3
32584
+ m.gauge ?? ZERO4
32368
32585
  ]),
32369
32586
  delegate
32370
32587
  ]
@@ -32913,7 +33130,7 @@ function getCachedTwyneDiscovery(chainId, lender, account, opts) {
32913
33130
  }
32914
33131
  var lower2 = (a) => String(a).toLowerCase();
32915
33132
  var isAddress4 = (v) => typeof v === "string" && /^0x[0-9a-fA-F]{40}$/.test(v);
32916
- async function discover(chainId, lender, account, opts) {
33133
+ async function discover2(chainId, lender, account, opts) {
32917
33134
  const key3 = discoveryKey3(chainId, lender, account, blockKey(opts));
32918
33135
  const cached = discoveryCache4.get(key3);
32919
33136
  if (cached && Date.now() - cached.at < DISCOVERY_TTL_MS3) return cached;
@@ -33015,7 +33232,7 @@ async function discover(chainId, lender, account, opts) {
33015
33232
  return result;
33016
33233
  }
33017
33234
  async function buildTwyneUserCall(chainId, lender, account, opts) {
33018
- const { vaults } = await discover(chainId, lender, account, opts);
33235
+ const { vaults } = await discover2(chainId, lender, account, opts);
33019
33236
  if (vaults.length === 0) return [];
33020
33237
  return vaults.flatMap(({ vault }) => [
33021
33238
  { address: vault, name: "totalAssetsDepositedOrReserved", args: [] },
@@ -33029,14 +33246,14 @@ async function buildTwyneUserCall(chainId, lender, account, opts) {
33029
33246
  }
33030
33247
  var DSS_CALLS_PER_CDP = 1;
33031
33248
  var MAX_CDP_WALK = 64;
33032
- var CACHE_TTL_MS2 = 5 * 6e4;
33249
+ var CACHE_TTL_MS3 = 5 * 6e4;
33033
33250
  var discoveryCache5 = /* @__PURE__ */ new Map();
33034
33251
  var cacheKey2 = (lender, chainId, account, block = "head") => `${lender}:${chainId}:${account.toLowerCase()}:${block}`;
33035
33252
  var getCachedDssCdps = (lender, chainId, account, opts) => {
33036
33253
  const hit = discoveryCache5.get(
33037
33254
  cacheKey2(lender, chainId, account, blockKey(opts))
33038
33255
  );
33039
- if (!hit || Date.now() - hit.at > CACHE_TTL_MS2) return void 0;
33256
+ if (!hit || Date.now() - hit.at > CACHE_TTL_MS3) return void 0;
33040
33257
  return hit;
33041
33258
  };
33042
33259
  var big7 = (v) => {
@@ -33279,12 +33496,12 @@ async function discoverTellerBidsViaLens(chainId, tellerV2, account, opts) {
33279
33496
 
33280
33497
  // src/lending/user-data/teller/userCallBuild.ts
33281
33498
  var TELLER_CALLS_PER_BID = 4;
33282
- var CACHE_TTL_MS3 = 5 * 6e4;
33499
+ var CACHE_TTL_MS4 = 5 * 6e4;
33283
33500
  var discoveryCache7 = /* @__PURE__ */ new Map();
33284
33501
  var cacheKey4 = (chainId, account, block = "head") => `${chainId}:${account.toLowerCase()}:${block}`;
33285
33502
  var getCachedTellerBids = (chainId, account, opts) => {
33286
33503
  const hit = discoveryCache7.get(cacheKey4(chainId, account, blockKey(opts)));
33287
- if (!hit || Date.now() - hit.at > CACHE_TTL_MS3) return void 0;
33504
+ if (!hit || Date.now() - hit.at > CACHE_TTL_MS4) return void 0;
33288
33505
  return hit;
33289
33506
  };
33290
33507
  var nowSec5 = () => Math.floor(Date.now() / 1e3);
@@ -33421,12 +33638,12 @@ var buildFlyingTulipUserCall = (chainId, lender, account) => {
33421
33638
  ];
33422
33639
  };
33423
33640
  var TERMMAX_MARKETS_PER_CALL = 180;
33424
- var CACHE_TTL_MS4 = 5 * 6e4;
33641
+ var CACHE_TTL_MS5 = 5 * 6e4;
33425
33642
  var discoveryCache8 = /* @__PURE__ */ new Map();
33426
33643
  var cacheKey5 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
33427
33644
  var getCachedTermMaxDiscovery = (chainId, account) => {
33428
33645
  const hit = discoveryCache8.get(cacheKey5(chainId, account));
33429
- if (!hit || Date.now() - hit.at > CACHE_TTL_MS4) return void 0;
33646
+ if (!hit || Date.now() - hit.at > CACHE_TTL_MS5) return void 0;
33430
33647
  return hit;
33431
33648
  };
33432
33649
  var buildTermMaxUserCall = async (chainId, _lender, account) => {
@@ -43694,7 +43911,6 @@ var MORPHO_API_CHAIN_IDS = {
43694
43911
  [Chain.POLYGON_MAINNET]: 137,
43695
43912
  [Chain.GNOSIS]: 100,
43696
43913
  [Chain.FRAXTAL]: 252,
43697
- [Chain.BLAST]: 81457,
43698
43914
  [Chain.LINEA]: 59144,
43699
43915
  [Chain.TAIKO_ALETHIA]: 167e3,
43700
43916
  [Chain.AVALANCHE_C_CHAIN]: 43114,
@@ -43706,7 +43922,7 @@ var MORPHO_API_CHAIN_IDS = {
43706
43922
  [Chain.UNICHAIN]: 130
43707
43923
  };
43708
43924
  var FETCH_TIMEOUT_MS = 3e3;
43709
- var CACHE_TTL_MS5 = 2e3;
43925
+ var CACHE_TTL_MS6 = 2e3;
43710
43926
  var buildSubgraphQuery = (account) => `
43711
43927
  {
43712
43928
  account(id: "${account.toLowerCase()}") {
@@ -43774,7 +43990,7 @@ async function dedupedFetch(chainId, account, loader) {
43774
43990
  const existing = inflight3.get(key3);
43775
43991
  if (existing) return existing;
43776
43992
  const promise = loader().then((value) => {
43777
- resolved.set(key3, { value, expiresAt: Date.now() + CACHE_TTL_MS5 });
43993
+ resolved.set(key3, { value, expiresAt: Date.now() + CACHE_TTL_MS6 });
43778
43994
  return value;
43779
43995
  }).finally(() => {
43780
43996
  inflight3.delete(key3);
@@ -56751,7 +56967,7 @@ var dtrinityRebateRewardFetcher = {
56751
56967
  };
56752
56968
  var SECONDS_PER_YEAR15 = 31536e3;
56753
56969
  var WAD16 = 10n ** 18n;
56754
- var ZERO4 = "0x0000000000000000000000000000000000000000";
56970
+ var ZERO5 = "0x0000000000000000000000000000000000000000";
56755
56971
  var UNBOOSTED_FACTOR = 0.4;
56756
56972
  var MAX_BOOST = 2.5;
56757
56973
  var GAUGE_CONTROLLER = "0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB";
@@ -56947,7 +57163,7 @@ async function fetchPrices(keys) {
56947
57163
  var priceOf = (prices, chainId, address) => prices[`${LLAMA_CHAIN_SLUG[chainId]}:${address.toLowerCase()}`] ?? 0;
56948
57164
  function rosterFor(chainId) {
56949
57165
  const markets = llamaLendChainData(Lender.LLAMALEND, chainId)?.markets ?? [];
56950
- return markets.filter((m) => m.gauge && m.gauge !== ZERO4).map((m) => ({
57166
+ return markets.filter((m) => m.gauge && m.gauge !== ZERO5).map((m) => ({
56951
57167
  controller: m.controller,
56952
57168
  vault: m.vault,
56953
57169
  gauge: m.gauge,
@@ -57024,7 +57240,7 @@ async function fetchForChain(chainId, nowSeconds) {
57024
57240
  }) : [];
57025
57241
  let cursor = 0;
57026
57242
  const withTokens = state.map((s) => {
57027
- const tokens = r2.slice(cursor, cursor + s.rewardCount).filter((t) => typeof t === "string" && t !== ZERO4);
57243
+ const tokens = r2.slice(cursor, cursor + s.rewardCount).filter((t) => typeof t === "string" && t !== ZERO5);
57028
57244
  cursor += s.rewardCount;
57029
57245
  return { ...s, tokens };
57030
57246
  });
@@ -57619,26 +57835,32 @@ function getMorphoAbi() {
57619
57835
  var MORPHO_GRAPHQL_URL = "https://blue-api.morpho.org/graphql";
57620
57836
  var MAX_UNLISTED_PRICE_PAGES = 10;
57621
57837
  var PRICE_PAGE_SIZE = 200;
57622
- var PRICE_QUERY = (first, skip, chainId, includeUnlisted) => `
57838
+ var PRICE_QUERY = (first, skip, chainId, includeUnlisted, uniqueKeys) => `
57623
57839
  query GetMarketPrices {
57624
57840
  markets(first: ${first}, skip: ${skip}, where: {
57625
- chainId_in: [${chainId}]${!includeUnlisted && chainId != Chain.ETHEREUM_MAINNET ? `,listed: true` : ""}
57841
+ chainId_in: [${chainId}]${uniqueKeys ? `,${uniqueKeyInFilter(uniqueKeys)}` : !includeUnlisted && chainId != Chain.ETHEREUM_MAINNET ? `,listed: true` : ""}
57626
57842
  },
57627
- orderBy: SupplyAssetsUsd,
57843
+ orderBy: ${uniqueKeys ? "UniqueKey" : "SupplyAssetsUsd"},
57628
57844
  orderDirection: Desc
57629
57845
  ) {
57630
57846
  items {
57631
57847
  uniqueKey: marketId
57632
- oracleAddress
57848
+ oracle {
57849
+ address
57850
+ }
57633
57851
  loanAsset {
57634
57852
  address
57635
57853
  decimals
57636
- priceUsd
57854
+ price {
57855
+ usd
57856
+ }
57637
57857
  }
57638
57858
  collateralAsset {
57639
57859
  address
57640
57860
  decimals
57641
- priceUsd
57861
+ price {
57862
+ usd
57863
+ }
57642
57864
  }
57643
57865
  state {
57644
57866
  price
@@ -57649,7 +57871,7 @@ query GetMarketPrices {
57649
57871
  `;
57650
57872
  async function fetchMorphoGraphQLPrices(chainId, includeUnlisted = false) {
57651
57873
  if (!morphoApiAvailable(chainId)) return null;
57652
- const post = (skip) => fetch(MORPHO_GRAPHQL_URL, {
57874
+ const post2 = (skip) => fetch(MORPHO_GRAPHQL_URL, {
57653
57875
  method: "POST",
57654
57876
  headers: { "Content-Type": "application/json" },
57655
57877
  body: JSON.stringify({
@@ -57670,7 +57892,7 @@ async function fetchMorphoGraphQLPrices(chainId, includeUnlisted = false) {
57670
57892
  const allMarkets = [];
57671
57893
  if (includeUnlisted) {
57672
57894
  for (let page = 0; page < MAX_UNLISTED_PRICE_PAGES; page++) {
57673
- const items = readItems(await post(page * PRICE_PAGE_SIZE));
57895
+ const items = readItems(await post2(page * PRICE_PAGE_SIZE));
57674
57896
  if (!items) return null;
57675
57897
  allMarkets.push(...items);
57676
57898
  if (items.length < PRICE_PAGE_SIZE) break;
@@ -57682,14 +57904,23 @@ async function fetchMorphoGraphQLPrices(chainId, includeUnlisted = false) {
57682
57904
  }
57683
57905
  } else {
57684
57906
  const skips = chainId === Chain.ETHEREUM_MAINNET ? [0, PRICE_PAGE_SIZE] : [0];
57685
- const results = await Promise.all(skips.map(post));
57907
+ const results = await Promise.all(skips.map(post2));
57686
57908
  for (const result of results) {
57687
57909
  const items = readItems(result);
57688
57910
  if (!items) return null;
57689
57911
  allMarkets.push(...items);
57690
57912
  }
57691
57913
  }
57692
- return processMarketsToEntries(chainId, allMarkets, "morpho-gql");
57914
+ const priced = includeUnlisted ? allMarkets : await appendVaultFundedMarkets(
57915
+ chainId,
57916
+ allMarkets,
57917
+ (keys) => PRICE_QUERY(keys.length, 0, chainId, false, keys)
57918
+ );
57919
+ return processMarketsToEntries(
57920
+ chainId,
57921
+ normalizeMorphoApiMarkets(priced),
57922
+ "morpho-gql"
57923
+ );
57693
57924
  } catch (err) {
57694
57925
  console.warn(
57695
57926
  `[morpho-gql] chain ${chainId}: API error, falling back to on-chain`,
@@ -64294,7 +64525,7 @@ var fetchSiloVaults = async (chainId, prices = {}, tokenList = {}, options) => {
64294
64525
  // src/vaults/euler-earn/entityLabels.ts
64295
64526
  var LABELS_BASE = "https://raw.githubusercontent.com/euler-xyz/euler-labels/master";
64296
64527
  var TTL_MS4 = 30 * 60 * 1e3;
64297
- var cache3 = /* @__PURE__ */ new Map();
64528
+ var cache4 = /* @__PURE__ */ new Map();
64298
64529
  var inflight4 = /* @__PURE__ */ new Map();
64299
64530
  async function fetchChainEntities(chainId) {
64300
64531
  const res = await fetch(`${LABELS_BASE}/${chainId}/entities.json`);
@@ -64318,12 +64549,12 @@ async function fetchChainEntities(chainId) {
64318
64549
  return map;
64319
64550
  }
64320
64551
  async function fetchEulerEntityNames(chainId) {
64321
- const hit = cache3.get(chainId);
64552
+ const hit = cache4.get(chainId);
64322
64553
  if (hit && Date.now() - hit.at <= TTL_MS4) return hit.map;
64323
64554
  const running = inflight4.get(chainId);
64324
64555
  if (running) return running;
64325
64556
  const p = fetchChainEntities(chainId).then((map) => {
64326
- cache3.set(chainId, { at: Date.now(), map });
64557
+ cache4.set(chainId, { at: Date.now(), map });
64327
64558
  return map;
64328
64559
  }).catch(() => {
64329
64560
  return hit?.map ?? /* @__PURE__ */ new Map();
@@ -64420,7 +64651,7 @@ query EvkByAssets($assets: [Bytes!]!) {
64420
64651
  }
64421
64652
  }
64422
64653
  `;
64423
- var ZERO5 = 0n;
64654
+ var ZERO6 = 0n;
64424
64655
  var RAY_TO_PERCENT3 = 1e25;
64425
64656
  function readAddress2(field13) {
64426
64657
  if (!field13) return void 0;
@@ -64435,28 +64666,28 @@ function parseVaultFee(v) {
64435
64666
  return n;
64436
64667
  }
64437
64668
  function safeBigInt(v) {
64438
- if (v == null || v === "") return ZERO5;
64669
+ if (v == null || v === "") return ZERO6;
64439
64670
  try {
64440
64671
  return BigInt(v);
64441
64672
  } catch {
64442
- return ZERO5;
64673
+ return ZERO6;
64443
64674
  }
64444
64675
  }
64445
64676
  function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent2, evkIndex) {
64446
64677
  if (!strategies?.length) return 0;
64447
64678
  const totalAssets = safeBigInt(totalAssetsRaw);
64448
- if (totalAssets === ZERO5) return 0;
64449
- let weightedRay = ZERO5;
64679
+ if (totalAssets === ZERO6) return 0;
64680
+ let weightedRay = ZERO6;
64450
64681
  for (const s of strategies) {
64451
64682
  const evk = s.strategy?.toLowerCase();
64452
64683
  if (!evk) continue;
64453
64684
  const apyRay = evkIndex.bySupplyApyRay.get(evk);
64454
64685
  if (apyRay == null) continue;
64455
64686
  const allocated = safeBigInt(s.allocatedAssets);
64456
- if (allocated === ZERO5) continue;
64687
+ if (allocated === ZERO6) continue;
64457
64688
  weightedRay += allocated * apyRay;
64458
64689
  }
64459
- if (weightedRay === ZERO5) return 0;
64690
+ if (weightedRay === ZERO6) return 0;
64460
64691
  const apyRayPerAsset = weightedRay / totalAssets;
64461
64692
  const grossPercent = apyToAprPercent(Number(apyRayPerAsset) / RAY_TO_PERCENT3);
64462
64693
  const netPercent = grossPercent * (1 - feePercent2 / 100);
@@ -64464,24 +64695,24 @@ function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent2, evkIn
64464
64695
  }
64465
64696
  function computeRealLiquidity(strategies, totalAssetsRaw, evkIndex) {
64466
64697
  const totalAssets = safeBigInt(totalAssetsRaw);
64467
- if (totalAssets === ZERO5) return ZERO5;
64698
+ if (totalAssets === ZERO6) return ZERO6;
64468
64699
  if (evkIndex.byCash.size === 0 && evkIndex.bySupplyApyRay.size === 0) {
64469
64700
  return totalAssets;
64470
64701
  }
64471
64702
  if (!strategies?.length) {
64472
64703
  return totalAssets;
64473
64704
  }
64474
- let allocSum = ZERO5;
64475
- let withdrawable = ZERO5;
64705
+ let allocSum = ZERO6;
64706
+ let withdrawable = ZERO6;
64476
64707
  for (const s of strategies) {
64477
64708
  const alloc = safeBigInt(s.allocatedAssets);
64478
- if (alloc === ZERO5) continue;
64709
+ if (alloc === ZERO6) continue;
64479
64710
  allocSum += alloc;
64480
64711
  const evk = s.strategy?.toLowerCase();
64481
64712
  const cash = evk ? evkIndex.byCash.get(evk) : void 0;
64482
64713
  withdrawable += cash == null ? alloc : alloc < cash ? alloc : cash;
64483
64714
  }
64484
- const idle = totalAssets > allocSum ? totalAssets - allocSum : ZERO5;
64715
+ const idle = totalAssets > allocSum ? totalAssets - allocSum : ZERO6;
64485
64716
  const result = idle + withdrawable;
64486
64717
  return result > totalAssets ? totalAssets : result;
64487
64718
  }
@@ -75058,7 +75289,7 @@ function isLiveMarket(market, nowSecs = Math.floor(Date.now() / 1e3)) {
75058
75289
  if (expiry === void 0) return false;
75059
75290
  return expiry > nowSecs;
75060
75291
  }
75061
- var CACHE_TTL_MS6 = 6e4;
75292
+ var CACHE_TTL_MS7 = 6e4;
75062
75293
  var marketsCache;
75063
75294
  var assetsCache;
75064
75295
  function clearPendleMarketsCache() {
@@ -75074,9 +75305,9 @@ async function getJson4(url, label) {
75074
75305
  }
75075
75306
  return response.json();
75076
75307
  }
75077
- function cache4(slot, build6, store) {
75308
+ function cache5(slot, build6, store) {
75078
75309
  const now = Date.now();
75079
- if (slot && now - slot.at < CACHE_TTL_MS6) return slot.promise;
75310
+ if (slot && now - slot.at < CACHE_TTL_MS7) return slot.promise;
75080
75311
  const promise = build6();
75081
75312
  const entry = { at: now, promise };
75082
75313
  store(entry);
@@ -75084,7 +75315,7 @@ function cache4(slot, build6, store) {
75084
75315
  return promise;
75085
75316
  }
75086
75317
  function fetchPendleApiMarkets() {
75087
- return cache4(
75318
+ return cache5(
75088
75319
  marketsCache,
75089
75320
  async () => (await getJson4(PENDLE_MARKETS_URL, "markets"))?.markets ?? [],
75090
75321
  (c) => {
@@ -75094,7 +75325,7 @@ function fetchPendleApiMarkets() {
75094
75325
  }
75095
75326
  var assetKey = (chainId, address) => `${chainId}-${address.toLowerCase()}`;
75096
75327
  function fetchPendleApiAssets() {
75097
- return cache4(
75328
+ return cache5(
75098
75329
  assetsCache,
75099
75330
  async () => {
75100
75331
  const json = await getJson4(PENDLE_ASSETS_URL, "assets");
@@ -75345,17 +75576,17 @@ function parsePtRate(raw) {
75345
75576
  if (!Number.isFinite(n) || n < 0 || n > 1.000001) return void 0;
75346
75577
  return n;
75347
75578
  }
75348
- var CACHE_TTL_MS7 = 6e4;
75349
- var cache5 = /* @__PURE__ */ new Map();
75579
+ var CACHE_TTL_MS8 = 6e4;
75580
+ var cache6 = /* @__PURE__ */ new Map();
75350
75581
  function clearSpectraMarketsCache() {
75351
- cache5.clear();
75582
+ cache6.clear();
75352
75583
  }
75353
75584
  function fetchSpectraApiMarkets(chainId) {
75354
75585
  const network = spectraNetwork(chainId);
75355
75586
  if (!network) return Promise.resolve([]);
75356
75587
  const now = Date.now();
75357
- const hit = cache5.get(network);
75358
- if (hit && now - hit.at < CACHE_TTL_MS7) return hit.promise;
75588
+ const hit = cache6.get(network);
75589
+ if (hit && now - hit.at < CACHE_TTL_MS8) return hit.promise;
75359
75590
  const promise = (async () => {
75360
75591
  const response = await fetch(spectraPoolsUrl(network), {
75361
75592
  headers: { Accept: "application/json" }
@@ -75368,9 +75599,9 @@ function fetchSpectraApiMarkets(chainId) {
75368
75599
  const json = await response.json();
75369
75600
  return Array.isArray(json) ? json : [];
75370
75601
  })();
75371
- cache5.set(network, { at: now, promise });
75602
+ cache6.set(network, { at: now, promise });
75372
75603
  promise.catch(() => {
75373
- if (cache5.get(network)?.promise === promise) cache5.delete(network);
75604
+ if (cache6.get(network)?.promise === promise) cache6.delete(network);
75374
75605
  });
75375
75606
  return promise;
75376
75607
  }