@1delta/margin-fetcher 0.0.339 → 0.0.341

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.
Files changed (43) hide show
  1. package/dist/abis/oracle/AaveOracle.d.ts +14 -0
  2. package/dist/abis/oracle/AaveOracle.d.ts.map +1 -1
  3. package/dist/index.d.ts +3 -3
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +625 -91
  6. package/dist/index.js.map +1 -1
  7. package/dist/prices/oracle-prices/derivation.d.ts +25 -0
  8. package/dist/prices/oracle-prices/derivation.d.ts.map +1 -0
  9. package/dist/prices/oracle-prices/feedStaleness.d.ts +44 -0
  10. package/dist/prices/oracle-prices/feedStaleness.d.ts.map +1 -0
  11. package/dist/prices/oracle-prices/feedStats.d.ts +145 -0
  12. package/dist/prices/oracle-prices/feedStats.d.ts.map +1 -0
  13. package/dist/prices/oracle-prices/fetchOraclePrices.d.ts +14 -2
  14. package/dist/prices/oracle-prices/fetchOraclePrices.d.ts.map +1 -1
  15. package/dist/prices/oracle-prices/fetchers/aave.d.ts +14 -0
  16. package/dist/prices/oracle-prices/fetchers/aave.d.ts.map +1 -1
  17. package/dist/prices/oracle-prices/fetchers/compoundV3.d.ts.map +1 -1
  18. package/dist/prices/oracle-prices/fetchers/euler.d.ts.map +1 -1
  19. package/dist/prices/oracle-prices/fetchers/morpho.d.ts.map +1 -1
  20. package/dist/prices/oracle-prices/index.d.ts +7 -2
  21. package/dist/prices/oracle-prices/index.d.ts.map +1 -1
  22. package/dist/prices/oracle-prices/lenderKeys.d.ts +18 -0
  23. package/dist/prices/oracle-prices/lenderKeys.d.ts.map +1 -0
  24. package/dist/prices/oracle-prices/outlierGuard.d.ts +43 -0
  25. package/dist/prices/oracle-prices/outlierGuard.d.ts.map +1 -0
  26. package/dist/prices/oracle-prices/selectAssetGroupPrices.d.ts +45 -4
  27. package/dist/prices/oracle-prices/selectAssetGroupPrices.d.ts.map +1 -1
  28. package/dist/prices/oracle-prices/types.d.ts +114 -1
  29. package/dist/prices/oracle-prices/types.d.ts.map +1 -1
  30. package/dist/prices/pendle/fetchPendlePrices.d.ts.map +1 -1
  31. package/dist/yields/intrinsic/fetcherRegistry.d.ts.map +1 -1
  32. package/dist/yields/intrinsic/fetchers/angle.d.ts.map +1 -1
  33. package/dist/yields/intrinsic/fetchers/anzen.d.ts +3 -0
  34. package/dist/yields/intrinsic/fetchers/anzen.d.ts.map +1 -0
  35. package/dist/yields/intrinsic/fetchers/liquidCollective.d.ts +3 -0
  36. package/dist/yields/intrinsic/fetchers/liquidCollective.d.ts.map +1 -0
  37. package/dist/yields/intrinsic/fetchers/reserve.d.ts.map +1 -1
  38. package/dist/yields/intrinsic/fetchers/stakewise.d.ts.map +1 -1
  39. package/dist/yields/intrinsic/fetchers/strata.d.ts +3 -0
  40. package/dist/yields/intrinsic/fetchers/strata.d.ts.map +1 -0
  41. package/dist/yields/intrinsic/fetchers/treehouse.d.ts +3 -0
  42. package/dist/yields/intrinsic/fetchers/treehouse.d.ts.map +1 -0
  43. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import './chunk-BYTNVMX7.js';
3
3
  import './chunk-PR4QN5HX.js';
4
4
  import { Lender, LIQUITY_FAMILY_LENDERS, isAaveType, isCompoundV3, isMultiMarket, isSiloV2Type, isSiloV3Type, isDolomite, isEulerType, isAaveV4Type, isInit, isMorphoType, isCompoundV2Type, isVenusType, isSumerType, AAVE_V3_LENDERS, AAVE_V2_LENDERS, isAaveV2Type, isAaveV32Type, isAaveV3Type, isFluid, isGearboxV3, isMidnight, isTerm, isExactly, isLiquityFamily, isRiver, isTeller, isYLDR, isCompoundV3Type, isLista, isTectonicType, isKineticType, isBenqiType } from '@1delta/lender-registry';
5
5
  export { 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, tellerConfigByChain, tellerPoolsByChain, aaveReserves, compoundV3Reserves, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, morphoTypeMarkets, resolveMidnightApiBase, resolveTermApiBase, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, aaveTokens, morphoTypeVaults, eulerConfigs, gearboxMarketCompressor, gearboxMarketConfigurators, gearboxV3LenderKey, midnightMarketsByChain, parseAaveV4SpokeLenderKey, gearboxAccountCompressor, compoundV2Tokens, exactlyMarketsByChain, aaveOracles, 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, tellerConfigByChain, tellerPoolsByChain, aaveReserves, compoundV3Reserves, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, aaveOracles, morphoTypeMarkets, resolveMidnightApiBase, resolveTermApiBase, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, aaveTokens, morphoTypeVaults, eulerConfigs, gearboxMarketCompressor, gearboxMarketConfigurators, gearboxV3LenderKey, midnightMarketsByChain, parseAaveV4SpokeLenderKey, gearboxAccountCompressor, compoundV2Tokens, exactlyMarketsByChain, aaveOraclesConfig, compoundV2Oracles, compoundV2TokenArray, compoundV2OraclesConfig, compoundV3OraclesData, compoundV3BaseData, compoundV2Reserves, aaveV4Oracles } from '@1delta/data-sdk';
7
7
  import lodash from 'lodash';
8
8
  import { getEvmClient, multicallRetryUniversal, getEvmChain, getEvmClientUniversal } from '@1delta/providers';
9
9
  import { LiquityTroveManagerAbi, LiquityActivePoolAbi, LiquityStabilityPoolAbi, LiquityPriceFeedAbi, LiquitySortedTrovesAbi, RiverTroveManagerAbi, RiverStabilityPoolAbi, TellerMarketRegistryAbi, TellerV2Abi, MetaMorphoAbi, ExactlyPreviewerAbi, ExactlyAuditorAbi, LenderCommitmentGroupAbi, FluidLendingResolverAbi, FluidVaultResolverAbi, FluidLiquidityResolverAbi, MoolahVaultAbi, MorphoLensAbi, AaveV4SpokeAbi, AaveV4OracleAbi, AaveV4HubAbi, DolomiteMarginAbi, GearboxMarketCompressorV310Abi, MorphoBlueAbi, MidnightAbi, TermRepoTokenAbi, TermRepoServicerAbi, TermRepoCollateralManagerAbi, LiquityTroveNFTAbi, LiquityCollSurplusPoolAbi, TellerCollateralManagerAbi, GearboxCreditAccountCompressorV310Abi, TermPriceConsumerAbi } from '@1delta/abis';
@@ -35208,7 +35208,12 @@ var osethFetcher = {
35208
35208
  operationName: "osTokenApy"
35209
35209
  })
35210
35210
  }).then((r) => r.json());
35211
- return { [osETH]: apyToAprPercent(res.data?.osTokens?.[0]?.apy) };
35211
+ const apr = apyToAprPercent(res.data?.osTokens?.[0]?.apy);
35212
+ return {
35213
+ [osETH]: apr,
35214
+ // token-lists unifies every osETH deployment (incl. bridged) to the bare `OSETH` group — emit there too.
35215
+ OSETH: apr
35216
+ };
35212
35217
  }
35213
35218
  };
35214
35219
 
@@ -37550,6 +37555,8 @@ var angleFetcher = {
37550
37555
  label: "ANGLE",
37551
37556
  fetch: async () => ({
37552
37557
  [stEur]: 0,
37558
+ // token-lists unifies every stEUR deployment to the bare `STEUR` group — emit there too.
37559
+ STEUR: 0,
37553
37560
  [stUSD]: 0
37554
37561
  })
37555
37562
  };
