@1delta/margin-fetcher 5.0.70 → 5.0.72

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