@1delta/margin-fetcher 5.0.56 → 5.0.57

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 CHANGED
@@ -8559,6 +8559,17 @@ interface UpshiftVault extends VaultClassificationFields {
8559
8559
  vaultAddress: string;
8560
8560
  /** Underlying ERC-20 address (first accepted deposit asset), lowercased. */
8561
8561
  underlying: string;
8562
+ /**
8563
+ * EVERY asset the vault accepts, lowercased — `underlying` is only the
8564
+ * first of them.
8565
+ *
8566
+ * The entry is genuinely multi-asset (`deposit(asset, amount, receiver)`
8567
+ * names the asset it pulls), and several vaults take four or five: Clearstar
8568
+ * Prism accepts USDC, USDT, USDS, deUSD and sdeUSD. Publishing only the
8569
+ * first made the other legs unreachable — a caller paying USDT was told the
8570
+ * vault takes USDC, which is true and not the whole truth.
8571
+ */
8572
+ depositAssets: string[];
8562
8573
  /** Receipt-token symbol, e.g. `earnAUSD`. */
8563
8574
  symbol: string;
8564
8575
  /** Vault display name as returned by the API. */
@@ -8698,7 +8709,8 @@ type UpshiftVaults = {
8698
8709
  };
8699
8710
 
8700
8711
  /**
8701
- * One-shot fetcher for all visible Upshift vaults on a chain.
8712
+ * One-shot fetcher for the Upshift vaults on a chain (see
8713
+ * {@link isServable} for which of them we serve).
8702
8714
  *
8703
8715
  * HTTP-only (Upshift public REST listing) — no multicall executor needed,
8704
8716
  * mirroring the Lagoon fetcher. The endpoint is global; we filter to the
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import './chunk-BYTNVMX7.js';
3
3
  import './chunk-PR4QN5HX.js';
4
4
  import { Lender, isExactly, isMidnight, isTerm, isTermMax, isTeller, isListaDao, isLiquityFamily, isRiver, isInverse, isCooler, isDssType, isCompoundV3Type, isFluid, isGearboxV3, isLlamaLend, isFrankencoin, isResupply, isCurvance, isTwyne, isFraxlend, LIQUITY_FAMILY_LENDERS, isAaveType, isCompoundV3, isMultiMarket, isSiloV2Type, isSiloV3Type, isDolomite, hasCrossMarginRisk, isEulerType, isAaveV4Type, isInit, isMorphoType, isCompoundV2Type, isVenusType, isSumerType, AAVE_V3_LENDERS, AAVE_V2_LENDERS, isMorphoBlue, isAaveV2Type, isAaveV32Type, isAaveV3Type, isUsdd, isSky, isYLDR, isLista, hasSubAccounts, isTectonicType, isKineticType, isBenqiType } from '@1delta/lender-registry';
5
5
  export { hasCrossMarginRisk, isAaveType, isAaveV2Type, isAaveV32Type, isAaveV3Type, isCompoundV3, isCompoundV3Type, isInit, isMorphoType, isMultiMarket, isYLDR } from '@1delta/lender-registry';
6
- import { fetchTokenLists, fetchTokenList, aavePools, compoundV3Pools, initConfig, morphoPools, compoundV2Pools, eulerVaults, siloMarkets, siloV2LenderKey, siloMarketsV3, siloV3LenderKey, aaveV4Spokes, aaveV4SpokeLenderKey, fluidResolvers, gearboxResolvers, dolomiteConfigs, midnightConfig, termConfig, termMarketsByChain, exactlyConfig, liquityLendersByChain, riverLendersByChain, inverseLendersByChain, coolerLendersByChain, llamaLendLendersByChain, usddLendersByChain, skyLendersByChain, frankencoinLendersByChain, resupplyLendersByChain, curvanceLendersByChain, fraxlendLendersByChain, twyneLendersByChain, tellerConfigByChain, tellerPoolsByChain, termMaxConfigByChain, aaveReserves, compoundV3Reserves, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, termMaxApiBaseUrl, termMaxLenderKey, inverseConfigFor, inverseChainData, coolerConfigFor, llamaLendConfigFor, llamaLendChainData, llamaLendApiBaseUrl, resupplyConfigFor, fraxlendConfigFor, dssConfigFor, dssChainData, dssDebtToken, dssDebtJoin, frankencoinConfigFor, frankencoinChainData, aaveOracles, morphoTypeMarkets, resolveMidnightApiBase, resolveTermApiBase, llamaLendMarketByVault, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, curvanceConfigFor, aaveTokens, morphoTypeVaults, listaCollateralProvider, eulerConfigs, gearboxMarketCompressor, gearboxMarketConfigurators, gearboxV3LenderKey, midnightMarketsByChain, twyneConfigFor, twyneChainData, parseAaveV4SpokeLenderKey, fraxlendPairsFor, gearboxAccountCompressor, compoundV2Tokens, exactlyMarketsByChain, aaveOraclesConfig, compoundV2Oracles, compoundV2TokenArray, compoundV2OraclesConfig, compoundV3OraclesData, compoundV3BaseData, compoundV2Reserves, aaveV4Oracles } from '@1delta/data-sdk';
6
+ import { fetchTokenLists, fetchTokenList, aavePools, compoundV3Pools, initConfig, morphoPools, compoundV2Pools, eulerVaults, siloMarkets, siloV2LenderKey, siloMarketsV3, siloV3LenderKey, aaveV4Spokes, aaveV4SpokeLenderKey, fluidResolvers, gearboxResolvers, dolomiteConfigs, midnightConfig, termConfig, termMarketsByChain, exactlyConfig, liquityLendersByChain, riverLendersByChain, inverseLendersByChain, coolerLendersByChain, llamaLendLendersByChain, usddLendersByChain, skyLendersByChain, frankencoinLendersByChain, resupplyLendersByChain, curvanceLendersByChain, fraxlendLendersByChain, twyneLendersByChain, tellerConfigByChain, tellerPoolsByChain, termMaxConfigByChain, aaveReserves, compoundV3Reserves, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, termMaxApiBaseUrl, termMaxLenderKey, inverseConfigFor, inverseChainData, coolerConfigFor, llamaLendConfigFor, llamaLendChainData, llamaLendApiBaseUrl, resupplyConfigFor, fraxlendConfigFor, dssConfigFor, dssChainData, dssDebtToken, dssDebtJoin, frankencoinConfigFor, frankencoinChainData, aaveOracles, morphoTypeMarkets, resolveMidnightApiBase, resolveTermApiBase, llamaLendMarketByVault, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, curvanceConfigFor, aaveTokens, morphoTypeVaults, listaCollateralProvider, eulerConfigs, gearboxMarketCompressor, gearboxMarketConfigurators, gearboxV3LenderKey, midnightMarketsByChain, twyneConfigFor, twyneChainData, parseAaveV4SpokeLenderKey, fraxlendPairsFor, gearboxAccountCompressor, compoundV2Tokens, exactlyMarketsByChain, aaveOraclesConfig, compoundV2Oracles, compoundV2TokenArray, compoundV2OraclesConfig, compoundV3OraclesData, compoundV3BaseData, compoundV2Reserves, aaveV4Oracles, morphoTypeOracles } from '@1delta/data-sdk';
7
7
  import lodash from 'lodash';
8
8
  import { Chain } from '@1delta/chain-registry';
9
9
  import { multicallRetryUniversal, getEvmClient, getEvmChain, getEvmClientUniversal } from '@1delta/providers';
@@ -28325,6 +28325,99 @@ var getLenderPublicDataViaApi = async (chainId, lenders, prices, additionalYield
28325
28325
  }
28326
28326
  return lenderData;
28327
28327
  };
28328
+ var ERC20_BALANCE_OF_ABI2 = [
28329
+ {
28330
+ inputs: [{ name: "account", type: "address" }],
28331
+ name: "balanceOf",
28332
+ outputs: [{ name: "", type: "uint256" }],
28333
+ stateMutability: "view",
28334
+ type: "function"
28335
+ }
28336
+ ];
28337
+ var MORPHO_BLUE_BUCKET_PREFIX = "MORPHO_BLUE_";
28338
+ function formatBalance(raw, decimals) {
28339
+ if (raw === void 0 || raw === null || raw === "0x") return void 0;
28340
+ let value;
28341
+ try {
28342
+ value = BigInt(raw);
28343
+ } catch {
28344
+ return void 0;
28345
+ }
28346
+ return Number(value) / 10 ** decimals;
28347
+ }
28348
+ async function enrichMorphoCollateralTotals(chainId, result, prices, multicallRetry) {
28349
+ const morpho = morphoPools()?.MORPHO_BLUE?.[chainId];
28350
+ if (!morpho) return result;
28351
+ const markets = [];
28352
+ for (const [bucket, entry] of Object.entries(result)) {
28353
+ if (!bucket.startsWith(MORPHO_BLUE_BUCKET_PREFIX)) continue;
28354
+ const market = entry?.params?.market;
28355
+ const rows = entry?.data;
28356
+ if (!market || !rows) continue;
28357
+ const collateral = String(market.collateralAddress ?? "").toLowerCase();
28358
+ const loan = String(market.loanAddress ?? "").toLowerCase();
28359
+ if (!collateral || !loan) continue;
28360
+ const loanRow = rows[createMarketUid(chainId, bucket, loan)];
28361
+ const supply = Number(loanRow?.totalDeposits ?? 0);
28362
+ const borrow = Number(loanRow?.totalDebt ?? 0);
28363
+ const loanIdle = Number.isFinite(supply) && Number.isFinite(borrow) ? supply - borrow : 0;
28364
+ markets.push({
28365
+ bucket,
28366
+ collateralUid: createMarketUid(chainId, bucket, collateral),
28367
+ collateral,
28368
+ loan,
28369
+ collateralDecimals: Number(market.collateralDecimals ?? 18),
28370
+ loanIdle
28371
+ });
28372
+ }
28373
+ if (markets.length === 0) return result;
28374
+ const marketsByCollateral = /* @__PURE__ */ new Map();
28375
+ for (const m of markets) {
28376
+ const list = marketsByCollateral.get(m.collateral);
28377
+ if (list) list.push(m);
28378
+ else marketsByCollateral.set(m.collateral, [m]);
28379
+ }
28380
+ const soleCollateralTokens = [...marketsByCollateral.entries()].filter(([, list]) => list.length === 1).map(([token]) => token);
28381
+ if (soleCollateralTokens.length === 0) return result;
28382
+ let balances;
28383
+ try {
28384
+ balances = await multicallRetry({
28385
+ chain: chainId,
28386
+ calls: soleCollateralTokens.map((token) => ({
28387
+ address: token,
28388
+ functionName: "balanceOf",
28389
+ args: [morpho]
28390
+ })),
28391
+ abi: soleCollateralTokens.map(() => ERC20_BALANCE_OF_ABI2),
28392
+ allowFailure: true
28393
+ });
28394
+ } catch {
28395
+ return result;
28396
+ }
28397
+ const idleByToken = /* @__PURE__ */ new Map();
28398
+ for (const m of markets) {
28399
+ idleByToken.set(m.loan, (idleByToken.get(m.loan) ?? 0) + m.loanIdle);
28400
+ }
28401
+ soleCollateralTokens.forEach((token, i) => {
28402
+ const m = marketsByCollateral.get(token)[0];
28403
+ const balance = formatBalance(balances?.[i], m.collateralDecimals);
28404
+ if (balance === void 0) return;
28405
+ const total = balance - (idleByToken.get(token) ?? 0);
28406
+ if (!Number.isFinite(total) || total < 0) return;
28407
+ const row = result[m.bucket]?.data?.[m.collateralUid];
28408
+ if (!row) return;
28409
+ const priceKey = toOracleKey(row.asset?.assetGroup ?? null) || toGenericPriceKey(token, chainId);
28410
+ const price2 = prices[priceKey] ?? 0;
28411
+ const usd = total * price2;
28412
+ row.totalDeposits = total;
28413
+ row.totalLiquidity = total;
28414
+ row.borrowLiquidity = total;
28415
+ row.totalDepositsUSD = usd;
28416
+ row.totalLiquidityUSD = usd;
28417
+ row.borrowLiquidityUSD = usd;
28418
+ });
28419
+ return result;
28420
+ }
28328
28421
  var warn5 = (...args) => {
28329
28422
  };
