@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.d.ts +6 -1
- package/dist/index.js +359 -128
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
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
|
|
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 (
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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}]${
|
|
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
|
-
|
|
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
|
-
|
|
12746
|
+
price {
|
|
12747
|
+
usd
|
|
12748
|
+
}
|
|
12513
12749
|
}
|
|
12514
12750
|
collateralAsset {
|
|
12515
12751
|
address
|
|
12516
12752
|
name
|
|
12517
12753
|
symbol
|
|
12518
12754
|
decimals
|
|
12519
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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 =
|
|
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
|
-
|
|
20490
|
+
cache2[chainId] = { at: Date.now(), data };
|
|
20241
20491
|
return data;
|
|
20242
20492
|
} catch {
|
|
20243
|
-
const prev =
|
|
20244
|
-
|
|
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) =>
|
|
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
|
|
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 =
|
|
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
|
-
|
|
20560
|
+
cache3[chainId] = { at: Date.now(), data };
|
|
20311
20561
|
return data;
|
|
20312
20562
|
} catch {
|
|
20313
|
-
const prev =
|
|
20314
|
-
|
|
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) =>
|
|
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
|
|
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: [
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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 ??
|
|
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) :
|
|
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
|
|
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 >
|
|
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
|
|
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 ??
|
|
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
|
|
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
|
|
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
|
|
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 >
|
|
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
|
|
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 >
|
|
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
|
|
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 >
|
|
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
|
|
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() +
|
|
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
|
|
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 !==
|
|
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 !==
|
|
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
|
-
|
|
57848
|
+
oracle {
|
|
57849
|
+
address
|
|
57850
|
+
}
|
|
57633
57851
|
loanAsset {
|
|
57634
57852
|
address
|
|
57635
57853
|
decimals
|
|
57636
|
-
|
|
57854
|
+
price {
|
|
57855
|
+
usd
|
|
57856
|
+
}
|
|
57637
57857
|
}
|
|
57638
57858
|
collateralAsset {
|
|
57639
57859
|
address
|
|
57640
57860
|
decimals
|
|
57641
|
-
|
|
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
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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
|
|
64669
|
+
if (v == null || v === "") return ZERO6;
|
|
64439
64670
|
try {
|
|
64440
64671
|
return BigInt(v);
|
|
64441
64672
|
} catch {
|
|
64442
|
-
return
|
|
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 ===
|
|
64449
|
-
let weightedRay =
|
|
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 ===
|
|
64687
|
+
if (allocated === ZERO6) continue;
|
|
64457
64688
|
weightedRay += allocated * apyRay;
|
|
64458
64689
|
}
|
|
64459
|
-
if (weightedRay ===
|
|
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 ===
|
|
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 =
|
|
64475
|
-
let withdrawable =
|
|
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 ===
|
|
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 :
|
|
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
|
|
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
|
|
75308
|
+
function cache5(slot, build6, store) {
|
|
75078
75309
|
const now = Date.now();
|
|
75079
|
-
if (slot && now - slot.at <
|
|
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
|
|
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
|
|
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
|
|
75349
|
-
var
|
|
75579
|
+
var CACHE_TTL_MS8 = 6e4;
|
|
75580
|
+
var cache6 = /* @__PURE__ */ new Map();
|
|
75350
75581
|
function clearSpectraMarketsCache() {
|
|
75351
|
-
|
|
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 =
|
|
75358
|
-
if (hit && now - hit.at <
|
|
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
|
-
|
|
75602
|
+
cache6.set(network, { at: now, promise });
|
|
75372
75603
|
promise.catch(() => {
|
|
75373
|
-
if (
|
|
75604
|
+
if (cache6.get(network)?.promise === promise) cache6.delete(network);
|
|
75374
75605
|
});
|
|
75375
75606
|
return promise;
|
|
75376
75607
|
}
|