@1delta/margin-fetcher 5.0.101 → 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.d.ts +6 -1
- package/dist/index.js +359 -124
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -10729,11 +10729,11 @@ async function resolveListaBrokers(chainId, marketKeys, getClient = getEvmClient
|
|
|
10729
10729
|
const moolah = morphoPools()?.LISTA_DAO?.[chainId];
|
|
10730
10730
|
const out = {};
|
|
10731
10731
|
if (!moolah || marketKeys.length === 0) return out;
|
|
10732
|
-
const
|
|
10732
|
+
const cache7 = BROKER_CACHE[chainId] ??= {};
|
|
10733
10733
|
const missing = [];
|
|
10734
10734
|
for (const key3 of marketKeys) {
|
|
10735
10735
|
const id = toBytes32MarketId(key3);
|
|
10736
|
-
if (
|
|
10736
|
+
if (cache7[id] === void 0) missing.push(id);
|
|
10737
10737
|
}
|
|
10738
10738
|
if (missing.length > 0) {
|
|
10739
10739
|
try {
|
|
@@ -10749,7 +10749,7 @@ async function resolveListaBrokers(chainId, marketKeys, getClient = getEvmClient
|
|
|
10749
10749
|
);
|
|
10750
10750
|
results.forEach((addr4, i) => {
|
|
10751
10751
|
if (addr4 === void 0) return;
|
|
10752
|
-
|
|
10752
|
+
cache7[missing[i]] = addr4.toLowerCase();
|
|
10753
10753
|
});
|
|
10754
10754
|
} catch (e) {
|
|
10755
10755
|
console.warn(
|
|
@@ -10760,7 +10760,7 @@ async function resolveListaBrokers(chainId, marketKeys, getClient = getEvmClient
|
|
|
10760
10760
|
}
|
|
10761
10761
|
for (const key3 of marketKeys) {
|
|
10762
10762
|
const id = toBytes32MarketId(key3);
|
|
10763
|
-
const broker =
|
|
10763
|
+
const broker = cache7[id];
|
|
10764
10764
|
if (broker && broker !== zeroAddress) out[id] = broker;
|
|
10765
10765
|
}
|
|
10766
10766
|
return out;
|
|
@@ -10788,7 +10788,7 @@ async function fetchListaFixedTerms(chainId, marketKeys, multicallRetry) {
|
|
|
10788
10788
|
})),
|
|
10789
10789
|
multicallRetry
|
|
10790
10790
|
);
|
|
10791
|
-
const
|
|
10791
|
+
const cache7 = FIXED_TERMS_CACHE[chainId] ??= {};
|
|
10792
10792
|
results.forEach((raw, i) => {
|
|
10793
10793
|
if (!raw) return;
|
|
10794
10794
|
const id = ids[i];
|
|
@@ -10802,7 +10802,7 @@ async function fetchListaFixedTerms(chainId, marketKeys, multicallRetry) {
|
|
|
10802
10802
|
};
|
|
10803
10803
|
});
|
|
10804
10804
|
out[id] = terms;
|
|
10805
|
-
|
|
10805
|
+
cache7[id] = terms;
|
|
10806
10806
|
});
|
|
10807
10807
|
} catch (e) {
|
|
10808
10808
|
console.warn(
|
|
@@ -12307,6 +12307,39 @@ function formatNr(n, d) {
|
|
|
12307
12307
|
return Number(formatUnits(BigInt(n ?? 0), d));
|
|
12308
12308
|
}
|
|
12309
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
|
+
|
|
12310
12343
|
// src/lending/public-data/morpho/convertPublic.ts
|
|
12311
12344
|
function convertMarketsToMorphoResponse(response, chainId, additionalYields = {
|
|
12312
12345
|
intrinsicYields: {},
|
|
@@ -12316,6 +12349,7 @@ function convertMarketsToMorphoResponse(response, chainId, additionalYields = {
|
|
|
12316
12349
|
const data = {};
|
|
12317
12350
|
const items = response?.markets?.items;
|
|
12318
12351
|
if (!items) return data;
|
|
12352
|
+
const listedFlagMeaningful = !morphoIncludesUnlisted(chainId);
|
|
12319
12353
|
items.forEach((market) => {
|
|
12320
12354
|
const {
|
|
12321
12355
|
uniqueKey,
|
|
@@ -12480,7 +12514,7 @@ function convertMarketsToMorphoResponse(response, chainId, additionalYields = {
|
|
|
12480
12514
|
irm: irmAddress,
|
|
12481
12515
|
collateralAddress: collateralAssetAddress,
|
|
12482
12516
|
loanAddress: loanAssetAddress,
|
|
12483
|
-
isListed: whitelisted,
|
|
12517
|
+
isListed: whitelisted || listedFlagMeaningful ? whitelisted : void 0,
|
|
12484
12518
|
fee: state.fee,
|
|
12485
12519
|
rateAtTarget: state?.rateAtTarget?.toString()
|
|
12486
12520
|
}
|
|
@@ -12490,18 +12524,220 @@ function convertMarketsToMorphoResponse(response, chainId, additionalYields = {
|
|
|
12490
12524
|
});
|
|
12491
12525
|
return data;
|
|
12492
12526
|
}
|
|
12493
|
-
|
|
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) => `
|
|
12494
12727
|
query GetMarkets {
|
|
12495
12728
|
markets(first: ${first}, skip: ${skip}, where: {
|
|
12496
|
-
chainId_in: [${chainId}]${
|
|
12729
|
+
chainId_in: [${chainId}]${uniqueKeys ? `,
|
|
12730
|
+
${uniqueKeyInFilter(uniqueKeys)}` : includeUnlisted ? "" : ",\n listed: true"}
|
|
12497
12731
|
},
|
|
12498
|
-
orderBy: SupplyAssetsUsd,
|
|
12732
|
+
orderBy: ${uniqueKeys ? "UniqueKey" : "SupplyAssetsUsd"},
|
|
12499
12733
|
orderDirection: Desc
|
|
12500
12734
|
) {
|
|
12501
12735
|
items {
|
|
12502
12736
|
uniqueKey: marketId
|
|
12503
12737
|
irmAddress
|
|
12504
|
-
|
|
12738
|
+
oracle {
|
|
12739
|
+
address
|
|
12740
|
+
}
|
|
12505
12741
|
lltv
|
|
12506
12742
|
whitelisted: listed
|
|
12507
12743
|
loanAsset {
|
|
@@ -12509,14 +12745,18 @@ query GetMarkets {
|
|
|
12509
12745
|
name
|
|
12510
12746
|
symbol
|
|
12511
12747
|
decimals
|
|
12512
|
-
|
|
12748
|
+
price {
|
|
12749
|
+
usd
|
|
12750
|
+
}
|
|
12513
12751
|
}
|
|
12514
12752
|
collateralAsset {
|
|
12515
12753
|
address
|
|
12516
12754
|
name
|
|
12517
12755
|
symbol
|
|
12518
12756
|
decimals
|
|
12519
|
-
|
|
12757
|
+
price {
|
|
12758
|
+
usd
|
|
12759
|
+
}
|
|
12520
12760
|
}
|
|
12521
12761
|
state {
|
|
12522
12762
|
borrowApy
|
|
@@ -12544,7 +12784,7 @@ query GetMarkets {
|
|
|
12544
12784
|
}
|
|
12545
12785
|
}
|
|
12546
12786
|
`;
|
|
12547
|
-
var
|
|
12787
|
+
var BASE_URL2 = "https://blue-api.morpho.org/graphql";
|
|
12548
12788
|
function assertNoGraphQLErrors(json) {
|
|
12549
12789
|
if (json?.errors?.length) {
|
|
12550
12790
|
throw new Error(
|
|
@@ -12553,12 +12793,25 @@ function assertNoGraphQLErrors(json) {
|
|
|
12553
12793
|
}
|
|
12554
12794
|
}
|
|
12555
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) {
|
|
12556
12809
|
if (chainId !== Chain.ETHEREUM_MAINNET) {
|
|
12557
12810
|
const requestBody = {
|
|
12558
12811
|
query: query(200, 0, chainId, includeUnlisted),
|
|
12559
12812
|
variables: {}
|
|
12560
12813
|
};
|
|
12561
|
-
const response = await fetch(
|
|
12814
|
+
const response = await fetch(BASE_URL2, {
|
|
12562
12815
|
method: "POST",
|
|
12563
12816
|
headers: {
|
|
12564
12817
|
"Content-Type": "application/json"
|
|
@@ -12583,14 +12836,14 @@ async function fetchMorphoMarkets(chainId, includeUnlisted = false) {
|
|
|
12583
12836
|
variables: {}
|
|
12584
12837
|
};
|
|
12585
12838
|
const [data0, data1] = await Promise.all([
|
|
12586
|
-
fetch(
|
|
12839
|
+
fetch(BASE_URL2, {
|
|
12587
12840
|
method: "POST",
|
|
12588
12841
|
headers: {
|
|
12589
12842
|
"Content-Type": "application/json"
|
|
12590
12843
|
},
|
|
12591
12844
|
body: JSON.stringify(requestBody0)
|
|
12592
12845
|
}).then((x) => x.json()),
|
|
12593
|
-
fetch(
|
|
12846
|
+
fetch(BASE_URL2, {
|
|
12594
12847
|
method: "POST",
|
|
12595
12848
|
headers: {
|
|
12596
12849
|
"Content-Type": "application/json"
|
|
@@ -20181,7 +20434,7 @@ var FLUID_API_BASE = "https://api.fluid.instadapp.io/v2";
|
|
|
20181
20434
|
var SUPPORTED_CHAINS = /* @__PURE__ */ new Set(["1", "56", "137", "8453", "9745", "42161"]);
|
|
20182
20435
|
var TTL_MS2 = 6e4;
|
|
20183
20436
|
var ZERO_ADDRESS4 = "0x0000000000000000000000000000000000000000";
|
|
20184
|
-
var
|
|
20437
|
+
var cache2 = {};
|
|
20185
20438
|
var inflight = /* @__PURE__ */ new Map();
|
|
20186
20439
|
var isRealDex = (d) => !!d && String(d.id ?? "0") !== "0" && String(d.address ?? ZERO_ADDRESS4).toLowerCase() !== ZERO_ADDRESS4;
|
|
20187
20440
|
var toBigInt7 = (v) => {
|
|
@@ -20226,7 +20479,7 @@ var parseChainPayload = (raw) => {
|
|
|
20226
20479
|
};
|
|
20227
20480
|
var fetchFluidApiData = async (chainId) => {
|
|
20228
20481
|
if (!SUPPORTED_CHAINS.has(chainId)) return void 0;
|
|
20229
|
-
const hit =
|
|
20482
|
+
const hit = cache2[chainId];
|
|
20230
20483
|
if (hit && Date.now() - hit.at < TTL_MS2) return hit.data;
|
|
20231
20484
|
const pending = inflight.get(chainId);
|
|
20232
20485
|
if (pending) return pending;
|
|
@@ -20237,11 +20490,11 @@ var fetchFluidApiData = async (chainId) => {
|
|
|
20237
20490
|
const json = await res.json();
|
|
20238
20491
|
if (!Array.isArray(json)) throw new Error("unexpected payload");
|
|
20239
20492
|
const data = parseChainPayload(json);
|
|
20240
|
-
|
|
20493
|
+
cache2[chainId] = { at: Date.now(), data };
|
|
20241
20494
|
return data;
|
|
20242
20495
|
} catch {
|
|
20243
|
-
const prev =
|
|
20244
|
-
|
|
20496
|
+
const prev = cache2[chainId]?.data;
|
|
20497
|
+
cache2[chainId] = { at: Date.now(), data: prev };
|
|
20245
20498
|
return prev;
|
|
20246
20499
|
} finally {
|
|
20247
20500
|
inflight.delete(chainId);
|
|
@@ -20250,7 +20503,7 @@ var fetchFluidApiData = async (chainId) => {
|
|
|
20250
20503
|
inflight.set(chainId, run);
|
|
20251
20504
|
return run;
|
|
20252
20505
|
};
|
|
20253
|
-
var getCachedFluidApiData = (chainId) =>
|
|
20506
|
+
var getCachedFluidApiData = (chainId) => cache2[chainId]?.data;
|
|
20254
20507
|
var DEX_RESOLVER_FALLBACK = {
|
|
20255
20508
|
"1": "0x11D80CfF056Cef4F9E6d23da8672fE9873e5cC07",
|
|
20256
20509
|
"137": "0x11D80CfF056Cef4F9E6d23da8672fE9873e5cC07",
|
|
@@ -20262,12 +20515,12 @@ var DEX_RESOLVER_FALLBACK = {
|
|
|
20262
20515
|
var dexResolverFor = (chainId) => fluidResolvers()?.[chainId]?.dexResolver ?? DEX_RESOLVER_FALLBACK[chainId];
|
|
20263
20516
|
var ZERO_ADDRESS5 = "0x0000000000000000000000000000000000000000";
|
|
20264
20517
|
var TTL_MS3 = 6e4;
|
|
20265
|
-
var
|
|
20518
|
+
var cache3 = {};
|
|
20266
20519
|
var inflight2 = /* @__PURE__ */ new Map();
|
|
20267
20520
|
var fetchFluidDexState = async (chainId, multicallRetry, extraDexAddresses = []) => {
|
|
20268
20521
|
const resolver = dexResolverFor(chainId);
|
|
20269
20522
|
if (!resolver) return void 0;
|
|
20270
|
-
const hit =
|
|
20523
|
+
const hit = cache3[chainId];
|
|
20271
20524
|
if (hit && Date.now() - hit.at < TTL_MS3) return hit.data;
|
|
20272
20525
|
const pending = inflight2.get(chainId);
|
|
20273
20526
|
if (pending) return pending;
|
|
@@ -20307,11 +20560,11 @@ var fetchFluidDexState = async (chainId, multicallRetry, extraDexAddresses = [])
|
|
|
20307
20560
|
totalBorrowShares: BigInt(s.totalBorrowShares ?? 0)
|
|
20308
20561
|
};
|
|
20309
20562
|
}
|
|
20310
|
-
|
|
20563
|
+
cache3[chainId] = { at: Date.now(), data };
|
|
20311
20564
|
return data;
|
|
20312
20565
|
} catch {
|
|
20313
|
-
const prev =
|
|
20314
|
-
|
|
20566
|
+
const prev = cache3[chainId]?.data;
|
|
20567
|
+
cache3[chainId] = { at: Date.now(), data: prev };
|
|
20315
20568
|
return prev;
|
|
20316
20569
|
} finally {
|
|
20317
20570
|
inflight2.delete(chainId);
|
|
@@ -20320,7 +20573,7 @@ var fetchFluidDexState = async (chainId, multicallRetry, extraDexAddresses = [])
|
|
|
20320
20573
|
inflight2.set(chainId, run);
|
|
20321
20574
|
return run;
|
|
20322
20575
|
};
|
|
20323
|
-
var getCachedFluidDexState = (chainId) =>
|
|
20576
|
+
var getCachedFluidDexState = (chainId) => cache3[chainId]?.data;
|
|
20324
20577
|
|
|
20325
20578
|
// src/lending/public-data/fluid/publicCallParse.ts
|
|
20326
20579
|
var FLUID_EEE_LOWER = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
|
|
@@ -25517,7 +25770,7 @@ var LLAMALEND_READ_ABI = [
|
|
|
25517
25770
|
...LlamaLendAmmAbi,
|
|
25518
25771
|
...Erc20Abi
|
|
25519
25772
|
];
|
|
25520
|
-
var
|
|
25773
|
+
var ZERO2 = "0x0000000000000000000000000000000000000000";
|
|
25521
25774
|
var WAD8 = 10n ** 18n;
|
|
25522
25775
|
var CALLS_PER_MARKET = 6;
|
|
25523
25776
|
var fetchJson2 = async (url, timeoutMs = 8e3) => {
|
|
@@ -25566,7 +25819,7 @@ async function fetchChainExtras(chainId, markets) {
|
|
|
25566
25819
|
{ address: m.amm, name: "price_oracle", params: [] },
|
|
25567
25820
|
{ address: m.amm, name: "active_band", params: [] },
|
|
25568
25821
|
{ address: m.controller, name: "n_loans", params: [] },
|
|
25569
|
-
{ address: m.vault, name: "maxDeposit", params: [
|
|
25822
|
+
{ address: m.vault, name: "maxDeposit", params: [ZERO2] },
|
|
25570
25823
|
// v1 controllers have no `borrow_cap`; allowFailure turns that into a
|
|
25571
25824
|
// null rather than sinking the whole batch.
|
|
25572
25825
|
{ address: m.controller, name: "borrow_cap", params: [] },
|
|
@@ -29339,7 +29592,7 @@ function convertFrankencoinMarketsToResponse(raw, chainId, prices = {}, _additio
|
|
|
29339
29592
|
}
|
|
29340
29593
|
|
|
29341
29594
|
// src/lending/public-data/silo-v2/fetchPublic.ts
|
|
29342
|
-
var
|
|
29595
|
+
var BASE_URL3 = "https://api-v3.silo.finance";
|
|
29343
29596
|
var SILO_API_SUPPORTED_CHAIN_IDS = /* @__PURE__ */ new Set([
|
|
29344
29597
|
"1",
|
|
29345
29598
|
// Ethereum
|
|
@@ -29482,7 +29735,7 @@ query GetSilosLite {
|
|
|
29482
29735
|
async function fetchSiloMarketsLite(chainId, options) {
|
|
29483
29736
|
if (!SILO_API_SUPPORTED_CHAIN_IDS.has(chainId)) return [];
|
|
29484
29737
|
const limit = options?.limit ?? 500;
|
|
29485
|
-
const response = await fetch(
|
|
29738
|
+
const response = await fetch(BASE_URL3, {
|
|
29486
29739
|
method: "POST",
|
|
29487
29740
|
headers: { "Content-Type": "application/json" },
|
|
29488
29741
|
body: JSON.stringify({ query: liteQuery(chainId, limit) })
|
|
@@ -29507,7 +29760,7 @@ async function fetchSiloMarketsLite(chainId, options) {
|
|
|
29507
29760
|
async function fetchSiloMarkets(chainId, options) {
|
|
29508
29761
|
if (!SILO_API_SUPPORTED_CHAIN_IDS.has(chainId)) return [];
|
|
29509
29762
|
const limit = options?.limit ?? 500;
|
|
29510
|
-
const response = await fetch(
|
|
29763
|
+
const response = await fetch(BASE_URL3, {
|
|
29511
29764
|
method: "POST",
|
|
29512
29765
|
headers: { "Content-Type": "application/json" },
|
|
29513
29766
|
body: JSON.stringify({ query: query2(chainId, limit) })
|
|
@@ -30288,39 +30541,6 @@ var getLenderPublicDataViaApi = async (chainId, lenders, prices, additionalYield
|
|
|
30288
30541
|
}
|
|
30289
30542
|
return lenderData;
|
|
30290
30543
|
};
|
|
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
30544
|
var ERC20_BALANCE_OF_ABI2 = [
|
|
30325
30545
|
{
|
|
30326
30546
|
inputs: [{ name: "account", type: "address" }],
|
|
@@ -30943,7 +31163,7 @@ function decodeVariableLensRows(blob, fixedWords, headerBytes = 0) {
|
|
|
30943
31163
|
}
|
|
30944
31164
|
|
|
30945
31165
|
// src/lending/user-data/aave-v3-type/lens.ts
|
|
30946
|
-
var
|
|
31166
|
+
var ZERO3 = "0x0000000000000000000000000000000000000000";
|
|
30947
31167
|
var AAVE_LENS_HEADER_BYTES = 3;
|
|
30948
31168
|
var HEADER_EMODE_OK = 1;
|
|
30949
31169
|
var HEADER_CONFIG_OK = 2;
|
|
@@ -30951,7 +31171,7 @@ var AAVE_LENS_WORDS = 7;
|
|
|
30951
31171
|
var reserveTuple = (tokens, asset) => {
|
|
30952
31172
|
const t = tokens?.[asset.toLowerCase()];
|
|
30953
31173
|
if (!t?.aToken || !t?.vToken) return void 0;
|
|
30954
|
-
return [asset, t.aToken, t.vToken, t.sToken ??
|
|
31174
|
+
return [asset, t.aToken, t.vToken, t.sToken ?? ZERO3];
|
|
30955
31175
|
};
|
|
30956
31176
|
var usesAaveLens = (chainId, lender) => {
|
|
30957
31177
|
if (getPositionLensFor(chainId, LENS_FAMILY.AAVE) === void 0) return false;
|
|
@@ -30981,7 +31201,7 @@ var buildAaveLensCall = (chainId, lender, account, assetsToQuery, withEMode) =>
|
|
|
30981
31201
|
getAaveTypePoolDataProviderAddress(chainId, lender),
|
|
30982
31202
|
// A zero pool disables the e-mode read, which is exactly what YLDR wants:
|
|
30983
31203
|
// it has no `getUserEMode` and the walk omits that call for it too.
|
|
30984
|
-
withEMode ? getAaveTypePoolAddress(chainId, lender) :
|
|
31204
|
+
withEMode ? getAaveTypePoolAddress(chainId, lender) : ZERO3
|
|
30985
31205
|
]
|
|
30986
31206
|
);
|
|
30987
31207
|
return [
|
|
@@ -32061,7 +32281,7 @@ var buildExactlyUserCall = (chainId, _lender, account) => {
|
|
|
32061
32281
|
return [{ address: cfg.previewer, name: "exactly", params: [account] }];
|
|
32062
32282
|
};
|
|
32063
32283
|
var OWNER_INDEX_PROBE_COUNT = 8;
|
|
32064
|
-
var
|
|
32284
|
+
var CACHE_TTL_MS2 = 5 * 6e4;
|
|
32065
32285
|
var discoveryCache = /* @__PURE__ */ new Map();
|
|
32066
32286
|
async function discoverViaLens(chainId, branches, zappers, account, opts) {
|
|
32067
32287
|
const lens = getPositionLensFor(chainId, LENS_FAMILY.LIQUITY);
|
|
@@ -32130,7 +32350,7 @@ var getCachedLiquityTroves = (chainId, lender, account, opts) => {
|
|
|
32130
32350
|
const hit = discoveryCache.get(
|
|
32131
32351
|
cacheKey(chainId, lender, account, blockKey(opts))
|
|
32132
32352
|
);
|
|
32133
|
-
if (!hit || Date.now() - hit.at >
|
|
32353
|
+
if (!hit || Date.now() - hit.at > CACHE_TTL_MS2) return void 0;
|
|
32134
32354
|
return hit;
|
|
32135
32355
|
};
|
|
32136
32356
|
var ADDRESS_ADDRESS_UINT = [
|
|
@@ -32350,7 +32570,7 @@ var buildRiverUserCall = (chainId, lender, account) => {
|
|
|
32350
32570
|
});
|
|
32351
32571
|
return calls;
|
|
32352
32572
|
};
|
|
32353
|
-
var
|
|
32573
|
+
var ZERO4 = "0x0000000000000000000000000000000000000000";
|
|
32354
32574
|
var LLAMALEND_LENS_WORDS = 12;
|
|
32355
32575
|
var LLAMALEND_CALLS_PER_MARKET = 8;
|
|
32356
32576
|
var usesLlamaLendLens = (chainId) => getPositionLensFor(chainId, LENS_FAMILY.LLAMALEND) !== void 0;
|
|
@@ -32364,7 +32584,7 @@ var buildLlamaLendLensCall = (chainId, markets, account, delegate) => {
|
|
|
32364
32584
|
m.controller,
|
|
32365
32585
|
m.amm,
|
|
32366
32586
|
m.vault,
|
|
32367
|
-
m.gauge ??
|
|
32587
|
+
m.gauge ?? ZERO4
|
|
32368
32588
|
]),
|
|
32369
32589
|
delegate
|
|
32370
32590
|
]
|
|
@@ -32913,7 +33133,7 @@ function getCachedTwyneDiscovery(chainId, lender, account, opts) {
|
|
|
32913
33133
|
}
|
|
32914
33134
|
var lower2 = (a) => String(a).toLowerCase();
|
|
32915
33135
|
var isAddress4 = (v) => typeof v === "string" && /^0x[0-9a-fA-F]{40}$/.test(v);
|
|
32916
|
-
async function
|
|
33136
|
+
async function discover2(chainId, lender, account, opts) {
|
|
32917
33137
|
const key3 = discoveryKey3(chainId, lender, account, blockKey(opts));
|
|
32918
33138
|
const cached = discoveryCache4.get(key3);
|
|
32919
33139
|
if (cached && Date.now() - cached.at < DISCOVERY_TTL_MS3) return cached;
|
|
@@ -33015,7 +33235,7 @@ async function discover(chainId, lender, account, opts) {
|
|
|
33015
33235
|
return result;
|
|
33016
33236
|
}
|
|
33017
33237
|
async function buildTwyneUserCall(chainId, lender, account, opts) {
|
|
33018
|
-
const { vaults } = await
|
|
33238
|
+
const { vaults } = await discover2(chainId, lender, account, opts);
|
|
33019
33239
|
if (vaults.length === 0) return [];
|
|
33020
33240
|
return vaults.flatMap(({ vault }) => [
|
|
33021
33241
|
{ address: vault, name: "totalAssetsDepositedOrReserved", args: [] },
|
|
@@ -33029,14 +33249,14 @@ async function buildTwyneUserCall(chainId, lender, account, opts) {
|
|
|
33029
33249
|
}
|
|
33030
33250
|
var DSS_CALLS_PER_CDP = 1;
|
|
33031
33251
|
var MAX_CDP_WALK = 64;
|
|
33032
|
-
var
|
|
33252
|
+
var CACHE_TTL_MS3 = 5 * 6e4;
|
|
33033
33253
|
var discoveryCache5 = /* @__PURE__ */ new Map();
|
|
33034
33254
|
var cacheKey2 = (lender, chainId, account, block = "head") => `${lender}:${chainId}:${account.toLowerCase()}:${block}`;
|
|
33035
33255
|
var getCachedDssCdps = (lender, chainId, account, opts) => {
|
|
33036
33256
|
const hit = discoveryCache5.get(
|
|
33037
33257
|
cacheKey2(lender, chainId, account, blockKey(opts))
|
|
33038
33258
|
);
|
|
33039
|
-
if (!hit || Date.now() - hit.at >
|
|
33259
|
+
if (!hit || Date.now() - hit.at > CACHE_TTL_MS3) return void 0;
|
|
33040
33260
|
return hit;
|
|
33041
33261
|
};
|
|
33042
33262
|
var big7 = (v) => {
|
|
@@ -33279,12 +33499,12 @@ async function discoverTellerBidsViaLens(chainId, tellerV2, account, opts) {
|
|
|
33279
33499
|
|
|
33280
33500
|
// src/lending/user-data/teller/userCallBuild.ts
|
|
33281
33501
|
var TELLER_CALLS_PER_BID = 4;
|
|
33282
|
-
var
|
|
33502
|
+
var CACHE_TTL_MS4 = 5 * 6e4;
|
|
33283
33503
|
var discoveryCache7 = /* @__PURE__ */ new Map();
|
|
33284
33504
|
var cacheKey4 = (chainId, account, block = "head") => `${chainId}:${account.toLowerCase()}:${block}`;
|
|
33285
33505
|
var getCachedTellerBids = (chainId, account, opts) => {
|
|
33286
33506
|
const hit = discoveryCache7.get(cacheKey4(chainId, account, blockKey(opts)));
|
|
33287
|
-
if (!hit || Date.now() - hit.at >
|
|
33507
|
+
if (!hit || Date.now() - hit.at > CACHE_TTL_MS4) return void 0;
|
|
33288
33508
|
return hit;
|
|
33289
33509
|
};
|
|
33290
33510
|
var nowSec5 = () => Math.floor(Date.now() / 1e3);
|
|
@@ -33421,12 +33641,12 @@ var buildFlyingTulipUserCall = (chainId, lender, account) => {
|
|
|
33421
33641
|
];
|
|
33422
33642
|
};
|
|
33423
33643
|
var TERMMAX_MARKETS_PER_CALL = 180;
|
|
33424
|
-
var
|
|
33644
|
+
var CACHE_TTL_MS5 = 5 * 6e4;
|
|
33425
33645
|
var discoveryCache8 = /* @__PURE__ */ new Map();
|
|
33426
33646
|
var cacheKey5 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
|
|
33427
33647
|
var getCachedTermMaxDiscovery = (chainId, account) => {
|
|
33428
33648
|
const hit = discoveryCache8.get(cacheKey5(chainId, account));
|
|
33429
|
-
if (!hit || Date.now() - hit.at >
|
|
33649
|
+
if (!hit || Date.now() - hit.at > CACHE_TTL_MS5) return void 0;
|
|
33430
33650
|
return hit;
|
|
33431
33651
|
};
|
|
33432
33652
|
var buildTermMaxUserCall = async (chainId, _lender, account) => {
|
|
@@ -43706,7 +43926,7 @@ var MORPHO_API_CHAIN_IDS = {
|
|
|
43706
43926
|
[Chain.UNICHAIN]: 130
|
|
43707
43927
|
};
|
|
43708
43928
|
var FETCH_TIMEOUT_MS = 3e3;
|
|
43709
|
-
var
|
|
43929
|
+
var CACHE_TTL_MS6 = 2e3;
|
|
43710
43930
|
var buildSubgraphQuery = (account) => `
|
|
43711
43931
|
{
|
|
43712
43932
|
account(id: "${account.toLowerCase()}") {
|
|
@@ -43774,7 +43994,7 @@ async function dedupedFetch(chainId, account, loader) {
|
|
|
43774
43994
|
const existing = inflight3.get(key3);
|
|
43775
43995
|
if (existing) return existing;
|
|
43776
43996
|
const promise = loader().then((value) => {
|
|
43777
|
-
resolved.set(key3, { value, expiresAt: Date.now() +
|
|
43997
|
+
resolved.set(key3, { value, expiresAt: Date.now() + CACHE_TTL_MS6 });
|
|
43778
43998
|
return value;
|
|
43779
43999
|
}).finally(() => {
|
|
43780
44000
|
inflight3.delete(key3);
|
|
@@ -56751,7 +56971,7 @@ var dtrinityRebateRewardFetcher = {
|
|
|
56751
56971
|
};
|
|
56752
56972
|
var SECONDS_PER_YEAR15 = 31536e3;
|
|
56753
56973
|
var WAD16 = 10n ** 18n;
|
|
56754
|
-
var
|
|
56974
|
+
var ZERO5 = "0x0000000000000000000000000000000000000000";
|
|
56755
56975
|
var UNBOOSTED_FACTOR = 0.4;
|
|
56756
56976
|
var MAX_BOOST = 2.5;
|
|
56757
56977
|
var GAUGE_CONTROLLER = "0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB";
|
|
@@ -56947,7 +57167,7 @@ async function fetchPrices(keys) {
|
|
|
56947
57167
|
var priceOf = (prices, chainId, address) => prices[`${LLAMA_CHAIN_SLUG[chainId]}:${address.toLowerCase()}`] ?? 0;
|
|
56948
57168
|
function rosterFor(chainId) {
|
|
56949
57169
|
const markets = llamaLendChainData(Lender.LLAMALEND, chainId)?.markets ?? [];
|
|
56950
|
-
return markets.filter((m) => m.gauge && m.gauge !==
|
|
57170
|
+
return markets.filter((m) => m.gauge && m.gauge !== ZERO5).map((m) => ({
|
|
56951
57171
|
controller: m.controller,
|
|
56952
57172
|
vault: m.vault,
|
|
56953
57173
|
gauge: m.gauge,
|
|
@@ -57024,7 +57244,7 @@ async function fetchForChain(chainId, nowSeconds) {
|
|
|
57024
57244
|
}) : [];
|
|
57025
57245
|
let cursor = 0;
|
|
57026
57246
|
const withTokens = state.map((s) => {
|
|
57027
|
-
const tokens = r2.slice(cursor, cursor + s.rewardCount).filter((t) => typeof t === "string" && t !==
|
|
57247
|
+
const tokens = r2.slice(cursor, cursor + s.rewardCount).filter((t) => typeof t === "string" && t !== ZERO5);
|
|
57028
57248
|
cursor += s.rewardCount;
|
|
57029
57249
|
return { ...s, tokens };
|
|
57030
57250
|
});
|
|
@@ -57619,26 +57839,32 @@ function getMorphoAbi() {
|
|
|
57619
57839
|
var MORPHO_GRAPHQL_URL = "https://blue-api.morpho.org/graphql";
|
|
57620
57840
|
var MAX_UNLISTED_PRICE_PAGES = 10;
|
|
57621
57841
|
var PRICE_PAGE_SIZE = 200;
|
|
57622
|
-
var PRICE_QUERY = (first, skip, chainId, includeUnlisted) => `
|
|
57842
|
+
var PRICE_QUERY = (first, skip, chainId, includeUnlisted, uniqueKeys) => `
|
|
57623
57843
|
query GetMarketPrices {
|
|
57624
57844
|
markets(first: ${first}, skip: ${skip}, where: {
|
|
57625
|
-
chainId_in: [${chainId}]${!includeUnlisted && chainId != Chain.ETHEREUM_MAINNET ? `,listed: true` : ""}
|
|
57845
|
+
chainId_in: [${chainId}]${uniqueKeys ? `,${uniqueKeyInFilter(uniqueKeys)}` : !includeUnlisted && chainId != Chain.ETHEREUM_MAINNET ? `,listed: true` : ""}
|
|
57626
57846
|
},
|
|
57627
|
-
orderBy: SupplyAssetsUsd,
|
|
57847
|
+
orderBy: ${uniqueKeys ? "UniqueKey" : "SupplyAssetsUsd"},
|
|
57628
57848
|
orderDirection: Desc
|
|
57629
57849
|
) {
|
|
57630
57850
|
items {
|
|
57631
57851
|
uniqueKey: marketId
|
|
57632
|
-
|
|
57852
|
+
oracle {
|
|
57853
|
+
address
|
|
57854
|
+
}
|
|
57633
57855
|
loanAsset {
|
|
57634
57856
|
address
|
|
57635
57857
|
decimals
|
|
57636
|
-
|
|
57858
|
+
price {
|
|
57859
|
+
usd
|
|
57860
|
+
}
|
|
57637
57861
|
}
|
|
57638
57862
|
collateralAsset {
|
|
57639
57863
|
address
|
|
57640
57864
|
decimals
|
|
57641
|
-
|
|
57865
|
+
price {
|
|
57866
|
+
usd
|
|
57867
|
+
}
|
|
57642
57868
|
}
|
|
57643
57869
|
state {
|
|
57644
57870
|
price
|
|
@@ -57649,7 +57875,7 @@ query GetMarketPrices {
|
|
|
57649
57875
|
`;
|
|
57650
57876
|
async function fetchMorphoGraphQLPrices(chainId, includeUnlisted = false) {
|
|
57651
57877
|
if (!morphoApiAvailable(chainId)) return null;
|
|
57652
|
-
const
|
|
57878
|
+
const post2 = (skip) => fetch(MORPHO_GRAPHQL_URL, {
|
|
57653
57879
|
method: "POST",
|
|
57654
57880
|
headers: { "Content-Type": "application/json" },
|
|
57655
57881
|
body: JSON.stringify({
|
|
@@ -57670,7 +57896,7 @@ async function fetchMorphoGraphQLPrices(chainId, includeUnlisted = false) {
|
|
|
57670
57896
|
const allMarkets = [];
|
|
57671
57897
|
if (includeUnlisted) {
|
|
57672
57898
|
for (let page = 0; page < MAX_UNLISTED_PRICE_PAGES; page++) {
|
|
57673
|
-
const items = readItems(await
|
|
57899
|
+
const items = readItems(await post2(page * PRICE_PAGE_SIZE));
|
|
57674
57900
|
if (!items) return null;
|
|
57675
57901
|
allMarkets.push(...items);
|
|
57676
57902
|
if (items.length < PRICE_PAGE_SIZE) break;
|
|
@@ -57682,14 +57908,23 @@ async function fetchMorphoGraphQLPrices(chainId, includeUnlisted = false) {
|
|
|
57682
57908
|
}
|
|
57683
57909
|
} else {
|
|
57684
57910
|
const skips = chainId === Chain.ETHEREUM_MAINNET ? [0, PRICE_PAGE_SIZE] : [0];
|
|
57685
|
-
const results = await Promise.all(skips.map(
|
|
57911
|
+
const results = await Promise.all(skips.map(post2));
|
|
57686
57912
|
for (const result of results) {
|
|
57687
57913
|
const items = readItems(result);
|
|
57688
57914
|
if (!items) return null;
|
|
57689
57915
|
allMarkets.push(...items);
|
|
57690
57916
|
}
|
|
57691
57917
|
}
|
|
57692
|
-
|
|
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
|
+
);
|
|
57693
57928
|
} catch (err) {
|
|
57694
57929
|
console.warn(
|
|
57695
57930
|
`[morpho-gql] chain ${chainId}: API error, falling back to on-chain`,
|
|
@@ -64294,7 +64529,7 @@ var fetchSiloVaults = async (chainId, prices = {}, tokenList = {}, options) => {
|
|
|
64294
64529
|
// src/vaults/euler-earn/entityLabels.ts
|
|
64295
64530
|
var LABELS_BASE = "https://raw.githubusercontent.com/euler-xyz/euler-labels/master";
|
|
64296
64531
|
var TTL_MS4 = 30 * 60 * 1e3;
|
|
64297
|
-
var
|
|
64532
|
+
var cache4 = /* @__PURE__ */ new Map();
|
|
64298
64533
|
var inflight4 = /* @__PURE__ */ new Map();
|
|
64299
64534
|
async function fetchChainEntities(chainId) {
|
|
64300
64535
|
const res = await fetch(`${LABELS_BASE}/${chainId}/entities.json`);
|
|
@@ -64318,12 +64553,12 @@ async function fetchChainEntities(chainId) {
|
|
|
64318
64553
|
return map;
|
|
64319
64554
|
}
|
|
64320
64555
|
async function fetchEulerEntityNames(chainId) {
|
|
64321
|
-
const hit =
|
|
64556
|
+
const hit = cache4.get(chainId);
|
|
64322
64557
|
if (hit && Date.now() - hit.at <= TTL_MS4) return hit.map;
|
|
64323
64558
|
const running = inflight4.get(chainId);
|
|
64324
64559
|
if (running) return running;
|
|
64325
64560
|
const p = fetchChainEntities(chainId).then((map) => {
|
|
64326
|
-
|
|
64561
|
+
cache4.set(chainId, { at: Date.now(), map });
|
|
64327
64562
|
return map;
|
|
64328
64563
|
}).catch(() => {
|
|
64329
64564
|
return hit?.map ?? /* @__PURE__ */ new Map();
|
|
@@ -64420,7 +64655,7 @@ query EvkByAssets($assets: [Bytes!]!) {
|
|
|
64420
64655
|
}
|
|
64421
64656
|
}
|
|
64422
64657
|
`;
|
|
64423
|
-
var
|
|
64658
|
+
var ZERO6 = 0n;
|
|
64424
64659
|
var RAY_TO_PERCENT3 = 1e25;
|
|
64425
64660
|
function readAddress2(field13) {
|
|
64426
64661
|
if (!field13) return void 0;
|
|
@@ -64435,28 +64670,28 @@ function parseVaultFee(v) {
|
|
|
64435
64670
|
return n;
|
|
64436
64671
|
}
|
|
64437
64672
|
function safeBigInt(v) {
|
|
64438
|
-
if (v == null || v === "") return
|
|
64673
|
+
if (v == null || v === "") return ZERO6;
|
|
64439
64674
|
try {
|
|
64440
64675
|
return BigInt(v);
|
|
64441
64676
|
} catch {
|
|
64442
|
-
return
|
|
64677
|
+
return ZERO6;
|
|
64443
64678
|
}
|
|
64444
64679
|
}
|
|
64445
64680
|
function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent2, evkIndex) {
|
|
64446
64681
|
if (!strategies?.length) return 0;
|
|
64447
64682
|
const totalAssets = safeBigInt(totalAssetsRaw);
|
|
64448
|
-
if (totalAssets ===
|
|
64449
|
-
let weightedRay =
|
|
64683
|
+
if (totalAssets === ZERO6) return 0;
|
|
64684
|
+
let weightedRay = ZERO6;
|
|
64450
64685
|
for (const s of strategies) {
|
|
64451
64686
|
const evk = s.strategy?.toLowerCase();
|
|
64452
64687
|
if (!evk) continue;
|
|
64453
64688
|
const apyRay = evkIndex.bySupplyApyRay.get(evk);
|
|
64454
64689
|
if (apyRay == null) continue;
|
|
64455
64690
|
const allocated = safeBigInt(s.allocatedAssets);
|
|
64456
|
-
if (allocated ===
|
|
64691
|
+
if (allocated === ZERO6) continue;
|
|
64457
64692
|
weightedRay += allocated * apyRay;
|
|
64458
64693
|
}
|
|
64459
|
-
if (weightedRay ===
|
|
64694
|
+
if (weightedRay === ZERO6) return 0;
|
|
64460
64695
|
const apyRayPerAsset = weightedRay / totalAssets;
|
|
64461
64696
|
const grossPercent = apyToAprPercent(Number(apyRayPerAsset) / RAY_TO_PERCENT3);
|
|
64462
64697
|
const netPercent = grossPercent * (1 - feePercent2 / 100);
|
|
@@ -64464,24 +64699,24 @@ function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent2, evkIn
|
|
|
64464
64699
|
}
|
|
64465
64700
|
function computeRealLiquidity(strategies, totalAssetsRaw, evkIndex) {
|
|
64466
64701
|
const totalAssets = safeBigInt(totalAssetsRaw);
|
|
64467
|
-
if (totalAssets ===
|
|
64702
|
+
if (totalAssets === ZERO6) return ZERO6;
|
|
64468
64703
|
if (evkIndex.byCash.size === 0 && evkIndex.bySupplyApyRay.size === 0) {
|
|
64469
64704
|
return totalAssets;
|
|
64470
64705
|
}
|
|
64471
64706
|
if (!strategies?.length) {
|
|
64472
64707
|
return totalAssets;
|
|
64473
64708
|
}
|
|
64474
|
-
let allocSum =
|
|
64475
|
-
let withdrawable =
|
|
64709
|
+
let allocSum = ZERO6;
|
|
64710
|
+
let withdrawable = ZERO6;
|
|
64476
64711
|
for (const s of strategies) {
|
|
64477
64712
|
const alloc = safeBigInt(s.allocatedAssets);
|
|
64478
|
-
if (alloc ===
|
|
64713
|
+
if (alloc === ZERO6) continue;
|
|
64479
64714
|
allocSum += alloc;
|
|
64480
64715
|
const evk = s.strategy?.toLowerCase();
|
|
64481
64716
|
const cash = evk ? evkIndex.byCash.get(evk) : void 0;
|
|
64482
64717
|
withdrawable += cash == null ? alloc : alloc < cash ? alloc : cash;
|
|
64483
64718
|
}
|
|
64484
|
-
const idle = totalAssets > allocSum ? totalAssets - allocSum :
|
|
64719
|
+
const idle = totalAssets > allocSum ? totalAssets - allocSum : ZERO6;
|
|
64485
64720
|
const result = idle + withdrawable;
|
|
64486
64721
|
return result > totalAssets ? totalAssets : result;
|
|
64487
64722
|
}
|
|
@@ -75058,7 +75293,7 @@ function isLiveMarket(market, nowSecs = Math.floor(Date.now() / 1e3)) {
|
|
|
75058
75293
|
if (expiry === void 0) return false;
|
|
75059
75294
|
return expiry > nowSecs;
|
|
75060
75295
|
}
|
|
75061
|
-
var
|
|
75296
|
+
var CACHE_TTL_MS7 = 6e4;
|
|
75062
75297
|
var marketsCache;
|
|
75063
75298
|
var assetsCache;
|
|
75064
75299
|
function clearPendleMarketsCache() {
|
|
@@ -75074,9 +75309,9 @@ async function getJson4(url, label) {
|
|
|
75074
75309
|
}
|
|
75075
75310
|
return response.json();
|
|
75076
75311
|
}
|
|
75077
|
-
function
|
|
75312
|
+
function cache5(slot, build6, store) {
|
|
75078
75313
|
const now = Date.now();
|
|
75079
|
-
if (slot && now - slot.at <
|
|
75314
|
+
if (slot && now - slot.at < CACHE_TTL_MS7) return slot.promise;
|
|
75080
75315
|
const promise = build6();
|
|
75081
75316
|
const entry = { at: now, promise };
|
|
75082
75317
|
store(entry);
|
|
@@ -75084,7 +75319,7 @@ function cache4(slot, build6, store) {
|
|
|
75084
75319
|
return promise;
|
|
75085
75320
|
}
|
|
75086
75321
|
function fetchPendleApiMarkets() {
|
|
75087
|
-
return
|
|
75322
|
+
return cache5(
|
|
75088
75323
|
marketsCache,
|
|
75089
75324
|
async () => (await getJson4(PENDLE_MARKETS_URL, "markets"))?.markets ?? [],
|
|
75090
75325
|
(c) => {
|
|
@@ -75094,7 +75329,7 @@ function fetchPendleApiMarkets() {
|
|
|
75094
75329
|
}
|
|
75095
75330
|
var assetKey = (chainId, address) => `${chainId}-${address.toLowerCase()}`;
|
|
75096
75331
|
function fetchPendleApiAssets() {
|
|
75097
|
-
return
|
|
75332
|
+
return cache5(
|
|
75098
75333
|
assetsCache,
|
|
75099
75334
|
async () => {
|
|
75100
75335
|
const json = await getJson4(PENDLE_ASSETS_URL, "assets");
|
|
@@ -75345,17 +75580,17 @@ function parsePtRate(raw) {
|
|
|
75345
75580
|
if (!Number.isFinite(n) || n < 0 || n > 1.000001) return void 0;
|
|
75346
75581
|
return n;
|
|
75347
75582
|
}
|
|
75348
|
-
var
|
|
75349
|
-
var
|
|
75583
|
+
var CACHE_TTL_MS8 = 6e4;
|
|
75584
|
+
var cache6 = /* @__PURE__ */ new Map();
|
|
75350
75585
|
function clearSpectraMarketsCache() {
|
|
75351
|
-
|
|
75586
|
+
cache6.clear();
|
|
75352
75587
|
}
|
|
75353
75588
|
function fetchSpectraApiMarkets(chainId) {
|
|
75354
75589
|
const network = spectraNetwork(chainId);
|
|
75355
75590
|
if (!network) return Promise.resolve([]);
|
|
75356
75591
|
const now = Date.now();
|
|
75357
|
-
const hit =
|
|
75358
|
-
if (hit && now - hit.at <
|
|
75592
|
+
const hit = cache6.get(network);
|
|
75593
|
+
if (hit && now - hit.at < CACHE_TTL_MS8) return hit.promise;
|
|
75359
75594
|
const promise = (async () => {
|
|
75360
75595
|
const response = await fetch(spectraPoolsUrl(network), {
|
|
75361
75596
|
headers: { Accept: "application/json" }
|
|
@@ -75368,9 +75603,9 @@ function fetchSpectraApiMarkets(chainId) {
|
|
|
75368
75603
|
const json = await response.json();
|
|
75369
75604
|
return Array.isArray(json) ? json : [];
|
|
75370
75605
|
})();
|
|
75371
|
-
|
|
75606
|
+
cache6.set(network, { at: now, promise });
|
|
75372
75607
|
promise.catch(() => {
|
|
75373
|
-
if (
|
|
75608
|
+
if (cache6.get(network)?.promise === promise) cache6.delete(network);
|
|
75374
75609
|
});
|
|
75375
75610
|
return promise;
|
|
75376
75611
|
}
|