@1delta/margin-fetcher 5.0.70 → 5.0.73

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
- 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';
10
+ import { LiquityTroveManagerAbi, LiquityActivePoolAbi, LiquityStabilityPoolAbi, LiquityPriceFeedAbi, LiquitySortedTrovesAbi, RiverTroveManagerAbi, RiverStabilityPoolAbi, TellerMarketRegistryAbi, TellerV2Abi, InverseMarketAbi, InverseOracleAbi, InverseDbrAbi, CurveTricryptoOracleAbi, 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",
@@ -6265,6 +6264,7 @@ var LENDER_SHORT_NAMES = {
6265
6264
  [Lender.AVALON_PUMPBTC]: "Avalon pumpBTC",
6266
6265
  [Lender.COMPOUND_V2]: "Comp. V2",
6267
6266
  [Lender.COMPOUND_V3_AERO]: "Comp. AERO",
6267
+ [Lender.COMPOUND_V3_INSTITUTIONAL_USDC]: "Comp. USDC (Inst.)",
6268
6268
  [Lender.COMPOUND_V3_USDBC]: "Comp. USDBC",
6269
6269
  [Lender.COMPOUND_V3_USDC]: "Comp. USDC",
6270
6270
  [Lender.COMPOUND_V3_USDCE]: "Comp. USDC.e",
@@ -21555,6 +21555,20 @@ function convertMidnightMarketsToResponse(raw, chainId, prices = {}, _additional
21555
21555
  const collPrice = prices[collKey] ?? 0;
21556
21556
  const collCapacityUSD = ltv > 0 ? borrowLiquidity * loanPrice / ltv : borrowLiquidity * loanPrice;
21557
21557
  const collCapacity = collPrice > 0 ? collCapacityUSD / collPrice : 0;
21558
+ const existing = entry.data[collUid];
21559
+ if (existing) {
21560
+ existing.collateralActive = true;
21561
+ existing.config = {
21562
+ 0: {
21563
+ ...existing.config?.[0] ?? {},
21564
+ borrowCollateralFactor: ltv,
21565
+ collateralFactor: ltv,
21566
+ liquidationPenalty,
21567
+ collateralDisabled: false
21568
+ }
21569
+ };
21570
+ return;
21571
+ }
21558
21572
  entry.data[collUid] = {
21559
21573
  marketUid: collUid,
21560
21574
  name: "Collateral " + (tokens[collAddr]?.symbol ?? ""),
@@ -24612,6 +24626,7 @@ var INVERSE_PUBLIC_READ_ABI = [
24612
24626
  ...InverseMarketAbi,
24613
24627
  ...InverseOracleAbi,
24614
24628
  ...InverseDbrAbi,
24629
+ ...CurveTricryptoOracleAbi,
24615
24630
  ...Erc20Abi
24616
24631
  ];
24617
24632
  var READS_PER_MARKET2 = 5;
@@ -24623,7 +24638,44 @@ var fetchJson = async (url, timeoutMs = 6e3) => {
24623
24638
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
24624
24639
  return res.json();
24625
24640
  };
24626
- var fetchDbrPriceDola = async (snapshot) => {
24641
+ var toNum3 = (v) => {
24642
+ if (typeof v === "bigint") return Number(v);
24643
+ return typeof v === "number" && Number.isFinite(v) ? v : null;
24644
+ };
24645
+ var fetchInverseChainWide = async (chainId, config) => {
24646
+ const pool = config.dbrPricePool;
24647
+ const calls = [
24648
+ { address: config.dbr, name: "replenishmentPriceBps", params: [] }
24649
+ ];
24650
+ if (pool) {
24651
+ calls.push(
24652
+ { address: pool, name: "coins", params: [0n] },
24653
+ { address: pool, name: "coins", params: [1n] },
24654
+ { address: pool, name: "price_oracle", params: [0n] }
24655
+ );
24656
+ }
24657
+ try {
24658
+ const r = await multicallRetryUniversal({
24659
+ chain: chainId,
24660
+ calls,
24661
+ abi: INVERSE_PUBLIC_READ_ABI,
24662
+ allowFailure: true
24663
+ });
24664
+ const replenishmentPriceBps = toNum3(r[0]);
24665
+ if (!pool) return { dbrPriceDola: null, replenishmentPriceBps };
24666
+ const same = (a, b) => typeof a === "string" && a.toLowerCase() === b.toLowerCase();
24667
+ const ordered = same(r[1], config.dola) && same(r[2], config.dbr);
24668
+ const raw = typeof r[3] === "bigint" ? Number(r[3]) / 1e18 : NaN;
24669
+ return {
24670
+ dbrPriceDola: ordered && Number.isFinite(raw) && raw > 0 ? raw : null,
24671
+ replenishmentPriceBps
24672
+ };
24673
+ } catch {
24674
+ return { dbrPriceDola: null, replenishmentPriceBps: null };
24675
+ }
24676
+ };
24677
+ var resolveDbrPriceDola = async (onChain, snapshot) => {
24678
+ if (onChain !== null) return onChain;
24627
24679
  try {
24628
24680
  const d = await fetchJson(DBR_URL);
24629
24681
  const p = Number(d?.priceDola);
@@ -24647,7 +24699,11 @@ async function fetchInverseMarkets(lender, chainId) {
24647
24699
  source: "none"
24648
24700
  };
24649
24701
  if (!config || markets.length === 0) return empty;
24650
- const dbrPricePromise = fetchDbrPriceDola(config.dbrPriceDolaSnapshot);
24702
+ const chainWidePromise = fetchInverseChainWide(chainId, config);
24703
+ const dbrPricePromise = chainWidePromise.then(
24704
+ (c) => resolveDbrPriceDola(c.dbrPriceDola, config.dbrPriceDolaSnapshot)
24705
+ );
24706
+ const replenishPromise = chainWidePromise.then((c) => c.replenishmentPriceBps);
24651
24707
  try {
24652
24708
  const api = await fetchJson(FIXED_MARKETS_URL);
24653
24709
  const byAddr = {};
@@ -24682,7 +24738,9 @@ async function fetchInverseMarkets(lender, chainId) {
24682
24738
  config,
24683
24739
  chainData,
24684
24740
  dbrPriceDola: await dbrPricePromise,
24685
- replenishmentPriceBps: num(api, "replenishmentPriceBps"),
24741
+ // On-chain is authoritative; the API field is a backstop that does
24742
+ // not exist today (see `num`).
24743
+ replenishmentPriceBps: await replenishPromise ?? num(api, "replenishmentPriceBps"),
24686
24744
  markets: rows,
24687
24745
  source: "api"
24688
24746
  };
@@ -24690,7 +24748,6 @@ async function fetchInverseMarkets(lender, chainId) {
24690
24748
  } catch {
24691
24749
  }
24692
24750
  const calls = [
24693
- { address: config.dbr, name: "replenishmentPriceBps", params: [] },
24694
24751
  ...markets.flatMap((m) => [
24695
24752
  { address: m.address, name: "totalDebt", params: [] },
24696
24753
  { address: m.address, name: "borrowPaused", params: [] },
@@ -24718,7 +24775,7 @@ async function fetchInverseMarkets(lender, chainId) {
24718
24775
  };
24719
24776
  const debtDecimals = config.debtDecimals ?? 18;
24720
24777
  const rows = markets.map((market, i) => {
24721
- const base = 1 + i * READS_PER_MARKET2;
24778
+ const base = i * READS_PER_MARKET2;
24722
24779
  const totalDebt = bigAt(base);
24723
24780
  const paused = results[base + 1];
24724
24781
  const liq = bigAt(base + 2);
@@ -24747,12 +24804,16 @@ async function fetchInverseMarkets(lender, chainId) {
24747
24804
  config,
24748
24805
  chainData,
24749
24806
  dbrPriceDola: await dbrPricePromise,
24750
- replenishmentPriceBps: bigAt(0) !== null ? Number(bigAt(0)) : null,
24807
+ replenishmentPriceBps: await replenishPromise,
24751
24808
  markets: rows,
24752
24809
  source: "chain"
24753
24810
  };
24754
24811
  } catch {
24755
- return { ...empty, dbrPriceDola: await dbrPricePromise };
24812
+ return {
24813
+ ...empty,
24814
+ dbrPriceDola: await dbrPricePromise,
24815
+ replenishmentPriceBps: await replenishPromise
24816
+ };
24756
24817
  }
24757
24818
  }
24758
24819
  function num(api, key3) {
@@ -26357,7 +26418,8 @@ function convertInverseMarketsToResponse(raw, chainId, prices = {}, _additionalY
26357
26418
  const dolaToken = tokens[dolaAddr];
26358
26419
  const dolaPriceKey = toOracleKey(dolaToken?.assetGroup) || toGenericPriceKey(dolaAddr, chainId);
26359
26420
  const dolaPrice = prices[dolaPriceKey] || 1;
26360
- const borrowAprPct = raw.dbrPriceDola !== null ? raw.dbrPriceDola * 100 : 0;
26421
+ const rateKnown = raw.dbrPriceDola !== null && raw.dbrPriceDola > 0;
26422
+ const borrowAprPct = rateKnown ? raw.dbrPriceDola * 100 : 0;
26361
26423
  for (const m of raw.markets ?? []) {
26362
26424
  const market = m.market;
26363
26425
  const lenderKey = inverseLenderKey(raw.lender, market.address);
@@ -26370,12 +26432,13 @@ function convertInverseMarketsToResponse(raw, chainId, prices = {}, _additionalY
26370
26432
  const collPrice = m.price ?? prices[collPriceKey] ?? 0;
26371
26433
  const totalDebt = m.totalDebt ?? 0;
26372
26434
  const paused = m.borrowPaused ?? !!market.borrowPaused;
26435
+ const borrowClosed = paused || !rateKnown;
26373
26436
  const ltv = Number(market.collateralFactorBps) / 1e4;
26374
26437
  const liqPenalty = Number(market.liquidationIncentiveBps) / 1e4;
26375
26438
  const closeFactor = Number(market.liquidationFactorBps) / 1e4 || 1;
26376
26439
  const collateralTotal = 0;
26377
26440
  let borrowLiquidity = m.leftToBorrow ?? m.dolaLiquidity ?? 0;
26378
- if (paused) borrowLiquidity = 0;
26441
+ if (borrowClosed) borrowLiquidity = 0;
26379
26442
  const entry = { data: {} };
26380
26443
  const collUid = createMarketUid(chainId, lenderKey, collAddr);
26381
26444
  entry.data[collUid] = {
@@ -26457,15 +26520,15 @@ function convertInverseMarketsToResponse(raw, chainId, prices = {}, _additionalY
26457
26520
  liquidationPenalty: liqPenalty,
26458
26521
  closeFactor,
26459
26522
  collateralDisabled: true,
26460
- debtDisabled: paused
26523
+ debtDisabled: borrowClosed
26461
26524
  }
26462
26525
  },
26463
26526
  closeFactor,
26464
26527
  collateralActive: false,
26465
- borrowingEnabled: !paused,
26528
+ borrowingEnabled: !borrowClosed,
26466
26529
  depositsEnabled: false,
26467
26530
  hasStable: false,
26468
- variableBorrowDisabled: paused,
26531
+ variableBorrowDisabled: borrowClosed,
26469
26532
  isActive: true,
26470
26533
  isFrozen: false
26471
26534
  };
@@ -26493,8 +26556,9 @@ function convertInverseMarketsToResponse(raw, chainId, prices = {}, _additionalY
26493
26556
  dolaLiquidity: m.dolaLiquidity !== null ? String(m.dolaLiquidity) : void 0,
26494
26557
  leftToBorrow: m.leftToBorrow !== null ? String(m.leftToBorrow) : void 0,
26495
26558
  liquidationFactorBps: market.liquidationFactorBps,
26496
- /** Fixed borrow APR as a DECIMAL (DBR price in DOLA). */
26497
- dbrPriceDola: raw.dbrPriceDola !== null ? String(raw.dbrPriceDola) : void 0,
26559
+ /** Fixed borrow APR as a DECIMAL (DBR price in DOLA). ABSENT when
26560
+ * unknown never `"0"`, which a consumer reads as a free loan. */
26561
+ dbrPriceDola: rateKnown ? String(raw.dbrPriceDola) : void 0,
26498
26562
  /** Force-replenish penalty (5475 = 54.75% APR on missed DBR):
26499
26563
  * the DOLA debt added per 1 DBR minted back to the borrower. */
26500
26564
  replenishmentPriceBps: raw.replenishmentPriceBps !== null ? String(raw.replenishmentPriceBps) : void 0,
@@ -29616,6 +29680,27 @@ var getLenderPublicDataViaApi = async (chainId, lenders, prices, additionalYield
29616
29680
  }
29617
29681
  return lenderData;
29618
29682
  };
29683
+
29684
+ // src/lending/public-data/morpho/unlisted.ts
29685
+ var MORPHO_UNLISTED_CHAINS = /* @__PURE__ */ new Set([
29686
+ // Robinhood Chain. 189 of its 194 markets are unlisted and essentially all of
29687
+ // them are Longbow — a curated Morpho Blue deployment (tokenized equities and
29688
+ // RWAs against USDG) that Morpho's own frontend does not carry, so `listed`
29689
+ // here says nothing about the market's quality. Enabled 2026-09-08 together
29690
+ // with the three things a chain needs before it can be:
29691
+ // 1. its collateral tokens in `token-lists` (wsNET was the last gap — the
29692
+ // collateral of the chain's LARGEST market), or the rows price at $0,
29693
+ // 2. `lender-metadata`'s `SERVES_UNLISTED_CHAINS` carrying the same chain
29694
+ // id, so the markets get a NAME and an oracle roster (5 -> 188 rows),
29695
+ // 3. a look at what the unlisted book actually holds — here 56 real
29696
+ // markets, $524k supplied / $351k borrowed, no runaway rates (the
29697
+ // highest borrow APR on the chain is 21.9 %).
29698
+ // See LONGBOW.md.
29699
+ "4663"
29700
+ ]);
29701
+ function morphoIncludesUnlisted(chainId) {
29702
+ return MORPHO_UNLISTED_CHAINS.has(chainId);
29703
+ }
29619
29704
  var ERC20_BALANCE_OF_ABI2 = [
29620
29705
  {
29621
29706
  inputs: [{ name: "account", type: "address" }],
@@ -29766,7 +29851,8 @@ function lenderApiWithOnChainFallback(lender, chainId) {
29766
29851
  }
29767
29852
  return false;
29768
29853
  }
29769
- var getLenderPublicDataAll = async (chainId, lenders, prices, additionalYields, multicallRetry, tokenList, includeUnlistedMorphoMarkets = false) => {
29854
+ var getLenderPublicDataAll = async (chainId, lenders, prices, additionalYields, multicallRetry, tokenList, includeUnlistedMorphoMarkets) => {
29855
+ const includeUnlisted = includeUnlistedMorphoMarkets ?? morphoIncludesUnlisted(chainId);
29770
29856
  const lendersApi = lenders.filter(
29771
29857
  (l) => lenderApiOnly(l, chainId) || lenderApiWithOnChainFallback(l, chainId)
29772
29858
  );
@@ -29779,7 +29865,7 @@ var getLenderPublicDataAll = async (chainId, lenders, prices, additionalYields,
29779
29865
  prices,
29780
29866
  additionalYields,
29781
29867
  tokenList,
29782
- includeUnlistedMorphoMarkets
29868
+ includeUnlisted
29783
29869
  );
29784
29870
  } catch (e) {
29785
29871
  warn5(
@@ -35220,11 +35306,11 @@ var getExactlyUserDataConverter = (_lender, chainId, account, meta) => {
35220
35306
  for (const p of m.fixedBorrowPositions) {
35221
35307
  const maturity = Number(p.maturity);
35222
35308
  const trancheStr = parseRawAmount(p.previewValue.toString(), decimals);
35223
- const isMatured2 = maturity < now;
35309
+ const isMatured = maturity < now;
35224
35310
  const face = faceOf(p);
35225
35311
  const faceStr = parseRawAmount(face.toString(), decimals);
35226
- const discount = isMatured2 ? "0" : parseRawAmount((face - p.previewValue).toString(), decimals);
35227
- const penalty = isMatured2 ? parseRawAmount((p.previewValue - face).toString(), decimals) : "0";
35312
+ const discount = isMatured ? "0" : parseRawAmount((face - p.previewValue).toString(), decimals);
35313
+ const penalty = isMatured ? parseRawAmount((p.previewValue - face).toString(), decimals) : "0";
35228
35314
  posData[`${loanUid}#${maturity}`] = {
35229
35315
  marketUid: loanUid,
35230
35316
  underlying: assetAddr,
@@ -35253,7 +35339,7 @@ var getExactlyUserDataConverter = (_lender, chainId, account, meta) => {
35253
35339
  p.position.fee.toString(),
35254
35340
  decimals
35255
35341
  ),
35256
- isMatured: isMatured2,
35342
+ isMatured,
35257
35343
  /** rebate if repaid now, before maturity (never a fee) */
35258
35344
  earlyRepayDiscount: discount,
35259
35345
  /** penalty already accrued past maturity */
@@ -35264,7 +35350,7 @@ var getExactlyUserDataConverter = (_lender, chainId, account, meta) => {
35264
35350
  decimals
35265
35351
  ),
35266
35352
  latePenaltyApr: penaltyApr,
35267
- secondsLate: isMatured2 ? now - maturity : 0
35353
+ secondsLate: isMatured ? now - maturity : 0
35268
35354
  }
35269
35355
  };
35270
35356
  }
@@ -37074,7 +37160,7 @@ var getTellerUserDataConverter = (_lender, chainId, account, meta) => {
37074
37160
  const loanDuration = Number(big20(field10(loanDetails, "loanDuration", 6)));
37075
37161
  const aprBps = Number(big20(field10(terms, "APR", 2)));
37076
37162
  const maturity = acceptedTs > 0 ? acceptedTs + loanDuration : void 0;
37077
- const isMatured2 = defaulted || maturity !== void 0 && maturity < now;
37163
+ const isMatured = defaulted || maturity !== void 0 && maturity < now;
37078
37164
  const collStr = parseRawAmount(collAmount.toString(), collDecimals);
37079
37165
  const collNum = Number(collStr);
37080
37166
  const debtStr = parseRawAmount(owedTotal.toString(), principalDecimals);
@@ -37130,7 +37216,7 @@ var getTellerUserDataConverter = (_lender, chainId, account, meta) => {
37130
37216
  apr: aprBps / 100,
37131
37217
  maturity,
37132
37218
  accruedInterest: interestStr,
37133
- isMatured: isMatured2
37219
+ isMatured
37134
37220
  }
37135
37221
  }
37136
37222
  };
@@ -37242,7 +37328,7 @@ var getTermMaxUserDataConverter = (_lender, chainId, account, meta) => {
37242
37328
  const loanDec = loanMeta?.asset?.decimals ?? market.debtDecimals;
37243
37329
  const collDec = collMeta?.asset?.decimals ?? market.collateralDecimals;
37244
37330
  const maturity = Number(market.maturity);
37245
- const isMatured2 = maturity > 0 && maturity <= now;
37331
+ const isMatured = maturity > 0 && maturity <= now;
37246
37332
  const positionsByAccount = {};
37247
37333
  const modes = {};
37248
37334
  const hist = {};
@@ -37318,7 +37404,7 @@ var getTermMaxUserDataConverter = (_lender, chainId, account, meta) => {
37318
37404
  isDynamic: false,
37319
37405
  debt: debtStr,
37320
37406
  maturity: maturity || void 0,
37321
- isMatured: isMatured2
37407
+ isMatured
37322
37408
  }
37323
37409
  }
37324
37410
  };
@@ -49656,6 +49742,302 @@ var NATIVE_WNLP_ENTRIES = Object.fromEntries(
49656
49742
  )
49657
49743
  ])
49658
49744
  );
49745
+ var RATIO_ABI = [
49746
+ {
49747
+ name: "ratio",
49748
+ type: "function",
49749
+ stateMutability: "view",
49750
+ inputs: [{ type: "uint256" }],
49751
+ outputs: [{ type: "uint256" }]
49752
+ },
49753
+ {
49754
+ name: "currentEpoch",
49755
+ type: "function",
49756
+ stateMutability: "view",
49757
+ inputs: [],
49758
+ outputs: [{ type: "uint256" }]
49759
+ }
49760
+ ];
49761
+ var EPOCH_RATIOS_ABI = [
49762
+ {
49763
+ name: "epochRatios",
49764
+ type: "function",
49765
+ stateMutability: "view",
49766
+ inputs: [{ type: "uint256" }],
49767
+ outputs: [
49768
+ { type: "uint64", name: "startRatio" },
49769
+ { type: "uint64", name: "endRatio" },
49770
+ { type: "uint64", name: "startTime" },
49771
+ { type: "uint64", name: "endTime" }
49772
+ ]
49773
+ }
49774
+ ];
49775
+ var WINDOW = 7;
49776
+ var SECONDS_PER_YEAR13 = 31536e3;
49777
+ var VAULT_EPOCH_ANCHOR = { epoch: 281, startTime: 1788858731 };
49778
+ var NOMINAL_EPOCH_SECONDS = 89580;
49779
+ var BFUSD_VAULTS = [
49780
+ { key: "hbfUSD", address: "0xde5d4ab42251ba9af6f247cf07c9a4793fa6ed88" },
49781
+ { key: "pbfUSD", address: "0x4f85cbfdefbdb3fa96fcf1e38b0ee68db9ae438b" }
49782
+ ];
49783
+ var BFBTC_DEPLOYMENTS = [
49784
+ {
49785
+ chain: Chain.ETHEREUM_MAINNET,
49786
+ address: "0xcdfb58c8c859cb3f62ebe9cf2767f9e036c7fb15"
49787
+ },
49788
+ {
49789
+ chain: Chain.BNB_SMART_CHAIN_MAINNET,
49790
+ address: "0x623f2774d9f27b59bc6b954544487532ce79d9df"
49791
+ },
49792
+ { chain: Chain.BASE, address: "0x623f2774d9f27b59bc6b954544487532ce79d9df" },
49793
+ {
49794
+ chain: Chain.HEMI_NETWORK,
49795
+ address: "0x623f2774d9f27b59bc6b954544487532ce79d9df"
49796
+ },
49797
+ {
49798
+ chain: Chain.BITLAYER_MAINNET,
49799
+ address: "0xcdfb58c8c859cb3f62ebe9cf2767f9e036c7fb15"
49800
+ },
49801
+ {
49802
+ chain: Chain.PHAROS_MAINNET,
49803
+ address: "0x623f2774d9f27b59bc6b954544487532ce79d9df"
49804
+ }
49805
+ ];
49806
+ var bitfiYieldKey = (chainId, address) => `bitfi::${chainId}::${address.toLowerCase()}`;
49807
+ var plausible = (apr) => Number.isFinite(apr) && apr > -50 && apr < 100;
49808
+ var asEpochRow = (cell) => {
49809
+ if (!Array.isArray(cell) || cell.length < 4) return void 0;
49810
+ const [a, b, c, d] = cell;
49811
+ if (typeof a !== "bigint" || typeof b !== "bigint" || typeof c !== "bigint" || typeof d !== "bigint")
49812
+ return void 0;
49813
+ return { startRatio: a, endRatio: b, startTime: c, endTime: d };
49814
+ };
49815
+ var readVaults = async () => {
49816
+ const estimate = VAULT_EPOCH_ANCHOR.epoch + Math.floor(
49817
+ (Date.now() / 1e3 - VAULT_EPOCH_ANCHOR.startTime) / NOMINAL_EPOCH_SECONDS
49818
+ );
49819
+ const probe = [];
49820
+ for (let e = estimate - 6; e <= estimate + 6; e++) {
49821
+ if (e - WINDOW >= 0) probe.push(e - WINDOW);
49822
+ if (e >= 0) probe.push(e);
49823
+ }
49824
+ const epochs = [...new Set(probe)].sort((a, b) => a - b);
49825
+ const results = await multicallRetryUniversal({
49826
+ chain: Chain.ETHEREUM_MAINNET,
49827
+ abi: EPOCH_RATIOS_ABI,
49828
+ calls: BFUSD_VAULTS.flatMap(
49829
+ ({ address }) => epochs.map((e) => ({
49830
+ address,
49831
+ name: "epochRatios",
49832
+ params: [BigInt(e)]
49833
+ }))
49834
+ ),
49835
+ allowFailure: true
49836
+ });
49837
+ const aprs = {};
49838
+ const cadences = [];
49839
+ BFUSD_VAULTS.forEach(({ address }, vi) => {
49840
+ const rows = /* @__PURE__ */ new Map();
49841
+ epochs.forEach((e, i) => {
49842
+ const row = asEpochRow(results[vi * epochs.length + i]);
49843
+ if (row && row.startTime > 0n && row.startRatio > 0n) rows.set(e, row);
49844
+ });
49845
+ const latest = Math.max(...[...rows.keys()], -1);
49846
+ if (latest < 0) return;
49847
+ const now = rows.get(latest);
49848
+ const then = rows.get(latest - WINDOW);
49849
+ if (!now || !then) return;
49850
+ const elapsed = Number(now.startTime - then.startTime);
49851
+ if (elapsed <= 0) return;
49852
+ cadences.push(elapsed / WINDOW);
49853
+ const growth = Number(now.startRatio) / Number(then.startRatio) - 1;
49854
+ const apr = 100 * SECONDS_PER_YEAR13 * growth / elapsed;
49855
+ if (plausible(apr)) {
49856
+ aprs[bitfiYieldKey(Chain.ETHEREUM_MAINNET, address)] = apr;
49857
+ }
49858
+ });
49859
+ const secondsPerEpoch = cadences.length ? cadences.reduce((a, b) => a + b, 0) / cadences.length : void 0;
49860
+ const usable = secondsPerEpoch !== void 0 && secondsPerEpoch > 43200 && secondsPerEpoch < 259200;
49861
+ return { aprs, secondsPerEpoch: usable ? secondsPerEpoch : void 0 };
49862
+ };
49863
+ var readBfbtc = async (chain, address, secondsPerEpoch) => {
49864
+ const [epochRaw] = await multicallRetryUniversal({
49865
+ chain,
49866
+ abi: RATIO_ABI,
49867
+ calls: [{ address, name: "currentEpoch", params: [] }],
49868
+ allowFailure: true
49869
+ });
49870
+ if (typeof epochRaw !== "bigint") return {};
49871
+ const latest = Number(epochRaw) - 1;
49872
+ if (latest - WINDOW < 0) return {};
49873
+ const [nowRaw, thenRaw] = await multicallRetryUniversal({
49874
+ chain,
49875
+ abi: RATIO_ABI,
49876
+ calls: [
49877
+ { address, name: "ratio", params: [BigInt(latest)] },
49878
+ { address, name: "ratio", params: [BigInt(latest - WINDOW)] }
49879
+ ],
49880
+ allowFailure: true
49881
+ });
49882
+ if (typeof nowRaw !== "bigint" || typeof thenRaw !== "bigint") return {};
49883
+ if (nowRaw <= 0n || thenRaw <= 0n) return {};
49884
+ const growth = Number(thenRaw) / Number(nowRaw) - 1;
49885
+ const apr = 100 * SECONDS_PER_YEAR13 * growth / (WINDOW * secondsPerEpoch);
49886
+ return plausible(apr) ? { [bitfiYieldKey(chain, address)]: apr } : {};
49887
+ };
49888
+ var bitfiFetcher = {
49889
+ label: "BITFI",
49890
+ fetch: async () => {
49891
+ const { aprs, secondsPerEpoch } = await readVaults();
49892
+ const clock = secondsPerEpoch ?? NOMINAL_EPOCH_SECONDS;
49893
+ const perChain = await Promise.all(
49894
+ BFBTC_DEPLOYMENTS.map(
49895
+ ({ chain, address }) => readBfbtc(chain, address, clock).catch(() => ({}))
49896
+ )
49897
+ );
49898
+ const out = { ...aprs };
49899
+ for (const part of perChain) Object.assign(out, part);
49900
+ if (Object.keys(out).length === 0) {
49901
+ throw new Error("BitFi: no product returned a readable epoch ratio");
49902
+ }
49903
+ return out;
49904
+ }
49905
+ };
49906
+
49907
+ // src/vaults/savings/registryBitfi.ts
49908
+ var BFBTC = [
49909
+ {
49910
+ chain: Chain.ETHEREUM_MAINNET,
49911
+ address: "0xcdfb58c8c859cb3f62ebe9cf2767f9e036c7fb15",
49912
+ underlying: "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599",
49913
+ // WBTC
49914
+ underlyingDecimals: 8,
49915
+ depositToken: "hemiBTC",
49916
+ exitNote: "Both legs are open; the flat fee is 0.00009 bfBTC to Ethereum and 0.000012 to Bitcoin"
49917
+ },
49918
+ {
49919
+ chain: Chain.BNB_SMART_CHAIN_MAINNET,
49920
+ address: "0x623f2774d9f27b59bc6b954544487532ce79d9df",
49921
+ underlying: "0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c",
49922
+ // BTCB
49923
+ underlyingDecimals: 18,
49924
+ depositToken: "BTCB",
49925
+ exitNote: "Both legs are open; the flat fee is 0.000006 bfBTC to BNB Chain and 0.000012 to Bitcoin"
49926
+ },
49927
+ {
49928
+ chain: Chain.BASE,
49929
+ address: "0x623f2774d9f27b59bc6b954544487532ce79d9df",
49930
+ underlying: "0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf",
49931
+ // cbBTC
49932
+ underlyingDecimals: 8,
49933
+ exitNote: "The only exit is to Bitcoin (flat 0.000012 bfBTC) \u2014 the EVM route is switched off by a 100 % fee"
49934
+ },
49935
+ {
49936
+ chain: Chain.HEMI_NETWORK,
49937
+ address: "0x623f2774d9f27b59bc6b954544487532ce79d9df",
49938
+ underlying: "0xaa40c0c7644e0b2b224509571e10ad20d9c4ef28",
49939
+ // hemiBTC
49940
+ underlyingDecimals: 8,
49941
+ depositToken: "hemiBTC",
49942
+ exitNote: "The only exit is to Hemi (flat 0.00002 bfBTC) \u2014 the Bitcoin route is off, contrary to the docs"
49943
+ },
49944
+ {
49945
+ chain: Chain.BITLAYER_MAINNET,
49946
+ address: "0xcdfb58c8c859cb3f62ebe9cf2767f9e036c7fb15",
49947
+ underlying: "0xff204e2681a6fa0e2c3fade68a1b28fb90e4fc5f",
49948
+ // WBTC
49949
+ underlyingDecimals: 18,
49950
+ depositToken: "the chain\u2019s native BTC gas token",
49951
+ exitNote: "The only exit is to Bitlayer (flat 0.000006 bfBTC) \u2014 the Bitcoin route is off"
49952
+ },
49953
+ {
49954
+ chain: Chain.PHAROS_MAINNET,
49955
+ address: "0x623f2774d9f27b59bc6b954544487532ce79d9df",
49956
+ underlying: "0xd990cf81e9aea2417326fdfac12b19aa66f8b6c2",
49957
+ // FBTC
49958
+ underlyingDecimals: 8,
49959
+ exitNote: "The only exit is to Bitcoin (flat 0.00002 bfBTC) \u2014 the EVM route is switched off by a 100 % fee"
49960
+ }
49961
+ ];
49962
+ 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}.`;
49963
+ var BITFI_ENTRIES = {
49964
+ ...Object.fromEntries(
49965
+ BFBTC.map((row) => [
49966
+ row.chain,
49967
+ [
49968
+ {
49969
+ reader: "bitfi-bfbtc",
49970
+ address: row.address,
49971
+ underlying: row.underlying,
49972
+ symbol: "bfBTC",
49973
+ brand: "BitFi",
49974
+ description: bfbtcDescription(row),
49975
+ decimals: 8,
49976
+ underlyingDecimals: row.underlyingDecimals,
49977
+ isRebasing: false,
49978
+ // Every deployment that still accepts an entry accepts it
49979
+ // permissionlessly; the ones that do not are closed by an
49980
+ // unreachable minimum, which the reader publishes as
49981
+ // `depositCapacity: 0` rather than as a permission.
49982
+ isMintable: true,
49983
+ withdrawalMode: "request-based",
49984
+ // One epoch of cooldown (`cooldownEpoches()` = 1) before the
49985
+ // multisig may approve, and an epoch is ~89,580 s — not a day.
49986
+ withdrawalCooldownSeconds: 89580,
49987
+ yieldFetcher: bitfiFetcher,
49988
+ yieldKey: bitfiYieldKey(row.chain, row.address)
49989
+ }
49990
+ ]
49991
+ ])
49992
+ )
49993
+ };
49994
+ var BFUSD_VAULTS2 = [
49995
+ {
49996
+ reader: "bitfi-vault",
49997
+ address: "0xde5d4ab42251ba9af6f247cf07c9a4793fa6ed88",
49998
+ underlying: "0xa3eb7a9e57fca4e40b79e394ed5eb37fed205a24",
49999
+ // bfUSD
50000
+ symbol: "hbfUSD",
50001
+ brand: "BitFi",
50002
+ 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.",
50003
+ decimals: 6,
50004
+ underlyingDecimals: 6,
50005
+ isRebasing: false,
50006
+ isMintable: true,
50007
+ withdrawalMode: "request-based",
50008
+ // 3 epochs of `settlementDelay()` at ~89,580 s each.
50009
+ withdrawalCooldownSeconds: 268740,
50010
+ yieldFetcher: bitfiFetcher,
50011
+ yieldKey: bitfiYieldKey(
50012
+ Chain.ETHEREUM_MAINNET,
50013
+ "0xde5d4ab42251ba9af6f247cf07c9a4793fa6ed88"
50014
+ )
50015
+ },
50016
+ {
50017
+ reader: "bitfi-vault",
50018
+ address: "0x4f85cbfdefbdb3fa96fcf1e38b0ee68db9ae438b",
50019
+ underlying: "0xa3eb7a9e57fca4e40b79e394ed5eb37fed205a24",
50020
+ // bfUSD
50021
+ symbol: "pbfUSD",
50022
+ brand: "BitFi",
50023
+ 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.",
50024
+ decimals: 6,
50025
+ underlyingDecimals: 6,
50026
+ isRebasing: false,
50027
+ isMintable: true,
50028
+ withdrawalMode: "request-based",
50029
+ withdrawalCooldownSeconds: 268740,
50030
+ yieldFetcher: bitfiFetcher,
50031
+ yieldKey: bitfiYieldKey(
50032
+ Chain.ETHEREUM_MAINNET,
50033
+ "0x4f85cbfdefbdb3fa96fcf1e38b0ee68db9ae438b"
50034
+ )
50035
+ }
50036
+ ];
50037
+ BITFI_ENTRIES[Chain.ETHEREUM_MAINNET] = [
50038
+ ...BITFI_ENTRIES[Chain.ETHEREUM_MAINNET] ?? [],
50039
+ ...BFUSD_VAULTS2
50040
+ ];
49659
50041
  var REWARD_RATE_ABI = [
49660
50042
  {
49661
50043
  name: "getCurrentRewardRate",
@@ -49859,7 +50241,9 @@ var DEFILLAMA_POOLS = {
49859
50241
  [vesperYieldKey("1", "0x4dbe3f01abe271d3e65432c74851625a8c30aa7b")]: "9b473092-6f2d-4fe6-af5a-f746b77ef5a0",
49860
50242
  // vaSTETH 1.41 %
49861
50243
  [vesperYieldKey("1", "0xd1c117319b3595fbc39b471ab1fd485629eb05f2")]: "359dd5cd-67a6-4f6a-83db-1edb301637e7",
49862
- // vaETH — 9.11 % (see divergence note)
50244
+ // vaETH — 9.11 %, then 89.65 % on
50245
+ // 2026-09-09 against a realized 0.47 %. THE WORST ROW IN THIS TABLE: never
50246
+ // treat a Llama value for this pool as plausible. See the hazard note above.
49863
50247
  [vesperYieldKey("1", "0xa8b607aa09b6a2e306f93e74c282fb13f6a80452")]: "eb342dc8-8d50-4300-8e92-c8d88e026c94",
49864
50248
  // vaUSDC 3.16 %
49865
50249
  [vesperYieldKey("1", "0x0538c8bac84e95a9df8ac10aad17dbe81b9e36ee")]: "d07783c3-bd68-4e38-927f-762fcb349dfc",
@@ -52037,6 +52421,10 @@ var SAVINGS_REGISTRY = (() => {
52037
52421
  if (!out[chainId]) out[chainId] = [];
52038
52422
  out[chainId].push(...entries);
52039
52423
  }
52424
+ for (const [chainId, entries] of Object.entries(BITFI_ENTRIES)) {
52425
+ if (!out[chainId]) out[chainId] = [];
52426
+ out[chainId].push(...entries);
52427
+ }
52040
52428
  for (const [chainId, entries] of Object.entries(VESPER_ENTRIES)) {
52041
52429
  if (!out[chainId]) out[chainId] = [];
52042
52430
  out[chainId].push(...entries);
@@ -53232,7 +53620,7 @@ var DLEND_POOLS = [
53232
53620
  }
53233
53621
  ];
53234
53622
  var ZERO_ADDRESS8 = "0x0000000000000000000000000000000000000000";
53235
- var SECONDS_PER_YEAR13 = 31536e3;
53623
+ var SECONDS_PER_YEAR14 = 31536e3;
53236
53624
  var ABI = [
53237
53625
  {
53238
53626
  name: "getReservesList",
@@ -53373,7 +53761,7 @@ function rebateApr(params) {
53373
53761
  if (nowSeconds >= Number(distributionEnd)) return 0;
53374
53762
  if (emissionPerSecond <= 0n || balanceTotalSupply <= 0n) return 0;
53375
53763
  if (!(rewardPrice > 0) || !(assetPrice > 0)) return 0;
53376
- const rewardsPerYearUsd = scale(emissionPerSecond, rewardDecimals) * SECONDS_PER_YEAR13 * rewardPrice;
53764
+ const rewardsPerYearUsd = scale(emissionPerSecond, rewardDecimals) * SECONDS_PER_YEAR14 * rewardPrice;
53377
53765
  const baseUsd = scale(balanceTotalSupply, balanceDecimals) * assetPrice;
53378
53766
  if (!(baseUsd > 0)) return 0;
53379
53767
  return rewardsPerYearUsd / baseUsd * 100;
@@ -53561,7 +53949,7 @@ var dtrinityRebateRewardFetcher = {
53561
53949
  return { byLender: merged };
53562
53950
  }
53563
53951
  };
53564
- var SECONDS_PER_YEAR14 = 31536e3;
53952
+ var SECONDS_PER_YEAR15 = 31536e3;
53565
53953
  var WAD16 = 10n ** 18n;
53566
53954
  var ZERO4 = "0x0000000000000000000000000000000000000000";
53567
53955
  var UNBOOSTED_FACTOR = 0.4;
@@ -53669,7 +54057,7 @@ function crvGaugeApr(params) {
53669
54057
  return 0;
53670
54058
  }
53671
54059
  if (!(crvPriceUsd > 0) || !(assetPriceUsd > 0)) return 0;
53672
- const crvPerYear = scale2(inflationRate, 18) * scale2(relativeWeight, 18) * SECONDS_PER_YEAR14;
54060
+ const crvPerYear = scale2(inflationRate, 18) * scale2(relativeWeight, 18) * SECONDS_PER_YEAR15;
53673
54061
  const stakedUsd = scale2(workingSupply, 18) * scale2(pricePerShare, 18) * assetPriceUsd;
53674
54062
  if (!(stakedUsd > 0)) return 0;
53675
54063
  return crvPerYear * crvPriceUsd / stakedUsd * 100 * UNBOOSTED_FACTOR;
@@ -53688,7 +54076,7 @@ function extraRewardApr(params) {
53688
54076
  if (nowSeconds >= Number(periodFinish)) return 0;
53689
54077
  if (rate <= 0n || totalSupply <= 0n) return 0;
53690
54078
  if (!(rewardPriceUsd > 0) || !(assetPriceUsd > 0)) return 0;
53691
- const rewardPerYearUsd = scale2(rate, rewardDecimals) * SECONDS_PER_YEAR14 * rewardPriceUsd;
54079
+ const rewardPerYearUsd = scale2(rate, rewardDecimals) * SECONDS_PER_YEAR15 * rewardPriceUsd;
53692
54080
  const stakedUsd = scale2(totalSupply, 18) * scale2(pricePerShare, 18) * assetPriceUsd;
53693
54081
  if (!(stakedUsd > 0)) return 0;
53694
54082
  return rewardPerYearUsd / stakedUsd * 100;
@@ -54429,10 +54817,12 @@ function getMorphoAbi() {
54429
54817
  return ProxyOracleAbi;
54430
54818
  }
54431
54819
  var MORPHO_GRAPHQL_URL = "https://blue-api.morpho.org/graphql";
54432
- var PRICE_QUERY = (first, skip, chainId) => `
54820
+ var MAX_UNLISTED_PRICE_PAGES = 10;
54821
+ var PRICE_PAGE_SIZE = 200;
54822
+ var PRICE_QUERY = (first, skip, chainId, includeUnlisted) => `
54433
54823
  query GetMarketPrices {
54434
54824
  markets(first: ${first}, skip: ${skip}, where: {
54435
- chainId_in: [${chainId}]${chainId != Chain.ETHEREUM_MAINNET ? `,listed: true` : ""}
54825
+ chainId_in: [${chainId}]${!includeUnlisted && chainId != Chain.ETHEREUM_MAINNET ? `,listed: true` : ""}
54436
54826
  },
54437
54827
  orderBy: SupplyAssetsUsd,
54438
54828
  orderDirection: Desc
@@ -54457,44 +54847,47 @@ query GetMarketPrices {
54457
54847
  }
54458
54848
  }
54459
54849
  `;
54460
- async function fetchMorphoGraphQLPrices(chainId) {
54850
+ async function fetchMorphoGraphQLPrices(chainId, includeUnlisted = false) {
54461
54851
  if (!morphoApiAvailable(chainId)) return null;
54852
+ const post = (skip) => fetch(MORPHO_GRAPHQL_URL, {
54853
+ method: "POST",
54854
+ headers: { "Content-Type": "application/json" },
54855
+ body: JSON.stringify({
54856
+ query: PRICE_QUERY(PRICE_PAGE_SIZE, skip, chainId, includeUnlisted)
54857
+ })
54858
+ }).then((r) => r.json());
54859
+ const readItems = (result) => {
54860
+ const items = result?.data?.markets?.items;
54861
+ if (!Array.isArray(items)) {
54862
+ console.warn(
54863
+ `[morpho-gql] chain ${chainId}: unexpected API shape, items is not an array`
54864
+ );
54865
+ return null;
54866
+ }
54867
+ return items;
54868
+ };
54462
54869
  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
54870
  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;
54871
+ if (includeUnlisted) {
54872
+ for (let page = 0; page < MAX_UNLISTED_PRICE_PAGES; page++) {
54873
+ const items = readItems(await post(page * PRICE_PAGE_SIZE));
54874
+ if (!items) return null;
54875
+ allMarkets.push(...items);
54876
+ if (items.length < PRICE_PAGE_SIZE) break;
54877
+ if (page === MAX_UNLISTED_PRICE_PAGES - 1) {
54878
+ console.warn(
54879
+ `[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`
54880
+ );
54881
+ }
54882
+ }
54883
+ } else {
54884
+ const skips = chainId === Chain.ETHEREUM_MAINNET ? [0, PRICE_PAGE_SIZE] : [0];
54885
+ const results = await Promise.all(skips.map(post));
54886
+ for (const result of results) {
54887
+ const items = readItems(result);
54888
+ if (!items) return null;
54889
+ allMarkets.push(...items);
54496
54890
  }
54497
- allMarkets.push(...items);
54498
54891
  }
54499
54892
  return processMarketsToEntries(chainId, allMarkets, "morpho-gql");
54500
54893
  } catch (err) {
@@ -57253,7 +57646,7 @@ async function executeGroup(group, chainId, chainBatchSize, retries, allowFailur
57253
57646
  };
57254
57647
  }
57255
57648
  }
57256
- async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3, batchSize = void 0, allowFailure = true, basePrices = {}, morphoMarketOverrides, listaMarketOverrides, stalenessThresholdSeconds = 3600, onlyFetchers, probeFeedStaleness = true, llamaLendMarketOverrides) {
57649
+ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3, batchSize = void 0, allowFailure = true, basePrices = {}, morphoMarketOverrides, listaMarketOverrides, stalenessThresholdSeconds = 3600, onlyFetchers, probeFeedStaleness = true, llamaLendMarketOverrides, includeUnlistedMorphoMarkets) {
57257
57650
  const totalStart = Date.now();
57258
57651
  const result = {};
57259
57652
  const chainPromises = chainIds.map(async (chainId) => {
@@ -57647,7 +58040,10 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
57647
58040
  return { chainId, data: chainResult, diagnostic: diag2 };
57648
58041
  }
57649
58042
  const chainBatchSize = batchSize?.[chainId];
57650
- const morphoGqlPromise = morphoUseMystic ? fetchMorphoMysticPrices(chainId) : morphoUseApi ? fetchMorphoGraphQLPrices(chainId) : Promise.resolve(null);
58043
+ const morphoGqlPromise = morphoUseMystic ? fetchMorphoMysticPrices(chainId) : morphoUseApi ? fetchMorphoGraphQLPrices(
58044
+ chainId,
58045
+ includeUnlistedMorphoMarkets ?? morphoIncludesUnlisted(chainId)
58046
+ ) : Promise.resolve(null);
57651
58047
  const siloV2GqlPromise = isActive("silov2") ? fetchSiloV2GraphQLPrices(chainId, basePrices, tokenList) : Promise.resolve(null);
57652
58048
  const siloV3GqlPromise = isActive("silov3") ? fetchSiloV3GraphQLPrices(chainId, basePrices, tokenList) : Promise.resolve(null);
57653
58049
  const feedTimestampsPromise = stalenessThresholdSeconds > 0 && probeFeedStaleness ? probeAaveFeedTimestamps(chainId, {
@@ -60242,10 +60638,15 @@ function parseVault3(entry, results, chainId, prices, tokenList, marketIds, rate
60242
60638
  // src/vaults/morpho/rateSanity.ts
60243
60639
  var IMPLAUSIBLE_APR_PERCENT = 100;
60244
60640
  var PINNED_LIQUIDITY_FRACTION = 1e-3;
60245
- var isUnrealizableRate = (v) => {
60246
- if (!(v.depositRate > IMPLAUSIBLE_APR_PERCENT)) return false;
60247
- if (!(v.totalAssetsFormatted > 0)) return false;
60248
- return v.liquidityFormatted / v.totalAssetsFormatted < PINNED_LIQUIDITY_FRACTION;
60641
+ var isUnrealizableRate = (v) => isPinnedMarketRate({
60642
+ aprPercent: v.depositRate,
60643
+ totalAssets: v.totalAssetsFormatted,
60644
+ liquidity: v.liquidityFormatted
60645
+ });
60646
+ var isPinnedMarketRate = (args) => {
60647
+ if (!(args.aprPercent > IMPLAUSIBLE_APR_PERCENT)) return false;
60648
+ if (!(args.totalAssets > 0)) return false;
60649
+ return args.liquidity / args.totalAssets < PINNED_LIQUIDITY_FRACTION;
60249
60650
  };
60250
60651
  var dropUnrealizableRates = (vaults) => {
60251
60652
  const entries = Object.entries(vaults);
@@ -60699,7 +61100,7 @@ function computeSiloUtilization(vaultId, totalAssetsFormatted, positionsByVault,
60699
61100
  }
60700
61101
  var clamp012 = (n) => !Number.isFinite(n) ? 0 : n < 0 ? 0 : n > 1 ? 1 : n;
60701
61102
  var PERFORMANCE_FEE_SCALE = 1e16;
60702
- var SECONDS_PER_YEAR15 = 31536e3;
61103
+ var SECONDS_PER_YEAR16 = 31536e3;
60703
61104
  function buildVaultRewards(vaultId, totalAssetsUsd, programsByShareToken, priceOf2, nowSeconds) {
60704
61105
  const programs = programsByShareToken.get(vaultId) ?? [];
60705
61106
  const rewards = [];
@@ -60715,7 +61116,7 @@ function buildVaultRewards(vaultId, totalAssetsUsd, programsByShareToken, priceO
60715
61116
  const tokenPrice = tokenAddress ? priceOf2(tokenAddress) : 0;
60716
61117
  let apr;
60717
61118
  if (tokenPrice > 0 && totalAssetsUsd > 0) {
60718
- const annualTokens = emission / 10 ** tokenDecimals * SECONDS_PER_YEAR15;
61119
+ const annualTokens = emission / 10 ** tokenDecimals * SECONDS_PER_YEAR16;
60719
61120
  apr = annualTokens * tokenPrice / totalAssetsUsd * 100;
60720
61121
  rewardsRate += apr;
60721
61122
  } else {
@@ -67661,6 +68062,243 @@ var VesperPoolReadAbi = [
67661
68062
  }
67662
68063
  ];
67663
68064
 
68065
+ // src/vaults/savings/abis/bitfi.ts
68066
+ var BfbtcReadAbi = [
68067
+ {
68068
+ name: "currentRatio",
68069
+ type: "function",
68070
+ stateMutability: "view",
68071
+ inputs: [],
68072
+ outputs: [{ type: "uint256" }]
68073
+ },
68074
+ {
68075
+ name: "currentEpoch",
68076
+ type: "function",
68077
+ stateMutability: "view",
68078
+ inputs: [],
68079
+ outputs: [{ type: "uint256" }]
68080
+ },
68081
+ {
68082
+ name: "ratio",
68083
+ type: "function",
68084
+ stateMutability: "view",
68085
+ inputs: [{ type: "uint256" }],
68086
+ outputs: [{ type: "uint256" }]
68087
+ },
68088
+ {
68089
+ name: "underlyingAsset",
68090
+ type: "function",
68091
+ stateMutability: "view",
68092
+ inputs: [],
68093
+ outputs: [{ type: "address" }]
68094
+ },
68095
+ {
68096
+ name: "underlyingDecimals",
68097
+ type: "function",
68098
+ stateMutability: "view",
68099
+ inputs: [],
68100
+ outputs: [{ type: "uint256" }]
68101
+ },
68102
+ {
68103
+ name: "cooldownEpoches",
68104
+ type: "function",
68105
+ stateMutability: "view",
68106
+ inputs: [],
68107
+ outputs: [{ type: "uint256" }]
68108
+ },
68109
+ {
68110
+ name: "minDepositTokenAmount",
68111
+ type: "function",
68112
+ stateMutability: "view",
68113
+ inputs: [],
68114
+ outputs: [{ type: "uint256" }]
68115
+ },
68116
+ {
68117
+ name: "minWithdrawBfbtcAmount",
68118
+ type: "function",
68119
+ stateMutability: "view",
68120
+ inputs: [],
68121
+ outputs: [{ type: "uint256" }]
68122
+ },
68123
+ {
68124
+ // `feeType` 0 = withdraw to this EVM chain, 1 = withdraw to the Bitcoin
68125
+ // network. `percentageFee` is scaled by 100_000 and `fixedFee` by 1e8
68126
+ // (bfBTC's own decimals). Either leg is DISABLED by making its fee
68127
+ // unpayable rather than by a flag — see `BITFI_FEE_PRECISION`.
68128
+ name: "feeConfigs",
68129
+ type: "function",
68130
+ stateMutability: "view",
68131
+ inputs: [{ type: "uint8" }],
68132
+ outputs: [
68133
+ { type: "uint128", name: "percentageFee" },
68134
+ { type: "uint128", name: "fixedFee" }
68135
+ ]
68136
+ },
68137
+ {
68138
+ name: "previewWithdraw",
68139
+ type: "function",
68140
+ stateMutability: "view",
68141
+ inputs: [
68142
+ { type: "uint256", name: "share" },
68143
+ { type: "bool", name: "native" }
68144
+ ],
68145
+ outputs: [
68146
+ { type: "uint256", name: "underlyingAmount" },
68147
+ { type: "uint256", name: "fee" }
68148
+ ]
68149
+ },
68150
+ {
68151
+ name: "previewDeposit",
68152
+ type: "function",
68153
+ stateMutability: "view",
68154
+ inputs: [{ type: "uint256", name: "amount" }],
68155
+ outputs: [{ type: "uint256" }]
68156
+ },
68157
+ {
68158
+ name: "paused",
68159
+ type: "function",
68160
+ stateMutability: "view",
68161
+ inputs: [],
68162
+ outputs: [{ type: "bool" }]
68163
+ },
68164
+ {
68165
+ name: "isBlacklisted",
68166
+ type: "function",
68167
+ stateMutability: "view",
68168
+ inputs: [{ type: "address" }],
68169
+ outputs: [{ type: "bool" }]
68170
+ },
68171
+ {
68172
+ name: "multisig",
68173
+ type: "function",
68174
+ stateMutability: "view",
68175
+ inputs: [],
68176
+ outputs: [{ type: "address" }]
68177
+ },
68178
+ {
68179
+ // The full withdrawal record. `status` walks PENDING → CLAIMABLE (EVM) or
68180
+ // SENT_ON_NATIVE (Bitcoin) → CLAIMED, and only the multisig moves it.
68181
+ name: "withdrawals",
68182
+ type: "function",
68183
+ stateMutability: "view",
68184
+ inputs: [{ type: "uint256" }],
68185
+ outputs: [
68186
+ { type: "address", name: "user" },
68187
+ { type: "uint256", name: "amount" },
68188
+ { type: "bytes32", name: "btcAddress" },
68189
+ { type: "uint256", name: "epoch" },
68190
+ { type: "uint256", name: "settleEpoch" },
68191
+ { type: "bytes32", name: "nativeTx" },
68192
+ { type: "uint8", name: "btcAddressType" },
68193
+ { type: "uint8", name: "status" }
68194
+ ]
68195
+ },
68196
+ {
68197
+ name: "withdrawIdCounter",
68198
+ type: "function",
68199
+ stateMutability: "view",
68200
+ inputs: [],
68201
+ outputs: [{ type: "uint256" }]
68202
+ },
68203
+ {
68204
+ name: "claimable",
68205
+ type: "function",
68206
+ stateMutability: "view",
68207
+ inputs: [{ type: "uint256", name: "id" }],
68208
+ outputs: [{ type: "uint256" }]
68209
+ }
68210
+ ];
68211
+ var BfusdVaultReadAbi = [
68212
+ {
68213
+ name: "currentRatio",
68214
+ type: "function",
68215
+ stateMutability: "view",
68216
+ inputs: [],
68217
+ outputs: [{ type: "uint256" }]
68218
+ },
68219
+ {
68220
+ name: "currentDepositRatio",
68221
+ type: "function",
68222
+ stateMutability: "view",
68223
+ inputs: [],
68224
+ outputs: [{ type: "uint256" }]
68225
+ },
68226
+ {
68227
+ name: "epochRatios",
68228
+ type: "function",
68229
+ stateMutability: "view",
68230
+ inputs: [{ type: "uint256" }],
68231
+ outputs: [
68232
+ { type: "uint64", name: "startRatio" },
68233
+ { type: "uint64", name: "endRatio" },
68234
+ { type: "uint64", name: "startTime" },
68235
+ { type: "uint64", name: "endTime" }
68236
+ ]
68237
+ },
68238
+ {
68239
+ name: "settlementDelay",
68240
+ type: "function",
68241
+ stateMutability: "view",
68242
+ inputs: [],
68243
+ outputs: [{ type: "uint256" }]
68244
+ },
68245
+ {
68246
+ // Share-denominated, NOT underlying-denominated: compare it against
68247
+ // `totalSupply()`, and convert with the ratio before reporting a
68248
+ // deposit capacity in bfUSD.
68249
+ name: "supplyCap",
68250
+ type: "function",
68251
+ stateMutability: "view",
68252
+ inputs: [],
68253
+ outputs: [{ type: "uint256" }]
68254
+ },
68255
+ {
68256
+ name: "pendingWithdrawals",
68257
+ type: "function",
68258
+ stateMutability: "view",
68259
+ inputs: [],
68260
+ outputs: [{ type: "uint256" }]
68261
+ },
68262
+ {
68263
+ name: "redemptionFee",
68264
+ type: "function",
68265
+ stateMutability: "view",
68266
+ inputs: [],
68267
+ outputs: [
68268
+ { type: "uint128", name: "percentageFee" },
68269
+ { type: "uint128", name: "fixedFee" }
68270
+ ]
68271
+ },
68272
+ {
68273
+ name: "withdrawalIdCounter",
68274
+ type: "function",
68275
+ stateMutability: "view",
68276
+ inputs: [],
68277
+ outputs: [{ type: "uint256" }]
68278
+ },
68279
+ {
68280
+ name: "withdrawals",
68281
+ type: "function",
68282
+ stateMutability: "view",
68283
+ inputs: [{ type: "uint256" }],
68284
+ outputs: [
68285
+ { type: "address", name: "user" },
68286
+ { type: "bool", name: "claimed" },
68287
+ { type: "uint256", name: "amount" },
68288
+ { type: "uint256", name: "epoch" },
68289
+ { type: "uint256", name: "unvestedYield" }
68290
+ ]
68291
+ },
68292
+ {
68293
+ name: "paused",
68294
+ type: "function",
68295
+ stateMutability: "view",
68296
+ inputs: [],
68297
+ outputs: [{ type: "bool" }]
68298
+ }
68299
+ ];
68300
+ var BITFI_FEE_PRECISION = 100000n;
68301
+
67664
68302
  // src/vaults/savings/abis/bitway.ts
67665
68303
  var BitwayVaultReadAbi = [
67666
68304
  {
@@ -67914,6 +68552,122 @@ var readerErc4626WithdrawLimit = (entry) => {
67914
68552
  };
67915
68553
  };
67916
68554
 
68555
+ // src/vaults/savings/readers/bitfiBfbtc.ts
68556
+ var BITFI_RATIO_SCALE = 10n ** 8n;
68557
+ var CLOSED_DEPOSIT_MIN = 10n ** 20n;
68558
+ var readerBitfiBfbtc = (entry) => {
68559
+ const shareUnit = 10n ** BigInt(entry.decimals);
68560
+ const underlyingUnit = 10n ** BigInt(entry.underlyingDecimals ?? entry.decimals);
68561
+ return {
68562
+ calls: [
68563
+ { address: entry.address, name: "totalSupply", params: [] },
68564
+ { address: entry.address, name: "currentRatio", params: [] },
68565
+ { address: entry.address, name: "feeConfigs", params: [0] },
68566
+ { address: entry.address, name: "feeConfigs", params: [1] },
68567
+ { address: entry.address, name: "minDepositTokenAmount", params: [] },
68568
+ { address: entry.address, name: "paused", params: [] }
68569
+ ],
68570
+ abis: [
68571
+ TotalSupplyAbi2,
68572
+ BfbtcReadAbi,
68573
+ BfbtcReadAbi,
68574
+ BfbtcReadAbi,
68575
+ BfbtcReadAbi,
68576
+ BfbtcReadAbi
68577
+ ],
68578
+ parse: ([supply, ratio, evmFee, nativeFee, minDeposit, paused]) => {
68579
+ const totalSupply = toBigInt15(supply);
68580
+ const currentRatio = toBigInt15(ratio);
68581
+ if (totalSupply === void 0) return void 0;
68582
+ if (currentRatio === void 0 || currentRatio <= 0n) return void 0;
68583
+ const exchangeRate = ONE_E1814 * BITFI_RATIO_SCALE / currentRatio;
68584
+ const totalAssets = totalSupply * exchangeRate * underlyingUnit / (ONE_E1814 * shareUnit);
68585
+ const pct3 = (cell) => Array.isArray(cell) ? toBigInt15(cell[0]) : void 0;
68586
+ const evmPct = pct3(evmFee);
68587
+ const nativePct = pct3(nativeFee);
68588
+ const evmExitEnabled = evmPct === void 0 ? true : evmPct < BITFI_FEE_PRECISION;
68589
+ const nativeExitEnabled = nativePct === void 0 ? true : nativePct < BITFI_FEE_PRECISION;
68590
+ const minDep = toBigInt15(minDeposit);
68591
+ const depositsClosed = minDep !== void 0 && minDep >= CLOSED_DEPOSIT_MIN;
68592
+ const isPaused = paused === true;
68593
+ return {
68594
+ totalAssets,
68595
+ totalSupply,
68596
+ exchangeRate,
68597
+ // The only exit is a request, and BitFi charges no PROPORTIONAL fee on
68598
+ // the enabled leg — the cost is a flat per-request amount (0.000006 to
68599
+ // 0.00009 bfBTC, per chain) that basis points cannot express. Publish
68600
+ // the honest 0 rather than a size-dependent number invented here; the
68601
+ // flat fee is stated on the row's description and enforced by the
68602
+ // action route, which reads `previewWithdraw` for the exact figure.
68603
+ withdrawFeeBps: evmExitEnabled && evmPct !== void 0 ? Number(evmPct * 10000n / BITFI_FEE_PRECISION) : void 0,
68604
+ // Neither route settles in this block, so there is no instant leg to
68605
+ // enable — but a paused contract or two dead routes IS a closed exit,
68606
+ // and that must not read as an ordinary queue.
68607
+ instantRedeemEnabled: false,
68608
+ depositCapacity: depositsClosed || isPaused ? 0n : void 0,
68609
+ bitfiExit: {
68610
+ evmExitEnabled: evmExitEnabled && !isPaused,
68611
+ nativeExitEnabled: nativeExitEnabled && !isPaused,
68612
+ paused: isPaused
68613
+ }
68614
+ };
68615
+ }
68616
+ };
68617
+ };
68618
+
68619
+ // src/vaults/savings/readers/bitfiVault.ts
68620
+ var readerBitfiVault = (entry) => {
68621
+ return {
68622
+ calls: [
68623
+ { address: entry.address, name: "totalAssets", params: [] },
68624
+ { address: entry.address, name: "totalSupply", params: [] },
68625
+ { address: entry.address, name: "currentRatio", params: [] },
68626
+ { address: entry.address, name: "currentDepositRatio", params: [] },
68627
+ { address: entry.address, name: "supplyCap", params: [] },
68628
+ { address: entry.address, name: "paused", params: [] }
68629
+ ],
68630
+ abis: [
68631
+ Erc4626ReadAbi2,
68632
+ TotalSupplyAbi2,
68633
+ BfusdVaultReadAbi,
68634
+ BfusdVaultReadAbi,
68635
+ BfusdVaultReadAbi,
68636
+ BfusdVaultReadAbi
68637
+ ],
68638
+ parse: ([assets, supply, ratio, depositRatio, cap, paused]) => {
68639
+ const totalAssets = toBigInt15(assets);
68640
+ const totalSupply = toBigInt15(supply);
68641
+ const currentRatio = toBigInt15(ratio);
68642
+ if (totalAssets === void 0 || totalSupply === void 0)
68643
+ return void 0;
68644
+ if (currentRatio === void 0 || currentRatio <= 0n) return void 0;
68645
+ const exchangeRate = currentRatio * ONE_E1814 / BITFI_RATIO_SCALE;
68646
+ const depRatio = toBigInt15(depositRatio);
68647
+ const fundamentalExchangeRate = depRatio !== void 0 && depRatio > 0n ? depRatio * ONE_E1814 / BITFI_RATIO_SCALE : void 0;
68648
+ const supplyCap = toBigInt15(cap);
68649
+ const isPaused = paused === true;
68650
+ let depositCapacity;
68651
+ if (isPaused) {
68652
+ depositCapacity = 0n;
68653
+ } else if (supplyCap !== void 0 && supplyCap > 0n) {
68654
+ const headroomShares = supplyCap > totalSupply ? supplyCap - totalSupply : 0n;
68655
+ const priceRatio = depRatio && depRatio > 0n ? depRatio : currentRatio;
68656
+ depositCapacity = headroomShares * priceRatio / BITFI_RATIO_SCALE;
68657
+ }
68658
+ const withdrawFeeBps = depRatio !== void 0 && depRatio > currentRatio ? Number((depRatio - currentRatio) * 10000n / currentRatio) : 0;
68659
+ return {
68660
+ totalAssets,
68661
+ totalSupply,
68662
+ exchangeRate,
68663
+ fundamentalExchangeRate,
68664
+ depositCapacity,
68665
+ withdrawFeeBps
68666
+ };
68667
+ }
68668
+ };
68669
+ };
68670
+
67917
68671
  // src/vaults/savings/readers/bitwayVault.ts
67918
68672
  var BITWAY_PENALTY_BPS = {
67919
68673
  // Absolute Return
@@ -68265,6 +69019,10 @@ var buildReader2 = (entry) => {
68265
69019
  return readerHyperbeatVault(entry);
68266
69020
  case "bitway-vault":
68267
69021
  return readerBitwayVault(entry);
69022
+ case "bitfi-bfbtc":
69023
+ return readerBitfiBfbtc(entry);
69024
+ case "bitfi-vault":
69025
+ return readerBitfiVault(entry);
68268
69026
  case "yieldbasis-lt":
68269
69027
  return readerYieldBasisLt(entry);
68270
69028
  case "wren-nav":
@@ -68389,7 +69147,11 @@ var fetchSavingsVaults = async (chainId, multicallRetry, prices = {}, tokenList
68389
69147
  // limit view / the exit lock), so they count; Native's wNLP and Re's
68390
69148
  // NAV-oracle tokens revert on
68391
69149
  // `asset()`/`totalAssets()`/`convertToAssets()` and do not.
68392
- isErc4626: entry.reader === void 0 || entry.reader === "erc4626" || entry.reader === "erc4626-cooldown" || entry.reader === "erc4626-idle" || entry.reader === "erc4626-withdraw-limit",
69150
+ 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
69151
+ // the epoch ledger and the share-denominated supply cap, not because
69152
+ // the standard surface is missing. bfBTC (`bitfi-bfbtc`) is the
69153
+ // opposite and correctly falls through to `false`.
69154
+ entry.reader === "bitfi-vault",
68393
69155
  isRebasing: entry.isRebasing,
68394
69156
  isMintable: entry.isMintable,
68395
69157
  mintContract: entry.mintContract?.toLowerCase() ?? addressLc,
@@ -69049,6 +69811,7 @@ var fetchUpshiftVaults = async (chainId, prices = {}, tokenList = {}) => {
69049
69811
  var NOISE_DEVIATION_BPS = 10;
69050
69812
  var IMPLAUSIBLE_APR_PERCENT2 = 1e3;
69051
69813
  var DUST_TVL_USD = 1e3;
69814
+ var AMPLIFYING_TENOR_SECS = 86400;
69052
69815
  var impliedDeviationBps = (c) => {
69053
69816
  const secs = c.expiry - c.nowSecs;
69054
69817
  if (!(secs > 0)) return 0;
@@ -69070,7 +69833,8 @@ var isUnearnableRate = (args) => {
69070
69833
  if (isImplausibleMagnitude(aprPercent, totalAssetsUsd)) return true;
69071
69834
  if (expiry === void 0) return false;
69072
69835
  const nowSecs = args.nowSecs ?? Math.floor(Date.now() / 1e3);
69073
- return (totalAssetsUsd ?? 0) < DUST_TVL_USD && isAnnualizationNoise({ aprPercent, expiry, nowSecs });
69836
+ if (!isAnnualizationNoise({ aprPercent, expiry, nowSecs })) return false;
69837
+ return (totalAssetsUsd ?? 0) < DUST_TVL_USD || expiry - nowSecs < AMPLIFYING_TENOR_SECS;
69074
69838
  };
69075
69839
 
69076
69840
  // src/vaults/yearn/fetchPublic.ts
@@ -71645,9 +72409,13 @@ function feePhrase(fee) {
71645
72409
  const bound = fee.mutable && fee.cap != null ? `, governance-set up to a maximum of ${fee.unit === "bps" ? `${fee.cap} bps` : pct(fee.cap)}` : fee.mutable ? ", governance-set" : "";
71646
72410
  return `${fee.label}: ${amount4}${rebate}${bound}${qualifier}`;
71647
72411
  }
72412
+ function hasMatured(m, nowSecs) {
72413
+ if (m.kind !== "fixed-date" || !m.maturity) return false;
72414
+ return m.maturity <= (Math.floor(Date.now() / 1e3));
72415
+ }
71648
72416
  function maturityPhrase(m) {
71649
72417
  if (m.kind === "fixed-date" && m.maturity)
71650
- return `until ${shortDate(m.maturity)}`;
72418
+ return `${hasMatured(m) ? "matured" : "until"} ${shortDate(m.maturity)}`;
71651
72419
  if (m.kind === "rolling-duration") {
71652
72420
  if (m.maxDurationSecs) return `for up to ${duration(m.maxDurationSecs)}`;
71653
72421
  return "for a term you choose";
@@ -71764,6 +72532,9 @@ function supplyHeadline(s, sheet = {}) {
71764
72532
  const rate = `${rateLabel(s)} ${pct(s.rate.aprTotal)}${windowNote(s.rate)}${provenance(s.rate)}`;
71765
72533
  const exit = headlineExitFromRoutes(s.exit.routes, sheet.asset?.symbol) ?? exitPhrase[String(s.exit.mode)] ?? (s.exit.settlement === "sync" ? "withdraw any time" : "delayed withdrawal");
71766
72534
  const cooldown = s.exit.cooldownSecs ? ` (${duration(s.exit.cooldownSecs)})` : "";
72535
+ if (hasMatured(s.maturity)) {
72536
+ return `Matured ${shortDate(s.maturity.maturity)} \xB7 ${exit}${cooldown}`;
72537
+ }
71767
72538
  const mat = s.maturity.kind === "perpetual" ? "" : ` ${maturityPhrase(s.maturity)}`;
71768
72539
  const warmup = s.rate.warmupSecs ? ` \xB7 earns after ${duration(s.rate.warmupSecs)}` : "";
71769
72540
  return `${rate}${mat}${warmup} \xB7 ${exit}${cooldown}`;
@@ -74112,10 +74883,12 @@ function stampEarnSubtitles(rows) {
74112
74883
  function renderedIdentity(m) {
74113
74884
  return [m.chainId, m.brand ?? m.venue, m.name ?? "", m.asset.symbol].join("|");
74114
74885
  }
74115
- function abbreviate(address) {
74886
+ function abbreviate(address, chars = 4) {
74116
74887
  const a = address?.trim();
74117
- if (!a || a.length < 6) return void 0;
74118
- return a.startsWith("0x") ? a.slice(0, 6) : `0x${a.slice(0, 4)}`;
74888
+ if (!a) return void 0;
74889
+ const hex = /^0x/i.test(a) ? a.slice(2) : a;
74890
+ if (!/^[0-9a-fA-F]+$/.test(hex) || hex.length < 4) return void 0;
74891
+ return `0x${hex.slice(0, chars)}`;
74119
74892
  }
74120
74893
  function disambiguateEarnNames(rows) {
74121
74894
  const groups = /* @__PURE__ */ new Map();
@@ -74138,19 +74911,33 @@ function disambiguateEarnNames(rows) {
74138
74911
  let changed = 0;
74139
74912
  for (const group of groups.values()) {
74140
74913
  if (group.length < 2) continue;
74141
- for (const pick3 of candidates) {
74142
- const marks = group.map(pick3);
74143
- if (marks.some((x) => !x)) continue;
74144
- if (new Set(marks).size !== marks.length) continue;
74145
- group.forEach((m, i) => {
74146
- m.name = m.name ? `${m.name} \xB7 ${marks[i]}` : marks[i];
74147
- changed++;
74148
- });
74149
- break;
74150
- }
74914
+ const marks = separatingMarks(group, candidates);
74915
+ if (!marks) continue;
74916
+ group.forEach((m, i) => {
74917
+ m.name = m.name ? `${m.name} \xB7 ${marks[i]}` : marks[i];
74918
+ changed++;
74919
+ });
74151
74920
  }
74152
74921
  return changed;
74153
74922
  }
74923
+ function separatingMarks(group, candidates) {
74924
+ const separates = (marks) => !marks.some((x) => !x) && new Set(marks).size === marks.length;
74925
+ for (const pick3 of candidates) {
74926
+ const marks = group.map(pick3);
74927
+ if (separates(marks)) return marks;
74928
+ }
74929
+ for (const width of [6, 8, 12, 40]) {
74930
+ for (const source of [
74931
+ (m) => m.refs?.oracle,
74932
+ (m) => m.venue.split("_").pop(),
74933
+ (m) => m.ref
74934
+ ]) {
74935
+ const marks = group.map((m) => abbreviate(source(m), width));
74936
+ if (separates(marks)) return marks;
74937
+ }
74938
+ }
74939
+ return void 0;
74940
+ }
74154
74941
  var SAME_BLOCK_EXIT_MODES = /* @__PURE__ */ new Set([
74155
74942
  "instant",
74156
74943
  "instant-capped",
@@ -74254,7 +75041,7 @@ var SDK_FRACTION_RATE_PROVIDERS = /* @__PURE__ */ new Set([
74254
75041
  "hypercore",
74255
75042
  "gmx"
74256
75043
  ]);
74257
- var RATE_SOURCE = {
75044
+ var EARN_RATE_SOURCE_BY_PROVIDER = {
74258
75045
  morpho: "api",
74259
75046
  silo: "api",
74260
75047
  lagoon: "api",
@@ -74348,24 +75135,27 @@ function earnMarketFromVault(row, chainId, opts = {}) {
74348
75135
  const deposit = toPercent2(rates.depositRate);
74349
75136
  const base = toPercent2(rates.supplyRate) ?? (deposit !== void 0 && rewards !== void 0 ? deposit - rewards : deposit);
74350
75137
  const total = toPercent2(rates.totalRate) ?? deposit ?? sum(base, rewards) ?? 0;
74351
- const rate = {
74352
- total,
74353
- base,
74354
- rewards,
74355
- // A vault has no separate intrinsic leg — whatever it pays IS the venue's
74356
- // own yield. Leaving this undefined rendered an empty "Venue APR" on every
74357
- // vault row, which read as "this vault pays nothing".
74358
- marketOwn: total,
74359
- // ...and for the same reason it can never be pass-through.
74360
- passthrough: false,
74361
- kind: resolveRateKind(provider, meta),
74362
- source: RATE_SOURCE[provider] ?? "api",
74363
- // The curator's cut. Dropped entirely until now, which left the earn row
74364
- // unable to say why its net rate sits below the gross one — and left the
74365
- // term sheet built from this row with no fee schedule at all.
74366
- fee: toPercent2(rates.fee)
74367
- };
74368
75138
  const maturity = resolveMaturity(meta);
75139
+ const rate = earnRateAtMaturity(
75140
+ {
75141
+ total,
75142
+ base,
75143
+ rewards,
75144
+ // A vault has no separate intrinsic leg — whatever it pays IS the venue's
75145
+ // own yield. Leaving this undefined rendered an empty "Venue APR" on every
75146
+ // vault row, which read as "this vault pays nothing".
75147
+ marketOwn: total,
75148
+ // ...and for the same reason it can never be pass-through.
75149
+ passthrough: false,
75150
+ kind: resolveRateKind(provider, meta),
75151
+ source: EARN_RATE_SOURCE_BY_PROVIDER[provider] ?? "api",
75152
+ // The curator's cut. Dropped entirely until now, which left the earn row
75153
+ // unable to say why its net rate sits below the gross one — and left the
75154
+ // term sheet built from this row with no fee schedule at all.
75155
+ fee: toPercent2(rates.fee)
75156
+ },
75157
+ maturity
75158
+ );
74369
75159
  const availability = resolveAvailability(meta, maturity);
74370
75160
  const exitMode = resolveExitMode2(provider, meta, tvl, liq);
74371
75161
  const market = {
@@ -74510,7 +75300,7 @@ function resolveAvailability(meta, maturity) {
74510
75300
  const capFull = capacity === "0";
74511
75301
  let gating;
74512
75302
  let reason;
74513
- if (isMatured(maturity)) {
75303
+ if (isMaturedTerm(maturity)) {
74514
75304
  gating = "matured";
74515
75305
  reason = "This market has reached maturity";
74516
75306
  } else if (isMintable === false) {
@@ -74555,9 +75345,26 @@ function resolveMaturity(meta) {
74555
75345
  atMaturity: str6(meta.atMaturity) ?? "stops-earning"
74556
75346
  };
74557
75347
  }
74558
- function isMatured(maturity) {
75348
+ function isMaturedTerm(maturity, nowSecs = Math.floor(Date.now() / 1e3)) {
74559
75349
  if (!maturity?.maturity) return false;
74560
- return maturity.maturity <= Math.floor(Date.now() / 1e3);
75350
+ return maturity.maturity <= nowSecs;
75351
+ }
75352
+ function earnRateAtMaturity(rate, maturity, nowSecs) {
75353
+ if (!isMaturedTerm(maturity, nowSecs)) return rate;
75354
+ return {
75355
+ ...rate,
75356
+ total: 0,
75357
+ // Every yield leg, not just the headline: a consumer that re-sums the legs
75358
+ // (or ranks on `marketOwn`, as the unified tab's second sort does) would
75359
+ // otherwise get the stale number back through the side door.
75360
+ ...rate.base !== void 0 ? { base: 0 } : {},
75361
+ ...rate.rewards !== void 0 ? { rewards: 0 } : {},
75362
+ ...rate.intrinsic !== void 0 ? { intrinsic: 0 } : {},
75363
+ ...rate.marketOwn !== void 0 ? { marketOwn: 0 } : {}
75364
+ // `fee`, `kind` and `source` are untouched: the fee schedule and the
75365
+ // mechanism are still facts about the instrument, and calling a matured
75366
+ // bond's rate anything but `fixed-term` would lose what it was.
75367
+ };
74561
75368
  }
74562
75369
  function amount2(raw, formatted, usd, decimals) {
74563
75370
  const rawStr = raw != null ? String(raw) : void 0;
@@ -78245,6 +79052,52 @@ function sum2(...parts) {
78245
79052
  const present = parts.filter((p) => p !== void 0);
78246
79053
  return present.length ? present.reduce((a, b) => a + b, 0) : void 0;
78247
79054
  }
79055
+
79056
+ // src/earn/rateSanity.ts
79057
+ var IMPOSSIBLE_TVL_USD = 1e11;
79058
+ var isUnrealizableEarnRate = (m) => {
79059
+ const tvl = m.tvl?.formatted;
79060
+ const liq = m.liquidity?.formatted;
79061
+ if (tvl === void 0 || liq === void 0) return false;
79062
+ return isPinnedMarketRate({
79063
+ aprPercent: m.rate.total,
79064
+ totalAssets: tvl,
79065
+ liquidity: liq
79066
+ });
79067
+ };
79068
+ var isUnearnableEarnRate = (m, nowSecs) => isUnearnableRate({
79069
+ aprPercent: m.rate.total,
79070
+ totalAssetsUsd: m.tvl?.usd,
79071
+ expiry: m.maturity?.maturity,
79072
+ nowSecs
79073
+ });
79074
+ var repairImpossibleTvl = (m) => {
79075
+ if ((m.tvl?.usd ?? 0) <= IMPOSSIBLE_TVL_USD) return false;
79076
+ m.tvl.usd = void 0;
79077
+ if (m.liquidity?.usd !== void 0 && m.liquidity.usd > IMPOSSIBLE_TVL_USD) {
79078
+ m.liquidity.usd = void 0;
79079
+ }
79080
+ return true;
79081
+ };
79082
+ var applyEarnSanity = (rows, opts = {}) => {
79083
+ const items = [];
79084
+ let unrealizable = 0;
79085
+ let unearnable = 0;
79086
+ let repricedTvl = 0;
79087
+ for (const m of rows) {
79088
+ if (isUnrealizableEarnRate(m)) {
79089
+ unrealizable++;
79090
+ continue;
79091
+ }
79092
+ if (isUnearnableEarnRate(m, opts.nowSecs)) {
79093
+ unearnable++;
79094
+ continue;
79095
+ }
79096
+ if (repairImpossibleTvl(m)) repricedTvl++;
79097
+ items.push(m);
79098
+ }
79099
+ return { items, unrealizable, unearnable, repricedTvl };
79100
+ };
78248
79101
  var ASYNC_EXIT_MODES = /* @__PURE__ */ new Set([
78249
79102
  "fixed-cooldown",
78250
79103
  "request-based",
@@ -78386,8 +79239,11 @@ function vaultCapabilities(row) {
78386
79239
  requires: claimRequires(row, provider)
78387
79240
  });
78388
79241
  }
78389
- if (supportsCancel(provider, meta)) {
78390
- caps.push({ action: "cancel" });
79242
+ if (supportsCancel(row, provider)) {
79243
+ caps.push({
79244
+ action: "cancel",
79245
+ requires: savingsVerbRequiresFor(row, provider, "cancel")
79246
+ });
78391
79247
  }
78392
79248
  return caps;
78393
79249
  }
@@ -78456,9 +79312,33 @@ function claimRequires(row, provider) {
78456
79312
  return ["claimableEpoch"];
78457
79313
  return void 0;
78458
79314
  }
78459
- function supportsCancel(provider, meta) {
79315
+ function savingsVerbRequiresFor(row, provider, verb) {
79316
+ if (provider === "gmx" || provider === "lst") return void 0;
79317
+ const share = row.shareToken?.address ?? row.ref;
79318
+ if (!share || !row.chainId) return void 0;
79319
+ try {
79320
+ return savingsVerbRequires(
79321
+ String(row.chainId),
79322
+ share,
79323
+ verb
79324
+ );
79325
+ } catch {
79326
+ return void 0;
79327
+ }
79328
+ }
79329
+ function supportsCancel(row, provider) {
78460
79330
  if (provider === "gmx") return true;
78461
- return typeof meta.withdrawQueue === "string" && meta.withdrawQueue.length > 0;
79331
+ const share = row.shareToken?.address ?? row.ref;
79332
+ if (!share || !row.chainId) return false;
79333
+ try {
79334
+ return savingsSupportsVerb(
79335
+ String(row.chainId),
79336
+ share,
79337
+ "cancel"
79338
+ );
79339
+ } catch {
79340
+ return false;
79341
+ }
78462
79342
  }
78463
79343
 
78464
79344
  // src/earn/positions.ts
@@ -78662,6 +79542,6 @@ function earnPositionTotals(items) {
78662
79542
  };
78663
79543
  }
78664
79544
 
78665
- 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, 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 };
79545
+ 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, earnRateAtMaturity, 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, isMaturedTerm, 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 };
78666
79546
  //# sourceMappingURL=index.js.map
78667
79547
  //# sourceMappingURL=index.js.map