28330
28423
  function lenderApiOnly(lender, chainId) {
@@ -28425,6 +28518,21 @@ var getLenderPublicDataAll = async (chainId, lenders, prices, additionalYields,
28425
28518
  e?.message ?? e
28426
28519
  );
28427
28520
  }
28521
+ if (lendersOnChain.some((l) => l === Lender.MORPHO_BLUE)) {
28522
+ try {
28523
+ onChainRes = await enrichMorphoCollateralTotals(
28524
+ chainId,
28525
+ onChainRes,
28526
+ prices,
28527
+ multicallRetry
28528
+ );
28529
+ } catch (e) {
28530
+ warn5(
28531
+ `[lending] morpho collateral enrichment failed for chain ${chainId}:`,
28532
+ e?.message ?? e
28533
+ );
28534
+ }
28535
+ }
28428
28536
  }
28429
28537
  return { ...onChainRes, ...apiRes };
28430
28538
  };
@@ -49837,8 +49945,13 @@ var UPSHIFT_CHAIN_IDS = /* @__PURE__ */ new Set([
49837
49945
  // Plasma
49838
49946
  "57073",
49839
49947
  // Ink
49840
- "999"
49948
+ "999",
49841
49949
  // HyperEVM
49950
+ // Citrea. Added 2026-08-19: the listing carries a live, visible $2.56M
49951
+ // RockawayX vault there (`Earn ctUSD`) that this gate was short-circuiting
49952
+ // away — the fetch itself is HTTP-only and chain-agnostic, so a chain
49953
+ // missing from this set is the only thing that can hide one.
49954
+ "4114"
49842
49955
  ]);