@@ -38298,10 +38305,13 @@ var rtokensFetcher = {
38298
38305
  const data = res?.rtokens?.["8453"];
38299
38306
  const dataMainnet = res?.rtokens?.["1"];
38300
38307
  const dataMainnetColalterals = res?.collaterals?.["1"];
38308
+ const sfrxethApr = apyToAprPercent((dataMainnetColalterals?.sfrxeth ?? 0) / 100) * 100;
38301
38309
  return {
38302
38310
  [bsdETH]: apyToAprPercent((data?.bsdETH ?? 0) / 100) * 100,
38303
38311
  [hyUSD]: apyToAprPercent((data?.hyUSD ?? 0) / 100) * 100,
38304
- [sfrxeth]: apyToAprPercent((dataMainnetColalterals?.sfrxeth ?? 0) / 100) * 100,
38312
+ [sfrxeth]: sfrxethApr,
38313
+ // token-lists unifies every sfrxETH deployment to the bare `SFRXETH` group — emit there too.
38314
+ SFRXETH: sfrxethApr,
38305
38315
  [sfrax]: apyToAprPercent((dataMainnetColalterals?.sfrax ?? 0) / 100) * 100,
38306
38316
  [ceth]: apyToAprPercent((dataMainnetColalterals?.ceth ?? 0) / 100) * 100,
38307
38317
  [ethPlus]: apyToAprPercent((dataMainnet?.["ETH+"] ?? 0) / 100) * 100,
@@ -38462,7 +38472,8 @@ async function fetchPendleYields(lists = {}) {
38462
38472
  const ptPrice = prices[market.pt];
38463
38473
  const ytPrice = prices[market.yt];
38464
38474
  const [chainId, address] = market.pt.split("-");
38465
- const assetKey = lists[chainId]?.list?.[address.toLowerCase()]?.assetGroup ?? market.pt;
38475
+ const assetKey = lists[chainId]?.list?.[address.toLowerCase()]?.assetGroup;
38476
+ if (!assetKey) return;
38466
38477
  const expiry = new Date(market.expiry);
38467
38478
  if (expiry <= now) {
38468
38479
  yields[assetKey] = 0;
@@ -38817,6 +38828,50 @@ var yearnKatanaFetcher = {
38817
38828
  }
38818
38829
  };
38819
38830
 
38831
+ // src/yields/intrinsic/fetchers/liquidCollective.ts
38832
+ var LSETH_POOL_ID = "465d177e-3d0d-42c0-b5f5-31c857567135";
38833
+ var KEYS = ["Liquid Staked ETH::LSETH", "LSETH"];
38834
+ var lsethFetcher = {
38835
+ label: "LSETH",
38836
+ fetch: async () => {
38837
+ const apr = apyToAprPercent(await fetchDefiLlamaApy(LSETH_POOL_ID));
38838
+ return Object.fromEntries(KEYS.map((k) => [k, apr]));
38839
+ }
38840
+ };
38841
+
38842
+ // src/yields/intrinsic/fetchers/treehouse.ts
38843
+ var TETH_POOL_ID = "5762f4a8-bb48-45d6-90ed-2d93d1777169";
38844
+ var KEYS2 = ["Treehouse ETH::tETH"];
38845
+ var tethFetcher = {
38846
+ label: "TETH",
38847
+ fetch: async () => {
38848
+ const apr = apyToAprPercent(await fetchDefiLlamaApy(TETH_POOL_ID));
38849
+ return Object.fromEntries(KEYS2.map((k) => [k, apr]));
38850
+ }
38851
+ };
38852
+
38853
+ // src/yields/intrinsic/fetchers/strata.ts
38854
+ var SRNUSD_POOL_ID = "979711ce-d0c0-4aae-a5fc-d7b76e868649";
38855
+ var KEYS3 = ["Strata Senior NUSD::srNUSD"];
38856
+ var srnusdFetcher = {
38857
+ label: "SRNUSD",
38858
+ fetch: async () => {
38859
+ const apr = apyToAprPercent(await fetchDefiLlamaApy(SRNUSD_POOL_ID));
38860
+ return Object.fromEntries(KEYS3.map((k) => [k, apr]));
38861
+ }
38862
+ };
38863
+
38864
+ // src/yields/intrinsic/fetchers/anzen.ts
38865
+ var SUSDZ_POOL_ID = "46518e93-8197-4539-9861-2340c2ac965a";
38866
+ var KEYS4 = ["Anzen Staked USDz::SUSDZ", "Anzen Staked USDz::sUSDz", "Staked USDz::sUSDz"];
38867
+ var susdzFetcher = {
38868
+ label: "SUSDZ",
38869
+ fetch: async () => {
38870
+ const apr = apyToAprPercent(await fetchDefiLlamaApy(SUSDZ_POOL_ID));
38871
+ return Object.fromEntries(KEYS4.map((k) => [k, apr]));
38872
+ }
38873
+ };
38874
+
38820
38875
  // src/yields/intrinsic/fetcherRegistry.ts
38821
38876
  var LENDING_ONLY_FETCHERS = [
38822
38877
  stmaticFetcher,
@@ -38842,7 +38897,12 @@ var LENDING_ONLY_FETCHERS = [
38842
38897
  nestFetcher,
38843
38898
  accountableFetcher,
38844
38899
  upshiftFetcher,
38845
- yearnKatanaFetcher
38900
+ yearnKatanaFetcher,
38901
+ // DefiLlama-mapped intrinsic yields for classifier assets lacking a bespoke source
38902
+ lsethFetcher,
38903
+ tethFetcher,
38904
+ srnusdFetcher,
38905
+ susdzFetcher
38846
38906
  ];
38847
38907
  var collectVaultFetchers = () => {
38848
38908
  const seen = /* @__PURE__ */ new Set();
@@ -39215,6 +39275,25 @@ var AaveOracleAbi = [
39215
39275
  ],
39216
39276
  stateMutability: "view",
39217
39277
  type: "function"
39278
+ },
39279
+ {
39280
+ inputs: [
39281
+ {
39282
+ internalType: "address",
39283
+ name: "asset",
39284
+ type: "address"
39285
+ }
39286
+ ],
39287
+ name: "getSourceOfAsset",
39288
+ outputs: [
39289
+ {
39290
+ internalType: "address",
39291
+ name: "",
39292
+ type: "address"
39293
+ }
39294
+ ],
39295
+ stateMutability: "view",
39296
+ type: "function"
39218
39297
  }
39219
39298
  ];
39220
39299
 
@@ -39571,6 +39650,8 @@ function processMarketsToEntries(chainId, allMarkets, source) {
39571
39650
  ) : 0;
39572
39651
  const resolvedLoanUSD = loanPriceUSD != null && loanPriceUSD > 0 ? loanPriceUSD : collateralPriceUSD != null && collateralPriceUSD > 0 && oracleRatio > 0 ? collateralPriceUSD / oracleRatio : 0;
39573
39652
  const resolvedCollateralUSD = collateralPriceUSD != null && collateralPriceUSD > 0 ? collateralPriceUSD : loanPriceUSD != null && loanPriceUSD > 0 && oracleRatio > 0 ? oracleRatio * loanPriceUSD : 0;
39653
+ const collateralFromApi = collateralPriceUSD != null && collateralPriceUSD > 0;
39654
+ const loanFromApi = loanPriceUSD != null && loanPriceUSD > 0;
39574
39655
  if (resolvedCollateralUSD > 0) {
39575
39656
  entries.push({
39576
39657
  asset: collateralAsset,
@@ -39579,7 +39660,8 @@ function processMarketsToEntries(chainId, allMarkets, source) {
39579
39660
  priceUSD: resolvedCollateralUSD,
39580
39661
  marketUid: createMarketUid(chainId, lenderKey, collateralAsset),
39581
39662
  targetLender: lenderKey,
39582
- baseAsset: loanAsset
39663
+ baseAsset: loanAsset,
39664
+ derivation: collateralFromApi ? "direct" : "derived"
39583
39665
  });
39584
39666
  }
39585
39667
  if (resolvedLoanUSD > 0) {
@@ -39591,7 +39673,8 @@ function processMarketsToEntries(chainId, allMarkets, source) {
39591
39673
  targetLender: lenderKey,
39592
39674
  description: "Morpho loan asset",
39593
39675
  staticBase: true,
39594
- baseAsset: loanAsset
39676
+ baseAsset: loanAsset,
39677
+ derivation: loanFromApi ? "direct" : "derived"
39595
39678
  });
39596
39679
  }
39597
39680
  }
@@ -40140,6 +40223,7 @@ var ChainlinkAggregatorAbi = [
40140
40223
  }
40141
40224
  ];
40142
40225
  var ANSWER_INDEX = 1;
40226
+ var UPDATED_AT_INDEX = 3;
40143
40227
  var CHAINLINK_DECIMALS = 8;
40144
40228
  var USD_PRICED_OVERRIDES = {
40145
40229
  [Lender.COMPOUND_V3_AERO]: /* @__PURE__ */ new Set(["8453"]),
@@ -40211,6 +40295,7 @@ function parseCompoundV3Results(data, meta, context) {
40211
40295
  priceUSD = rawPrice * baseAssetUSD;
40212
40296
  }
40213
40297
  }
40298
+ const updatedAtRaw = Array.isArray(rawResult) ? Number(rawResult[UPDATED_AT_INDEX]) : 0;
40214
40299
  entries.push({
40215
40300
  asset: assetLc,
40216
40301
  price: rawPrice,
@@ -40219,7 +40304,9 @@ function parseCompoundV3Results(data, meta, context) {
40219
40304
  marketUid: createMarketUid(chainId, queryMeta.lender, queryMeta.asset),
40220
40305
  description: queryMeta.description,
40221
40306
  staticBase: queryMeta.staticBase || void 0,
40222
- baseAsset: queryMeta.baseAsset
40307
+ baseAsset: queryMeta.baseAsset,
40308
+ updatedAt: updatedAtRaw > 0 ? updatedAtRaw : void 0,
40309
+ feedSource: updatedAtRaw > 0 ? queryMeta.oracle : void 0
40223
40310
  });
40224
40311
  } catch {
40225
40312
  }
@@ -40467,12 +40554,15 @@ function parseEulerV2Results(data, meta, context) {
40467
40554
  const priceInUoA = Number(amountOutMid) / Number(10n ** unitOfAccountDecimals);
40468
40555
  if (isNaN(priceInUoA) || priceInUoA === 0) return;
40469
40556
  let priceUSD;
40557
+ let derivation;
40470
40558
  if (isUsdUnitOfAccount(unitOfAccount)) {
40471
40559
  priceUSD = priceInUoA;
40560
+ derivation = "direct";
40472
40561
  } else {
40473
40562
  const uoaUSD = context.usdPrices[unitOfAccount] ?? 0;
40474
40563
  if (uoaUSD === 0) return;
40475
40564
  priceUSD = priceInUoA * uoaUSD;
40565
+ derivation = "quoted";
40476
40566
  }
40477
40567
  if (isNaN(priceUSD) || priceUSD === 0) return;
40478
40568
  if (priceUSD > MAX_SANE_PRICE_USD) return;
@@ -40484,7 +40574,8 @@ function parseEulerV2Results(data, meta, context) {
40484
40574
  context.chainId,
40485
40575
  queryMeta.lender,
40486
40576
  queryMeta.vault
40487
- )
40577
+ ),
40578
+ derivation
40488
40579
  });
40489
40580
  } catch {
40490
40581
  }
@@ -41197,7 +41288,7 @@ function lookupUSD3(context, asset) {
41197
41288
  return context.usdPrices[groupKey] ?? context.usdPrices[lc] ?? 0;
41198
41289
  }
