@1delta/margin-fetcher 5.0.69 → 5.0.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5,11 +5,11 @@ import { Lender, isExactly, isMidnight, isTerm, isTermMax, isTeller, isListaDao,
5
5
  export { hasCrossMarginRisk, isAaveType, isAaveV2Type, isAaveV32Type, isAaveV3Type, isCompoundV3, isCompoundV3Type, isInit, isMorphoType, isMultiMarket, isYLDR } from '@1delta/lender-registry';
6
6
  import { fetchTokenLists, fetchTokenList, aavePools, compoundV3Pools, initConfig, morphoPools, compoundV2Pools, eulerVaults, siloMarkets, siloV2LenderKey, siloMarketsV3, siloV3LenderKey, aaveV4Spokes, aaveV4SpokeLenderKey, fluidResolvers, gearboxResolvers, dolomiteConfigs, midnightConfig, termConfig, termMarketsByChain, exactlyConfig, flyingTulipLendersByChain, liquityLendersByChain, riverLendersByChain, inverseLendersByChain, coolerLendersByChain, llamaLendLendersByChain, usddLendersByChain, skyLendersByChain, frankencoinLendersByChain, resupplyLendersByChain, curvanceLendersByChain, fraxlendLendersByChain, twyneLendersByChain, tellerConfigByChain, tellerPoolsByChain, termMaxConfigByChain, aaveReserves, compoundV3Reserves, resolveTermApiBase, flyingTulipConfigFor, flyingTulipAssetsFor, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, termMaxApiBaseUrl, termMaxLenderKey, inverseConfigFor, inverseChainData, coolerConfigFor, llamaLendConfigFor, llamaLendChainData, llamaLendApiBaseUrl, resupplyConfigFor, fraxlendConfigFor, dssConfigFor, dssChainData, dssDebtToken, dssDebtJoin, frankencoinConfigFor, frankencoinChainData, aaveOracles, morphoTypeMarkets, resolveMidnightApiBase, llamaLendMarketByVault, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, curvanceConfigFor, aaveTokens, morphoTypeVaults, listaCollateralProvider, eulerConfigs, gearboxMarketCompressor, gearboxMarketConfigurators, compoundV2TokenArray, gearboxV3LenderKey, midnightMarketsByChain, twyneConfigFor, twyneChainData, parseAaveV4SpokeLenderKey, fraxlendPairsFor, gearboxAccountCompressor, compoundV2Tokens, exactlyMarketsByChain, aaveOraclesConfig, compoundV2Oracles, compoundV2OraclesConfig, compoundV3OraclesData, compoundV3BaseData, compoundV2Reserves, aaveV4Oracles, morphoTypeOracles } from '@1delta/data-sdk';
7
7
  import lodash from 'lodash';
8
- import { Chain } from '@1delta/chain-registry';
8
+ import { Chain, isEvmChainId } from '@1delta/chain-registry';
9
9
  import { multicallRetryUniversal, getEvmClient, getEvmChain, getEvmClientUniversal } from '@1delta/providers';
10
10
  import { LiquityTroveManagerAbi, LiquityActivePoolAbi, LiquityStabilityPoolAbi, LiquityPriceFeedAbi, LiquitySortedTrovesAbi, RiverTroveManagerAbi, RiverStabilityPoolAbi, TellerMarketRegistryAbi, TellerV2Abi, InverseMarketAbi, InverseOracleAbi, InverseDbrAbi, Erc20Abi, CoolerMonoAbi, CoolerLtvOracleAbi, LlamaLendControllerAbi, LlamaLendControllerV1Abi, LlamaLendControllerV2Abi, LlamaLendVaultAbi, LlamaLendAmmAbi, TwyneCollateralVaultAbi, MetaMorphoAbi, FluidDexResolverAbi, ExactlyPreviewerAbi, ExactlyAuditorAbi, FlyingTulipLendingLensAbi, LenderCommitmentGroupAbi, ResupplyRegistryAbi, ResupplyPairAbi, ResupplyUtilitiesAbi, ResupplyRewardHandlerAbi, ResupplyPairEmissionsAbi, ConvexPoolUtilAbi, FraxlendPairAbi, FraxlendLeverAbi, FrankencoinPositionAbi, FluidLendingResolverAbi, FluidVaultResolverAbi, FluidLiquidityResolverAbi, MoolahVaultAbi, UsddVatAbi, UsddJugAbi, UsddSpotAbi, MorphoLensAbi, AaveV4SpokeAbi, AaveV4OracleAbi, AaveV4HubAbi, DolomiteMarginAbi, GearboxMarketCompressorV310Abi, MorphoBlueAbi, MidnightAbi, TermRepoTokenAbi, TermRepoServicerAbi, TermRepoCollateralManagerAbi, LiquityTroveNFTAbi, LiquityCollSurplusPoolAbi, TellerCollateralManagerAbi, TermMaxViewerAbi, InverseEscrowAbi, CurvanceMarketManagerAbi, CurvanceCTokenAbi, GearboxCreditAccountCompressorV310Abi, TwyneVaultManagerAbi, TwyneCollateralVaultFactoryAbi, AaveV2V3Abi, TwyneATokenWrapperAbi, UsddCdpManagerAbi, UsddProxyRegistryAbi, CurvanceProtocolReaderAbi, CurvanceCentralRegistryAbi, TermPriceConsumerAbi, CurvanceOracleManagerAbi, TermMaxOracleAggregatorV2Abi } from '@1delta/abis';
11
11
  export { MorphoLensAbi } from '@1delta/abis';
12
- import { prepareDebitDataMulticall, prepareLenderDebitMulticall, parseDebitDataResult, parseLenderDebitResult, getPermit2ContractAddress, getLstAcceptedInputs, getCompoundV2Comptroller as getCompoundV2Comptroller$1, getCompoundV3CometAddress as getCompoundV3CometAddress$1, getMorphoAddress, FLUID_VAULT_FACTORY, getAaveStyleLenderTokenAddress, LendingMode, getAaveCollateralTokenAddress, getSiloHalfForUnderlying, findSavingsWithdrawEntry, bandLtvCurve, InitMarginAddresses, ignoresReceiver, buildLstWithdrawRequest, SAVINGS_RECEIVER_CAPABILITY } from '@1delta/calldata-sdk';
12
+ import { prepareDebitDataMulticall, prepareLenderDebitMulticall, parseDebitDataResult, parseLenderDebitResult, getPermit2ContractAddress, getLstAcceptedInputs, savingsVerbRequires, savingsSupportsVerb, getCompoundV2Comptroller as getCompoundV2Comptroller$1, getCompoundV3CometAddress as getCompoundV3CometAddress$1, getMorphoAddress, FLUID_VAULT_FACTORY, getAaveStyleLenderTokenAddress, LendingMode, getAaveCollateralTokenAddress, getSiloHalfForUnderlying, findSavingsWithdrawEntry, bandLtvCurve, InitMarginAddresses, ignoresReceiver, buildLstWithdrawRequest, SAVINGS_RECEIVER_CAPABILITY } from '@1delta/calldata-sdk';
13
13
  import { proxyNativeFetch } from '@1delta/proxy-fetch';
14
14
  import { BALANCER_V2_FORKS, BALANCER_V3_FORKS, UNISWAP_V4_FORKS, isFlashLoanSourceExcluded, FLASH_LOAN_IDS } from '@1delta/dex-registry';
15
15
 
@@ -6247,15 +6247,14 @@ var IrgetterAbi = [
6247
6247
  type: "function"
6248
6248
  }
6249
6249
  ];
6250
-
6251
- // src/utils/marketUid.ts
6252
6250
  function createMarketUid(chainId, lender, refAddress) {
6253
6251
  if (!refAddress || !lender || !chainId) {
6254
6252
  throw new Error(
6255
6253
  `Invalid marketUid parameters: lender=${lender}, chainId=${chainId}, refAddress=${refAddress}`
6256
6254
  );
6257
6255
  }
6258
- return `${lender}:${chainId}:${refAddress.toLowerCase()}`;
6256
+ const ref = isEvmChainId(chainId) ? refAddress.toLowerCase() : refAddress;
6257
+ return `${lender}:${chainId}:${ref}`;
6259
6258
  }