49843
49956
  var hasUpshiftVaults = (chainId) => UPSHIFT_CHAIN_IDS.has(String(chainId));
49844
49957
  async function fetchUpshiftApiVaults() {
@@ -51466,7 +51579,8 @@ function generateMorphoLenderKey(marketId) {
51466
51579
  }
51467
51580
  function getMorphoMarketsForChain(chainId, marketOverrides) {
51468
51581
  const chainOverrides = marketOverrides?.[chainId] ?? [];
51469
- return chainOverrides.map((override) => ({
51582
+ const markets = chainOverrides.length ? chainOverrides : morphoTypeOracles()?.[chainId]?.[Lender.MORPHO_BLUE] ?? [];
51583
+ return markets.map((override) => ({
51470
51584
  oracle: override.oracle,
51471
51585
  loanAsset: override.loanAsset,
51472
51586
  collateralAsset: override.collateralAsset,
@@ -65305,6 +65419,7 @@ function parseVault8(v, chainId, prices, tokenList) {
65305
65419
  const vaultAddr = (v?.address ?? receiptAddr).toLowerCase();
65306
65420
  const asset0 = v.depositAssets?.find((a) => a?.address);
65307
65421
  const assetAddr = (asset0?.address ?? "").toLowerCase();
65422
+ const depositAssets = (v.depositAssets ?? []).map((a) => (a?.address ?? "").toLowerCase()).filter((a) => isEvmAddress(a));
65308
65423
  if (!receiptAddr || !assetAddr) return null;
65309
65424
  if (!isEvmAddress(receiptAddr) || !isEvmAddress(assetAddr)) return null;
65310
65425
  const assetMeta = tokenList[assetAddr];
@@ -65342,6 +65457,7 @@ function parseVault8(v, chainId, prices, tokenList) {
65342
65457
  address: receiptAddr,
65343
65458
  vaultAddress: vaultAddr,
65344
65459
  underlying: assetAddr,
65460
+ depositAssets,
65345
65461
  symbol,
65346
65462
  name: name || symbol,
65347
65463
  decimals,
@@ -65392,6 +65508,7 @@ function parseVault8(v, chainId, prices, tokenList) {
65392
65508
  totalAssetsUsd
65393
65509
  };
65394
65510
  }
65511
+ var isServable = (v) => v?.isVisible !== false || v?.withdrawalOnly === true;
65395
65512
  var fetchUpshiftVaults = async (chainId, prices = {}, tokenList = {}) => {
65396
65513
  if (!hasUpshiftVaults(chainId)) return {};
65397
65514
  const items = await fetchUpshiftApiVaults();
@@ -65399,7 +65516,7 @@ var fetchUpshiftVaults = async (chainId, prices = {}, tokenList = {}) => {
65399
65516
  const out = {};
65400
65517
  for (const item of items) {
65401
65518
  if (Number(item?.chainId) !== want) continue;
65402
- if (item?.isVisible === false) continue;
65519
+ if (!isServable(item)) continue;
65403
65520
  const parsed = parseVault8(item, chainId, prices, tokenList);
65404
65521
  if (parsed) out[parsed.address] = parsed;
65405
65522
  }
@@ -74329,6 +74446,7 @@ function acceptsVaultZap(row, provider) {
74329
74446
  if (ZAP_EXCLUDED_PROVIDERS.has(provider)) return false;
74330
74447
  const share = row.shareToken?.address ?? row.ref;
74331
74448
  if (!share) return false;
74449
+ if (provider === "upshift" && isSplitUpshiftRow(row, share)) return false;
74332
74450
  try {
74333
74451
  const entry = findSavingsWithdrawEntry(row.chainId, share);
74334
74452
  if (entry && NON_4626_DEPOSIT_KINDS.has(entry.kind)) return false;
@@ -74337,6 +74455,10 @@ function acceptsVaultZap(row, provider) {
74337
74455
  }
74338
74456
  return true;
74339
74457
  }
74458
+ function isSplitUpshiftRow(row, share) {
74459
+ const deposit = (row.providerMeta ?? {}).depositContract;
74460
+ return typeof deposit === "string" && deposit.toLowerCase() !== String(share).toLowerCase();
74461
+ }
74340
74462
  function isSecondaryMarketRow(row) {
74341
74463
  const meta = row.providerMeta ?? {};
74342
74464
  if (meta.secondaryMarketOnly === true) return true;
@@ -74413,7 +74535,7 @@ function vaultCapabilities(row) {
74413
74535
  caps.push({
74414
74536
  action: "claim",
74415
74537
  async: false,
74416
- requires: claimRequires()
74538
+ requires: claimRequires(row, provider)
74417
74539
  });
74418
74540
  }
74419
74541
  if (supportsCancel(provider, meta)) {
@@ -74429,6 +74551,11 @@ function swapRoutedProvidersArePriceConsistent() {
74429
74551
  return [...SWAP_ROUTED_PROVIDERS].filter((p) => !isBookPriced(p));
74430
74552
  }
74431
74553
  function depositInputs(row, provider) {
74554
+ if (provider === "upshift") {
74555
+ const assets = (row.providerMeta ?? {}).depositAssets;
74556
+ if (!Array.isArray(assets) || assets.length < 2) return void 0;
74557
+ return assets.filter((a) => typeof a === "string").map((asset) => ({ asset, mode: "direct" }));
74558
+ }
74432
74559
  if (provider !== "lst") return void 0;
74433
74560
  const share = row.shareToken?.address ?? row.ref;
74434
74561
  if (!share) return void 0;
@@ -74475,7 +74602,10 @@ function requestRequires(provider) {
74475
74602
  if (isBookPriced(provider)) requires.push("slippage");
74476
74603
  return requires.length ? requires : void 0;
74477
74604
  }
74478
- function claimRequires(provider) {
74605
+ function claimRequires(row, provider) {
74606
+ const share = row.shareToken?.address ?? row.ref;
74607
+ if (provider === "upshift" && share && isSplitUpshiftRow(row, share))
74608
+ return ["claimableEpoch"];
74479
74609
  return void 0;
74480
74610
  }
74481
74611
  function supportsCancel(provider, meta) {