41199
41290
  function parseSiloV2GraphQLResults(items, context) {
41200
- const ZERO_ADDRESS7 = "0x0000000000000000000000000000000000000000";
41291
+ const ZERO_ADDRESS8 = "0x0000000000000000000000000000000000000000";
41201
41292
  const out = [];
41202
41293
  const seen = /* @__PURE__ */ new Set();
41203
41294
  for (const item of items) {
@@ -41220,8 +41311,8 @@ function parseSiloV2GraphQLResults(items, context) {
41220
41311
  const partnerTokenLc = other.token.toLowerCase();
41221
41312
  const dedupKey = `${lenderKey}:${tokenLc}`;
41222
41313
  if (seen.has(dedupKey)) continue;
41223
- const oracleAddr = (side.solvencyOracleAddress ?? side.solvencyOracle?.id ?? self.solvencyOracle ?? ZERO_ADDRESS7).toLowerCase();
41224
- const isStatic = !oracleAddr || oracleAddr === ZERO_ADDRESS7;
41314
+ const oracleAddr = (side.solvencyOracleAddress ?? side.solvencyOracle?.id ?? self.solvencyOracle ?? ZERO_ADDRESS8).toLowerCase();
41315
+ const isStatic = !oracleAddr || oracleAddr === ZERO_ADDRESS8;
41225
41316
  const siloAddrLc = self.silo.toLowerCase();
41226
41317
  try {
41227
41318
  let priceUSD = 0;
@@ -41339,7 +41430,7 @@ function lookupUSD4(context, asset) {
41339
41430
  return context.usdPrices[groupKey] ?? context.usdPrices[lc] ?? 0;
41340
41431
  }
41341
41432
  function parseSiloV3GraphQLResults(items, context) {
41342
- const ZERO_ADDRESS7 = "0x0000000000000000000000000000000000000000";
41433
+ const ZERO_ADDRESS8 = "0x0000000000000000000000000000000000000000";
41343
41434
  const out = [];
41344
41435
  const seen = /* @__PURE__ */ new Set();
41345
41436
  for (const item of items) {
@@ -41362,8 +41453,8 @@ function parseSiloV3GraphQLResults(items, context) {
41362
41453
  const partnerTokenLc = other.token.toLowerCase();
41363
41454
  const dedupKey = `${lenderKey}:${tokenLc}`;
41364
41455
  if (seen.has(dedupKey)) continue;
41365
- const oracleAddr = (side.solvencyOracleAddress ?? side.solvencyOracle?.id ?? self.solvencyOracle ?? ZERO_ADDRESS7).toLowerCase();
41366
- const isStatic = !oracleAddr || oracleAddr === ZERO_ADDRESS7;
41456
+ const oracleAddr = (side.solvencyOracleAddress ?? side.solvencyOracle?.id ?? self.solvencyOracle ?? ZERO_ADDRESS8).toLowerCase();
41457
+ const isStatic = !oracleAddr || oracleAddr === ZERO_ADDRESS8;
41367
41458
  const siloAddrLc = self.silo.toLowerCase();
41368
41459
  try {
41369
41460
  let priceUSD = 0;
@@ -41472,6 +41563,116 @@ async function fetchMorphoMysticPrices(chainId) {
41472
41563
  return null;
41473
41564
  }
41474
41565
  }
41566
+ var DESCRIPTION_ABI = [
41567
+ {
41568
+ inputs: [],
41569
+ name: "description",
41570
+ outputs: [{ internalType: "string", name: "", type: "string" }],
41571
+ stateMutability: "view",
41572
+ type: "function"
41573
+ }
41574
+ ];
41575
+ var AGGREGATOR_ABI = [...ChainlinkAggregatorAbi, ...DESCRIPTION_ABI];
41576
+ function isFailed(r) {
41577
+ return r === "0x" || r === void 0 || r === null;
41578
+ }
41579
+ var ZERO_ADDRESS7 = "0x0000000000000000000000000000000000000000";
41580
+ async function probeAaveFeedTimestamps(chainId, options = {}) {
41581
+ const { rpcOverrides, batchSize, retries = 2 } = options;
41582
+ const result = {};
41583
+ const oracles = aaveOracles() ?? {};
41584
+ const reserves = aaveReserves() ?? {};
41585
+ const jobs = [];
41586
+ for (const [lender, chains] of Object.entries(oracles)) {
41587
+ const oracle = chains?.[chainId];
41588
+ const assets = reserves[lender]?.[chainId] ?? [];
41589
+ if (!oracle || assets.length === 0) continue;
41590
+ for (const asset of assets) jobs.push({ lender, oracle, asset });
41591
+ }
41592
+ if (jobs.length === 0) return result;
41593
+ try {
41594
+ const sourceResults = await multicallRetryUniversal({
41595
+ chain: chainId,
41596
+ calls: jobs.map((j) => ({
41597
+ address: j.oracle,
41598
+ name: "getSourceOfAsset",
41599
+ params: [j.asset]
41600
+ })),
41601
+ abi: AaveOracleAbi,
41602
+ batchSize,
41603
+ maxRetries: retries,
41604
+ providerId: void 0,
41605
+ allowFailure: true,
41606
+ overrdies: rpcOverrides,
41607
+ logErrors: false
41608
+ });
41609
+ const sourceOf = /* @__PURE__ */ new Map();
41610
+ const uniqueSources = [];
41611
+ const sourceIndex = /* @__PURE__ */ new Map();
41612
+ jobs.forEach((_3, i) => {
41613
+ const raw = sourceResults[i];
41614
+ if (isFailed(raw)) return;
41615
+ const source = String(raw).toLowerCase();
41616
+ if (source === ZERO_ADDRESS7) return;
41617
+ sourceOf.set(i, source);
41618
+ if (!sourceIndex.has(source)) {
41619
+ sourceIndex.set(source, uniqueSources.length);
41620
+ uniqueSources.push(source);
41621
+ }
41622
+ });
41623
+ if (uniqueSources.length === 0) return result;
41624
+ const roundResults = await multicallRetryUniversal({
41625
+ chain: chainId,
41626
+ calls: uniqueSources.flatMap((source) => [
41627
+ { address: source, name: "latestRoundData", params: [] },
41628
+ { address: source, name: "description", params: [] }
41629
+ ]),
41630
+ abi: AGGREGATOR_ABI,
41631
+ batchSize,
41632
+ maxRetries: retries,
41633
+ providerId: void 0,
41634
+ allowFailure: true,
41635
+ overrdies: rpcOverrides,
41636
+ logErrors: false
41637
+ });
41638
+ const infoOfSource = /* @__PURE__ */ new Map();
41639
+ uniqueSources.forEach((source, i) => {
41640
+ const round = roundResults[i * 2];
41641
+ const description = roundResults[i * 2 + 1];
41642
+ if (isFailed(round) || !Array.isArray(round)) return;
41643
+ const updatedAt = Number(round[3]);
41644
+ if (!(updatedAt > 0)) return;
41645
+ infoOfSource.set(source, {
41646
+ source,
41647
+ updatedAt,
41648
+ description: isFailed(description) ? void 0 : String(description)
41649
+ });
41650
+ });
41651
+ for (const [i, source] of sourceOf) {
41652
+ const info = infoOfSource.get(source);
41653
+ if (!info) continue;
41654
+ const { lender, asset } = jobs[i];
41655
+ if (!result[lender]) result[lender] = {};
41656
+ result[lender][asset.toLowerCase()] = info;
41657
+ }
41658
+ } catch {
41659
+ return result;
41660
+ }
41661
+ return result;
41662
+ }
41663
+
41664
+ // src/prices/oracle-prices/derivation.ts
41665
+ var DERIVATION_RANK = {
41666
+ direct: 0,
41667
+ quoted: 1,
41668
+ derived: 2
41669
+ };
41670
+ function resolveDerivation(entry, groupDefault) {
41671
+ if (entry.derivation) return entry.derivation;
41672
+ if (groupDefault === "derived") return "derived";
41673
+ if (entry.baseAsset && !entry.staticBase) return "quoted";
41674
+ return groupDefault ?? "direct";
41675
+ }
41475
41676
 
41476
41677
  // src/prices/oracle-prices/fetchOraclePrices.ts
41477
41678
  function countFailures(data, offset, count) {
@@ -41489,11 +41690,12 @@ function safeGetCalls(fetcherName, fn, errors) {
41489
41690
  return [];
41490
41691
  }
41491
41692
  }
41492
- function buildGroup(fetcherName, results, parse, abi) {
41693
+ function buildGroup(fetcherName, results, parse, abi, derivation) {
41493
41694
  const group = {
41494
41695
  fetcherName,
41495
41696
  calls: [],
41496
41697
  abi,
41698
+ derivation,
41497
41699
  trackers: []
41498
41700
  };
41499
41701
  for (const fr of results) {
@@ -41508,7 +41710,7 @@ function buildGroup(fetcherName, results, parse, abi) {
41508
41710
  }
41509
41711
  return group;
41510
41712
  }
41511
- function isFailed(r) {
41713
+ function isFailed2(r) {
41512
41714
  return r === "0x" || r === void 0;
41513
41715
  }
41514
41716
  async function executeGroup(group, chainId, chainBatchSize, retries, allowFailure, rpcOverrides, failRetries = 2) {
@@ -41527,7 +41729,7 @@ async function executeGroup(group, chainId, chainBatchSize, retries, allowFailur
41527
41729
  overrdies: rpcOverrides,
41528
41730
  logErrors: true
41529
41731
  });
41530
- let failedIndices = results.map((r, i) => isFailed(r) ? i : -1).filter((i) => i >= 0);
41732
+ let failedIndices = results.map((r, i) => isFailed2(r) ? i : -1).filter((i) => i >= 0);
41531
41733
  for (let round = 0; round < failRetries && failedIndices.length > 0; round++) {
41532
41734
  const retryCalls = failedIndices.map((i) => group.calls[i]);
41533
41735
  try {
@@ -41545,7 +41747,7 @@ async function executeGroup(group, chainId, chainBatchSize, retries, allowFailur
41545
41747
  });
41546
41748
  const stillFailed = [];
41547
41749
  for (let j = 0; j < failedIndices.length; j++) {
41548
- if (!isFailed(retryResults[j])) {
41750
+ if (!isFailed2(retryResults[j])) {
41549
41751
  results[failedIndices[j]] = retryResults[j];
41550
41752
  } else {
41551
41753
  stillFailed.push(failedIndices[j]);
@@ -41556,7 +41758,7 @@ async function executeGroup(group, chainId, chainBatchSize, retries, allowFailur
41556
41758
  break;
41557
41759
  }
41558
41760
  }
41559
- const failCount = results.filter((r) => isFailed(r)).length;
41761
+ const failCount = results.filter((r) => isFailed2(r)).length;
41560
41762
  const allFailed = failCount === results.length && results.length > 0;
41561
41763
  return {
41562
41764
  results,
@@ -41570,7 +41772,7 @@ async function executeGroup(group, chainId, chainBatchSize, retries, allowFailur
41570
41772
  };
41571
41773
  }
41572
41774
  }
41573
- async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3, batchSize = void 0, allowFailure = true, basePrices = {}, morphoMarketOverrides, listaMarketOverrides, stalenessThresholdSeconds = 3600, onlyFetchers) {
41775
+ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3, batchSize = void 0, allowFailure = true, basePrices = {}, morphoMarketOverrides, listaMarketOverrides, stalenessThresholdSeconds = 3600, onlyFetchers, probeFeedStaleness = true) {
41574
41776
  const totalStart = Date.now();
41575
41777
  const result = {};
41576
41778
  const chainPromises = chainIds.map(async (chainId) => {
@@ -41638,7 +41840,11 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
41638
41840
  () => exactlyFetcher.getCalls(chainId),
41639
41841
  getCallsErrors
41640
41842
  ) : [];
41641
- const termResults = isActive("term") ? safeGetCalls("term", () => termFetcher.getCalls(chainId), getCallsErrors) : [];
41843
+ const termResults = isActive("term") ? safeGetCalls(
41844
+ "term",
41845
+ () => termFetcher.getCalls(chainId),
41846
+ getCallsErrors
41847
+ ) : [];
41642
41848
  const liquityResults = isActive("liquity") ? safeGetCalls(
41643
41849
  "liquity",
41644
41850
  () => liquityFetcher.getCalls(chainId),
@@ -41683,109 +41889,127 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
41683
41889
  "aave",
41684
41890
  aaveResults,
41685
41891
  aaveFetcher.parse,
41686
- AaveOracleAbi
41892
+ AaveOracleAbi,
41893
+ "direct"
41687
41894
  );
41688
41895
  const compoundV2Group = buildGroup(
41689
41896
  "compoundV2",
41690
41897
  compoundV2Results,
41691
41898
  compoundV2Fetcher.parse,
41692
- CompoundV2OracleAbi
41899
+ CompoundV2OracleAbi,
41900
+ "direct"
41693
41901
  );
41694
41902
  const compoundV3Group = buildGroup(
41695
41903
  "compoundV3",
41696
41904
  compoundV3Results,
41697
41905
  compoundV3Fetcher.parse,
41698
- ChainlinkAggregatorAbi
41906
+ ChainlinkAggregatorAbi,
41907
+ "direct"
41699
41908
  );
41700
41909
  const listaGroup = buildGroup(
41701
41910
  "lista",
41702
41911
  listaResults,
41703
41912
  listaFetcher.parse,
41704
- ProxyOracleAbi
41913
+ ProxyOracleAbi,
41914
+ "direct"
41705
41915
  );
41706
41916
  const eulerGroup = buildGroup(
41707
41917
  "eulerV2",
41708
41918
  eulerResults,
41709
41919
  eulerV2Fetcher.parse,
41710
- getEulerV2Abi()
41920
+ getEulerV2Abi(),
41921
+ "direct"
41711
41922
  );
41712
41923
  const aaveV4Group = buildGroup(
41713
41924
  "aaveV4",
41714
41925
  aaveV4Results,
41715
41926
  aaveV4Fetcher.parse,
41716
- getAaveV4Abi()
41927
+ getAaveV4Abi(),
41928
+ "direct"
41717
41929
  );
41718
41930
  const morphoGroup = buildGroup(
41719
41931
  "morpho",
41720
41932
  morphoResults,
41721
41933
  morphoFetcher.parse,
41722
- ProxyOracleAbi
41934
+ ProxyOracleAbi,
41935
+ "derived"
41723
41936
  );
41724
41937
  const midnightGroup = buildGroup(
41725
41938
  "midnight",
41726
41939
  midnightResults,
41727
41940
  midnightFetcher.parse,
41728
- ProxyOracleAbi
41941
+ ProxyOracleAbi,
41942
+ "derived"
41729
41943
  );
41730
41944
  const exactlyGroup = buildGroup(
41731
41945
  "exactly",
41732
41946
  exactlyResults,
41733
41947
  exactlyFetcher.parse,
41734
- getExactlyAbi()
41948
+ getExactlyAbi(),
41949
+ "direct"
41735
41950
  );
41736
41951
  const termGroup = buildGroup(
41737
41952
  "term",
41738
41953
  termResults,
41739
41954
  termFetcher.parse,
41740
- getTermAbi()
41955
+ getTermAbi(),
41956
+ "direct"
41741
41957
  );
41742
41958
  const liquityGroup = buildGroup(
41743
41959
  "liquity",
41744
41960
  liquityResults,
41745
41961
  liquityFetcher.parse,
41746
- getLiquityAbi()
41962
+ getLiquityAbi(),
41963
+ "direct"
41747
41964
  );
41748
41965
  const riverGroup = buildGroup(
41749
41966
  "river",
41750
41967
  riverResults,
41751
41968
  riverFetcher.parse,
41752
- getRiverAbi()
41969
+ getRiverAbi(),
41970
+ "direct"
41753
41971
  );
41754
41972
  const tellerGroup = buildGroup(
41755
41973
  "teller",
41756
41974
  tellerResults,
41757
41975
  tellerFetcher.parse,
41758
- getTellerAbi()
41976
+ getTellerAbi(),
41977
+ "derived"
41759
41978
  );
41760
41979
  const siloV2Group = buildGroup(
41761
41980
  "siloV2",
41762
41981
  siloV2Results,
41763
41982
  siloV2Fetcher.parse,
41764
- getSiloV2Abi()
41983
+ getSiloV2Abi(),
41984
+ "derived"
41765
41985
  );
41766
41986
  const siloV3Group = buildGroup(
41767
41987
  "siloV3",
41768
41988
  siloV3Results,
41769
41989
  siloV3Fetcher.parse,
41770
- getSiloV3Abi()
41990
+ getSiloV3Abi(),
41991
+ "derived"
41771
41992
  );
41772
41993
  const fluidGroup = buildGroup(
41773
41994
  "fluid",
41774
41995
  fluidResults,
41775
41996
  fluidFetcher.parse,
41776
- getFluidAbi()
41997
+ getFluidAbi(),
41998
+ "derived"
41777
41999
  );
41778
42000
  const gearboxV3Group = buildGroup(
41779
42001
  "gearboxV3",
41780
42002
  gearboxV3Results,
41781
42003
  gearboxV3Fetcher.parse,
41782
- getGearboxV3Abi()
42004
+ getGearboxV3Abi(),
42005
+ "derived"
41783
42006
  );
41784
42007
  const dolomiteGroup = buildGroup(
41785
42008
  "dolomite",
41786
42009
  dolomiteResults,
41787
42010
  dolomiteFetcher.parse,
41788
- getDolomiteAbi()
42011
+ getDolomiteAbi(),
42012
+ "direct"
41789
42013
  );
41790
42014
  const allGroups = [
41791
42015
  aaveGroup,
@@ -41826,6 +42050,11 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
41826
42050
  const morphoGqlPromise = morphoUseMystic ? fetchMorphoMysticPrices(chainId) : morphoUseApi ? fetchMorphoGraphQLPrices(chainId) : Promise.resolve(null);
41827
42051
  const siloV2GqlPromise = isActive("silov2") ? fetchSiloV2GraphQLPrices(chainId, basePrices, tokenList) : Promise.resolve(null);
41828
42052
  const siloV3GqlPromise = isActive("silov3") ? fetchSiloV3GraphQLPrices(chainId, basePrices, tokenList) : Promise.resolve(null);
42053
+ const feedTimestampsPromise = stalenessThresholdSeconds > 0 && probeFeedStaleness ? probeAaveFeedTimestamps(chainId, {
42054
+ rpcOverrides,
42055
+ batchSize: chainBatchSize,
42056
+ retries
42057
+ }) : Promise.resolve({});
41829
42058
  const [
41830
42059
  aaveData,
41831
42060
  compoundV2Data,
@@ -42052,6 +42281,7 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
42052
42281
  if (!chainResult[lender]) {
42053
42282
  chainResult[lender] = [];
42054
42283
  }
42284
+ entry.derivation = resolveDerivation(entry, group.derivation);
42055
42285
  chainResult[lender].push(entry);
42056
42286
  if (updatePrices) {
42057
42287
  const oracleKey = tokenList[entry.asset]?.assetGroup ?? `${chainId}-${entry.asset}`;
@@ -42076,29 +42306,6 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
42076
42306
  parseTrackers(listaGroup, listaData.results);
42077
42307
  parseTrackers(eulerGroup, eulerData.results);
42078
42308
  parseTrackers(aaveV4Group, aaveV4Data.results);
42079
- if (stalenessThresholdSeconds > 0) {
42080
- const nowSeconds = Math.floor(Date.now() / 1e3);
42081
- for (const tracker of compoundV3Group.trackers) {
42082
- const meta = tracker.meta;
42083
- for (let i = 0; i < tracker.count; i++) {
42084
- const raw = compoundV3Data.results[tracker.offset + i];
42085
- if (!raw || raw === "0x" || !Array.isArray(raw)) continue;
42086
- const updatedAt = Number(raw[3]);
42087
- if (updatedAt > 0) {
42088
- const staleSeconds = nowSeconds - updatedAt;
42089
- if (staleSeconds > stalenessThresholdSeconds) {
42090
- const queryMeta = meta[i];
42091
- staleFeeds.push({
42092
- asset: queryMeta?.asset?.toLowerCase() ?? "unknown",
42093
- lender: queryMeta?.lender ?? tracker.lender,
42094
- oracle: queryMeta?.oracle ?? "unknown",
42095
- staleSeconds
42096
- });
42097
- }
42098
- }
42099
- }
42100
- }
42101
- }
42102
42309
  parseTrackers(
42103
42310
  aaveGroup,
42104
42311
  aaveData.results,
@@ -42122,6 +42329,7 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
42122
42329
  for (const entry of siloV2GqlEntries) {
42123
42330
  const lender = entry.targetLender ?? "SILO_V2";
42124
42331
  if (!chainResult[lender]) chainResult[lender] = [];
42332
+ entry.derivation = resolveDerivation(entry, "derived");
42125
42333
  chainResult[lender].push(entry);
42126
42334
  const oracleKey = tokenList[entry.asset]?.assetGroup ?? `${chainId}-${entry.asset}`;
42127
42335
  usdPrices[oracleKey] = entry.priceUSD;
@@ -42141,6 +42349,7 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
42141
42349
  for (const entry of siloV3GqlEntries) {
42142
42350
  const lender = entry.targetLender ?? "SILO_V3";
42143
42351
  if (!chainResult[lender]) chainResult[lender] = [];
42352
+ entry.derivation = resolveDerivation(entry, "derived");
42144
42353
  chainResult[lender].push(entry);
42145
42354
  const oracleKey = tokenList[entry.asset]?.assetGroup ?? `${chainId}-${entry.asset}`;
42146
42355
  usdPrices[oracleKey] = entry.priceUSD;
@@ -42172,6 +42381,7 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
42172
42381
  const key = `${lender}|${entry.marketUid}|${entry.asset}`;
42173
42382
  if (onChainKeys.has(key)) continue;
42174
42383
  if (!chainResult[lender]) chainResult[lender] = [];
42384
+ entry.derivation = resolveDerivation(entry, "derived");
42175
42385
  chainResult[lender].push(entry);
42176
42386
  gqlPushed++;
42177
42387
  }
@@ -42191,6 +42401,7 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
42191
42401
  for (const entry of morphoGqlEntries) {
42192
42402
  const lender = entry.targetLender ?? "MORPHO_BLUE";
42193
42403
  if (!chainResult[lender]) chainResult[lender] = [];
42404
+ entry.derivation = resolveDerivation(entry, "derived");
42194
42405
  chainResult[lender].push(entry);
42195
42406
  }
42196
42407
  trackerDiags.push(morphoGqlDiag);
@@ -42217,6 +42428,39 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
42217
42428
  }
42218
42429
  parseTrackers(midnightGroup, midnightData.results, false);
42219
42430
  parseTrackers(tellerGroup, tellerData.results, false);
42431
+ if (stalenessThresholdSeconds > 0) {
42432
+ const feedTimestamps = await feedTimestampsPromise;
42433
+ for (const [lender, assetMap] of Object.entries(feedTimestamps)) {
42434
+ for (const entry of chainResult[lender] ?? []) {
42435
+ const info = assetMap[entry.asset];
42436
+ if (!info) continue;
42437
+ entry.updatedAt = info.updatedAt;
42438
+ entry.feedSource = info.source;
42439
+ if (!entry.description && info.description) {
42440
+ entry.description = info.description;
42441
+ }
42442
+ }
42443
+ }
42444
+ const nowSeconds = Math.floor(Date.now() / 1e3);
42445
+ const reported = /* @__PURE__ */ new Set();
42446
+ for (const [lender, entries] of Object.entries(chainResult)) {
42447
+ for (const entry of entries) {
42448
+ if (!entry.updatedAt || entry.updatedAt <= 0) continue;
42449
+ const staleSeconds = nowSeconds - entry.updatedAt;
42450
+ if (staleSeconds <= stalenessThresholdSeconds) continue;
42451
+ const key = `${lender}|${entry.asset}|${entry.feedSource ?? ""}`;
42452
+ if (reported.has(key)) continue;
42453
+ reported.add(key);
42454
+ staleFeeds.push({
42455
+ asset: entry.asset,
42456
+ lender,
42457
+ oracle: entry.feedSource ?? "unknown",
42458
+ staleSeconds,
42459
+ description: entry.description
42460
+ });
42461
+ }
42462
+ }
42463
+ }
42220
42464
  const totalFailedCalls = trackerDiags.reduce(
42221
42465
  (sum, d) => sum + d.failedCalls,
42222
42466
  0
@@ -42272,6 +42516,217 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
42272
42516
  };
42273
42517
  return { prices: result, diagnostics };
42274
42518
  }
42519
+
42520
+ // src/prices/oracle-prices/lenderKeys.ts
42521
+ function lenderFamily(lender) {
42522
+ return lender.replace(/_(0X)?[0-9A-F]{6,}$/i, "");
42523
+ }
42524
+
42525
+ // src/prices/oracle-prices/outlierGuard.ts
42526
+ var DEFAULT_OUTLIER_GUARD = {
42527
+ minAgreeingFamilies: 3,
42528
+ agreementTolerance: 0.05,
42529
+ rejectFactor: 2
42530
+ };
42531
+ function median(values) {
42532
+ const sorted = [...values].sort((a, b) => a - b);
42533
+ const mid = Math.floor(sorted.length / 2);
42534
+ return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
42535
+ }
42536
+ function consensusReference(candidates, guard = DEFAULT_OUTLIER_GUARD) {
42537
+ if (candidates.length < guard.minAgreeingFamilies) return void 0;
42538
+ const perFeed = /* @__PURE__ */ new Map();
42539
+ for (const c of candidates) {
42540
+ const bucket = perFeed.get(c.feedKey);
42541
+ if (bucket) bucket.push(c.priceUSD);
42542
+ else perFeed.set(c.feedKey, [c.priceUSD]);
42543
+ }
42544
+ if (perFeed.size < guard.minAgreeingFamilies) return void 0;
42545
+ const feedPrices = [...perFeed.values()].map(median);
42546
+ const reference = median(feedPrices);
42547
+ if (!(reference > 0)) return void 0;
42548
+ const agreeing = feedPrices.filter(
42549
+ (p) => Math.abs(p / reference - 1) <= guard.agreementTolerance
42550
+ ).length;
42551
+ if (agreeing < guard.minAgreeingFamilies) return void 0;
42552
+ return reference;
42553
+ }
42554
+ function rejectOutliers(candidates, guard = DEFAULT_OUTLIER_GUARD) {
42555
+ const reference = consensusReference(candidates, guard);
42556
+ if (reference === void 0) return candidates;
42557
+ const upper = reference * guard.rejectFactor;
42558
+ const lower = reference / guard.rejectFactor;
42559
+ const kept = candidates.filter(
42560
+ (c) => c.priceUSD <= upper && c.priceUSD >= lower
42561
+ );
42562
+ return kept.length > 0 ? kept : candidates;
42563
+ }
42564
+
42565
+ // src/prices/oracle-prices/feedStats.ts
42566
+ var EWMA_ALPHA = 0.1;
42567
+ var MIN_DEVIATION_SAMPLES = 5;
42568
+ var BAD_DEVIATION = 0.25;
42569
+ var DEGRADED_DEVIATION = 0.05;
42570
+ var STALE_INTERVAL_MULTIPLE = 4;
42571
+ var MIN_LEARNED_STALE_SECONDS = 6 * 3600;
42572
+ var MIN_UPDATES_FOR_INTERVAL = 4;
42573
+ var FRESHNESS_RANK = {
42574
+ fresh: 0,
42575
+ unknown: 0,
42576
+ // absence of evidence must not demote
42577
+ stale: 1
42578
+ };
42579
+ var RELIABILITY_RANK = {
42580
+ good: 0,
42581
+ unknown: 0,
42582
+ // absence of evidence must not demote
42583
+ degraded: 1,
42584
+ bad: 2
42585
+ };
42586
+ function feedKeyOf(entry, lender) {
42587
+ if (entry.feedSource) return entry.feedSource.toLowerCase();
42588
+ return `${lenderFamily(lender)}|${entry.asset.toLowerCase()}`;
42589
+ }
42590
+ function feedStatKey(chainId, feedKey) {
42591
+ return `${chainId}|${feedKey}`;
42592
+ }
42593
+ function ewma(prev, sample) {
42594
+ if (prev === void 0 || !(prev > 0)) return sample;
42595
+ return prev * (1 - EWMA_ALPHA) + sample * EWMA_ALPHA;
42596
+ }
42597
+ function updateFeedStats(prev, observations, nowSeconds = Math.floor(Date.now() / 1e3)) {
42598
+ const next = { ...prev };
42599
+ for (const obs of observations) {
42600
+ const key = feedStatKey(obs.chainId, obs.feedKey);
42601
+ const existing = next[key];
42602
+ const stat = existing ? { ...existing } : {
42603
+ chainId: obs.chainId,
42604
+ feedKey: obs.feedKey,
42605
+ lastUpdatedAt: 0,
42606
+ lastObservedAt: nowSeconds,
42607
+ updates: 0,
42608
+ intervalEwmaSeconds: 0,
42609
+ intervalMaxSeconds: 0,
42610
+ deviationSamples: 0
42611
+ };
42612
+ if (obs.updatedAt && obs.updatedAt > 0) {
42613
+ if (obs.updatedAt > stat.lastUpdatedAt) {
42614
+ if (stat.lastUpdatedAt > 0) {
42615
+ const interval = obs.updatedAt - stat.lastUpdatedAt;
42616
+ stat.intervalEwmaSeconds = ewma(stat.intervalEwmaSeconds, interval);
42617
+ stat.intervalMaxSeconds = Math.max(stat.intervalMaxSeconds, interval);
42618
+ }
42619
+ stat.lastUpdatedAt = obs.updatedAt;
42620
+ stat.updates += 1;
42621
+ }
42622
+ }
42623
+ if (obs.consensusDeviation !== void 0) {
42624
+ stat.deviationEwma = ewma(stat.deviationEwma, obs.consensusDeviation);
42625
+ stat.deviationSamples += 1;
42626
+ }
42627
+ stat.lastObservedAt = nowSeconds;
42628
+ next[key] = stat;
42629
+ }
42630
+ return next;
42631
+ }
42632
+ function classifyFreshness(updatedAt, stat, defaultStaleSeconds, nowSeconds = Math.floor(Date.now() / 1e3)) {
42633
+ if (!updatedAt || updatedAt <= 0) return "unknown";
42634
+ const age = nowSeconds - updatedAt;
42635
+ if (age < 0) return "fresh";
42636
+ const learned = stat && stat.updates >= MIN_UPDATES_FOR_INTERVAL ? Math.max(
42637
+ stat.intervalEwmaSeconds * STALE_INTERVAL_MULTIPLE,
42638
+ stat.intervalMaxSeconds * 1.5,
42639
+ MIN_LEARNED_STALE_SECONDS
42640
+ ) : void 0;
42641
+ const threshold = learned === void 0 ? defaultStaleSeconds : Math.min(learned, defaultStaleSeconds * 2);
42642
+ return age > threshold ? "stale" : "fresh";
42643
+ }
42644
+ function classifyReliability(stat) {
42645
+ if (!stat) return "unknown";
42646
+ if (stat.deviationEwma === void 0 || stat.deviationSamples < MIN_DEVIATION_SAMPLES) {
42647
+ return "unknown";
42648
+ }
42649
+ if (stat.deviationEwma > BAD_DEVIATION) return "bad";
42650
+ if (stat.deviationEwma > DEGRADED_DEVIATION) return "degraded";
42651
+ return "good";
42652
+ }
42653
+ function collectFeedObservations(structuredPrices, lists = {}, guard = DEFAULT_OUTLIER_GUARD) {
42654
+ const byGroup = /* @__PURE__ */ new Map();
42655
+ const samples = [];
42656
+ for (const [chainId, lenders] of Object.entries(structuredPrices)) {
42657
+ const tokenList = lists[chainId] ?? {};
42658
+ for (const [lender, entries] of Object.entries(lenders)) {
42659
+ if (!Array.isArray(entries)) continue;
42660
+ for (const entry of entries) {
42661
+ if (!entry?.asset || !(entry.priceUSD > 0)) continue;
42662
+ const sample = {
42663
+ chainId,
42664
+ feedKey: feedKeyOf(entry, lender),
42665
+ priceUSD: entry.priceUSD,
42666
+ updatedAt: entry.updatedAt
42667
+ };
42668
+ samples.push(sample);
42669
+ const groupKey = tokenList[entry.asset]?.assetGroup ?? `${chainId}-${entry.asset.toLowerCase()}`;
42670
+ const bucket = byGroup.get(groupKey);
42671
+ if (bucket) bucket.push(sample);
42672
+ else byGroup.set(groupKey, [sample]);
42673
+ }
42674
+ }
42675
+ }
42676
+ const observations = [];
42677
+ const seen = /* @__PURE__ */ new Set();
42678
+ for (const [, group] of byGroup) {
42679
+ const perFeed = /* @__PURE__ */ new Map();
42680
+ for (const s of group) {
42681
+ const bucket = perFeed.get(s.feedKey);
42682
+ if (bucket) bucket.push(s.priceUSD);
42683
+ else perFeed.set(s.feedKey, [s.priceUSD]);
42684
+ }
42685
+ if (perFeed.size < 2) continue;
42686
+ const feedPrices = [...perFeed.entries()].map(([feedKey, prices]) => ({
42687
+ feedKey,
42688
+ price: median(prices)
42689
+ }));
42690
+ for (const { feedKey, price: price2 } of feedPrices) {
42691
+ const others = feedPrices.filter((f) => f.feedKey !== feedKey).map((f) => ({ feedKey: f.feedKey, priceUSD: f.price }));
42692
+ const reference = consensusReference(others, guard);
42693
+ const sample = group.find((s) => s.feedKey === feedKey);
42694
+ const dedupKey = `${sample.chainId}|${feedKey}`;
42695
+ if (seen.has(dedupKey)) continue;
42696
+ seen.add(dedupKey);
42697
+ observations.push({
42698
+ chainId: sample.chainId,
42699
+ feedKey,
42700
+ updatedAt: sample.updatedAt,
42701
+ // Undefined when the rest of the group does not agree on anything —
42702
+ // no verdict is recorded rather than a meaningless one.
42703
+ consensusDeviation: reference === void 0 ? void 0 : Math.abs(price2 / reference - 1)
42704
+ });
42705
+ }
42706
+ }
42707
+ for (const s of samples) {
42708
+ const dedupKey = `${s.chainId}|${s.feedKey}`;
42709
+ if (seen.has(dedupKey)) continue;
42710
+ seen.add(dedupKey);
42711
+ observations.push({
42712
+ chainId: s.chainId,
42713
+ feedKey: s.feedKey,
42714
+ updatedAt: s.updatedAt
42715
+ });
42716
+ }
42717
+ return observations;
42718
+ }
42719
+ function pruneFeedStats(stats, maxAgeSeconds = 30 * 24 * 3600, nowSeconds = Math.floor(Date.now() / 1e3)) {
42720
+ const out = {};
42721
+ for (const [key, stat] of Object.entries(stats)) {
42722
+ if (nowSeconds - stat.lastObservedAt <= maxAgeSeconds) out[key] = stat;
42723
+ }
42724
+ return out;
42725
+ }
42726
+
42727
+ // src/prices/oracle-prices/selectAssetGroupPrices.ts
42728
+ var DEFAULT_STALE_REJECT_SECONDS = 172800;
42729
+ var AAVE_V4_PREFIX = "AAVE_V4";
42275
42730
  var DEFAULT_PRIORITY = {
42276
42731
  chainPriority: [
42277
42732
  Chain.ETHEREUM_MAINNET,
@@ -42280,7 +42735,10 @@ var DEFAULT_PRIORITY = {
42280
42735
  Chain.BASE,
42281
42736
  Chain.AVALANCHE_C_CHAIN
42282
42737
  ],
42283
- lenderPriority: [Lender.AAVE_V3, "COMPOUND_V3"],
42738
+ // Aave V4 has no enum member — every key is the runtime-synthesized
42739
+ // `AAVE_V4_<SPOKE_HEX>` — so it is matched by the literal prefix, the same
42740
+ // way `isAaveV4Type()` does.
42741
+ lenderPriority: [Lender.AAVE_V3, AAVE_V4_PREFIX, "COMPOUND_V3"],
42284
42742
  lowPriorityLenders: [Lender.ZEROLEND, Lender.AVALON, Lender.MORPHO_BLUE],
42285
42743
  excludedLenders: {
42286
42744
  // paused
@@ -42291,64 +42749,140 @@ var DEFAULT_PRIORITY = {
42291
42749
  "1": [Lender.ZEROLEND_STABLECOINS_RWA, Lender.ZEROLEND_ETH_LRTS],
42292
42750
  "534352": ["LORE"],
42293
42751
  "167000": [Lender.TAKOTAKO, Lender.TAKOTAKO_ETH],
42294
- "56": [Lender.AVALON_USDX],
42752
+ // GAMMA (Planet Finance) is abandoned and its oracle is frozen at ~2022
42753
+ // prices across the board — AVAX $23.78 vs $6.44, BTCB $23k vs $64k, and
42754
+ // it still quotes LUNA/UST. Kept as a hard veto because it prices several
42755
+ // dead assets NOTHING else prices, so no consensus can form to catch it.
42756
+ "56": [Lender.AVALON_USDX, Lender.GAMMA],
42295
42757
  // broken
42296
42758
  "169": [Lender.ZEROLEND]
42297
42759
  },
42298
42760
  lenderPriorityPerChain: {
42299
- [Chain.BNB_SMART_CHAIN_MAINNET]: [Lender.AAVE_V3, Lender.VENUS],
42761
+ // NOTE: a per-chain list REPLACES the global one, so it has to repeat
42762
+ // every prefix that should still rank on that chain.
42763
+ [Chain.BNB_SMART_CHAIN_MAINNET]: [
42764
+ Lender.AAVE_V3,
42765
+ AAVE_V4_PREFIX,
42766
+ Lender.VENUS
42767
+ ],
42300
42768
  [Chain.XDC_NETWORK]: [Lender.PRIME_FI, Lender.FATHOM],
42301
42769
  [Chain.HYPEREVM]: [Lender.HYPERLEND, Lender.HYPURRFI]
42302
42770
  },
42303
42771
  lowPriorityLendersPerChain: {},
42304
- excludedLendersPerChain: {}
42305
- };
42306
- function computePriority(lender, chainId, cfg) {
42307
- const NOT_FOUND = 1e3;
42772
+ excludedLendersPerChain: {},
42773
+ staleRejectSeconds: DEFAULT_STALE_REJECT_SECONDS,
42774
+ outlierGuard: DEFAULT_OUTLIER_GUARD
42775
+ };
42776
+ var LENDER_RANK_UNLISTED = 1e3;
42777
+ var LENDER_RANK_LOW = 2e3;
42778
+ var CHAIN_RANK_UNLISTED = 1e3;
42779
+ function lenderRankOf(lender, chainId, cfg) {
42308
42780
  const excluded = cfg.excludedLenders[chainId];
42309
42781
  if (excluded?.some((p) => lender.startsWith(p))) return -1;
42310
42782
  const excludedPerChain = cfg.excludedLendersPerChain[chainId];
42311
42783
  if (excludedPerChain?.some((p) => lender.startsWith(p))) return -1;
42312
42784
  const lowPerChain = cfg.lowPriorityLendersPerChain[chainId];
42313
42785
  const isLow = lowPerChain ? lowPerChain.some((p) => lender.startsWith(p)) : cfg.lowPriorityLenders.some((p) => lender.startsWith(p));
42314
- if (isLow) return 2e6;
42786
+ if (isLow) return LENDER_RANK_LOW;
42315
42787
  const lenderPriority = cfg.lenderPriorityPerChain[chainId] ?? cfg.lenderPriority;
42316
- const lenderIdx = lenderPriority.findIndex((p) => lender.startsWith(p));
42317
- const lenderScore = lenderIdx >= 0 ? lenderIdx : NOT_FOUND;
42318
- const chainIdx = cfg.chainPriority.indexOf(chainId);
42319
- const chainScore = chainIdx >= 0 ? chainIdx : NOT_FOUND;
42320
- return lenderScore * 1e4 + chainScore;
42321
- }
42322
- function selectAssetGroupPrices(structuredPrices, lists = {}, tvlMap = {}, priorityCfg = DEFAULT_PRIORITY) {
42323
- const candidates = [];
42788
+ const idx = lenderPriority.findIndex((p) => lender.startsWith(p));
42789
+ return idx >= 0 ? idx : LENDER_RANK_UNLISTED;
42790
+ }
42791
+ function depthOf(entryMarketUid, lender, depth) {
42792
+ if (!depth) return 0;
42793
+ if (entryMarketUid) {
42794
+ const perMarket = depth[entryMarketUid];
42795
+ if (typeof perMarket === "number") return perMarket;
42796
+ }
42797
+ const perLender = depth[lender];
42798
+ return typeof perLender === "number" ? perLender : 0;
42799
+ }
42800
+ function compareCandidates(a, b) {
42801
+ return a.freshnessRank - b.freshnessRank || a.reliabilityRank - b.reliabilityRank || a.derivationRank - b.derivationRank || a.lenderRank - b.lenderRank || b.depth - a.depth || a.chainRank - b.chainRank || cmpStr(a.lender, b.lender) || cmpStr(a.chainId, b.chainId) || // One lender can emit many entries for the same asset (Euler prices a
42802
+ // token in every vault that lists it), so lender+chain is NOT a unique
42803
+ // identity. Without these last two the winner among them fell out of
42804
+ // enumeration order and the flat price moved between runs.
42805
+ cmpStr(a.marketUid, b.marketUid) || a.priceUSD - b.priceUSD;
42806
+ }
42807
+ function cmpStr(a, b) {
42808
+ return a < b ? -1 : a > b ? 1 : 0;
42809
+ }
42810
+ function selectAssetGroupPrices(structuredPrices, lists = {}, depthOrTvl = {}, priorityCfg = DEFAULT_PRIORITY, options = {}) {
42811
+ const staleRejectSeconds = priorityCfg.staleRejectSeconds ?? DEFAULT_STALE_REJECT_SECONDS;
42812
+ const guard = priorityCfg.outlierGuard === void 0 ? DEFAULT_OUTLIER_GUARD : priorityCfg.outlierGuard;
42813
+ const depth = options.depth ?? depthOrTvl;
42814
+ const feedStats = options.feedStats;
42815
+ const nowSeconds = options.nowSeconds ?? Math.floor(Date.now() / 1e3);
42816
+ const byKey = /* @__PURE__ */ new Map();
42324
42817
  for (const [chainId, lenders] of Object.entries(structuredPrices)) {
42325
42818
  const tokenList = lists[chainId] ?? {};
42326
42819
  for (const [lender, entries] of Object.entries(lenders)) {
42327
42820
  if (!Array.isArray(entries)) continue;
42328
- const prio = computePriority(lender, chainId, priorityCfg);
42329
- if (prio < 0) continue;
42330
- const tvl = tvlMap[lender] ?? 0;
42821
+ const lenderRank = lenderRankOf(lender, chainId, priorityCfg);
42822
+ if (lenderRank < 0) continue;
42823
+ const family = lenderFamily(lender);
42824
+ const chainIdx = priorityCfg.chainPriority.indexOf(chainId);
42825
+ const chainRank = chainIdx >= 0 ? chainIdx : CHAIN_RANK_UNLISTED;
42331
42826
  for (const entry of entries) {
42332
42827
  if (!entry?.asset || entry.priceUSD <= 0) continue;
42828
+ const feedKey = feedKeyOf(entry, lender);
42829
+ const stat = feedStats?.[feedStatKey(chainId, feedKey)];
42830
+ const freshness = staleRejectSeconds > 0 ? classifyFreshness(
42831
+ entry.updatedAt,
42832
+ stat,
42833
+ staleRejectSeconds,
42834
+ nowSeconds
42835
+ ) : "unknown";
42333
42836
  const oracleKey = tokenList[entry.asset]?.assetGroup ?? `${chainId}-${entry.asset.toLowerCase()}`;
42334
- candidates.push({
42837
+ const candidate = {
42335
42838
  oracleKey,
42336
42839
  priceUSD: entry.priceUSD,
42337
- priority: prio,
42338
- tvl
42339
- });
42840
+ chainId,
42841
+ lender,
42842
+ family,
42843
+ feedKey,
42844
+ marketUid: entry.marketUid ?? "",
42845
+ derivationRank: DERIVATION_RANK[resolveDerivation(entry)],
42846
+ freshnessRank: FRESHNESS_RANK[freshness],
42847
+ reliabilityRank: RELIABILITY_RANK[classifyReliability(stat)],
42848
+ lenderRank,
42849
+ depth: depthOf(entry.marketUid, lender, depth),
42850
+ chainRank
42851
+ };
42852
+ const bucket = byKey.get(oracleKey);
42853
+ if (bucket) bucket.push(candidate);
42854
+ else byKey.set(oracleKey, [candidate]);
42340
42855
  }
42341
42856
  }
42342
42857
  }
42343
- candidates.sort((a, b) => a.priority - b.priority || b.tvl - a.tvl);
42344
42858
  const flatPrices = {};
42345
- for (const c of candidates) {
42346
- if (!(c.oracleKey in flatPrices)) {
42347
- flatPrices[c.oracleKey] = c.priceUSD;
42859
+ for (const [oracleKey, candidates] of byKey) {
42860
+ const viable = guard ? rejectOutliers(candidates, guard) : candidates;
42861
+ let best = viable[0];
42862
+ for (const c of viable) {
42863
+ if (compareCandidates(c, best) < 0) best = c;
42864
+ }
42865
+ if (!best) continue;
42866
+ flatPrices[oracleKey] = best.priceUSD;
42867
+ if (options.onSelection) {
42868
+ options.onSelection({
42869
+ assetGroup: oracleKey,
42870
+ priceUSD: best.priceUSD,
42871
+ chainId: best.chainId,
42872
+ lender: best.lender,
42873
+ feedKey: best.feedKey,
42874
+ derivation: derivationOfRank(best.derivationRank),
42875
+ candidates: candidates.length,
42876
+ rejected: candidates.length - viable.length
42877
+ });
42348
42878
  }
42349
42879
  }
42350
42880
  return flatPrices;
42351
42881
  }
42882
+ var RANK_TO_DERIVATION = ["direct", "quoted", "derived"];
42883
+ function derivationOfRank(rank) {
42884
+ return RANK_TO_DERIVATION[rank] ?? "derived";
42885
+ }
42352
42886
  var { uniq: uniq2 } = lodash;
42353
42887
  function createAssetArrayPerChain() {
42354
42888
  let assetsPerChain = {};
@@ -53051,6 +53585,6 @@ async function fetchTokenBalances(chainId, account, tokens, options = {}) {
53051
53585
  return parseTokenBalanceResult(rawResult, prepared.query);
53052
53586
  }
53053
53587
 
53054
- export { ApiBookSource, DEFAULT_MIDNIGHT_API, EMPTY_BALANCE, GMX_API_HOSTS, GMX_READ_CONTRACTS, GMX_SUPPORTED_CHAINS, HYPERCORE_VAULT_REGISTRY, IDLE_MARKET_ID, INTERFACE_IDS, LAGOON_API_URL, LAGOON_CHAIN_IDS, MORPHO_LENS, MaxParamThresholds, STABLECOIN_SYMBOLS, STCELO_MANAGER_ADDRESS, TELLER_CALLS_PER_BID, TermSubgraphSource, UPSHIFT_CHAIN_IDS, UPSHIFT_VAULTS_URL, VAULT_SHARE_PRICE_PROBE, VOLATILE_VAULT_OVERRIDES, YEARN_CHAIN_IDS, YEARN_YDAEMON_BASE, accountDepositListKey, accountWithdrawalListKey, appendSnapshot, applyPositionDelta, attachPricesToFlashLiquidity, buildFluidFTokensCall, buildLiquityUserCall, buildLoopResult, buildMorphoTypeCall, buildMorphoTypeUserCallWithLens, buildPortfolioTotals, buildSumerAccumulators, buildSummaries, buildTellerUserCall, buildVaultLookup, calculateLeverage, calculateNetApr, calculateOverallNetApr, calculateWeightedAverage, classifyVault, computeBorrowDelta2 as computeBorrowDelta, computeCloseTradeDeltas, computeCollateralSwapDeltas, computeDebtSwapDeltas, computeDepositDelta2 as computeDepositDelta, computeEModeAnalysis, computeOpenTradeDeltas, computePostTradeMetrics, computeRepayDelta2 as computeRepayDelta, computeSumerBorrowDelta, computeSumerDepositDelta, computeSumerRepayDelta, computeSumerWaterfall, computeSumerWithdrawDelta, computeVaultApr, computeWithdrawDelta2 as computeWithdrawDelta, computeZapTradeDeltas, convertExactlyMarketsToResponse, convertLenderUserDataResult, convertLiquityMarketsToResponse, convertRiverMarketsToResponse, convertTellerMarketsToResponse, convertTermMarketsToResponse, createMarketUid, createMidnightBookSource, createMulticallRpcCall, createRawRpcCalls, createTermBookSource, decodeListaMarkets, decodeMarkets, decodePackedListaUserDataset, decodePackedMorphoUserDataset, detectInterfaceKinds, encodeBalanceFetcherCalldata, exactlyLenderKey, exactlyMarketFromLenderKey, exactlyPairLtv, exactlyPenaltyRateToAprPercent, exactlyWadRateToPercent, fetchDolomiteAccountNumbers, fetchEulerEarnVaults, fetchEulerEarnVaultsFromSubgraph, fetchEulerSubAccountIndexes, fetchExactlyMarkets, fetchFlashLiquidityForChain, fetchFluidFTokens, fetchGeneralYields, fetchGeneralYieldsByMarketUid, fetchGmxExecutionFees, fetchGmxTickerPrices, fetchGmxVaults, fetchHypercoreVaults, fetchLagoonApiVaults, fetchLagoonVaults, fetchLiquityMarkets, fetchListaVaultsFromChain, fetchMorphoUserBalances, fetchMorphoUserPositionMarkets, fetchMorphoVaults, fetchMorphoVaultsFromApi, fetchMorphoVaultsFromChain, fetchOraclePrices, fetchPendlePrices, fetchRiverMarkets, fetchSiloVaults, fetchTellerMarkets, fetchTermMarkets, fetchTokenBalances, fetchTokenMetadata, fetchUpshiftApiVaults, fetchUpshiftVaults, fetchYearnApiVaults, fetchYearnVaults, filterActiveLenders, filterLendersByProtocol, fuseLenderData, generateLendingPools, getAavesForChain, getAssetConfig, getBalanceForMarketUid, getBorrowCapacity, getCachedLiquityTroves, getCachedTellerBids, getCoreValidators, getFluidFTokensConverter, getGmxApiHost, getGmxReadContracts, getGmxUserPositions, getHealthFactor, getHypercoreUserPositions, getHypercoreVaultRegistry, getLenderAssets, getLenderPublicData, getLenderPublicDataAll, getLenderPublicDataViaApi, getLenderUserDataMulti, getLenderUserDataResult, getLendersForChain, getLstDelegation, getLstValidators, getLstWithdrawalRegistry, getLstWithdrawalRequests, getMaxAmountClose, getMaxAmountCollateralSwap, getMaxAmountDebtSwap, getMaxAmountOpen, getMergedUserData, getMorphoTypeMarketConverter, getResolvedDolomiteAccountNumbers, getStCeloValidatorGroups, getSubAccountAddress, getSubAccountIndex, getVaultPublicDataAll, getVaultWithdrawalRequests, hasEulerEarnVaultSubgraph, hasLagoonVaults, hasMorphoPositionIndex, hasMorphoUserApi, hasMorphoUserSubgraph, hasUpshiftVaults, hasYearnVaults, isStablecoinSymbol, isYearnV3, keysFromMaps, liquityCandidateTroveIds, liquityKeyParts, liquityLenderKey, multicall3Abi, nanTo, needsLenderApproval, needsTokenApproval, noOpResult, normalizeToBytes, parseBalanceFetcherResult, parseMergedResult, parseMulticallRpcResponses, parseRawRpcBatchResponses, parseRawRpcResponses, parseTokenBalanceResult, positivePart2 as positivePart, prepareLenderUserDataRpcCalls, prepareMergedMulticallParams, prepareMergedRpcCalls, prepareMulticallInputs, prepareTokenBalanceRpcCalls, priceGlvVaults, priceGmMarkets, readVaultSharePrices, resolveStCeloDepositGroup, riverKeyParts, riverLenderKey, selectAssetGroupPrices, stampVaultClassification, tellerBpsToPercent, tellerImpliedLtv, tellerLenderKey, tellerPoolFromLenderKey, termLenderKey, tickToAprNumber, tickToPrice, unflattenLenderData };
53588
+ export { ApiBookSource, DEFAULT_MIDNIGHT_API, DEFAULT_OUTLIER_GUARD, DEFAULT_STALE_REJECT_SECONDS, EMPTY_BALANCE, GMX_API_HOSTS, GMX_READ_CONTRACTS, GMX_SUPPORTED_CHAINS, HYPERCORE_VAULT_REGISTRY, IDLE_MARKET_ID, INTERFACE_IDS, LAGOON_API_URL, LAGOON_CHAIN_IDS, MORPHO_LENS, MaxParamThresholds, STABLECOIN_SYMBOLS, STCELO_MANAGER_ADDRESS, TELLER_CALLS_PER_BID, TermSubgraphSource, UPSHIFT_CHAIN_IDS, UPSHIFT_VAULTS_URL, VAULT_SHARE_PRICE_PROBE, VOLATILE_VAULT_OVERRIDES, YEARN_CHAIN_IDS, YEARN_YDAEMON_BASE, accountDepositListKey, accountWithdrawalListKey, appendSnapshot, applyPositionDelta, attachPricesToFlashLiquidity, buildFluidFTokensCall, buildLiquityUserCall, buildLoopResult, buildMorphoTypeCall, buildMorphoTypeUserCallWithLens, buildPortfolioTotals, buildSumerAccumulators, buildSummaries, buildTellerUserCall, buildVaultLookup, calculateLeverage, calculateNetApr, calculateOverallNetApr, calculateWeightedAverage, classifyFreshness, classifyReliability, classifyVault, collectFeedObservations, computeBorrowDelta2 as computeBorrowDelta, computeCloseTradeDeltas, computeCollateralSwapDeltas, computeDebtSwapDeltas, computeDepositDelta2 as computeDepositDelta, computeEModeAnalysis, computeOpenTradeDeltas, computePostTradeMetrics, computeRepayDelta2 as computeRepayDelta, computeSumerBorrowDelta, computeSumerDepositDelta, computeSumerRepayDelta, computeSumerWaterfall, computeSumerWithdrawDelta, computeVaultApr, computeWithdrawDelta2 as computeWithdrawDelta, computeZapTradeDeltas, consensusReference, convertExactlyMarketsToResponse, convertLenderUserDataResult, convertLiquityMarketsToResponse, convertRiverMarketsToResponse, convertTellerMarketsToResponse, convertTermMarketsToResponse, createMarketUid, createMidnightBookSource, createMulticallRpcCall, createRawRpcCalls, createTermBookSource, decodeListaMarkets, decodeMarkets, decodePackedListaUserDataset, decodePackedMorphoUserDataset, detectInterfaceKinds, encodeBalanceFetcherCalldata, exactlyLenderKey, exactlyMarketFromLenderKey, exactlyPairLtv, exactlyPenaltyRateToAprPercent, exactlyWadRateToPercent, feedKeyOf, feedStatKey, fetchDolomiteAccountNumbers, fetchEulerEarnVaults, fetchEulerEarnVaultsFromSubgraph, fetchEulerSubAccountIndexes, fetchExactlyMarkets, fetchFlashLiquidityForChain, fetchFluidFTokens, fetchGeneralYields, fetchGeneralYieldsByMarketUid, fetchGmxExecutionFees, fetchGmxTickerPrices, fetchGmxVaults, fetchHypercoreVaults, fetchLagoonApiVaults, fetchLagoonVaults, fetchLiquityMarkets, fetchListaVaultsFromChain, fetchMorphoUserBalances, fetchMorphoUserPositionMarkets, fetchMorphoVaults, fetchMorphoVaultsFromApi, fetchMorphoVaultsFromChain, fetchOraclePrices, fetchPendlePrices, fetchRiverMarkets, fetchSiloVaults, fetchTellerMarkets, fetchTermMarkets, fetchTokenBalances, fetchTokenMetadata, fetchUpshiftApiVaults, fetchUpshiftVaults, fetchYearnApiVaults, fetchYearnVaults, filterActiveLenders, filterLendersByProtocol, fuseLenderData, generateLendingPools, getAavesForChain, getAssetConfig, getBalanceForMarketUid, getBorrowCapacity, getCachedLiquityTroves, getCachedTellerBids, getCoreValidators, getFluidFTokensConverter, getGmxApiHost, getGmxReadContracts, getGmxUserPositions, getHealthFactor, getHypercoreUserPositions, getHypercoreVaultRegistry, getLenderAssets, getLenderPublicData, getLenderPublicDataAll, getLenderPublicDataViaApi, getLenderUserDataMulti, getLenderUserDataResult, getLendersForChain, getLstDelegation, getLstValidators, getLstWithdrawalRegistry, getLstWithdrawalRequests, getMaxAmountClose, getMaxAmountCollateralSwap, getMaxAmountDebtSwap, getMaxAmountOpen, getMergedUserData, getMorphoTypeMarketConverter, getResolvedDolomiteAccountNumbers, getStCeloValidatorGroups, getSubAccountAddress, getSubAccountIndex, getVaultPublicDataAll, getVaultWithdrawalRequests, hasEulerEarnVaultSubgraph, hasLagoonVaults, hasMorphoPositionIndex, hasMorphoUserApi, hasMorphoUserSubgraph, hasUpshiftVaults, hasYearnVaults, isStablecoinSymbol, isYearnV3, keysFromMaps, lenderFamily, liquityCandidateTroveIds, liquityKeyParts, liquityLenderKey, multicall3Abi, nanTo, needsLenderApproval, needsTokenApproval, noOpResult, normalizeToBytes, parseBalanceFetcherResult, parseMergedResult, parseMulticallRpcResponses, parseRawRpcBatchResponses, parseRawRpcResponses, parseTokenBalanceResult, positivePart2 as positivePart, prepareLenderUserDataRpcCalls, prepareMergedMulticallParams, prepareMergedRpcCalls, prepareMulticallInputs, prepareTokenBalanceRpcCalls, priceGlvVaults, priceGmMarkets, probeAaveFeedTimestamps, pruneFeedStats, readVaultSharePrices, rejectOutliers as rejectPriceOutliers, resolveDerivation, resolveStCeloDepositGroup, riverKeyParts, riverLenderKey, selectAssetGroupPrices, stampVaultClassification, tellerBpsToPercent, tellerImpliedLtv, tellerLenderKey, tellerPoolFromLenderKey, termLenderKey, tickToAprNumber, tickToPrice, unflattenLenderData, updateFeedStats };
53055
53589
  //# sourceMappingURL=index.js.map
53056
53590
  //# sourceMappingURL=index.js.map