6260
6259
  var LENDER_SHORT_NAMES = {
6261
6260
  [Lender.AAVE_V2]: "Aave V2",
@@ -24633,6 +24632,20 @@ var fetchDbrPriceDola = async (snapshot) => {
24633
24632
  const snap = Number(snapshot);
24634
24633
  return Number.isFinite(snap) && snap > 0 ? snap : null;
24635
24634
  };
24635
+ var fetchReplenishmentPriceBps = async (chainId, dbr) => {
24636
+ try {
24637
+ const [v] = await multicallRetryUniversal({
24638
+ chain: chainId,
24639
+ calls: [{ address: dbr, name: "replenishmentPriceBps", params: [] }],
24640
+ abi: INVERSE_PUBLIC_READ_ABI,
24641
+ allowFailure: true
24642
+ });
24643
+ if (typeof v === "bigint") return Number(v);
24644
+ if (typeof v === "number" && Number.isFinite(v)) return v;
24645
+ } catch {
24646
+ }
24647
+ return null;
24648
+ };
24636
24649
  async function fetchInverseMarkets(lender, chainId) {
24637
24650
  const config = inverseConfigFor(lender, chainId);
24638
24651
  const chainData = inverseChainData(lender, chainId);
@@ -24648,6 +24661,7 @@ async function fetchInverseMarkets(lender, chainId) {
24648
24661
  };
24649
24662
  if (!config || markets.length === 0) return empty;
24650
24663
  const dbrPricePromise = fetchDbrPriceDola(config.dbrPriceDolaSnapshot);
24664
+ const replenishPromise = fetchReplenishmentPriceBps(chainId, config.dbr);
24651
24665
  try {
24652
24666
  const api = await fetchJson(FIXED_MARKETS_URL);
24653
24667
  const byAddr = {};
@@ -24682,7 +24696,9 @@ async function fetchInverseMarkets(lender, chainId) {
24682
24696
  config,
24683
24697
  chainData,
24684
24698
  dbrPriceDola: await dbrPricePromise,
24685
- replenishmentPriceBps: num(api, "replenishmentPriceBps"),
24699
+ // On-chain is authoritative; the API field is a backstop that does
24700
+ // not exist today (see `num`).
24701
+ replenishmentPriceBps: await replenishPromise ?? num(api, "replenishmentPriceBps"),
24686
24702
  markets: rows,
24687
24703
  source: "api"
24688
24704
  };
@@ -24690,7 +24706,6 @@ async function fetchInverseMarkets(lender, chainId) {
24690
24706
  } catch {
24691
24707
  }
24692
24708
  const calls = [
24693
- { address: config.dbr, name: "replenishmentPriceBps", params: [] },
24694
24709
  ...markets.flatMap((m) => [
24695
24710
  { address: m.address, name: "totalDebt", params: [] },
24696
24711
  { address: m.address, name: "borrowPaused", params: [] },
@@ -24718,7 +24733,7 @@ async function fetchInverseMarkets(lender, chainId) {
24718
24733
  };
24719
24734
  const debtDecimals = config.debtDecimals ?? 18;
24720
24735
  const rows = markets.map((market, i) => {
24721
- const base = 1 + i * READS_PER_MARKET2;
24736
+ const base = i * READS_PER_MARKET2;
24722
24737
  const totalDebt = bigAt(base);
24723
24738
  const paused = results[base + 1];
24724
24739
  const liq = bigAt(base + 2);
@@ -24747,12 +24762,16 @@ async function fetchInverseMarkets(lender, chainId) {
24747
24762
  config,
24748
24763
  chainData,
24749
24764
  dbrPriceDola: await dbrPricePromise,
24750
- replenishmentPriceBps: bigAt(0) !== null ? Number(bigAt(0)) : null,
24765
+ replenishmentPriceBps: await replenishPromise,
24751
24766
  markets: rows,
24752
24767
  source: "chain"
24753
24768
  };
24754
24769
  } catch {
24755
- return { ...empty, dbrPriceDola: await dbrPricePromise };
24770
+ return {
24771
+ ...empty,
24772
+ dbrPriceDola: await dbrPricePromise,
24773
+ replenishmentPriceBps: await replenishPromise
24774
+ };
24756
24775
  }
24757
24776
  }
24758
24777
  function num(api, key3) {
@@ -26357,7 +26376,8 @@ function convertInverseMarketsToResponse(raw, chainId, prices = {}, _additionalY
26357
26376
  const dolaToken = tokens[dolaAddr];
26358
26377
  const dolaPriceKey = toOracleKey(dolaToken?.assetGroup) || toGenericPriceKey(dolaAddr, chainId);
26359
26378
  const dolaPrice = prices[dolaPriceKey] || 1;
26360
- const borrowAprPct = raw.dbrPriceDola !== null ? raw.dbrPriceDola * 100 : 0;
26379
+ const rateKnown = raw.dbrPriceDola !== null && raw.dbrPriceDola > 0;
26380
+ const borrowAprPct = rateKnown ? raw.dbrPriceDola * 100 : 0;
26361
26381
  for (const m of raw.markets ?? []) {
26362
26382
  const market = m.market;
26363
26383
  const lenderKey = inverseLenderKey(raw.lender, market.address);
@@ -26370,12 +26390,13 @@ function convertInverseMarketsToResponse(raw, chainId, prices = {}, _additionalY
26370
26390
  const collPrice = m.price ?? prices[collPriceKey] ?? 0;
26371
26391
  const totalDebt = m.totalDebt ?? 0;
26372
26392
  const paused = m.borrowPaused ?? !!market.borrowPaused;
26393
+ const borrowClosed = paused || !rateKnown;
26373
26394
  const ltv = Number(market.collateralFactorBps) / 1e4;
26374
26395
  const liqPenalty = Number(market.liquidationIncentiveBps) / 1e4;
26375
26396
  const closeFactor = Number(market.liquidationFactorBps) / 1e4 || 1;
26376
26397
  const collateralTotal = 0;
26377
26398
  let borrowLiquidity = m.leftToBorrow ?? m.dolaLiquidity ?? 0;
26378
- if (paused) borrowLiquidity = 0;
26399
+ if (borrowClosed) borrowLiquidity = 0;
26379
26400
  const entry = { data: {} };
26380
26401
  const collUid = createMarketUid(chainId, lenderKey, collAddr);
26381
26402
  entry.data[collUid] = {
@@ -26457,15 +26478,15 @@ function convertInverseMarketsToResponse(raw, chainId, prices = {}, _additionalY
26457
26478
  liquidationPenalty: liqPenalty,
26458
26479
  closeFactor,
26459
26480
  collateralDisabled: true,
26460
- debtDisabled: paused
26481
+ debtDisabled: borrowClosed
26461
26482
  }
26462
26483
  },
26463
26484
  closeFactor,
26464
26485
  collateralActive: false,
26465
- borrowingEnabled: !paused,
26486
+ borrowingEnabled: !borrowClosed,
26466
26487
  depositsEnabled: false,
26467
26488
  hasStable: false,
26468
- variableBorrowDisabled: paused,
26489
+ variableBorrowDisabled: borrowClosed,
26469
26490
  isActive: true,
26470
26491
  isFrozen: false
26471
26492
  };
@@ -26493,8 +26514,9 @@ function convertInverseMarketsToResponse(raw, chainId, prices = {}, _additionalY
26493
26514
  dolaLiquidity: m.dolaLiquidity !== null ? String(m.dolaLiquidity) : void 0,
26494
26515
  leftToBorrow: m.leftToBorrow !== null ? String(m.leftToBorrow) : void 0,
26495
26516
  liquidationFactorBps: market.liquidationFactorBps,
26496
- /** Fixed borrow APR as a DECIMAL (DBR price in DOLA). */
26497
- dbrPriceDola: raw.dbrPriceDola !== null ? String(raw.dbrPriceDola) : void 0,
26517
+ /** Fixed borrow APR as a DECIMAL (DBR price in DOLA). ABSENT when
26518
+ * unknown never `"0"`, which a consumer reads as a free loan. */
26519
+ dbrPriceDola: rateKnown ? String(raw.dbrPriceDola) : void 0,
26498
26520
  /** Force-replenish penalty (5475 = 54.75% APR on missed DBR):
26499
26521
  * the DOLA debt added per 1 DBR minted back to the borrower. */
26500
26522
  replenishmentPriceBps: raw.replenishmentPriceBps !== null ? String(raw.replenishmentPriceBps) : void 0,
@@ -29616,6 +29638,27 @@ var getLenderPublicDataViaApi = async (chainId, lenders, prices, additionalYield
29616
29638
  }
29617
29639
  return lenderData;
29618
29640
  };
29641
+
29642
+ // src/lending/public-data/morpho/unlisted.ts
29643
+ var MORPHO_UNLISTED_CHAINS = /* @__PURE__ */ new Set([
29644
+ // Robinhood Chain. 189 of its 194 markets are unlisted and essentially all of
29645
+ // them are Longbow — a curated Morpho Blue deployment (tokenized equities and
29646
+ // RWAs against USDG) that Morpho's own frontend does not carry, so `listed`
29647
+ // here says nothing about the market's quality. Enabled 2026-09-08 together
29648
+ // with the three things a chain needs before it can be:
29649
+ // 1. its collateral tokens in `token-lists` (wsNET was the last gap — the
29650
+ // collateral of the chain's LARGEST market), or the rows price at $0,
29651
+ // 2. `lender-metadata`'s `SERVES_UNLISTED_CHAINS` carrying the same chain
29652
+ // id, so the markets get a NAME and an oracle roster (5 -> 188 rows),
29653
+ // 3. a look at what the unlisted book actually holds — here 56 real
29654
+ // markets, $524k supplied / $351k borrowed, no runaway rates (the
29655
+ // highest borrow APR on the chain is 21.9 %).
29656
+ // See LONGBOW.md.
29657
+ "4663"
29658
+ ]);
29659
+ function morphoIncludesUnlisted(chainId) {
29660
+ return MORPHO_UNLISTED_CHAINS.has(chainId);
29661
+ }
29619
29662
  var ERC20_BALANCE_OF_ABI2 = [
29620
29663
  {
29621
29664
  inputs: [{ name: "account", type: "address" }],
@@ -29766,7 +29809,8 @@ function lenderApiWithOnChainFallback(lender, chainId) {
29766
29809
  }
29767
29810
  return false;
29768
29811
  }
29769
- var getLenderPublicDataAll = async (chainId, lenders, prices, additionalYields, multicallRetry, tokenList, includeUnlistedMorphoMarkets = false) => {
29812
+ var getLenderPublicDataAll = async (chainId, lenders, prices, additionalYields, multicallRetry, tokenList, includeUnlistedMorphoMarkets) => {
29813
+ const includeUnlisted = includeUnlistedMorphoMarkets ?? morphoIncludesUnlisted(chainId);
29770
29814
  const lendersApi = lenders.filter(
29771
29815
  (l) => lenderApiOnly(l, chainId) || lenderApiWithOnChainFallback(l, chainId)
29772
29816
  );
@@ -29779,7 +29823,7 @@ var getLenderPublicDataAll = async (chainId, lenders, prices, additionalYields,
29779
29823
  prices,
29780
29824
  additionalYields,
29781
29825
  tokenList,
29782
- includeUnlistedMorphoMarkets
29826
+ includeUnlisted
29783
29827
  );
29784
29828
  } catch (e) {
29785
29829
  warn5(
@@ -49656,6 +49700,302 @@ var NATIVE_WNLP_ENTRIES = Object.fromEntries(
49656
49700
  )
49657
49701
  ])
49658
49702
  );
49703
+ var RATIO_ABI = [
49704
+ {
49705
+ name: "ratio",
49706
+ type: "function",
49707
+ stateMutability: "view",
49708
+ inputs: [{ type: "uint256" }],
49709
+ outputs: [{ type: "uint256" }]
49710
+ },
49711
+ {
49712
+ name: "currentEpoch",
49713
+ type: "function",
49714
+ stateMutability: "view",
49715
+ inputs: [],
49716
+ outputs: [{ type: "uint256" }]
49717
+ }
49718
+ ];
49719
+ var EPOCH_RATIOS_ABI = [
49720
+ {
49721
+ name: "epochRatios",
49722
+ type: "function",
49723
+ stateMutability: "view",
49724
+ inputs: [{ type: "uint256" }],
49725
+ outputs: [
49726
+ { type: "uint64", name: "startRatio" },
49727
+ { type: "uint64", name: "endRatio" },
49728
+ { type: "uint64", name: "startTime" },
49729
+ { type: "uint64", name: "endTime" }
49730
+ ]
49731
+ }
49732
+ ];
49733
+ var WINDOW = 7;
49734
+ var SECONDS_PER_YEAR13 = 31536e3;
49735
+ var VAULT_EPOCH_ANCHOR = { epoch: 281, startTime: 1788858731 };
49736
+ var NOMINAL_EPOCH_SECONDS = 89580;
49737
+ var BFUSD_VAULTS = [
49738
+ { key: "hbfUSD", address: "0xde5d4ab42251ba9af6f247cf07c9a4793fa6ed88" },
49739
+ { key: "pbfUSD", address: "0x4f85cbfdefbdb3fa96fcf1e38b0ee68db9ae438b" }
49740
+ ];
49741
+ var BFBTC_DEPLOYMENTS = [
49742
+ {
49743
+ chain: Chain.ETHEREUM_MAINNET,
49744
+ address: "0xcdfb58c8c859cb3f62ebe9cf2767f9e036c7fb15"
49745
+ },
49746
+ {
49747
+ chain: Chain.BNB_SMART_CHAIN_MAINNET,
49748
+ address: "0x623f2774d9f27b59bc6b954544487532ce79d9df"
49749
+ },
49750
+ { chain: Chain.BASE, address: "0x623f2774d9f27b59bc6b954544487532ce79d9df" },
49751
+ {
49752
+ chain: Chain.HEMI_NETWORK,
49753
+ address: "0x623f2774d9f27b59bc6b954544487532ce79d9df"
49754
+ },
49755
+ {
49756
+ chain: Chain.BITLAYER_MAINNET,
49757
+ address: "0xcdfb58c8c859cb3f62ebe9cf2767f9e036c7fb15"
49758
+ },
49759
+ {
49760
+ chain: Chain.PHAROS_MAINNET,
49761
+ address: "0x623f2774d9f27b59bc6b954544487532ce79d9df"
49762
+ }
49763
+ ];
49764
+ var bitfiYieldKey = (chainId, address) => `bitfi::${chainId}::${address.toLowerCase()}`;
49765
+ var plausible = (apr) => Number.isFinite(apr) && apr > -50 && apr < 100;
49766
+ var asEpochRow = (cell) => {
49767
+ if (!Array.isArray(cell) || cell.length < 4) return void 0;
49768
+ const [a, b, c, d] = cell;
49769
+ if (typeof a !== "bigint" || typeof b !== "bigint" || typeof c !== "bigint" || typeof d !== "bigint")
49770
+ return void 0;
49771
+ return { startRatio: a, endRatio: b, startTime: c, endTime: d };
49772
+ };
49773
+ var readVaults = async () => {
49774
+ const estimate = VAULT_EPOCH_ANCHOR.epoch + Math.floor(
49775
+ (Date.now() / 1e3 - VAULT_EPOCH_ANCHOR.startTime) / NOMINAL_EPOCH_SECONDS
49776
+ );
49777
+ const probe = [];
49778
+ for (let e = estimate - 6; e <= estimate + 6; e++) {
49779
+ if (e - WINDOW >= 0) probe.push(e - WINDOW);
49780
+ if (e >= 0) probe.push(e);
49781
+ }
49782
+ const epochs = [...new Set(probe)].sort((a, b) => a - b);
49783
+ const results = await multicallRetryUniversal({
49784
+ chain: Chain.ETHEREUM_MAINNET,
49785
+ abi: EPOCH_RATIOS_ABI,
49786
+ calls: BFUSD_VAULTS.flatMap(
49787
+ ({ address }) => epochs.map((e) => ({
49788
+ address,
49789
+ name: "epochRatios",
49790
+ params: [BigInt(e)]
49791
+ }))
49792
+ ),
49793
+ allowFailure: true
49794
+ });
49795
+ const aprs = {};
49796
+ const cadences = [];
49797
+ BFUSD_VAULTS.forEach(({ address }, vi) => {
49798
+ const rows = /* @__PURE__ */ new Map();
49799
+ epochs.forEach((e, i) => {
49800
+ const row = asEpochRow(results[vi * epochs.length + i]);
49801
+ if (row && row.startTime > 0n && row.startRatio > 0n) rows.set(e, row);
49802
+ });
49803
+ const latest = Math.max(...[...rows.keys()], -1);
49804
+ if (latest < 0) return;
49805
+ const now = rows.get(latest);
49806
+ const then = rows.get(latest - WINDOW);
49807
+ if (!now || !then) return;
49808
+ const elapsed = Number(now.startTime - then.startTime);
49809
+ if (elapsed <= 0) return;
49810
+ cadences.push(elapsed / WINDOW);
49811
+ const growth = Number(now.startRatio) / Number(then.startRatio) - 1;
49812
+ const apr = 100 * SECONDS_PER_YEAR13 * growth / elapsed;
49813
+ if (plausible(apr)) {
49814
+ aprs[bitfiYieldKey(Chain.ETHEREUM_MAINNET, address)] = apr;
49815
+ }
49816
+ });
49817
+ const secondsPerEpoch = cadences.length ? cadences.reduce((a, b) => a + b, 0) / cadences.length : void 0;
49818
+ const usable = secondsPerEpoch !== void 0 && secondsPerEpoch > 43200 && secondsPerEpoch < 259200;
49819
+ return { aprs, secondsPerEpoch: usable ? secondsPerEpoch : void 0 };
49820
+ };
49821
+ var readBfbtc = async (chain, address, secondsPerEpoch) => {
49822
+ const [epochRaw] = await multicallRetryUniversal({
49823
+ chain,
49824
+ abi: RATIO_ABI,
49825
+ calls: [{ address, name: "currentEpoch", params: [] }],
49826
+ allowFailure: true
49827
+ });
49828
+ if (typeof epochRaw !== "bigint") return {};
49829
+ const latest = Number(epochRaw) - 1;
49830
+ if (latest - WINDOW < 0) return {};
49831
+ const [nowRaw, thenRaw] = await multicallRetryUniversal({
49832
+ chain,
49833
+ abi: RATIO_ABI,
49834
+ calls: [
49835
+ { address, name: "ratio", params: [BigInt(latest)] },
49836
+ { address, name: "ratio", params: [BigInt(latest - WINDOW)] }
49837
+ ],
49838
+ allowFailure: true
49839
+ });
49840
+ if (typeof nowRaw !== "bigint" || typeof thenRaw !== "bigint") return {};
49841
+ if (nowRaw <= 0n || thenRaw <= 0n) return {};
49842
+ const growth = Number(thenRaw) / Number(nowRaw) - 1;
49843
+ const apr = 100 * SECONDS_PER_YEAR13 * growth / (WINDOW * secondsPerEpoch);
49844
+ return plausible(apr) ? { [bitfiYieldKey(chain, address)]: apr } : {};
49845
+ };
49846
+ var bitfiFetcher = {
49847
+ label: "BITFI",
49848
+ fetch: async () => {
49849
+ const { aprs, secondsPerEpoch } = await readVaults();
49850
+ const clock = secondsPerEpoch ?? NOMINAL_EPOCH_SECONDS;
49851
+ const perChain = await Promise.all(
49852
+ BFBTC_DEPLOYMENTS.map(
49853
+ ({ chain, address }) => readBfbtc(chain, address, clock).catch(() => ({}))
49854
+ )
49855
+ );
49856
+ const out = { ...aprs };
49857
+ for (const part of perChain) Object.assign(out, part);
49858
+ if (Object.keys(out).length === 0) {
49859
+ throw new Error("BitFi: no product returned a readable epoch ratio");
49860
+ }
49861
+ return out;
49862
+ }
49863
+ };
49864
+
49865
+ // src/vaults/savings/registryBitfi.ts
49866
+ var BFBTC = [
49867
+ {
49868
+ chain: Chain.ETHEREUM_MAINNET,
49869
+ address: "0xcdfb58c8c859cb3f62ebe9cf2767f9e036c7fb15",
49870
+ underlying: "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599",
49871
+ // WBTC
49872
+ underlyingDecimals: 8,
49873
+ depositToken: "hemiBTC",
49874
+ exitNote: "Both legs are open; the flat fee is 0.00009 bfBTC to Ethereum and 0.000012 to Bitcoin"
49875
+ },
49876
+ {
49877
+ chain: Chain.BNB_SMART_CHAIN_MAINNET,
49878
+ address: "0x623f2774d9f27b59bc6b954544487532ce79d9df",
49879
+ underlying: "0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c",
49880
+ // BTCB
49881
+ underlyingDecimals: 18,
49882
+ depositToken: "BTCB",
49883
+ exitNote: "Both legs are open; the flat fee is 0.000006 bfBTC to BNB Chain and 0.000012 to Bitcoin"
49884
+ },
49885
+ {
49886
+ chain: Chain.BASE,
49887
+ address: "0x623f2774d9f27b59bc6b954544487532ce79d9df",
49888
+ underlying: "0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf",
49889
+ // cbBTC
49890
+ underlyingDecimals: 8,
49891
+ exitNote: "The only exit is to Bitcoin (flat 0.000012 bfBTC) \u2014 the EVM route is switched off by a 100 % fee"
49892
+ },
49893
+ {
49894
+ chain: Chain.HEMI_NETWORK,
49895
+ address: "0x623f2774d9f27b59bc6b954544487532ce79d9df",
49896
+ underlying: "0xaa40c0c7644e0b2b224509571e10ad20d9c4ef28",
49897
+ // hemiBTC
49898
+ underlyingDecimals: 8,
49899
+ depositToken: "hemiBTC",
49900
+ exitNote: "The only exit is to Hemi (flat 0.00002 bfBTC) \u2014 the Bitcoin route is off, contrary to the docs"
49901
+ },
49902
+ {
49903
+ chain: Chain.BITLAYER_MAINNET,
49904
+ address: "0xcdfb58c8c859cb3f62ebe9cf2767f9e036c7fb15",
49905
+ underlying: "0xff204e2681a6fa0e2c3fade68a1b28fb90e4fc5f",
49906
+ // WBTC
49907
+ underlyingDecimals: 18,
49908
+ depositToken: "the chain\u2019s native BTC gas token",
49909
+ exitNote: "The only exit is to Bitlayer (flat 0.000006 bfBTC) \u2014 the Bitcoin route is off"
49910
+ },
49911
+ {
49912
+ chain: Chain.PHAROS_MAINNET,
49913
+ address: "0x623f2774d9f27b59bc6b954544487532ce79d9df",
49914
+ underlying: "0xd990cf81e9aea2417326fdfac12b19aa66f8b6c2",
49915
+ // FBTC
49916
+ underlyingDecimals: 8,
49917
+ exitNote: "The only exit is to Bitcoin (flat 0.00002 bfBTC) \u2014 the EVM route is switched off by a 100 % fee"
49918
+ }
49919
+ ];
49920
+ var bfbtcDescription = (row) => `bfBTC accrues against BTC through a daily settled exchange ratio, so one bfBTC is worth more than one BTC. The yield is not staking: it is delta-neutral derivatives trading (perpetual funding and spot-vs-futures basis) run by third-party quant teams on assets in Ceffu custody, so the backing is off-chain with no on-chain solvency invariant. ` + (row.depositToken ? `Deposits take ${row.depositToken}. ` : `No on-chain deposit here \u2014 BTC is sent on the Bitcoin network. `) + `Exiting is a request BitFi's multisig must approve before it can be claimed. ${row.exitNote}.`;
49921
+ var BITFI_ENTRIES = {
49922
+ ...Object.fromEntries(
49923
+ BFBTC.map((row) => [
49924
+ row.chain,
49925
+ [
49926
+ {
49927
+ reader: "bitfi-bfbtc",
49928
+ address: row.address,
49929
+ underlying: row.underlying,
49930
+ symbol: "bfBTC",
49931
+ brand: "BitFi",
49932
+ description: bfbtcDescription(row),
49933
+ decimals: 8,
49934
+ underlyingDecimals: row.underlyingDecimals,
49935
+ isRebasing: false,
49936
+ // Every deployment that still accepts an entry accepts it
49937
+ // permissionlessly; the ones that do not are closed by an
49938
+ // unreachable minimum, which the reader publishes as
49939
+ // `depositCapacity: 0` rather than as a permission.
49940
+ isMintable: true,
49941
+ withdrawalMode: "request-based",
49942
+ // One epoch of cooldown (`cooldownEpoches()` = 1) before the
49943
+ // multisig may approve, and an epoch is ~89,580 s — not a day.
49944
+ withdrawalCooldownSeconds: 89580,
49945
+ yieldFetcher: bitfiFetcher,
49946
+ yieldKey: bitfiYieldKey(row.chain, row.address)
49947
+ }
49948
+ ]
49949
+ ])
49950
+ )
49951
+ };
49952
+ var BFUSD_VAULTS2 = [
49953
+ {
49954
+ reader: "bitfi-vault",
49955
+ address: "0xde5d4ab42251ba9af6f247cf07c9a4793fa6ed88",
49956
+ underlying: "0xa3eb7a9e57fca4e40b79e394ed5eb37fed205a24",
49957
+ // bfUSD
49958
+ symbol: "hbfUSD",
49959
+ brand: "BitFi",
49960
+ description: "Horizon is the conservative of BitFi's two bfUSD pools. bfUSD is minted 1:1 against USDC or USDT and the pool runs delta-neutral derivatives strategies on assets in Ceffu custody, so the backing is off-chain with no on-chain solvency invariant. Part of its revenue boosts the Pulsar pool, which in exchange stands as first-loss capital for Horizon. A redemption is a request settled three epochs later and then claimed, and the protocol keeps the rest of that epoch's yield \u2014 so leaving early in an epoch costs more. Deposits price at the epoch's end ratio, above the current share price.",
49961
+ decimals: 6,
49962
+ underlyingDecimals: 6,
49963
+ isRebasing: false,
49964
+ isMintable: true,
49965
+ withdrawalMode: "request-based",
49966
+ // 3 epochs of `settlementDelay()` at ~89,580 s each.
49967
+ withdrawalCooldownSeconds: 268740,
49968
+ yieldFetcher: bitfiFetcher,
49969
+ yieldKey: bitfiYieldKey(
49970
+ Chain.ETHEREUM_MAINNET,
49971
+ "0xde5d4ab42251ba9af6f247cf07c9a4793fa6ed88"
49972
+ )
49973
+ },
49974
+ {
49975
+ reader: "bitfi-vault",
49976
+ address: "0x4f85cbfdefbdb3fa96fcf1e38b0ee68db9ae438b",
49977
+ underlying: "0xa3eb7a9e57fca4e40b79e394ed5eb37fed205a24",
49978
+ // bfUSD
49979
+ symbol: "pbfUSD",
49980
+ brand: "BitFi",
49981
+ description: "Pulsar is the levered of BitFi's two bfUSD pools: it takes the residual of the same delta-neutral derivatives book, is boosted by Horizon revenue, and in exchange is first-loss capital for Horizon \u2014 so it is designed to draw down between epochs. The backing sits in Ceffu custody with no on-chain solvency invariant. A redemption is a request settled three epochs later and then claimed, and the protocol keeps the rest of that epoch's yield \u2014 so leaving early in an epoch costs more. Deposits price at the epoch's end ratio, above the current share price.",
49982
+ decimals: 6,
49983
+ underlyingDecimals: 6,
49984
+ isRebasing: false,
49985
+ isMintable: true,
49986
+ withdrawalMode: "request-based",
49987
+ withdrawalCooldownSeconds: 268740,
49988
+ yieldFetcher: bitfiFetcher,
49989
+ yieldKey: bitfiYieldKey(
49990
+ Chain.ETHEREUM_MAINNET,
49991
+ "0x4f85cbfdefbdb3fa96fcf1e38b0ee68db9ae438b"
49992
+ )
49993
+ }
49994
+ ];
49995
+ BITFI_ENTRIES[Chain.ETHEREUM_MAINNET] = [
49996
+ ...BITFI_ENTRIES[Chain.ETHEREUM_MAINNET] ?? [],
49997
+ ...BFUSD_VAULTS2
49998
+ ];
49659
49999
  var REWARD_RATE_ABI = [
49660
50000
  {
49661
50001
  name: "getCurrentRewardRate",
@@ -52037,6 +52377,10 @@ var SAVINGS_REGISTRY = (() => {
52037
52377
  if (!out[chainId]) out[chainId] = [];
52038
52378
  out[chainId].push(...entries);
52039
52379
  }
52380
+ for (const [chainId, entries] of Object.entries(BITFI_ENTRIES)) {
52381
+ if (!out[chainId]) out[chainId] = [];
52382
+ out[chainId].push(...entries);
52383
+ }
52040
52384
  for (const [chainId, entries] of Object.entries(VESPER_ENTRIES)) {
52041
52385
  if (!out[chainId]) out[chainId] = [];
52042
52386
  out[chainId].push(...entries);
@@ -53232,7 +53576,7 @@ var DLEND_POOLS = [
53232
53576
  }
53233
53577
  ];
53234
53578
  var ZERO_ADDRESS8 = "0x0000000000000000000000000000000000000000";
53235
- var SECONDS_PER_YEAR13 = 31536e3;
53579
+ var SECONDS_PER_YEAR14 = 31536e3;
53236
53580
  var ABI = [
53237
53581
  {
53238
53582
  name: "getReservesList",
@@ -53373,7 +53717,7 @@ function rebateApr(params) {
53373
53717
  if (nowSeconds >= Number(distributionEnd)) return 0;
53374
53718
  if (emissionPerSecond <= 0n || balanceTotalSupply <= 0n) return 0;
53375
53719
  if (!(rewardPrice > 0) || !(assetPrice > 0)) return 0;
53376
- const rewardsPerYearUsd = scale(emissionPerSecond, rewardDecimals) * SECONDS_PER_YEAR13 * rewardPrice;
53720
+ const rewardsPerYearUsd = scale(emissionPerSecond, rewardDecimals) * SECONDS_PER_YEAR14 * rewardPrice;
53377
53721
  const baseUsd = scale(balanceTotalSupply, balanceDecimals) * assetPrice;
53378
53722
  if (!(baseUsd > 0)) return 0;
53379
53723
  return rewardsPerYearUsd / baseUsd * 100;
@@ -53561,7 +53905,7 @@ var dtrinityRebateRewardFetcher = {
53561
53905
  return { byLender: merged };
53562
53906
  }
53563
53907
  };
53564
- var SECONDS_PER_YEAR14 = 31536e3;
53908
+ var SECONDS_PER_YEAR15 = 31536e3;
53565
53909
  var WAD16 = 10n ** 18n;
53566
53910
  var ZERO4 = "0x0000000000000000000000000000000000000000";
53567
53911
  var UNBOOSTED_FACTOR = 0.4;
@@ -53669,7 +54013,7 @@ function crvGaugeApr(params) {
53669
54013
  return 0;
53670
54014
  }
53671
54015
  if (!(crvPriceUsd > 0) || !(assetPriceUsd > 0)) return 0;
53672
- const crvPerYear = scale2(inflationRate, 18) * scale2(relativeWeight, 18) * SECONDS_PER_YEAR14;
54016
+ const crvPerYear = scale2(inflationRate, 18) * scale2(relativeWeight, 18) * SECONDS_PER_YEAR15;
53673
54017
  const stakedUsd = scale2(workingSupply, 18) * scale2(pricePerShare, 18) * assetPriceUsd;
53674
54018
  if (!(stakedUsd > 0)) return 0;
53675
54019
  return crvPerYear * crvPriceUsd / stakedUsd * 100 * UNBOOSTED_FACTOR;
@@ -53688,7 +54032,7 @@ function extraRewardApr(params) {
53688
54032
  if (nowSeconds >= Number(periodFinish)) return 0;
53689
54033
  if (rate <= 0n || totalSupply <= 0n) return 0;
53690
54034
  if (!(rewardPriceUsd > 0) || !(assetPriceUsd > 0)) return 0;
53691
- const rewardPerYearUsd = scale2(rate, rewardDecimals) * SECONDS_PER_YEAR14 * rewardPriceUsd;
54035
+ const rewardPerYearUsd = scale2(rate, rewardDecimals) * SECONDS_PER_YEAR15 * rewardPriceUsd;
53692
54036
  const stakedUsd = scale2(totalSupply, 18) * scale2(pricePerShare, 18) * assetPriceUsd;
53693
54037
  if (!(stakedUsd > 0)) return 0;
53694
54038
  return rewardPerYearUsd / stakedUsd * 100;
@@ -54327,8 +54671,8 @@ var MORPHO_API_INCOMPLETE_CHAINS = /* @__PURE__ */ new Set([
54327
54671
  // Mystic — no state.price
54328
54672
  Chain.PLUME_MAINNET,
54329
54673
  // Mystic — no state.price
54330
- "4114"
54331
- // Citrea (Mystic)not yet in chain-registry
54674
+ Chain.CITREA_MAINNET
54675
+ // Mystic — no state.price
54332
54676
  ]);
54333
54677
  function morphoApiIncomplete(chainId) {
54334
54678
  return MORPHO_API_INCOMPLETE_CHAINS.has(chainId);
@@ -54429,10 +54773,12 @@ function getMorphoAbi() {
54429
54773
  return ProxyOracleAbi;
54430
54774
  }
54431
54775
  var MORPHO_GRAPHQL_URL = "https://blue-api.morpho.org/graphql";
54432
- var PRICE_QUERY = (first, skip, chainId) => `
54776
+ var MAX_UNLISTED_PRICE_PAGES = 10;
54777
+ var PRICE_PAGE_SIZE = 200;
54778
+ var PRICE_QUERY = (first, skip, chainId, includeUnlisted) => `
54433
54779
  query GetMarketPrices {
54434
54780
  markets(first: ${first}, skip: ${skip}, where: {
54435
- chainId_in: [${chainId}]${chainId != Chain.ETHEREUM_MAINNET ? `,listed: true` : ""}
54781
+ chainId_in: [${chainId}]${!includeUnlisted && chainId != Chain.ETHEREUM_MAINNET ? `,listed: true` : ""}
54436
54782
  },
54437
54783
  orderBy: SupplyAssetsUsd,
54438
54784
  orderDirection: Desc
@@ -54457,44 +54803,47 @@ query GetMarketPrices {
54457
54803
  }
54458
54804
  }
54459
54805
  `;
54460
- async function fetchMorphoGraphQLPrices(chainId) {
54806
+ async function fetchMorphoGraphQLPrices(chainId, includeUnlisted = false) {
54461
54807
  if (!morphoApiAvailable(chainId)) return null;
54808
+ const post = (skip) => fetch(MORPHO_GRAPHQL_URL, {
54809
+ method: "POST",
54810
+ headers: { "Content-Type": "application/json" },
54811
+ body: JSON.stringify({
54812
+ query: PRICE_QUERY(PRICE_PAGE_SIZE, skip, chainId, includeUnlisted)
54813
+ })
54814
+ }).then((r) => r.json());
54815
+ const readItems = (result) => {
54816
+ const items = result?.data?.markets?.items;
54817
+ if (!Array.isArray(items)) {
54818
+ console.warn(
54819
+ `[morpho-gql] chain ${chainId}: unexpected API shape, items is not an array`
54820
+ );
54821
+ return null;
54822
+ }
54823
+ return items;
54824
+ };
54462
54825
  try {
54463
- const pages = chainId === Chain.ETHEREUM_MAINNET ? [
54464
- fetch(MORPHO_GRAPHQL_URL, {
54465
- method: "POST",
54466
- headers: { "Content-Type": "application/json" },
54467
- body: JSON.stringify({
54468
- query: PRICE_QUERY(200, 0, chainId)
54469
- })
54470
- }).then((r) => r.json()),
54471
- fetch(MORPHO_GRAPHQL_URL, {
54472
- method: "POST",
54473
- headers: { "Content-Type": "application/json" },
54474
- body: JSON.stringify({
54475
- query: PRICE_QUERY(200, 200, chainId)
54476
- })
54477
- }).then((r) => r.json())
54478
- ] : [
54479
- fetch(MORPHO_GRAPHQL_URL, {
54480
- method: "POST",
54481
- headers: { "Content-Type": "application/json" },
54482
- body: JSON.stringify({
54483
- query: PRICE_QUERY(200, 0, chainId)
54484
- })
54485
- }).then((r) => r.json())
54486
- ];
54487
- const results = await Promise.all(pages);
54488
54826
  const allMarkets = [];
54489
- for (const result of results) {
54490
- const items = result?.data?.markets?.items;
54491
- if (!Array.isArray(items)) {
54492
- console.warn(
54493
- `[morpho-gql] chain ${chainId}: unexpected API shape, items is not an array`
54494
- );
54495
- return null;
54827
+ if (includeUnlisted) {
54828
+ for (let page = 0; page < MAX_UNLISTED_PRICE_PAGES; page++) {
54829
+ const items = readItems(await post(page * PRICE_PAGE_SIZE));
54830
+ if (!items) return null;
54831
+ allMarkets.push(...items);
54832
+ if (items.length < PRICE_PAGE_SIZE) break;
54833
+ if (page === MAX_UNLISTED_PRICE_PAGES - 1) {
54834
+ console.warn(
54835
+ `[morpho-gql] chain ${chainId}: hit MAX_UNLISTED_PRICE_PAGES (${MAX_UNLISTED_PRICE_PAGES * PRICE_PAGE_SIZE} markets); markets below that rank by supply are unpriced`
54836
+ );
54837
+ }
54838
+ }
54839
+ } else {
54840
+ const skips = chainId === Chain.ETHEREUM_MAINNET ? [0, PRICE_PAGE_SIZE] : [0];
54841
+ const results = await Promise.all(skips.map(post));
54842
+ for (const result of results) {
54843
+ const items = readItems(result);
54844
+ if (!items) return null;
54845
+ allMarkets.push(...items);
54496
54846
  }
54497
- allMarkets.push(...items);
54498
54847
  }
54499
54848
  return processMarketsToEntries(chainId, allMarkets, "morpho-gql");
54500
54849
  } catch (err) {
@@ -56696,9 +57045,10 @@ async function fetchSiloV2GraphQLPrices(chainId, basePrices = {}, tokenList = {}
56696
57045
  const context = { chainId, usdPrices, tokenList };
56697
57046
  const entries = parseSiloV2GraphQLResults(items, context);
56698
57047
  if (entries.length === 0) {
56699
- console.warn(
56700
- `[silo-v2-gql] chain ${chainId}: ${items.length} markets fetched but 0 price entries produced`
56701
- );
57048
+ if (items.length > 0)
57049
+ console.warn(
57050
+ `[silo-v2-gql] chain ${chainId}: ${items.length} markets fetched but 0 price entries produced`
57051
+ );
56702
57052
  return null;
56703
57053
  }
56704
57054
  return entries;
@@ -56838,9 +57188,10 @@ async function fetchSiloV3GraphQLPrices(chainId, basePrices = {}, tokenList = {}
56838
57188
  const context = { chainId, usdPrices, tokenList };
56839
57189
  const entries = parseSiloV3GraphQLResults(items, context);
56840
57190
  if (entries.length === 0) {
56841
- console.warn(
56842
- `[silo-v3-gql] chain ${chainId}: ${items.length} markets fetched but 0 price entries produced`
56843
- );
57191
+ if (items.length > 0)
57192
+ console.warn(
57193
+ `[silo-v3-gql] chain ${chainId}: ${items.length} markets fetched but 0 price entries produced`
57194
+ );
56844
57195
  return null;
56845
57196
  }
56846
57197
  return entries;
@@ -56961,6 +57312,17 @@ function parseSiloV3GraphQLResults(items, context) {
56961
57312
  return out;
56962
57313
  }
56963
57314
 
57315
+ // src/prices/oracle-prices/fetchers/mysticApiKey.ts
57316
+ var mysticApiKey;
57317
+ function setMysticApiKey(key3) {
57318
+ mysticApiKey = key3 && key3.length > 0 ? key3 : void 0;
57319
+ }
57320
+ function getMysticApiKey() {
57321
+ if (mysticApiKey) return mysticApiKey;
57322
+ const fromEnv = typeof process !== "undefined" ? process.env?.MYSTIC_API_KEY : void 0;
57323
+ return fromEnv && fromEnv.length > 0 ? fromEnv : void 0;
57324
+ }
57325
+
56964
57326
  // src/prices/oracle-prices/fetchers/fetchMysticApi.ts
56965
57327
  var MYSTIC_CHAIN_IDS = /* @__PURE__ */ new Set([
56966
57328
  "14",
@@ -56976,10 +57338,26 @@ function hasMysticApi(chainId) {
56976
57338
 
56977
57339
  // src/prices/oracle-prices/fetchers/fetchMorphoMysticPrices.ts
56978
57340
  var FULL_URL = "https://api.mysticfinance.xyz/morphoCache/";
57341
+ function mysticPricesAvailable(chainId) {
57342
+ return hasMysticApi(chainId) && Boolean(getMysticApiKey());
57343
+ }
57344
+ var warnedUnauthorized = /* @__PURE__ */ new Set();
56979
57345
  async function fetchMorphoMysticPrices(chainId) {
56980
57346
  try {
56981
- const res = await fetch(`${FULL_URL}?chainId=${chainId}`);
57347
+ const apiKey = getMysticApiKey();
57348
+ const res = await fetch(`${FULL_URL}?chainId=${chainId}`, {
57349
+ headers: apiKey ? { "x-api-key": apiKey } : {}
57350
+ });
56982
57351
  if (!res.ok) {
57352
+ if (res.status === 401) {
57353
+ if (!warnedUnauthorized.has(chainId)) {
57354
+ warnedUnauthorized.add(chainId);
57355
+ console.warn(
57356
+ `[morpho-mystic] chain ${chainId}: 401 Unauthorized \u2014 the configured x-api-key was rejected; falling back to on-chain Morpho oracle prices only`
57357
+ );
57358
+ }
57359
+ return null;
57360
+ }
56983
57361
  console.warn(
56984
57362
  `[morpho-mystic] chain ${chainId}: ${res.status} ${res.statusText}`
56985
57363
  );
@@ -57013,10 +57391,7 @@ async function fetchMorphoMysticPrices(chainId) {
57013
57391
  }
57014
57392
  return processMarketsToEntries(chainId, allMarkets, "morpho-mystic");
57015
57393
  } catch (err) {
57016
- console.warn(
57017
- `[morpho-mystic] chain ${chainId}: fetch error, skipping`,
57018
- err
57019
- );
57394
+ console.warn(`[morpho-mystic] chain ${chainId}: fetch error, skipping`, err);
57020
57395
  return null;
57021
57396
  }
57022
57397
  }
@@ -57227,7 +57602,7 @@ async function executeGroup(group, chainId, chainBatchSize, retries, allowFailur
57227
57602
  };
57228
57603
  }
57229
57604
  }
57230
- async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3, batchSize = void 0, allowFailure = true, basePrices = {}, morphoMarketOverrides, listaMarketOverrides, stalenessThresholdSeconds = 3600, onlyFetchers, probeFeedStaleness = true, llamaLendMarketOverrides) {
57605
+ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3, batchSize = void 0, allowFailure = true, basePrices = {}, morphoMarketOverrides, listaMarketOverrides, stalenessThresholdSeconds = 3600, onlyFetchers, probeFeedStaleness = true, llamaLendMarketOverrides, includeUnlistedMorphoMarkets) {
57231
57606
  const totalStart = Date.now();
57232
57607
  const result = {};
57233
57608
  const chainPromises = chainIds.map(async (chainId) => {
@@ -57295,7 +57670,7 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
57295
57670
  () => aaveV4Fetcher.getCalls(chainId),
57296
57671
  getCallsErrors
57297
57672
  ) : [];
57298
- const morphoUseMystic = isActive("morpho") && hasMysticApi(chainId);
57673
+ const morphoUseMystic = isActive("morpho") && mysticPricesAvailable(chainId);
57299
57674
  const morphoUseApi = isActive("morpho") && !morphoUseMystic && morphoApiAvailable(chainId);
57300
57675
  const morphoUseRemote = morphoUseMystic || morphoUseApi;
57301
57676
  const morphoUseHybrid = morphoUseRemote && morphoApiIncomplete(chainId);
@@ -57621,7 +57996,10 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
57621
57996
  return { chainId, data: chainResult, diagnostic: diag2 };
57622
57997
  }
57623
57998
  const chainBatchSize = batchSize?.[chainId];
57624
- const morphoGqlPromise = morphoUseMystic ? fetchMorphoMysticPrices(chainId) : morphoUseApi ? fetchMorphoGraphQLPrices(chainId) : Promise.resolve(null);
57999
+ const morphoGqlPromise = morphoUseMystic ? fetchMorphoMysticPrices(chainId) : morphoUseApi ? fetchMorphoGraphQLPrices(
58000
+ chainId,
58001
+ includeUnlistedMorphoMarkets ?? morphoIncludesUnlisted(chainId)
58002
+ ) : Promise.resolve(null);
57625
58003
  const siloV2GqlPromise = isActive("silov2") ? fetchSiloV2GraphQLPrices(chainId, basePrices, tokenList) : Promise.resolve(null);
57626
58004
  const siloV3GqlPromise = isActive("silov3") ? fetchSiloV3GraphQLPrices(chainId, basePrices, tokenList) : Promise.resolve(null);
57627
58005
  const feedTimestampsPromise = stalenessThresholdSeconds > 0 && probeFeedStaleness ? probeAaveFeedTimestamps(chainId, {
@@ -57845,7 +58223,9 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
57845
58223
  siloV2GqlPromise,
57846
58224
  siloV3GqlPromise
57847
58225
  ]);
57848
- if (siloV2GqlEntries == null && siloV2Group.calls.length > 0) {
58226
+ if (siloV2GqlEntries == null && siloV2Group.calls.length > 0 && // Chains the indexer does not cover return null on EVERY run; the
58227
+ // on-chain path is their normal source, not a degraded one.
58228
+ SILO_API_SUPPORTED_CHAIN_IDS.has(chainId)) {
57849
58229
  console.warn(
57850
58230
  `[prices] chain ${chainId}: Silo v2 GraphQL returned null, falling back to on-chain (${siloV2Group.trackers.length} trackers)`
57851
58231
  );
@@ -57858,7 +58238,9 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
57858
58238
  allowFailure,
57859
58239
  rpcOverrides
57860
58240
  );
57861
- if (siloV3GqlEntries == null && siloV3Group.calls.length > 0) {
58241
+ if (siloV3GqlEntries == null && siloV3Group.calls.length > 0 && // Chains the indexer does not cover return null on EVERY run; the
58242
+ // on-chain path is their normal source, not a degraded one.
58243
+ SILO_API_SUPPORTED_CHAIN_IDS.has(chainId)) {
57862
58244
  console.warn(
57863
58245
  `[prices] chain ${chainId}: Silo v3 GraphQL returned null, falling back to on-chain (${siloV3Group.trackers.length} trackers)`
57864
58246
  );
@@ -60212,10 +60594,15 @@ function parseVault3(entry, results, chainId, prices, tokenList, marketIds, rate
60212
60594
  // src/vaults/morpho/rateSanity.ts
60213
60595
  var IMPLAUSIBLE_APR_PERCENT = 100;
60214
60596
  var PINNED_LIQUIDITY_FRACTION = 1e-3;
60215
- var isUnrealizableRate = (v) => {
60216
- if (!(v.depositRate > IMPLAUSIBLE_APR_PERCENT)) return false;
60217
- if (!(v.totalAssetsFormatted > 0)) return false;
60218
- return v.liquidityFormatted / v.totalAssetsFormatted < PINNED_LIQUIDITY_FRACTION;
60597
+ var isUnrealizableRate = (v) => isPinnedMarketRate({
60598
+ aprPercent: v.depositRate,
60599
+ totalAssets: v.totalAssetsFormatted,
60600
+ liquidity: v.liquidityFormatted
60601
+ });
60602
+ var isPinnedMarketRate = (args) => {
60603
+ if (!(args.aprPercent > IMPLAUSIBLE_APR_PERCENT)) return false;
60604
+ if (!(args.totalAssets > 0)) return false;
60605
+ return args.liquidity / args.totalAssets < PINNED_LIQUIDITY_FRACTION;
60219
60606
  };
60220
60607
  var dropUnrealizableRates = (vaults) => {
60221
60608
  const entries = Object.entries(vaults);
@@ -60669,7 +61056,7 @@ function computeSiloUtilization(vaultId, totalAssetsFormatted, positionsByVault,
60669
61056
  }
60670
61057
  var clamp012 = (n) => !Number.isFinite(n) ? 0 : n < 0 ? 0 : n > 1 ? 1 : n;
60671
61058
  var PERFORMANCE_FEE_SCALE = 1e16;
60672
- var SECONDS_PER_YEAR15 = 31536e3;
61059
+ var SECONDS_PER_YEAR16 = 31536e3;
60673
61060
  function buildVaultRewards(vaultId, totalAssetsUsd, programsByShareToken, priceOf2, nowSeconds) {
60674
61061
  const programs = programsByShareToken.get(vaultId) ?? [];
60675
61062
  const rewards = [];
@@ -60685,7 +61072,7 @@ function buildVaultRewards(vaultId, totalAssetsUsd, programsByShareToken, priceO
60685
61072
  const tokenPrice = tokenAddress ? priceOf2(tokenAddress) : 0;
60686
61073
  let apr;
60687
61074
  if (tokenPrice > 0 && totalAssetsUsd > 0) {
60688
- const annualTokens = emission / 10 ** tokenDecimals * SECONDS_PER_YEAR15;
61075
+ const annualTokens = emission / 10 ** tokenDecimals * SECONDS_PER_YEAR16;
60689
61076
  apr = annualTokens * tokenPrice / totalAssetsUsd * 100;
60690
61077
  rewardsRate += apr;
60691
61078
  } else {
@@ -67631,6 +68018,243 @@ var VesperPoolReadAbi = [
67631
68018
  }
67632
68019
  ];
67633
68020
 
68021
+ // src/vaults/savings/abis/bitfi.ts
68022
+ var BfbtcReadAbi = [
68023
+ {
68024
+ name: "currentRatio",
68025
+ type: "function",
68026
+ stateMutability: "view",
68027
+ inputs: [],
68028
+ outputs: [{ type: "uint256" }]
68029
+ },
68030
+ {
68031
+ name: "currentEpoch",
68032
+ type: "function",
68033
+ stateMutability: "view",
68034
+ inputs: [],
68035
+ outputs: [{ type: "uint256" }]
68036
+ },
68037
+ {
68038
+ name: "ratio",
68039
+ type: "function",
68040
+ stateMutability: "view",
68041
+ inputs: [{ type: "uint256" }],
68042
+ outputs: [{ type: "uint256" }]
68043
+ },
68044
+ {
68045
+ name: "underlyingAsset",
68046
+ type: "function",
68047
+ stateMutability: "view",
68048
+ inputs: [],
68049
+ outputs: [{ type: "address" }]
68050
+ },
68051
+ {
68052
+ name: "underlyingDecimals",
68053
+ type: "function",
68054
+ stateMutability: "view",
68055
+ inputs: [],
68056
+ outputs: [{ type: "uint256" }]
68057
+ },
68058
+ {
68059
+ name: "cooldownEpoches",
68060
+ type: "function",
68061
+ stateMutability: "view",
68062
+ inputs: [],
68063
+ outputs: [{ type: "uint256" }]
68064
+ },
68065
+ {
68066
+ name: "minDepositTokenAmount",
68067
+ type: "function",
68068
+ stateMutability: "view",
68069
+ inputs: [],
68070
+ outputs: [{ type: "uint256" }]
68071
+ },
68072
+ {
68073
+ name: "minWithdrawBfbtcAmount",
68074
+ type: "function",
68075
+ stateMutability: "view",
68076
+ inputs: [],
68077
+ outputs: [{ type: "uint256" }]
68078
+ },
68079
+ {
68080
+ // `feeType` 0 = withdraw to this EVM chain, 1 = withdraw to the Bitcoin
68081
+ // network. `percentageFee` is scaled by 100_000 and `fixedFee` by 1e8
68082
+ // (bfBTC's own decimals). Either leg is DISABLED by making its fee
68083
+ // unpayable rather than by a flag — see `BITFI_FEE_PRECISION`.
68084
+ name: "feeConfigs",
68085
+ type: "function",
68086
+ stateMutability: "view",
68087
+ inputs: [{ type: "uint8" }],
68088
+ outputs: [
68089
+ { type: "uint128", name: "percentageFee" },
68090
+ { type: "uint128", name: "fixedFee" }
68091
+ ]
68092
+ },
68093
+ {
68094
+ name: "previewWithdraw",
68095
+ type: "function",
68096
+ stateMutability: "view",
68097
+ inputs: [
68098
+ { type: "uint256", name: "share" },
68099
+ { type: "bool", name: "native" }
68100
+ ],
68101
+ outputs: [
68102
+ { type: "uint256", name: "underlyingAmount" },
68103
+ { type: "uint256", name: "fee" }
68104
+ ]
68105
+ },
68106
+ {
68107
+ name: "previewDeposit",
68108
+ type: "function",
68109
+ stateMutability: "view",
68110
+ inputs: [{ type: "uint256", name: "amount" }],
68111
+ outputs: [{ type: "uint256" }]
68112
+ },
68113
+ {
68114
+ name: "paused",
68115
+ type: "function",
68116
+ stateMutability: "view",
68117
+ inputs: [],
68118
+ outputs: [{ type: "bool" }]
68119
+ },
68120
+ {
68121
+ name: "isBlacklisted",
68122
+ type: "function",
68123
+ stateMutability: "view",
68124
+ inputs: [{ type: "address" }],
68125
+ outputs: [{ type: "bool" }]
68126
+ },
68127
+ {
68128
+ name: "multisig",
68129
+ type: "function",
68130
+ stateMutability: "view",
68131
+ inputs: [],
68132
+ outputs: [{ type: "address" }]
68133
+ },
68134
+ {
68135
+ // The full withdrawal record. `status` walks PENDING → CLAIMABLE (EVM) or
68136
+ // SENT_ON_NATIVE (Bitcoin) → CLAIMED, and only the multisig moves it.
68137
+ name: "withdrawals",
68138
+ type: "function",
68139
+ stateMutability: "view",
68140
+ inputs: [{ type: "uint256" }],
68141
+ outputs: [
68142
+ { type: "address", name: "user" },
68143
+ { type: "uint256", name: "amount" },
68144
+ { type: "bytes32", name: "btcAddress" },
68145
+ { type: "uint256", name: "epoch" },
68146
+ { type: "uint256", name: "settleEpoch" },
68147
+ { type: "bytes32", name: "nativeTx" },
68148
+ { type: "uint8", name: "btcAddressType" },
68149
+ { type: "uint8", name: "status" }
68150
+ ]
68151
+ },
68152
+ {
68153
+ name: "withdrawIdCounter",
68154
+ type: "function",
68155
+ stateMutability: "view",
68156
+ inputs: [],
68157
+ outputs: [{ type: "uint256" }]
68158
+ },
68159
+ {
68160
+ name: "claimable",
68161
+ type: "function",
68162
+ stateMutability: "view",
68163
+ inputs: [{ type: "uint256", name: "id" }],
68164
+ outputs: [{ type: "uint256" }]
68165
+ }
68166
+ ];
68167
+ var BfusdVaultReadAbi = [
68168
+ {
68169
+ name: "currentRatio",
68170
+ type: "function",
68171
+ stateMutability: "view",
68172
+ inputs: [],
68173
+ outputs: [{ type: "uint256" }]
68174
+ },
68175
+ {
68176
+ name: "currentDepositRatio",
68177
+ type: "function",
68178
+ stateMutability: "view",
68179
+ inputs: [],
68180
+ outputs: [{ type: "uint256" }]
68181
+ },
68182
+ {
68183
+ name: "epochRatios",
68184
+ type: "function",
68185
+ stateMutability: "view",
68186
+ inputs: [{ type: "uint256" }],
68187
+ outputs: [
68188
+ { type: "uint64", name: "startRatio" },
68189
+ { type: "uint64", name: "endRatio" },
68190
+ { type: "uint64", name: "startTime" },
68191
+ { type: "uint64", name: "endTime" }
68192
+ ]
68193
+ },
68194
+ {
68195
+ name: "settlementDelay",
68196
+ type: "function",
68197
+ stateMutability: "view",
68198
+ inputs: [],
68199
+ outputs: [{ type: "uint256" }]
68200
+ },
68201
+ {
68202
+ // Share-denominated, NOT underlying-denominated: compare it against
68203
+ // `totalSupply()`, and convert with the ratio before reporting a
68204
+ // deposit capacity in bfUSD.
68205
+ name: "supplyCap",
68206
+ type: "function",
68207
+ stateMutability: "view",
68208
+ inputs: [],
68209
+ outputs: [{ type: "uint256" }]
68210
+ },
68211
+ {
68212
+ name: "pendingWithdrawals",
68213
+ type: "function",
68214
+ stateMutability: "view",
68215
+ inputs: [],
68216
+ outputs: [{ type: "uint256" }]
68217
+ },
68218
+ {
68219
+ name: "redemptionFee",
68220
+ type: "function",
68221
+ stateMutability: "view",
68222
+ inputs: [],
68223
+ outputs: [
68224
+ { type: "uint128", name: "percentageFee" },
68225
+ { type: "uint128", name: "fixedFee" }
68226
+ ]
68227
+ },
68228
+ {
68229
+ name: "withdrawalIdCounter",
68230
+ type: "function",
68231
+ stateMutability: "view",
68232
+ inputs: [],
68233
+ outputs: [{ type: "uint256" }]
68234
+ },
68235
+ {
68236
+ name: "withdrawals",
68237
+ type: "function",
68238
+ stateMutability: "view",
68239
+ inputs: [{ type: "uint256" }],
68240
+ outputs: [
68241
+ { type: "address", name: "user" },
68242
+ { type: "bool", name: "claimed" },
68243
+ { type: "uint256", name: "amount" },
68244
+ { type: "uint256", name: "epoch" },
68245
+ { type: "uint256", name: "unvestedYield" }
68246
+ ]
68247
+ },
68248
+ {
68249
+ name: "paused",
68250
+ type: "function",
68251
+ stateMutability: "view",
68252
+ inputs: [],
68253
+ outputs: [{ type: "bool" }]
68254
+ }
68255
+ ];
68256
+ var BITFI_FEE_PRECISION = 100000n;
68257
+
67634
68258
  // src/vaults/savings/abis/bitway.ts
67635
68259
  var BitwayVaultReadAbi = [
67636
68260
  {
@@ -67884,6 +68508,122 @@ var readerErc4626WithdrawLimit = (entry) => {
67884
68508
  };
67885
68509
  };
67886
68510
 
68511
+ // src/vaults/savings/readers/bitfiBfbtc.ts
68512
+ var BITFI_RATIO_SCALE = 10n ** 8n;
68513
+ var CLOSED_DEPOSIT_MIN = 10n ** 20n;
68514
+ var readerBitfiBfbtc = (entry) => {
68515
+ const shareUnit = 10n ** BigInt(entry.decimals);
68516
+ const underlyingUnit = 10n ** BigInt(entry.underlyingDecimals ?? entry.decimals);
68517
+ return {
68518
+ calls: [
68519
+ { address: entry.address, name: "totalSupply", params: [] },
68520
+ { address: entry.address, name: "currentRatio", params: [] },
68521
+ { address: entry.address, name: "feeConfigs", params: [0] },
68522
+ { address: entry.address, name: "feeConfigs", params: [1] },
68523
+ { address: entry.address, name: "minDepositTokenAmount", params: [] },
68524
+ { address: entry.address, name: "paused", params: [] }
68525
+ ],
68526
+ abis: [
68527
+ TotalSupplyAbi2,
68528
+ BfbtcReadAbi,
68529
+ BfbtcReadAbi,
68530
+ BfbtcReadAbi,
68531
+ BfbtcReadAbi,
68532
+ BfbtcReadAbi
68533
+ ],
68534
+ parse: ([supply, ratio, evmFee, nativeFee, minDeposit, paused]) => {
68535
+ const totalSupply = toBigInt15(supply);
68536
+ const currentRatio = toBigInt15(ratio);
68537
+ if (totalSupply === void 0) return void 0;
68538
+ if (currentRatio === void 0 || currentRatio <= 0n) return void 0;
68539
+ const exchangeRate = ONE_E1814 * BITFI_RATIO_SCALE / currentRatio;
68540
+ const totalAssets = totalSupply * exchangeRate * underlyingUnit / (ONE_E1814 * shareUnit);
68541
+ const pct3 = (cell) => Array.isArray(cell) ? toBigInt15(cell[0]) : void 0;
68542
+ const evmPct = pct3(evmFee);
68543
+ const nativePct = pct3(nativeFee);
68544
+ const evmExitEnabled = evmPct === void 0 ? true : evmPct < BITFI_FEE_PRECISION;
68545
+ const nativeExitEnabled = nativePct === void 0 ? true : nativePct < BITFI_FEE_PRECISION;
68546
+ const minDep = toBigInt15(minDeposit);
68547
+ const depositsClosed = minDep !== void 0 && minDep >= CLOSED_DEPOSIT_MIN;
68548
+ const isPaused = paused === true;
68549
+ return {
68550
+ totalAssets,
68551
+ totalSupply,
68552
+ exchangeRate,
68553
+ // The only exit is a request, and BitFi charges no PROPORTIONAL fee on
68554
+ // the enabled leg — the cost is a flat per-request amount (0.000006 to
68555
+ // 0.00009 bfBTC, per chain) that basis points cannot express. Publish
68556
+ // the honest 0 rather than a size-dependent number invented here; the
68557
+ // flat fee is stated on the row's description and enforced by the
68558
+ // action route, which reads `previewWithdraw` for the exact figure.
68559
+ withdrawFeeBps: evmExitEnabled && evmPct !== void 0 ? Number(evmPct * 10000n / BITFI_FEE_PRECISION) : void 0,
68560
+ // Neither route settles in this block, so there is no instant leg to
68561
+ // enable — but a paused contract or two dead routes IS a closed exit,
68562
+ // and that must not read as an ordinary queue.
68563
+ instantRedeemEnabled: false,
68564
+ depositCapacity: depositsClosed || isPaused ? 0n : void 0,
68565
+ bitfiExit: {
68566
+ evmExitEnabled: evmExitEnabled && !isPaused,
68567
+ nativeExitEnabled: nativeExitEnabled && !isPaused,
68568
+ paused: isPaused
68569
+ }
68570
+ };
68571
+ }
68572
+ };
68573
+ };
68574
+
68575
+ // src/vaults/savings/readers/bitfiVault.ts
68576
+ var readerBitfiVault = (entry) => {
68577
+ return {
68578
+ calls: [
68579
+ { address: entry.address, name: "totalAssets", params: [] },
68580
+ { address: entry.address, name: "totalSupply", params: [] },
68581
+ { address: entry.address, name: "currentRatio", params: [] },
68582
+ { address: entry.address, name: "currentDepositRatio", params: [] },
68583
+ { address: entry.address, name: "supplyCap", params: [] },
68584
+ { address: entry.address, name: "paused", params: [] }
68585
+ ],
68586
+ abis: [
68587
+ Erc4626ReadAbi2,
68588
+ TotalSupplyAbi2,
68589
+ BfusdVaultReadAbi,
68590
+ BfusdVaultReadAbi,
68591
+ BfusdVaultReadAbi,
68592
+ BfusdVaultReadAbi
68593
+ ],
68594
+ parse: ([assets, supply, ratio, depositRatio, cap, paused]) => {
68595
+ const totalAssets = toBigInt15(assets);
68596
+ const totalSupply = toBigInt15(supply);
68597
+ const currentRatio = toBigInt15(ratio);
68598
+ if (totalAssets === void 0 || totalSupply === void 0)
68599
+ return void 0;
68600
+ if (currentRatio === void 0 || currentRatio <= 0n) return void 0;
68601
+ const exchangeRate = currentRatio * ONE_E1814 / BITFI_RATIO_SCALE;
68602
+ const depRatio = toBigInt15(depositRatio);
68603
+ const fundamentalExchangeRate = depRatio !== void 0 && depRatio > 0n ? depRatio * ONE_E1814 / BITFI_RATIO_SCALE : void 0;
68604
+ const supplyCap = toBigInt15(cap);
68605
+ const isPaused = paused === true;
68606
+ let depositCapacity;
68607
+ if (isPaused) {
68608
+ depositCapacity = 0n;
68609
+ } else if (supplyCap !== void 0 && supplyCap > 0n) {
68610
+ const headroomShares = supplyCap > totalSupply ? supplyCap - totalSupply : 0n;
68611
+ const priceRatio = depRatio && depRatio > 0n ? depRatio : currentRatio;
68612
+ depositCapacity = headroomShares * priceRatio / BITFI_RATIO_SCALE;
68613
+ }
68614
+ const withdrawFeeBps = depRatio !== void 0 && depRatio > currentRatio ? Number((depRatio - currentRatio) * 10000n / currentRatio) : 0;
68615
+ return {
68616
+ totalAssets,
68617
+ totalSupply,
68618
+ exchangeRate,
68619
+ fundamentalExchangeRate,
68620
+ depositCapacity,
68621
+ withdrawFeeBps
68622
+ };
68623
+ }
68624
+ };
68625
+ };
68626
+
67887
68627
  // src/vaults/savings/readers/bitwayVault.ts
67888
68628
  var BITWAY_PENALTY_BPS = {
67889
68629
  // Absolute Return
@@ -68235,6 +68975,10 @@ var buildReader2 = (entry) => {
68235
68975
  return readerHyperbeatVault(entry);
68236
68976
  case "bitway-vault":
68237
68977
  return readerBitwayVault(entry);
68978
+ case "bitfi-bfbtc":
68979
+ return readerBitfiBfbtc(entry);
68980
+ case "bitfi-vault":
68981
+ return readerBitfiVault(entry);
68238
68982
  case "yieldbasis-lt":
68239
68983
  return readerYieldBasisLt(entry);
68240
68984
  case "wren-nav":
@@ -68359,7 +69103,11 @@ var fetchSavingsVaults = async (chainId, multicallRetry, prices = {}, tokenList
68359
69103
  // limit view / the exit lock), so they count; Native's wNLP and Re's
68360
69104
  // NAV-oracle tokens revert on
68361
69105
  // `asset()`/`totalAssets()`/`convertToAssets()` and do not.
68362
- isErc4626: entry.reader === void 0 || entry.reader === "erc4626" || entry.reader === "erc4626-cooldown" || entry.reader === "erc4626-idle" || entry.reader === "erc4626-withdraw-limit",
69106
+ isErc4626: entry.reader === void 0 || entry.reader === "erc4626" || entry.reader === "erc4626-cooldown" || entry.reader === "erc4626-idle" || entry.reader === "erc4626-withdraw-limit" || // hbfUSD / pbfUSD ARE conforming 4626 — the bespoke reader exists for
69107
+ // the epoch ledger and the share-denominated supply cap, not because
69108
+ // the standard surface is missing. bfBTC (`bitfi-bfbtc`) is the
69109
+ // opposite and correctly falls through to `false`.
69110
+ entry.reader === "bitfi-vault",
68363
69111
  isRebasing: entry.isRebasing,
68364
69112
  isMintable: entry.isMintable,
68365
69113
  mintContract: entry.mintContract?.toLowerCase() ?? addressLc,
@@ -74082,10 +74830,12 @@ function stampEarnSubtitles(rows) {
74082
74830
  function renderedIdentity(m) {
74083
74831
  return [m.chainId, m.brand ?? m.venue, m.name ?? "", m.asset.symbol].join("|");
74084
74832
  }
74085
- function abbreviate(address) {
74833
+ function abbreviate(address, chars = 4) {
74086
74834
  const a = address?.trim();
74087
- if (!a || a.length < 6) return void 0;
74088
- return a.startsWith("0x") ? a.slice(0, 6) : `0x${a.slice(0, 4)}`;
74835
+ if (!a) return void 0;
74836
+ const hex = /^0x/i.test(a) ? a.slice(2) : a;
74837
+ if (!/^[0-9a-fA-F]+$/.test(hex) || hex.length < 4) return void 0;
74838
+ return `0x${hex.slice(0, chars)}`;
74089
74839
  }
74090
74840
  function disambiguateEarnNames(rows) {
74091
74841
  const groups = /* @__PURE__ */ new Map();
@@ -74108,19 +74858,33 @@ function disambiguateEarnNames(rows) {
74108
74858
  let changed = 0;
74109
74859
  for (const group of groups.values()) {
74110
74860
  if (group.length < 2) continue;
74111
- for (const pick3 of candidates) {
74112
- const marks = group.map(pick3);
74113
- if (marks.some((x) => !x)) continue;
74114
- if (new Set(marks).size !== marks.length) continue;
74115
- group.forEach((m, i) => {
74116
- m.name = m.name ? `${m.name} \xB7 ${marks[i]}` : marks[i];
74117
- changed++;
74118
- });
74119
- break;
74120
- }
74861
+ const marks = separatingMarks(group, candidates);
74862
+ if (!marks) continue;
74863
+ group.forEach((m, i) => {
74864
+ m.name = m.name ? `${m.name} \xB7 ${marks[i]}` : marks[i];
74865
+ changed++;
74866
+ });
74121
74867
  }
74122
74868
  return changed;
74123
74869
  }
74870
+ function separatingMarks(group, candidates) {
74871
+ const separates = (marks) => !marks.some((x) => !x) && new Set(marks).size === marks.length;
74872
+ for (const pick3 of candidates) {
74873
+ const marks = group.map(pick3);
74874
+ if (separates(marks)) return marks;
74875
+ }
74876
+ for (const width of [6, 8, 12, 40]) {
74877
+ for (const source of [
74878
+ (m) => m.refs?.oracle,
74879
+ (m) => m.venue.split("_").pop(),
74880
+ (m) => m.ref
74881
+ ]) {
74882
+ const marks = group.map((m) => abbreviate(source(m), width));
74883
+ if (separates(marks)) return marks;
74884
+ }
74885
+ }
74886
+ return void 0;
74887
+ }
74124
74888
  var SAME_BLOCK_EXIT_MODES = /* @__PURE__ */ new Set([
74125
74889
  "instant",
74126
74890
  "instant-capped",
@@ -74224,7 +74988,7 @@ var SDK_FRACTION_RATE_PROVIDERS = /* @__PURE__ */ new Set([
74224
74988
  "hypercore",
74225
74989
  "gmx"
74226
74990
  ]);
74227
- var RATE_SOURCE = {
74991
+ var EARN_RATE_SOURCE_BY_PROVIDER = {
74228
74992
  morpho: "api",
74229
74993
  silo: "api",
74230
74994
  lagoon: "api",
@@ -74329,7 +75093,7 @@ function earnMarketFromVault(row, chainId, opts = {}) {
74329
75093
  // ...and for the same reason it can never be pass-through.
74330
75094
  passthrough: false,
74331
75095
  kind: resolveRateKind(provider, meta),
74332
- source: RATE_SOURCE[provider] ?? "api",
75096
+ source: EARN_RATE_SOURCE_BY_PROVIDER[provider] ?? "api",
74333
75097
  // The curator's cut. Dropped entirely until now, which left the earn row
74334
75098
  // unable to say why its net rate sits below the gross one — and left the
74335
75099
  // term sheet built from this row with no fee schedule at all.
@@ -78215,6 +78979,52 @@ function sum2(...parts) {
78215
78979
  const present = parts.filter((p) => p !== void 0);
78216
78980
  return present.length ? present.reduce((a, b) => a + b, 0) : void 0;
78217
78981
  }
78982
+
78983
+ // src/earn/rateSanity.ts
78984
+ var IMPOSSIBLE_TVL_USD = 1e11;
78985
+ var isUnrealizableEarnRate = (m) => {
78986
+ const tvl = m.tvl?.formatted;
78987
+ const liq = m.liquidity?.formatted;
78988
+ if (tvl === void 0 || liq === void 0) return false;
78989
+ return isPinnedMarketRate({
78990
+ aprPercent: m.rate.total,
78991
+ totalAssets: tvl,
78992
+ liquidity: liq
78993
+ });
78994
+ };
78995
+ var isUnearnableEarnRate = (m, nowSecs) => isUnearnableRate({
78996
+ aprPercent: m.rate.total,
78997
+ totalAssetsUsd: m.tvl?.usd,
78998
+ expiry: m.maturity?.maturity,
78999
+ nowSecs
79000
+ });
79001
+ var repairImpossibleTvl = (m) => {
79002
+ if ((m.tvl?.usd ?? 0) <= IMPOSSIBLE_TVL_USD) return false;
79003
+ m.tvl.usd = void 0;
79004
+ if (m.liquidity?.usd !== void 0 && m.liquidity.usd > IMPOSSIBLE_TVL_USD) {
79005
+ m.liquidity.usd = void 0;
79006
+ }
79007
+ return true;
79008
+ };
79009
+ var applyEarnSanity = (rows, opts = {}) => {
79010
+ const items = [];
79011
+ let unrealizable = 0;
79012
+ let unearnable = 0;
79013
+ let repricedTvl = 0;
79014
+ for (const m of rows) {
79015
+ if (isUnrealizableEarnRate(m)) {
79016
+ unrealizable++;
79017
+ continue;
79018
+ }
79019
+ if (isUnearnableEarnRate(m, opts.nowSecs)) {
79020
+ unearnable++;
79021
+ continue;
79022
+ }
79023
+ if (repairImpossibleTvl(m)) repricedTvl++;
79024
+ items.push(m);
79025
+ }
79026
+ return { items, unrealizable, unearnable, repricedTvl };
79027
+ };
78218
79028
  var ASYNC_EXIT_MODES = /* @__PURE__ */ new Set([
78219
79029
  "fixed-cooldown",
78220
79030
  "request-based",
@@ -78356,8 +79166,11 @@ function vaultCapabilities(row) {
78356
79166
  requires: claimRequires(row, provider)
78357
79167
  });
78358
79168
  }
78359
- if (supportsCancel(provider, meta)) {
78360
- caps.push({ action: "cancel" });
79169
+ if (supportsCancel(row, provider)) {
79170
+ caps.push({
79171
+ action: "cancel",
79172
+ requires: savingsVerbRequiresFor(row, provider, "cancel")
79173
+ });
78361
79174
  }
78362
79175
  return caps;
78363
79176
  }
@@ -78426,9 +79239,33 @@ function claimRequires(row, provider) {
78426
79239
  return ["claimableEpoch"];
78427
79240
  return void 0;
78428
79241
  }
78429
- function supportsCancel(provider, meta) {
79242
+ function savingsVerbRequiresFor(row, provider, verb) {
79243
+ if (provider === "gmx" || provider === "lst") return void 0;
79244
+ const share = row.shareToken?.address ?? row.ref;
79245
+ if (!share || !row.chainId) return void 0;
79246
+ try {
79247
+ return savingsVerbRequires(
79248
+ String(row.chainId),
79249
+ share,
79250
+ verb
79251
+ );
79252
+ } catch {
79253
+ return void 0;
79254
+ }
79255
+ }
79256
+ function supportsCancel(row, provider) {
78430
79257
  if (provider === "gmx") return true;
78431
- return typeof meta.withdrawQueue === "string" && meta.withdrawQueue.length > 0;
79258
+ const share = row.shareToken?.address ?? row.ref;
79259
+ if (!share || !row.chainId) return false;
79260
+ try {
79261
+ return savingsSupportsVerb(
79262
+ String(row.chainId),
79263
+ share,
79264
+ "cancel"
79265
+ );
79266
+ } catch {
79267
+ return false;
79268
+ }
78432
79269
  }
78433
79270
 
78434
79271
  // src/earn/positions.ts
@@ -78632,6 +79469,6 @@ function earnPositionTotals(items) {
78632
79469
  };
78633
79470
  }
78634
79471
 
78635
- export { ApiBookSource, DEFAULT_MIDNIGHT_API, DEFAULT_OUTLIER_GUARD, DEFAULT_PROFILE_ID, DEFAULT_STALE_REJECT_SECONDS, DEFAULT_TERMMAX_API, DEFAULT_TERM_ORDER_STORE, EARN_DESCRIPTIONS, EARN_LABELS, EMPTY_BALANCE, EXACTLY_LENDER_KEY, FLYING_TULIP_LENDER_KEY, FRACTION_RATE_PROVIDERS, 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, MULTICALL_FAILURE, MaxParamThresholds, PASSTHROUGH_RATE_EPSILON, PENDLE_ASSETS_URL, PENDLE_CHAIN_IDS, PENDLE_MARKETS_URL, SDK_FRACTION_RATE_PROVIDERS, SPECTRA_NETWORKS, SPECTRA_RATE_MAX_PERCENT, SPECTRA_RATE_MIN_PERCENT, STABLECOIN_SYMBOLS, STCELO_MANAGER_ADDRESS, TELLER_CALLS_PER_BID, DECIMAL_BASE as TERMMAX_DECIMAL_BASE, TERMMAX_LIQUIDATION_PENALTY, TERMMAX_LIQUIDATION_WINDOW_SECS, TERMMAX_LIQUIDATOR_BONUS, TERMMAX_MARKETS_PER_CALL, TERMMAX_PARTIAL_CLOSE_FACTOR, TERMMAX_PARTIAL_LIQUIDATION_THRESHOLD_USD, TERM_ADAPTERS, TERM_PROFILES, TERM_SHEET_SCHEMA_VERSION, TermMaxApiSource, TermSubgraphSource, UPSHIFT_CHAIN_IDS, UPSHIFT_VAULTS_URL, VAULT_PROVIDERS, VAULT_PROVIDER_PROFILE, VAULT_PROVIDER_TRAITS, VAULT_SHARE_PRICE_PROBE, VAULT_VENUE_PREFIX, VOLATILE_VAULT_OVERRIDES, YEARN_CHAIN_IDS, YEARN_YDAEMON_BASE, __resetResupplyUserCaches, accountDepositListKey, accountWithdrawalListKey, appendSnapshot, applyPositionDelta, attachImplications, attachPricesToFlashLiquidity, borrowDescription, borrowFindings, borrowHeadline, buildExposures2 as buildExposures, buildFluidFTokensCall, buildLendingPositionUid, buildLiquityUserCall, buildLoopResult, buildMorphoTypeCall, buildMorphoTypeUserCallWithLens, buildPortfolioTotals, buildSumerAccumulators, buildSummaries, buildTellerUserCall, buildTermMaxUserCall, buildTermSheet, buildTermSheetsForGroup, buildVaultEarnUid, buildVaultLookup, buildVaultTermSheet, calculateLeverage, calculateNetApr, calculateOverallNetApr, calculateWeightedAverage, classifyFreshness, classifyReliability, classifyVault, clearPendleMarketsCache, clearSpectraMarketsCache, collateralSymbolsByVenue, 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, convertCoolerMarketsToResponse, convertDssMarketsToResponse, convertExactlyMarketsToResponse, convertFlyingTulipMarketsToResponse, convertFrankencoinMarketsToResponse, convertFraxlendPairsToResponse, convertInverseMarketsToResponse, convertLenderUserDataResult, convertLiquityMarketsToResponse, convertLlamaLendMarketsToResponse, convertResupplyMarketsToResponse, convertRiverMarketsToResponse, convertTellerMarketsToResponse, convertTermMarketsToResponse, convertTermMaxMarketsToResponse, convertUsddMarketsToResponse, createMarketUid, createMidnightBookSource, createMulticallRpcCall, createRawRpcCalls, createTermBookSource, createTermMaxDataSource, decodeListaMarkets, decodeMarkets, decodePackedListaUserDataset, decodePackedMorphoUserDataset, deriveBorrowTags, deriveSupplyTags, detectInterfaceKinds, dexResolverFor, disambiguateEarnNames, dssIlkBytes32, dssKeyParts, dssLenderKey, duration, earnDescription, earnLabel, earnMarketFromPool, earnMarketFromVault, earnMarketLabel, earnPositionFromLenderEntry, earnPositionFromVaultBalance, earnPositionTotals, earnRowSubtitle, earnUidFromMarketUid, earnVaultTerms, earnVenueKind, encodeBalanceFetcherCalldata, enrichTermSheet, enrichmentIndexFromRows, exactlyPairLtv, exactlyPenaltyRateToAprPercent, exactlyWadRateToPercent, feePhrase, feedKeyOf, feedStatKey, fetchCoolerMarkets, fetchDolomiteAccountNumbers, fetchDssMarkets, fetchEulerEarnVaults, fetchEulerEarnVaultsFromSubgraph, fetchEulerSubAccountIndexes, fetchExactlyMarkets, fetchFlashLiquidityForChain, fetchFluidDexState, fetchFluidFTokens, fetchFlyingTulipMarkets, fetchFrankencoinMarkets, fetchFraxlendPairs, fetchGeneralYields, fetchGeneralYieldsByMarketUid, fetchGmxExecutionFees, fetchGmxTickerPrices, fetchGmxVaults, fetchHypercoreVaults, fetchInverseMarkets, fetchLagoonApiVaults, fetchLagoonVaults, fetchLiquityMarkets, fetchListaVaultsFromChain, fetchLlamaLendMarkets, fetchMorphoUserBalances, fetchMorphoUserPositionMarkets, fetchMorphoVaults, fetchMorphoVaultsFromApi, fetchMorphoVaultsFromChain, fetchOraclePrices, fetchPendleApiAssets, fetchPendleApiMarkets, fetchPendlePrices, fetchPendlePtMarkets, fetchResupplyMarkets, fetchRiverMarkets, fetchSiloVaults, fetchSpectraApiMarkets, fetchSpectraPtMarkets, fetchTellerMarkets, fetchTermMarkets, fetchTermMaxMarkets, fetchTermStoreOrders, fetchTokenBalances, fetchTokenMetadata, fetchUpshiftApiVaults, fetchUpshiftVaults, fetchUsddMarkets, fetchYearnApiVaults, fetchYearnVaults, fillableRemaining, filterActiveLenders, filterLendersByProtocol, finalizeInfo, findingsFor, formatRaw, frankencoinKeyParts, frankencoinLenderKey, fraxlendAssetPerCollateral, fraxlendKeyParts, fraxlendLenderKey, fuseLenderData, generateLendingPools, getAavesForChain, getAssetConfig, getBalanceForMarketUid, getBorrowCapacity, getCachedFluidDexState, getCachedLiquityTroves, getCachedTellerBids, getCachedTermMaxDiscovery, getCachedTermMaxMarket, getCachedTermMaxMarkets, 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, getReadFailurePolicy, getResolvedDolomiteAccountNumbers, getStCeloValidatorGroups, getSubAccountAddress, getSubAccountIndex, getTermProfile, getVaultPublicDataAll, getVaultWithdrawalRequests, hasCritical, hasEulerEarnVaultSubgraph, hasLagoonVaults, hasMorphoPositionIndex, hasMorphoUserApi, hasMorphoUserSubgraph, hasPendleMarkets, hasSpectraMarkets, hasUpshiftVaults, hasYearnVaults, ilkToKeySegment, implausibleRatePercent, inverseKeyParts, inverseLenderKey, isBoundNeed, isFailedCall, isIlliquid, isLendingPosition, isLiveMarket as isLivePendleMarket, isLiveSpectraMarket, isSecondaryMarketOnly, isStablecoinSymbol, isVaultPosition, isVaultVenue, isYearnV3, keySegmentToIlk, keysFromMaps, lenderApiOnly, lenderFamily, liquityCandidateTroveIds, liquityKeyParts, liquityLenderKey, llamaLendKeyParts, llamaLendLenderKey, meetsLiquidityFloor, mergeDeep, multicall3Abi2 as multicall3Abi, nanTo, needsLenderApproval, needsTokenApproval, noOpResult, normalizeToBytes, organizeUserQueries, parseBalanceFetcherResult, parseEarnUid, parseMergedResult, parseMulticallRpcResponses, parseExpirySeconds as parsePendleExpirySeconds, parseRawRpcBatchResponses, parseRawRpcResponses, parseCurveFee as parseSpectraCurveFee, parsePtRate as parseSpectraPtRate, parseTermMaxLtv, parseTokenBalanceResult, pct, assetKey as pendleAssetKey, pickPool as pickSpectraPool, positivePart2 as positivePart, predictInverseEscrow, prepareLenderUserDataRpcCalls, prepareMergedMulticallParams, prepareMergedRpcCalls, prepareMulticallInputs, prepareTokenBalanceRpcCalls, priceGlvVaults, priceGmMarkets, probeAaveFeedTimestamps, pruneFeedStats, rankFindings, ratePercent, readVaultSharePrices, rejectOutliers as rejectPriceOutliers, resolveAdapter, resolveDerivation, resolveEarnIdentity, resolveModeConfig, resolveStCeloDepositGroup, resolveVaultProfileId, resupplyKeyParts, resupplyLenderKey, resupplyMarketLabel, riverKeyParts, riverLenderKey, sanePercent as saneSpectraPercent, savingsAddresses, savingsBalanceKind, secondaryMarketVault, selectAssetGroupPrices, shortDate, spectraAddress, spectraNetwork, spectraPoolsUrl, splitChainScopedAddress as splitPendleChainScopedAddress, stampCapabilities, stampEarnSubtitles, stampVaultClassification, stampVaultTermSheets, stripLeadingBrand, supplyDescription, supplyFindings, supplyHeadline, swapRoutedProvidersArePriceConsistent, tellerBpsToPercent, tellerImpliedLtv, tellerLenderKey, tellerPoolFromLenderKey, termApiBaseUrl, termLenderKey, termMaxApiBase, borrowNif as termMaxBorrowNif, curveApr as termMaxCurveApr, curveAprNumber as termMaxCurveAprNumber, daysToMaturity as termMaxDaysToMaturity, lendNif as termMaxLendNif, mintGtFeeRatio as termMaxMintGtFeeRatio, ratioToNumber as termMaxRatioToNumber, ratioToPercent as termMaxRatioToPercent, termOfferRateToAprPct, termOrderStoreBaseUrl, tickToAprNumber, tickToPrice, toDigest, toTermFillNow, toTermSheetInput, toVaultTermInput, trancheFromCounterparty, tryParseEarnUid, unflattenLenderData, updateFeedStats, usdValue, usddIlkBytes32, usddKeyParts, usddLenderKey, validateTermSheet, validateTermSheets, validateUserData, vaultSharesToAssets, vaultTermInputFromEarnMarket, vaultTermInputFromSourceRow, vaultTraits, vaultVenue, venueBrand, venueBrandKey, withMaturityLabel, withTrancheLabel };
79472
+ export { ApiBookSource, DEFAULT_MIDNIGHT_API, DEFAULT_OUTLIER_GUARD, DEFAULT_PROFILE_ID, DEFAULT_STALE_REJECT_SECONDS, DEFAULT_TERMMAX_API, DEFAULT_TERM_ORDER_STORE, EARN_DESCRIPTIONS, EARN_LABELS, EARN_RATE_SOURCE_BY_PROVIDER, EMPTY_BALANCE, EXACTLY_LENDER_KEY, FLYING_TULIP_LENDER_KEY, FRACTION_RATE_PROVIDERS, 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, MULTICALL_FAILURE, MaxParamThresholds, PASSTHROUGH_RATE_EPSILON, PENDLE_ASSETS_URL, PENDLE_CHAIN_IDS, PENDLE_MARKETS_URL, SDK_FRACTION_RATE_PROVIDERS, SPECTRA_NETWORKS, SPECTRA_RATE_MAX_PERCENT, SPECTRA_RATE_MIN_PERCENT, STABLECOIN_SYMBOLS, STCELO_MANAGER_ADDRESS, TELLER_CALLS_PER_BID, DECIMAL_BASE as TERMMAX_DECIMAL_BASE, TERMMAX_LIQUIDATION_PENALTY, TERMMAX_LIQUIDATION_WINDOW_SECS, TERMMAX_LIQUIDATOR_BONUS, TERMMAX_MARKETS_PER_CALL, TERMMAX_PARTIAL_CLOSE_FACTOR, TERMMAX_PARTIAL_LIQUIDATION_THRESHOLD_USD, TERM_ADAPTERS, TERM_PROFILES, TERM_SHEET_SCHEMA_VERSION, TermMaxApiSource, TermSubgraphSource, UPSHIFT_CHAIN_IDS, UPSHIFT_VAULTS_URL, VAULT_PROVIDERS, VAULT_PROVIDER_PROFILE, VAULT_PROVIDER_TRAITS, VAULT_SHARE_PRICE_PROBE, VAULT_VENUE_PREFIX, VOLATILE_VAULT_OVERRIDES, YEARN_CHAIN_IDS, YEARN_YDAEMON_BASE, __resetResupplyUserCaches, accountDepositListKey, accountWithdrawalListKey, appendSnapshot, applyEarnSanity, applyPositionDelta, attachImplications, attachPricesToFlashLiquidity, borrowDescription, borrowFindings, borrowHeadline, buildExposures2 as buildExposures, buildFluidFTokensCall, buildLendingPositionUid, buildLiquityUserCall, buildLoopResult, buildMorphoTypeCall, buildMorphoTypeUserCallWithLens, buildPortfolioTotals, buildSumerAccumulators, buildSummaries, buildTellerUserCall, buildTermMaxUserCall, buildTermSheet, buildTermSheetsForGroup, buildVaultEarnUid, buildVaultLookup, buildVaultTermSheet, calculateLeverage, calculateNetApr, calculateOverallNetApr, calculateWeightedAverage, classifyFreshness, classifyReliability, classifyVault, clearPendleMarketsCache, clearSpectraMarketsCache, collateralSymbolsByVenue, 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, convertCoolerMarketsToResponse, convertDssMarketsToResponse, convertExactlyMarketsToResponse, convertFlyingTulipMarketsToResponse, convertFrankencoinMarketsToResponse, convertFraxlendPairsToResponse, convertInverseMarketsToResponse, convertLenderUserDataResult, convertLiquityMarketsToResponse, convertLlamaLendMarketsToResponse, convertResupplyMarketsToResponse, convertRiverMarketsToResponse, convertTellerMarketsToResponse, convertTermMarketsToResponse, convertTermMaxMarketsToResponse, convertUsddMarketsToResponse, createMarketUid, createMidnightBookSource, createMulticallRpcCall, createRawRpcCalls, createTermBookSource, createTermMaxDataSource, decodeListaMarkets, decodeMarkets, decodePackedListaUserDataset, decodePackedMorphoUserDataset, deriveBorrowTags, deriveSupplyTags, detectInterfaceKinds, dexResolverFor, disambiguateEarnNames, dssIlkBytes32, dssKeyParts, dssLenderKey, duration, earnDescription, earnLabel, earnMarketFromPool, earnMarketFromVault, earnMarketLabel, earnPositionFromLenderEntry, earnPositionFromVaultBalance, earnPositionTotals, earnRowSubtitle, earnUidFromMarketUid, earnVaultTerms, earnVenueKind, encodeBalanceFetcherCalldata, enrichTermSheet, enrichmentIndexFromRows, exactlyPairLtv, exactlyPenaltyRateToAprPercent, exactlyWadRateToPercent, feePhrase, feedKeyOf, feedStatKey, fetchCoolerMarkets, fetchDolomiteAccountNumbers, fetchDssMarkets, fetchEulerEarnVaults, fetchEulerEarnVaultsFromSubgraph, fetchEulerSubAccountIndexes, fetchExactlyMarkets, fetchFlashLiquidityForChain, fetchFluidDexState, fetchFluidFTokens, fetchFlyingTulipMarkets, fetchFrankencoinMarkets, fetchFraxlendPairs, fetchGeneralYields, fetchGeneralYieldsByMarketUid, fetchGmxExecutionFees, fetchGmxTickerPrices, fetchGmxVaults, fetchHypercoreVaults, fetchInverseMarkets, fetchLagoonApiVaults, fetchLagoonVaults, fetchLiquityMarkets, fetchListaVaultsFromChain, fetchLlamaLendMarkets, fetchMorphoUserBalances, fetchMorphoUserPositionMarkets, fetchMorphoVaults, fetchMorphoVaultsFromApi, fetchMorphoVaultsFromChain, fetchOraclePrices, fetchPendleApiAssets, fetchPendleApiMarkets, fetchPendlePrices, fetchPendlePtMarkets, fetchResupplyMarkets, fetchRiverMarkets, fetchSiloVaults, fetchSpectraApiMarkets, fetchSpectraPtMarkets, fetchTellerMarkets, fetchTermMarkets, fetchTermMaxMarkets, fetchTermStoreOrders, fetchTokenBalances, fetchTokenMetadata, fetchUpshiftApiVaults, fetchUpshiftVaults, fetchUsddMarkets, fetchYearnApiVaults, fetchYearnVaults, fillableRemaining, filterActiveLenders, filterLendersByProtocol, finalizeInfo, findingsFor, formatRaw, frankencoinKeyParts, frankencoinLenderKey, fraxlendAssetPerCollateral, fraxlendKeyParts, fraxlendLenderKey, fuseLenderData, generateLendingPools, getAavesForChain, getAssetConfig, getBalanceForMarketUid, getBorrowCapacity, getCachedFluidDexState, getCachedLiquityTroves, getCachedTellerBids, getCachedTermMaxDiscovery, getCachedTermMaxMarket, getCachedTermMaxMarkets, 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, getReadFailurePolicy, getResolvedDolomiteAccountNumbers, getStCeloValidatorGroups, getSubAccountAddress, getSubAccountIndex, getTermProfile, getVaultPublicDataAll, getVaultWithdrawalRequests, hasCritical, hasEulerEarnVaultSubgraph, hasLagoonVaults, hasMorphoPositionIndex, hasMorphoUserApi, hasMorphoUserSubgraph, hasPendleMarkets, hasSpectraMarkets, hasUpshiftVaults, hasYearnVaults, ilkToKeySegment, implausibleRatePercent, inverseKeyParts, inverseLenderKey, isBoundNeed, isFailedCall, isIlliquid, isLendingPosition, isLiveMarket as isLivePendleMarket, isLiveSpectraMarket, isSecondaryMarketOnly, isStablecoinSymbol, isUnearnableEarnRate, isUnrealizableEarnRate, isVaultPosition, isVaultVenue, isYearnV3, keySegmentToIlk, keysFromMaps, lenderApiOnly, lenderFamily, liquityCandidateTroveIds, liquityKeyParts, liquityLenderKey, llamaLendKeyParts, llamaLendLenderKey, meetsLiquidityFloor, mergeDeep, multicall3Abi2 as multicall3Abi, nanTo, needsLenderApproval, needsTokenApproval, noOpResult, normalizeToBytes, organizeUserQueries, parseBalanceFetcherResult, parseEarnUid, parseMergedResult, parseMulticallRpcResponses, parseExpirySeconds as parsePendleExpirySeconds, parseRawRpcBatchResponses, parseRawRpcResponses, parseCurveFee as parseSpectraCurveFee, parsePtRate as parseSpectraPtRate, parseTermMaxLtv, parseTokenBalanceResult, pct, assetKey as pendleAssetKey, pickPool as pickSpectraPool, positivePart2 as positivePart, predictInverseEscrow, prepareLenderUserDataRpcCalls, prepareMergedMulticallParams, prepareMergedRpcCalls, prepareMulticallInputs, prepareTokenBalanceRpcCalls, priceGlvVaults, priceGmMarkets, probeAaveFeedTimestamps, pruneFeedStats, rankFindings, ratePercent, readVaultSharePrices, rejectOutliers as rejectPriceOutliers, repairImpossibleTvl, resolveAdapter, resolveDerivation, resolveEarnIdentity, resolveModeConfig, resolveStCeloDepositGroup, resolveVaultProfileId, resupplyKeyParts, resupplyLenderKey, resupplyMarketLabel, riverKeyParts, riverLenderKey, sanePercent as saneSpectraPercent, savingsAddresses, savingsBalanceKind, secondaryMarketVault, selectAssetGroupPrices, setMysticApiKey, shortDate, spectraAddress, spectraNetwork, spectraPoolsUrl, splitChainScopedAddress as splitPendleChainScopedAddress, stampCapabilities, stampEarnSubtitles, stampVaultClassification, stampVaultTermSheets, stripLeadingBrand, supplyDescription, supplyFindings, supplyHeadline, swapRoutedProvidersArePriceConsistent, tellerBpsToPercent, tellerImpliedLtv, tellerLenderKey, tellerPoolFromLenderKey, termApiBaseUrl, termLenderKey, termMaxApiBase, borrowNif as termMaxBorrowNif, curveApr as termMaxCurveApr, curveAprNumber as termMaxCurveAprNumber, daysToMaturity as termMaxDaysToMaturity, lendNif as termMaxLendNif, mintGtFeeRatio as termMaxMintGtFeeRatio, ratioToNumber as termMaxRatioToNumber, ratioToPercent as termMaxRatioToPercent, termOfferRateToAprPct, termOrderStoreBaseUrl, tickToAprNumber, tickToPrice, toDigest, toTermFillNow, toTermSheetInput, toVaultTermInput, trancheFromCounterparty, tryParseEarnUid, unflattenLenderData, updateFeedStats, usdValue, usddIlkBytes32, usddKeyParts, usddLenderKey, validateTermSheet, validateTermSheets, validateUserData, vaultSharesToAssets, vaultTermInputFromEarnMarket, vaultTermInputFromSourceRow, vaultTraits, vaultVenue, venueBrand, venueBrandKey, withMaturityLabel, withTrancheLabel };
78636
79473
  //# sourceMappingURL=index.js.map
78637
79474
  //# sourceMappingURL=index.js.map