@1delta/margin-fetcher 0.0.405 → 0.0.407

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
@@ -1,9 +1,9 @@
1
1
  import { parseAbi, keccak256, encodeAbiParameters, formatEther, BaseError, pad, encodeFunctionData, formatUnits, isAddress, getAddress, decodeFunctionResult, decodeAbiParameters, concat, AbiEncodingLengthMismatchError, concatHex, toBytes, slice, InvalidAddressError, stringToHex, boolToHex, integerRegex, numberToHex, bytesRegex, BytesSizeMismatchError, arrayRegex, UnsupportedPackedAbiType } from './chunk-SRWUFRRR.js';
2
2
  import './chunk-BYTNVMX7.js';
3
3
  import './chunk-PR4QN5HX.js';
4
- import { Lender, LIQUITY_FAMILY_LENDERS, isAaveType, isCompoundV3, isMultiMarket, isSiloV2Type, isSiloV3Type, isDolomite, isMidnight, isTerm, isExactly, isLiquityFamily, isRiver, isTeller, isEulerType, isAaveV4Type, isInit, isMorphoType, isCompoundV2Type, isVenusType, isSumerType, AAVE_V3_LENDERS, AAVE_V2_LENDERS, isAaveV2Type, isAaveV32Type, isAaveV3Type, isFluid, isGearboxV3, isInverse, isTermMax, isYLDR, isCompoundV3Type, isLista, isTectonicType, isKineticType, isBenqiType } from '@1delta/lender-registry';
4
+ import { Lender, LIQUITY_FAMILY_LENDERS, isAaveType, isCompoundV3, isMultiMarket, isSiloV2Type, isSiloV3Type, isDolomite, isMidnight, isTerm, isExactly, isLiquityFamily, isRiver, isTeller, isInverse, isTermMax, isEulerType, isAaveV4Type, isInit, isMorphoType, isCompoundV2Type, isVenusType, isSumerType, AAVE_V3_LENDERS, AAVE_V2_LENDERS, isAaveV2Type, isAaveV32Type, isAaveV3Type, isFluid, isGearboxV3, isYLDR, isCompoundV3Type, isLista, isTectonicType, isKineticType, isBenqiType } from '@1delta/lender-registry';
5
5
  export { isAaveType, isAaveV2Type, isAaveV32Type, isAaveV3Type, isCompoundV3, isCompoundV3Type, isInit, isMorphoType, isMultiMarket, isYLDR } from '@1delta/lender-registry';
6
- import { fetchTokenLists, fetchTokenList, aavePools, compoundV3Pools, initConfig, morphoPools, compoundV2Pools, eulerVaults, siloMarkets, siloV2LenderKey, siloMarketsV3, siloV3LenderKey, aaveV4Spokes, aaveV4SpokeLenderKey, fluidResolvers, gearboxResolvers, dolomiteConfigs, midnightConfig, termConfig, termMarketsByChain, exactlyConfig, liquityLendersByChain, riverLendersByChain, inverseLendersByChain, tellerConfigByChain, tellerPoolsByChain, aaveReserves, compoundV3Reserves, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, termMaxApiBaseUrl, termMaxConfigByChain, termMaxLenderKey, inverseConfigFor, inverseChainData, aaveOracles, morphoTypeMarkets, resolveMidnightApiBase, resolveTermApiBase, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, aaveTokens, morphoTypeVaults, eulerConfigs, gearboxMarketCompressor, gearboxMarketConfigurators, gearboxV3LenderKey, midnightMarketsByChain, parseAaveV4SpokeLenderKey, gearboxAccountCompressor, compoundV2Tokens, exactlyMarketsByChain, aaveOraclesConfig, compoundV2Oracles, compoundV2TokenArray, compoundV2OraclesConfig, compoundV3OraclesData, compoundV3BaseData, compoundV2Reserves, aaveV4Oracles } from '@1delta/data-sdk';
6
+ import { fetchTokenLists, fetchTokenList, aavePools, compoundV3Pools, initConfig, morphoPools, compoundV2Pools, eulerVaults, siloMarkets, siloV2LenderKey, siloMarketsV3, siloV3LenderKey, aaveV4Spokes, aaveV4SpokeLenderKey, fluidResolvers, gearboxResolvers, dolomiteConfigs, midnightConfig, termConfig, termMarketsByChain, exactlyConfig, liquityLendersByChain, riverLendersByChain, inverseLendersByChain, tellerConfigByChain, tellerPoolsByChain, termMaxConfigByChain, aaveReserves, compoundV3Reserves, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, termMaxApiBaseUrl, termMaxLenderKey, inverseConfigFor, inverseChainData, aaveOracles, morphoTypeMarkets, resolveMidnightApiBase, resolveTermApiBase, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, aaveTokens, morphoTypeVaults, eulerConfigs, gearboxMarketCompressor, gearboxMarketConfigurators, gearboxV3LenderKey, midnightMarketsByChain, parseAaveV4SpokeLenderKey, gearboxAccountCompressor, compoundV2Tokens, exactlyMarketsByChain, aaveOraclesConfig, compoundV2Oracles, compoundV2TokenArray, compoundV2OraclesConfig, compoundV3OraclesData, compoundV3BaseData, compoundV2Reserves, aaveV4Oracles } from '@1delta/data-sdk';
7
7
  import lodash from 'lodash';
8
8
  import { multicallRetryUniversal, getEvmClient, getEvmChain, getEvmClientUniversal } from '@1delta/providers';
9
9
  import { LiquityTroveManagerAbi, LiquityActivePoolAbi, LiquityStabilityPoolAbi, LiquityPriceFeedAbi, LiquitySortedTrovesAbi, RiverTroveManagerAbi, RiverStabilityPoolAbi, TellerMarketRegistryAbi, TellerV2Abi, InverseMarketAbi, InverseOracleAbi, InverseDbrAbi, Erc20Abi, MetaMorphoAbi, ExactlyPreviewerAbi, ExactlyAuditorAbi, LenderCommitmentGroupAbi, FluidLendingResolverAbi, FluidVaultResolverAbi, FluidLiquidityResolverAbi, MoolahVaultAbi, MorphoLensAbi, AaveV4SpokeAbi, AaveV4OracleAbi, AaveV4HubAbi, DolomiteMarginAbi, GearboxMarketCompressorV310Abi, MorphoBlueAbi, MidnightAbi, TermRepoTokenAbi, TermRepoServicerAbi, TermRepoCollateralManagerAbi, LiquityTroveNFTAbi, LiquityCollSurplusPoolAbi, TellerCollateralManagerAbi, InverseEscrowAbi, GearboxCreditAccountCompressorV310Abi, TermPriceConsumerAbi, TermMaxOracleAggregatorV2Abi } from '@1delta/abis';
@@ -7522,6 +7522,9 @@ var getLendersForChain = (c) => {
7522
7522
  if (tellerConfigByChain(c)?.tellerV2 && tellerPoolsByChain(c).length > 0) {
7523
7523
  lenders.push(Lender.TELLER);
7524
7524
  }
7525
+ if (termMaxConfigByChain(c)?.viewer) {
7526
+ lenders.push(Lender.TERMMAX);
7527
+ }
7525
7528
  return lenders.filter((l) => !isExcludedLender(l));
7526
7529
  };
7527
7530
  var filterLendersByProtocol = (allLenders, protocolList) => {
@@ -23068,9 +23071,13 @@ function parseMarket(raw, assetDecimals) {
23068
23071
  xt: lower(c.xtAddr),
23069
23072
  gt: lower(c.gtAddr),
23070
23073
  debtToken,
23074
+ // A missing entry means the payload changed shape — fall back to 18 so the
23075
+ // row still renders, but flag it so it is visible rather than silent.
23071
23076
  debtDecimals: assetDecimals.get(debtToken) ?? 18,
23077
+ debtDecimalsResolved: assetDecimals.has(debtToken),
23072
23078
  collateral,
23073
23079
  collateralDecimals: assetDecimals.get(collateral) ?? 18,
23080
+ collateralDecimalsResolved: assetDecimals.has(collateral),
23074
23081
  symbol: raw.symbol,
23075
23082
  maturity: toUnix(raw.maturity),
23076
23083
  maxLtv: String(raw.maxLtv ?? "0"),
@@ -23170,8 +23177,8 @@ var TermMaxApiSource = class {
23170
23177
  if (!data) return null;
23171
23178
  const assetDecimals = /* @__PURE__ */ new Map();
23172
23179
  for (const a of Array.isArray(data.assetConfigs) ? data.assetConfigs : []) {
23173
- const addr2 = lower(a?.assetAddress);
23174
- const dec = Number(a?.assetDecimals);
23180
+ const addr2 = lower(a?.contractAddress ?? a?.assetAddress);
23181
+ const dec = Number(a?.decimals ?? a?.assetDecimals);
23175
23182
  if (addr2 && Number.isFinite(dec)) assetDecimals.set(addr2, dec);
23176
23183
  }
23177
23184
  const markets = [];
@@ -23608,6 +23615,14 @@ function parseTermMaxLtv(v) {
23608
23615
  return Number.isFinite(n) ? n / Number(DECIMAL_BASE) : 0;
23609
23616
  }
23610
23617
  }
23618
+ function termMaxLtvToWad(v) {
23619
+ if (v === void 0 || v === null || v === "") return "0";
23620
+ try {
23621
+ return (BigInt(v) * 10000000000n).toString();
23622
+ } catch {
23623
+ return "0";
23624
+ }
23625
+ }
23611
23626
 
23612
23627
  // src/lending/public-data/termmax/convertPublic.ts
23613
23628
  var nowSec4 = () => Math.floor(Date.now() / 1e3);
@@ -23769,7 +23784,9 @@ function convertTermMaxMarketsToResponse(raw, chainId, prices = {}, _additionalY
23769
23784
  loanDecimals: config.debtDecimals,
23770
23785
  collateralDecimals: config.collateralDecimals,
23771
23786
  id: config.market,
23772
- lltv: config.liquidationLtv,
23787
+ // WAD-scaled to match Morpho/Midnight on this shared field — the raw
23788
+ // 1e8 values stay on `maxLtv` / `liquidationLtv` below.
23789
+ lltv: termMaxLtvToWad(config.liquidationLtv),
23773
23790
  oracle: config.oracle ?? zeroAddress,
23774
23791
  irm: zeroAddress,
23775
23792
  collateralAddress: collAddr,
@@ -25021,6 +25038,8 @@ function lenderApiOnly(lender, chainId) {
25021
25038
  if (isLiquityFamily(lender)) return true;
25022
25039
  if (isRiver(lender)) return true;
25023
25040
  if (isTeller(lender)) return true;
25041
+ if (isInverse(lender)) return true;
25042
+ if (isTermMax(lender)) return true;
25024
25043
  return false;
25025
25044
  }
25026
25045
  function lenderApiWithOnChainFallback(lender, chainId) {
@@ -39678,6 +39697,218 @@ var reProtocolFetcher = {
39678
39697
  }
39679
39698
  };
39680
39699
 
39700
+ // src/yields/intrinsic/fetchers/threeJane.ts
39701
+ var USD3_KEY = "3JANE::USD3";
39702
+ var SUSD3_KEY = "3JANE::sUSD3";
39703
+ var USD3_GROUP_KEY = "3Jane USD3::USD3";
39704
+ var SUSD3_GROUP_KEY = "3Jane Staked USD3::SUSD3";
39705
+ var USD3_POOL = "f8cd444e-d99f-4132-b234-fd3482bf8806";
39706
+ var SUSD3_POOL = "a99bb965-ebaa-4d98-9ed2-fa18de52c605";
39707
+ var threeJaneFetcher = {
39708
+ label: "THREE_JANE",
39709
+ fetch: async () => {
39710
+ const [usd3, susd3] = await Promise.allSettled([
39711
+ fetchDefiLlamaApy(USD3_POOL),
39712
+ fetchDefiLlamaApy(SUSD3_POOL)
39713
+ ]);
39714
+ const out = {};
39715
+ if (usd3.status === "fulfilled") {
39716
+ const apr = apyToAprPercent(usd3.value);
39717
+ out[USD3_KEY] = apr;
39718
+ out[USD3_GROUP_KEY] = apr;
39719
+ }
39720
+ if (susd3.status === "fulfilled") {
39721
+ const apr = apyToAprPercent(susd3.value);
39722
+ out[SUSD3_KEY] = apr;
39723
+ out[SUSD3_GROUP_KEY] = apr;
39724
+ }
39725
+ if (Object.keys(out).length === 0) {
39726
+ throw new Error("3Jane: DefiLlama returned no apy for either pool");
39727
+ }
39728
+ return out;
39729
+ }
39730
+ };
39731
+
39732
+ // src/yields/intrinsic/fetchers/tori.ts
39733
+ var TORI_APY_URL = "https://app.tori.finance/api/apy";
39734
+ var TORI_DEFILLAMA_POOL = "e7fdda30-ce71-5dea-8b3a-dd43de77ce55";
39735
+ var STRUSD_KEY = "STRUSD";
39736
+ var STRUSD_GROUP_KEY = "Tori Staked trUSD::STRUSD";
39737
+ var fetchToriApyPercent = async () => {
39738
+ const res = await fetch(TORI_APY_URL, {
39739
+ headers: { accept: "application/json" },
39740
+ signal: AbortSignal.timeout(8e3)
39741
+ });
39742
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
39743
+ const apy = Number((await res.json())?.apy);
39744
+ if (Number.isFinite(apy) && apy > 0) return apy;
39745
+ throw new Error("apy missing");
39746
+ };
39747
+ var toriFetcher = {
39748
+ label: "STRUSD",
39749
+ fetch: async () => {
39750
+ const apy = await fetchToriApyPercent().catch(
39751
+ () => fetchDefiLlamaApy(TORI_DEFILLAMA_POOL)
39752
+ );
39753
+ const apr = apyToAprPercent(apy);
39754
+ return { [STRUSD_KEY]: apr, [STRUSD_GROUP_KEY]: apr };
39755
+ }
39756
+ };
39757
+ var CHAIN_ID8 = Chain.ETHEREUM_MAINNET;
39758
+ var SNUSD = "0x08efcc2f3e61185d0ea7f8830b3fec9bfa2ee313";
39759
+ var YEAR_SECONDS6 = 31536000n;
39760
+ var ONE_E187 = 10n ** 18n;
39761
+ var SNUSD_KEY = "SNUSD";
39762
+ var SNUSD_GROUP_KEY = "Staked NUSD::sNUSD";
39763
+ var SNUSD_LEGACY_GROUP_KEY = "sNUSD::Staked NUSD";
39764
+ var STAKED_NUSD_ABI = [
39765
+ {
39766
+ name: "vestingAmount",
39767
+ type: "function",
39768
+ stateMutability: "view",
39769
+ inputs: [],
39770
+ outputs: [{ type: "uint256" }]
39771
+ },
39772
+ {
39773
+ name: "lastDistributionTimestamp",
39774
+ type: "function",
39775
+ stateMutability: "view",
39776
+ inputs: [],
39777
+ outputs: [{ type: "uint256" }]
39778
+ },
39779
+ {
39780
+ name: "vestingPeriod",
39781
+ type: "function",
39782
+ stateMutability: "view",
39783
+ inputs: [],
39784
+ outputs: [{ type: "uint256" }]
39785
+ },
39786
+ {
39787
+ name: "totalAssets",
39788
+ type: "function",
39789
+ stateMutability: "view",
39790
+ inputs: [],
39791
+ outputs: [{ type: "uint256" }]
39792
+ }
39793
+ ];
39794
+ var fetchSnusdAprOnChain = async () => {
39795
+ const [vestingAmount, lastDistribution, vestingPeriod, totalAssets] = await multicallRetryUniversal({
39796
+ chain: CHAIN_ID8,
39797
+ abi: STAKED_NUSD_ABI,
39798
+ calls: [
39799
+ { address: SNUSD, name: "vestingAmount", params: [] },
39800
+ { address: SNUSD, name: "lastDistributionTimestamp", params: [] },
39801
+ { address: SNUSD, name: "vestingPeriod", params: [] },
39802
+ { address: SNUSD, name: "totalAssets", params: [] }
39803
+ ],
39804
+ allowFailure: false
39805
+ });
39806
+ if (totalAssets === 0n) return 0;
39807
+ const elapsed = BigInt(Math.floor(Date.now() / 1e3)) - lastDistribution;
39808
+ const window = elapsed > vestingPeriod ? elapsed : vestingPeriod;
39809
+ if (window <= 0n) return 0;
39810
+ const perSecond = vestingAmount / window;
39811
+ return Number(perSecond * YEAR_SECONDS6 * ONE_E187 / totalAssets) / 1e16;
39812
+ };
39813
+ var snusdFetcher = {
39814
+ label: "SNUSD",
39815
+ fetch: async () => {
39816
+ const apr = await fetchSnusdAprOnChain().catch(() => 0);
39817
+ return {
39818
+ [SNUSD_KEY]: apr,
39819
+ [SNUSD_GROUP_KEY]: apr,
39820
+ [SNUSD_LEGACY_GROUP_KEY]: apr
39821
+ };
39822
+ }
39823
+ };
39824
+ var RAY4 = 10n ** 27n;
39825
+ var YEAR_SECONDS7 = 31536e3;
39826
+ var DSR_ABI = [
39827
+ {
39828
+ name: "dsr",
39829
+ type: "function",
39830
+ stateMutability: "view",
39831
+ inputs: [],
39832
+ outputs: [{ type: "uint256" }]
39833
+ }
39834
+ ];
39835
+ var USDD_POTS = [
39836
+ {
39837
+ chainId: Chain.ETHEREUM_MAINNET,
39838
+ pot: "0xe789578252cc026ffb3413a1104ba223fdeca500",
39839
+ apiKey: "ethApy"
39840
+ },
39841
+ {
39842
+ chainId: Chain.BNB_SMART_CHAIN_MAINNET,
39843
+ pot: "0xf0c506e48383c1925c025ec9f4a9e1dd94ff8b18",
39844
+ apiKey: "bscApy"
39845
+ }
39846
+ ];
39847
+ var USDD_EARN_APY_URL = "https://openapi.usdd.io/api/v1/external/earn-apy";
39848
+ var susddKey = (chainId) => `USDD::${chainId}::sUSDD`;
39849
+ var SUSDD_GROUP_KEY = "Savings Usdd::sUSDD";
39850
+ var aprFromDsr = (dsr) => {
39851
+ if (dsr <= RAY4) return 0;
39852
+ const perSecond = Number(dsr - RAY4) / 1e27;
39853
+ return perSecond * YEAR_SECONDS7 * 100;
39854
+ };
39855
+ var fetchChainDsr = async (chainId, pot) => {
39856
+ const [dsr] = await multicallRetryUniversal({
39857
+ chain: chainId,
39858
+ abi: DSR_ABI,
39859
+ calls: [{ address: pot, name: "dsr", params: [] }],
39860
+ allowFailure: false
39861
+ });
39862
+ if (typeof dsr !== "bigint" || dsr < RAY4) {
39863
+ throw new Error(`USDD: unreadable dsr() on chain ${chainId}`);
39864
+ }
39865
+ return aprFromDsr(dsr);
39866
+ };
39867
+ var fetchApiAprs = async () => {
39868
+ const res = await fetch(USDD_EARN_APY_URL, {
39869
+ method: "GET",
39870
+ headers: { Accept: "application/json" }
39871
+ }).then((r) => r.json());
39872
+ if (res?.code !== 0 || !res?.data) return {};
39873
+ const out = {};
39874
+ for (const key of ["ethApy", "bscApy"]) {
39875
+ const apy = Number(res.data[key]);
39876
+ if (Number.isFinite(apy) && apy > 0) out[key] = apyToApr(apy) * 100;
39877
+ }
39878
+ return out;
39879
+ };
39880
+ var usddFetcher = {
39881
+ label: "USDD_SUSDD",
39882
+ fetch: async () => {
39883
+ const settled = await Promise.allSettled(
39884
+ USDD_POTS.map(({ chainId, pot }) => fetchChainDsr(chainId, pot))
39885
+ );
39886
+ const out = {};
39887
+ const missed = [];
39888
+ USDD_POTS.forEach((p, i) => {
39889
+ const r = settled[i];
39890
+ if (r.status === "fulfilled") out[susddKey(p.chainId)] = r.value;
39891
+ else missed.push(p);
39892
+ });
39893
+ if (missed.length > 0) {
39894
+ try {
39895
+ const api = await fetchApiAprs();
39896
+ for (const p of missed) {
39897
+ const apr = api[p.apiKey];
39898
+ if (apr !== void 0) out[susddKey(p.chainId)] = apr;
39899
+ }
39900
+ } catch {
39901
+ }
39902
+ }
39903
+ if (Object.keys(out).length === 0) {
39904
+ throw new Error("USDD: no chain returned a readable savings rate");
39905
+ }
39906
+ const group = out[susddKey(Chain.ETHEREUM_MAINNET)] ?? out[susddKey(Chain.BNB_SMART_CHAIN_MAINNET)];
39907
+ if (group !== void 0) out[SUSDD_GROUP_KEY] = group;
39908
+ return out;
39909
+ }
39910
+ };
39911
+
39681
39912
  // src/yields/intrinsic/fetchers/nativeCreditPool.ts
39682
39913
  var nativeCreditPoolYieldKey = (chainId, underlying) => `${chainId}:${underlying.toLowerCase()}`;
39683
39914
  var POOL_IDS = {
@@ -40778,6 +41009,7 @@ var NATIVE_WNLP_ENTRIES = Object.fromEntries(
40778
41009
  underlying,
40779
41010
  symbol,
40780
41011
  brand: "Native",
41012
+ description: "Native Credit Pool: deposits fund a credit line that KYB'd market makers draw to quote on Native's order book, and yield is a rebate on their trading fees \u2014 not loan interest. The share price is operator-pushed with no on-chain solvency invariant; exit instantly at a fee (capped by the chain's CreditVault inventory) or free through the withdrawal queue.",
40781
41013
  decimals,
40782
41014
  isRebasing: false,
40783
41015
  isMintable: true,
@@ -40798,6 +41030,7 @@ var stUsdGroup = {
40798
41030
  base: {
40799
41031
  symbol: "stUSD",
40800
41032
  brand: "Angle",
41033
+ description: "USDA is Angle's overcollateralised USD stablecoin; stUSD stakes it and accrues a governance-managed savings rate funded by the yield on Angle's reserves (RWAs and DeFi lending). Instant permissionless stake and unstake.",
40801
41034
  decimals: 18,
40802
41035
  isRebasing: false,
40803
41036
  isMintable: true,
@@ -40832,6 +41065,7 @@ var stEurGroup = {
40832
41065
  base: {
40833
41066
  symbol: "stEUR",
40834
41067
  brand: "Angle",
41068
+ description: "EURA is Angle's overcollateralised euro stablecoin; stEUR stakes it and accrues a governance-managed savings rate funded by the yield on Angle's reserves. Instant permissionless stake and unstake.",
40835
41069
  decimals: 18,
40836
41070
  isRebasing: false,
40837
41071
  isMintable: true,
@@ -40863,6 +41097,7 @@ var yUsdGroup = {
40863
41097
  base: {
40864
41098
  symbol: "yUSD",
40865
41099
  brand: "YieldFi",
41100
+ description: "YieldFi's managed USD vault over USDC: deposits are allocated to curated DeFi and CeDeFi strategies and yield accrues into the share price (rewards vest over ~24h to smooth the curve). Instant exit.",
40866
41101
  // 18-decimal share over 6-decimal USDC — see TIMELOCKS_AND_CHAINS.md.
40867
41102
  decimals: 18,
40868
41103
  underlyingDecimals: 6,
@@ -40892,6 +41127,7 @@ var sUsdcGroup = {
40892
41127
  reader: "erc4626-idle",
40893
41128
  symbol: "sUSDC",
40894
41129
  brand: "Spark",
41130
+ description: "Not a standalone vault: a share is sUSDS held via Spark's PSM3, so sUSDC earns the Sky Savings Rate verbatim with USDC in and out routed through the PSM. Exits settle instantly but are capped by the PSM pocket's USDC balance \u2014 deep on Ethereum, materially thinner on the L2 deployments.",
40895
41131
  decimals: 18,
40896
41132
  underlyingDecimals: 6,
40897
41133
  isRebasing: false,
@@ -40935,6 +41171,7 @@ var reUsdGroup = {
40935
41171
  reader: "nav-oracle",
40936
41172
  symbol: "reUSD",
40937
41173
  brand: "Re Protocol",
41174
+ description: "Senior tranche of Re's reinsurance capital stack: deposits back insurance-linked programs and earn underwriting premium (the junior reUSDe absorbs losses first). The token is a bare ERC-20 priced by a daily NAV oracle; exits are instant (small fee) only while the redemption buffer holds, otherwise they queue \u2014 quarterly in the worst case.",
40938
41175
  decimals: 18,
40939
41176
  underlyingDecimals: 6,
40940
41177
  isRebasing: false,
@@ -40987,6 +41224,7 @@ var sUsdpGroup = {
40987
41224
  base: {
40988
41225
  symbol: "sUSDp",
40989
41226
  brand: "Parallel",
41227
+ description: "USDp is Parallel's (Angle-lineage) stablecoin; sUSDp accrues yield as keeper-minted USDp at a governance-set rate, with backing held in the Parallelizer reserves rather than enforced by an on-chain solvency invariant. Instant permissionless exit.",
40990
41228
  decimals: 18,
40991
41229
  isRebasing: false,
40992
41230
  isMintable: true,
@@ -41020,6 +41258,7 @@ var cUsdoGroup = {
41020
41258
  base: {
41021
41259
  symbol: "cUSDO",
41022
41260
  brand: "OpenEden",
41261
+ description: "USDO is OpenEden's rebasing, T-bill-backed yieldcoin (minting against fiat is KYC-gated at OpenEden); cUSDO is the permissionless non-rebasing wrapper that turns the rebase into an appreciating share price. Instant wrap and unwrap.",
41023
41262
  decimals: 18,
41024
41263
  isRebasing: false,
41025
41264
  isMintable: true,
@@ -41043,6 +41282,32 @@ var cUsdoGroup = {
41043
41282
  }
41044
41283
  }
41045
41284
  };
41285
+ var sUsddGroup = {
41286
+ base: {
41287
+ symbol: "sUSDD",
41288
+ brand: "USDD",
41289
+ description: "USDD 2.0 is the TRON-ecosystem, Maker-fork USD stablecoin; sUSDD is an sDAI-style vault accruing the USDD Savings Rate from its per-chain Pot. Instant exit; the Ethereum and BNB stacks are independent, with independent rates.",
41290
+ decimals: 18,
41291
+ isRebasing: false,
41292
+ isMintable: true,
41293
+ withdrawalMode: "instant",
41294
+ yieldFetcher: usddFetcher
41295
+ },
41296
+ chains: {
41297
+ "1": {
41298
+ address: "0xc5d6a7b61d18afa11435a889557b068bb9f29930",
41299
+ underlying: "0x4f8e5de400de08b164e7421b3ee387f461becd1a",
41300
+ // USDD 2.0
41301
+ yieldKey: susddKey("1")
41302
+ },
41303
+ "56": {
41304
+ address: "0x8ba9da757d1d66c58b1ae7e2ed6c04087348a82d",
41305
+ underlying: "0x45e51bc23d592eb2dba86da3985299f7895d66ba",
41306
+ // USDD 2.0
41307
+ yieldKey: susddKey("56")
41308
+ }
41309
+ }
41310
+ };
41046
41311
  var MULTI_CHAIN_GROUPS = [
41047
41312
  stUsdGroup,
41048
41313
  stEurGroup,
@@ -41050,12 +41315,14 @@ var MULTI_CHAIN_GROUPS = [
41050
41315
  sUsdcGroup,
41051
41316
  reUsdGroup,
41052
41317
  sUsdpGroup,
41053
- cUsdoGroup
41318
+ cUsdoGroup,
41319
+ sUsddGroup
41054
41320
  ];
41055
41321
  var sparkV2Base = (symbol, decimals) => ({
41056
41322
  reader: "erc4626-idle",
41057
41323
  symbol,
41058
41324
  brand: "Spark",
41325
+ description: "Spark Vaults V2: deposits are lent out through the Spark Liquidity Layer and accrue an admin-set vault savings rate \u2014 the vault's assets are a claim on Spark, not cash in the contract, with no on-chain solvency invariant. Exits are instant up to the vault's idle balance; anything larger settles through Spark's withdrawal intents, typically within minutes.",
41059
41326
  decimals,
41060
41327
  underlyingDecimals: decimals,
41061
41328
  isRebasing: false,
@@ -41071,6 +41338,7 @@ var SINGLE_CHAIN_ENTRIES = {
41071
41338
  underlying: "0x4c9edd5852cd905f086c759e8383e09bff1e68b3",
41072
41339
  symbol: "sUSDe",
41073
41340
  brand: "Ethena",
41341
+ description: "USDe is Ethena's synthetic dollar \u2014 staked-ETH/BTC collateral hedged with short perpetual futures (delta-neutral). sUSDe stakes it and accrues the basis and staking revenue via an appreciating share price; unstaking requires a cooldown (7 days pinned here, governance-mutable).",
41074
41342
  decimals: 18,
41075
41343
  isRebasing: false,
41076
41344
  isMintable: true,
@@ -41082,6 +41350,51 @@ var SINGLE_CHAIN_ENTRIES = {
41082
41350
  yieldFetcher: susdeFetcher,
41083
41351
  yieldKey: "SUSDE"
41084
41352
  },
41353
+ {
41354
+ // Tori strUSD — StakedUSDeV2 clone over trUSD (delta-neutral
41355
+ // synthetic dollar). Cooldown verified on-chain 2026-08:
41356
+ // `cooldownDuration() = 604800`, silo = 0xF7c0d885…, direct
41357
+ // withdraw/redeem disabled while active.
41358
+ address: "0x280839980a7ed0d7717f64125fe241012e5f5815",
41359
+ underlying: "0xd0580192e98ea6ceb9c7b6191ed2e27560911697",
41360
+ // trUSD
41361
+ symbol: "strUSD",
41362
+ brand: "Tori",
41363
+ description: "trUSD is Tori's delta-neutral synthetic dollar \u2014 capital runs market-neutral money-market, futures-basis and calendar-spread strategies with off-chain custodians. strUSD stakes it with an appreciating share price (a 10% performance fee is already netted in); unstaking requires a 7-day cooldown claimed through the trUSD Silo.",
41364
+ decimals: 18,
41365
+ isRebasing: false,
41366
+ isMintable: true,
41367
+ withdrawalMode: "fixed-cooldown",
41368
+ withdrawalCooldownSeconds: 7 * 86400,
41369
+ yieldFetcher: toriFetcher,
41370
+ yieldKey: STRUSD_KEY
41371
+ },
41372
+ {
41373
+ // Neutrl sNUSD — StakedUSDeV2 clone over NUSD (market-neutral
41374
+ // OTC-discount arbitrage + funding-rate synthetic dollar).
41375
+ // Verified on-chain 2026-08: `cooldownDuration() = 864000` (10d,
41376
+ // governance-mutable), `vestingPeriod() = 604800`, maxWithdraw = 0
41377
+ // while active, exits park in the NUSD Silo 0x6cdfc009… and claim
41378
+ // via `unstake`. A docs-listed InstantUnstaking contract
41379
+ // (0x4Bb8F67D…, 1% fee) exists but held ~2k NUSD against $35M TVL
41380
+ // at integration — dust coverage, deliberately not modeled;
41381
+ // revisit as `fee-or-queued` if Neutrl ever funds the buffer.
41382
+ // Arbitrum/Plasma carry same-address LayerZero OFT bridges whose
41383
+ // 4626 surface reverts (bare ERC-20s) — Ethereum-only row.
41384
+ address: "0x08efcc2f3e61185d0ea7f8830b3fec9bfa2ee313",
41385
+ underlying: "0xe556aba6fe6036275ec1f87eda296be72c811bce",
41386
+ // NUSD
41387
+ symbol: "sNUSD",
41388
+ brand: "Neutrl",
41389
+ description: "NUSD is Neutrl's market-neutral synthetic dollar \u2014 capital runs hedged OTC-discount arbitrage (buying locked altcoin positions at a discount, shorting the exposure) plus funding-rate strategies. sNUSD stakes it with an appreciating share price; rewards vest linearly over 7 days and unstaking requires a 10-day cooldown claimed through the NUSD Silo.",
41390
+ decimals: 18,
41391
+ isRebasing: false,
41392
+ isMintable: true,
41393
+ withdrawalMode: "fixed-cooldown",
41394
+ withdrawalCooldownSeconds: 10 * 86400,
41395
+ yieldFetcher: snusdFetcher,
41396
+ yieldKey: SNUSD_KEY
41397
+ },
41085
41398
  {
41086
41399
  // Avant savETH — staked avETH (Ethereum, where avETH is native);
41087
41400
  // StakedUSDeV2-style 24h cooldown.
@@ -41090,6 +41403,7 @@ var SINGLE_CHAIN_ENTRIES = {
41090
41403
  // avETH
41091
41404
  symbol: "savETH",
41092
41405
  brand: "Avant",
41406
+ description: "avETH is Avant's ETH-denominated synthetic asset; savETH stakes it and accrues yield from Avant's market-neutral trading strategies via an appreciating share price, with a 24-hour unstake cooldown.",
41093
41407
  decimals: 18,
41094
41408
  isRebasing: false,
41095
41409
  isMintable: true,
@@ -41103,6 +41417,7 @@ var SINGLE_CHAIN_ENTRIES = {
41103
41417
  underlying: "0xdc035d45d973e3ec169d2276ddab16f1e407384f",
41104
41418
  symbol: "sUSDS",
41105
41419
  brand: "Sky",
41420
+ description: "USDS is Sky's (ex-MakerDAO) upgraded DAI; sUSDS accrues the Sky Savings Rate, funded by the protocol's collateralised lending and RWA revenue. Instant permissionless entry and exit.",
41106
41421
  decimals: 18,
41107
41422
  isRebasing: false,
41108
41423
  isMintable: true,
@@ -41115,6 +41430,7 @@ var SINGLE_CHAIN_ENTRIES = {
41115
41430
  underlying: "0xdc035d45d973e3ec169d2276ddab16f1e407384f",
41116
41431
  symbol: "stUSDS",
41117
41432
  brand: "Sky",
41433
+ description: "Sky's higher-yield staking module over USDS, with a utilisation-driven rate instead of the flat Sky Savings Rate. Withdrawals are instant but liquidity-dependent \u2014 the pool targets ~90% utilisation, so maxWithdraw can temporarily return less than your balance.",
41118
41434
  decimals: 18,
41119
41435
  isRebasing: false,
41120
41436
  isMintable: true,
@@ -41132,6 +41448,7 @@ var SINGLE_CHAIN_ENTRIES = {
41132
41448
  // frxUSD
41133
41449
  symbol: "sfrxUSD",
41134
41450
  brand: "Frax",
41451
+ description: "frxUSD is Frax's fiat-redeemable USD stablecoin; sfrxUSD accrues protocol revenue streamed to the vault, with the rate set by a distribution cap rather than utilisation (in practice the cap is the rate). Instant exit.",
41135
41452
  decimals: 18,
41136
41453
  isRebasing: false,
41137
41454
  isMintable: true,
@@ -41149,6 +41466,7 @@ var SINGLE_CHAIN_ENTRIES = {
41149
41466
  // FRAX
41150
41467
  symbol: "sFRAX",
41151
41468
  brand: "Frax",
41469
+ description: "The pre-rename sibling of sfrxUSD over legacy FRAX \u2014 same vault family, same cap-set rate mechanism. Instant exit.",
41152
41470
  decimals: 18,
41153
41471
  isRebasing: false,
41154
41472
  isMintable: true,
@@ -41170,6 +41488,7 @@ var SINGLE_CHAIN_ENTRIES = {
41170
41488
  // DOLA
41171
41489
  symbol: "sDOLA",
41172
41490
  brand: "Inverse",
41491
+ description: "DOLA is Inverse Finance's stablecoin; sDOLA compounds FiRM's DBR interest revenue, converted to DOLA by a continuous on-chain auction \u2014 deposits never leave the contract (no rehypothecation). Instant permissionless exit.",
41173
41492
  decimals: 18,
41174
41493
  isRebasing: false,
41175
41494
  isMintable: true,
@@ -41182,6 +41501,7 @@ var SINGLE_CHAIN_ENTRIES = {
41182
41501
  underlying: "0x6b175474e89094c44da98b954eedeac495271d0f",
41183
41502
  symbol: "sDAI",
41184
41503
  brand: "Maker",
41504
+ description: "DAI deposited into MakerDAO's Dai Savings Rate; the share price accrues the DSR. Instant entry and exit through the Pot.",
41185
41505
  decimals: 18,
41186
41506
  isRebasing: false,
41187
41507
  isMintable: true,
@@ -41193,6 +41513,7 @@ var SINGLE_CHAIN_ENTRIES = {
41193
41513
  underlying: "0x09d4214c03d01f49544c0448dbe3a27f768f2b34",
41194
41514
  symbol: "wsrUSD",
41195
41515
  brand: "Reservoir",
41516
+ description: "rUSD is Reservoir's asset-backed stablecoin; srUSD accrues the Reservoir savings rate funded by the protocol's RWA and credit portfolios, and wsrUSD is its non-rebasing wrapper. Instant exit, subject to PSM liquidity.",
41196
41517
  decimals: 18,
41197
41518
  isRebasing: false,
41198
41519
  isMintable: true,
@@ -41205,6 +41526,7 @@ var SINGLE_CHAIN_ENTRIES = {
41205
41526
  underlying: "0x6c8984bc7dbbedaf4f6b2fd766f16ebb7d10aab4",
41206
41527
  symbol: "wstUSR",
41207
41528
  brand: "Resolv",
41529
+ description: "USR is Resolv's delta-neutral synthetic dollar (ETH collateral hedged with perpetual shorts; the RLP insurance layer absorbs losses first). stUSR stakes it and rebases; wstUSR is the non-rebasing wrapper. Instant unwrap with no cooldown.",
41208
41530
  decimals: 18,
41209
41531
  // Wraps the rebasing stUSR — wstUSR itself does NOT rebase.
41210
41532
  isRebasing: false,
@@ -41218,6 +41540,7 @@ var SINGLE_CHAIN_ENTRIES = {
41218
41540
  underlying: "0xfa2b947eec368f42195f24f36d2af29f7c24cec2",
41219
41541
  symbol: "sUSDf",
41220
41542
  brand: "Falcon",
41543
+ description: "USDf is Falcon Finance's overcollateralised synthetic dollar; sUSDf stakes it and accrues yield from Falcon's diversified institutional trading strategies. The share exits instantly to USDf \u2014 the 7-day cooling period applies only to the downstream USDf \u2192 collateral redemption.",
41221
41544
  decimals: 18,
41222
41545
  isRebasing: false,
41223
41546
  isMintable: true,
@@ -41233,6 +41556,7 @@ var SINGLE_CHAIN_ENTRIES = {
41233
41556
  underlying: "0x48f9e38f3070ad8945dfeae3fa70987722e3d89c",
41234
41557
  symbol: "siUSD",
41235
41558
  brand: "InfiniFi",
41559
+ description: "iUSD is infiniFi's USD receipt token over USDC; siUSD accrues a blended rate from the protocol's laddered allocation across liquid and locked yield instruments. Instant exit while reserves cover it \u2014 the locked tier (liUSD) is a separate token.",
41236
41560
  decimals: 18,
41237
41561
  isRebasing: false,
41238
41562
  isMintable: true,
@@ -41245,6 +41569,7 @@ var SINGLE_CHAIN_ENTRIES = {
41245
41569
  underlying: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
41246
41570
  symbol: "syrupUSDC",
41247
41571
  brand: "Maple",
41572
+ description: "Deposits fund Maple's institutional credit book \u2014 collateralised loans to vetted trading firms \u2014 and yield is loan interest. The share price is managed by Maple with no on-chain solvency invariant; exits go through a cycle-based withdrawal queue (~7 days typical), though most process much faster via the instant buffer.",
41248
41573
  decimals: 6,
41249
41574
  isRebasing: false,
41250
41575
  isMintable: true,
@@ -41258,6 +41583,7 @@ var SINGLE_CHAIN_ENTRIES = {
41258
41583
  underlying: "0xdac17f958d2ee523a2206206994597c13d831ec7",
41259
41584
  symbol: "syrupUSDT",
41260
41585
  brand: "Maple",
41586
+ description: "The USDT sibling of syrupUSDC \u2014 same Maple institutional credit book, same cycle-based withdrawal queue.",
41261
41587
  decimals: 6,
41262
41588
  isRebasing: false,
41263
41589
  isMintable: true,
@@ -41272,6 +41598,7 @@ var SINGLE_CHAIN_ENTRIES = {
41272
41598
  // USDG
41273
41599
  symbol: "syrupUSDG",
41274
41600
  brand: "Maple",
41601
+ description: "The USDG sibling of syrupUSDC \u2014 same Maple institutional credit book, same cycle-based withdrawal queue.",
41275
41602
  decimals: 6,
41276
41603
  isRebasing: false,
41277
41604
  isMintable: true,
@@ -41294,6 +41621,7 @@ var SINGLE_CHAIN_ENTRIES = {
41294
41621
  // wYLDS
41295
41622
  symbol: "PRIME",
41296
41623
  brand: "Hastra",
41624
+ description: "Hastra's Democratized PRIME: an ERC-4626 over wYLDS (itself a vault over USDC), with the rate published via Hastra's Proof-of-Reserve feed. Deposits are whitelist-gated; exit is a two-phase request-then-complete redemption.",
41297
41625
  decimals: 6,
41298
41626
  underlyingDecimals: 6,
41299
41627
  isRebasing: false,
@@ -41302,6 +41630,64 @@ var SINGLE_CHAIN_ENTRIES = {
41302
41630
  yieldFetcher: hastraPrimeFetcher,
41303
41631
  yieldKey: "Hastra PRIME::PRIME"
41304
41632
  },
41633
+ {
41634
+ // 3Jane USD3 — senior tranche of the credit-based money market
41635
+ // (docs.3jane.xyz): USDC funds unsecured fintech/crypto credit
41636
+ // lines through a MorphoCredit (Morpho Blue augmentation) market,
41637
+ // idle cash in Aave. Yearn-v3-strategy ERC-4626, 6-dec shares over
41638
+ // USDC, price accrues on-chain (`pricePerShare`). Exit is instant
41639
+ // but capped by real multi-source liquidity — idle USDC + what the
41640
+ // MorphoCredit market can redeem out of waEthUSDC — read via
41641
+ // `availableWithdrawLimit` (~4.7 % of the $75M TVL at 2026-08-04
41642
+ // integration), hence the `erc4626-withdraw-limit` reader. No
41643
+ // on-chain solvency invariant on the credit sleeves (Maple /
41644
+ // Spark-V2 trust class); unrealized losses zero the limit until
41645
+ // marked down. `isMintable: true` is structural — the whitelist is
41646
+ // disabled — but deposits are cap-gated (`USD3_SUPPLY_CAP`,
41647
+ // guarded-launch style) and the cap was FULL at integration time
41648
+ // (`availableDepositLimit = 0`), plus a 1,000-USDC minimum first
41649
+ // deposit; consult `maxDeposit` live before advertising the mint.
41650
+ reader: "erc4626-withdraw-limit",
41651
+ address: "0x056b269eb1f75477a8666ae8c7fe01b64dd55ecc",
41652
+ underlying: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
41653
+ // USDC
41654
+ symbol: "USD3",
41655
+ brand: "3Jane",
41656
+ description: "3Jane's senior tranche: USDC funds unsecured, credit-underwritten fintech and crypto credit lines through a MorphoCredit market, with idle cash parked in Aave. Yield is loan interest and the junior sUSD3 absorbs defaults first; exits are instant but capped by live liquidity, and deposits are supply-cap-gated.",
41657
+ decimals: 6,
41658
+ isRebasing: false,
41659
+ isMintable: true,
41660
+ withdrawalMode: "instant-capped",
41661
+ yieldFetcher: threeJaneFetcher,
41662
+ yieldKey: USD3_KEY
41663
+ },
41664
+ {
41665
+ // 3Jane sUSD3 — the junior, first-loss tranche: an ERC-4626 whose
41666
+ // underlying is USD3 itself (the reUSDe pattern — key the pair,
41667
+ // not the brand). Earns a fixed `TRANCHE_SHARE_VARIANT` slice of
41668
+ // pool interest over a much smaller base (~2x USD3's rate),
41669
+ // absorbs losses first, and its supply is capped by the
41670
+ // subordination ratio (deposits permissionless within it). Exit is
41671
+ // `startCooldown(shares)` → wait → `redeem` inside a withdrawal
41672
+ // window (+ a ProtocolConfig lock on new deposits, 0 at
41673
+ // integration time), so `request-based` with the cooldown pinned
41674
+ // from the live `cooldownDuration()` read (30 days, 2026-08-04;
41675
+ // governance-mutable via ProtocolConfig — the window read
41676
+ // ~100 years, i.e. effectively no expiry today).
41677
+ address: "0xf689555121e529ff0463e191f9bd9d1e496164a7",
41678
+ underlying: "0x056b269eb1f75477a8666ae8c7fe01b64dd55ecc",
41679
+ // USD3
41680
+ symbol: "sUSD3",
41681
+ brand: "3Jane",
41682
+ description: "3Jane's junior, first-loss tranche: an ERC-4626 over USD3 that earns a fixed share of pool interest on a smaller base (roughly 2x USD3's rate) and absorbs credit losses first. Exit requires a 30-day cooldown, then redeeming within the withdrawal window.",
41683
+ decimals: 6,
41684
+ isRebasing: false,
41685
+ isMintable: true,
41686
+ withdrawalMode: "request-based",
41687
+ withdrawalCooldownSeconds: 30 * 86400,
41688
+ yieldFetcher: threeJaneFetcher,
41689
+ yieldKey: SUSD3_KEY
41690
+ },
41305
41691
  {
41306
41692
  // Spark Vaults V2 — the mainnet book, and by far the largest of
41307
41693
  // the family. Only the Ethereum rows carry the intents contract as
@@ -41357,6 +41743,7 @@ var SINGLE_CHAIN_ENTRIES = {
41357
41743
  // ICL
41358
41744
  symbol: "reUSDe",
41359
41745
  brand: "Re Protocol",
41746
+ description: "Junior tranche of Re's reinsurance capital stack, denominated in USDe: it pays roughly double the senior reUSD rate because it absorbs underwriting losses first. Bare ERC-20 priced by a daily NAV oracle; exits are request-based, with a quarterly queue in the worst case.",
41360
41747
  decimals: 18,
41361
41748
  underlyingDecimals: 18,
41362
41749
  isRebasing: false,
@@ -41394,6 +41781,7 @@ var SINGLE_CHAIN_ENTRIES = {
41394
41781
  underlying: "0x4200000000000000000000000000000000000006",
41395
41782
  symbol: "yoETH",
41396
41783
  brand: "YO",
41784
+ description: "YO's ETH yield optimizer: WETH is allocated across curated on-chain strategies and yield accrues into the share price. Async ERC-7540 redemption \u2014 instant when idle liquidity covers it, up to ~24 hours when unwinding non-liquid strategies.",
41397
41785
  decimals: 18,
41398
41786
  isRebasing: false,
41399
41787
  isMintable: true,
@@ -41408,6 +41796,7 @@ var SINGLE_CHAIN_ENTRIES = {
41408
41796
  underlying: "0x24de8771bc5ddb3362db529fc3358f2df3a0e346",
41409
41797
  symbol: "savUSD",
41410
41798
  brand: "Avant",
41799
+ description: "avUSD is Avant's synthetic dollar; savUSD stakes it and accrues yield from Avant's market-neutral trading strategies via an appreciating share price, with a 24-hour unstake cooldown.",
41411
41800
  decimals: 18,
41412
41801
  isRebasing: false,
41413
41802
  isMintable: true,
@@ -41423,6 +41812,7 @@ var SINGLE_CHAIN_ENTRIES = {
41423
41812
  // avBTC
41424
41813
  symbol: "savBTC",
41425
41814
  brand: "Avant",
41815
+ description: "avBTC is Avant's BTC-denominated synthetic asset; savBTC stakes it and accrues yield from Avant's market-neutral strategies via an appreciating share price, with a 24-hour unstake cooldown.",
41426
41816
  decimals: 18,
41427
41817
  isRebasing: false,
41428
41818
  isMintable: true,
@@ -43370,6 +43760,76 @@ var riverFetcher = {
43370
43760
  parse: parseRiverResults,
43371
43761
  getAbi: getRiverAbi
43372
43762
  };
43763
+ function getInverseCalls(chainId) {
43764
+ const results = [];
43765
+ for (const lender of inverseLendersByChain(chainId)) {
43766
+ const config = inverseConfigFor(lender, chainId);
43767
+ const markets = inverseChainData(lender, chainId)?.markets ?? [];
43768
+ if (!config?.oracle || markets.length === 0) continue;
43769
+ for (const m of markets) {
43770
+ if (!m.address || !m.collToken) continue;
43771
+ const calls = [
43772
+ {
43773
+ address: config.oracle,
43774
+ name: "viewPrice",
43775
+ params: [m.collToken, BigInt(m.collateralFactorBps)]
43776
+ }
43777
+ ];
43778
+ results.push({
43779
+ calls,
43780
+ meta: {
43781
+ lender,
43782
+ chainId,
43783
+ market: m.address.toLowerCase(),
43784
+ collToken: m.collToken.toLowerCase(),
43785
+ collDecimals: m.collDecimals,
43786
+ dola: config.dola?.toLowerCase()
43787
+ },
43788
+ lender: inverseLenderKey(lender, m.address)
43789
+ });
43790
+ }
43791
+ }
43792
+ return results;
43793
+ }
43794
+ function parseInverseResults(data, meta, context) {
43795
+ const { chainId } = context;
43796
+ const key = inverseLenderKey(meta.lender, meta.market);
43797
+ const entries = [];
43798
+ const raw = data?.[0];
43799
+ const price2 = typeof raw === "bigint" ? raw : raw != null && raw !== "0x" ? BigInt(raw) : 0n;
43800
+ const collUSD = Number(price2) / 10 ** (36 - meta.collDecimals);
43801
+ if (collUSD > 0 && collUSD < 1e9) {
43802
+ entries.push({
43803
+ asset: meta.collToken,
43804
+ price: collUSD,
43805
+ priceUSD: collUSD,
43806
+ marketUid: createMarketUid(chainId, key, meta.collToken),
43807
+ targetLender: key,
43808
+ description: "Inverse FiRM pessimistic oracle (USD, ~2-day low)"
43809
+ });
43810
+ }
43811
+ if (meta.dola) {
43812
+ entries.push({
43813
+ asset: meta.dola,
43814
+ price: 1,
43815
+ priceUSD: 1,
43816
+ marketUid: createMarketUid(chainId, key, meta.dola),
43817
+ targetLender: key,
43818
+ description: "Inverse DOLA (par)",
43819
+ staticBase: true,
43820
+ baseAsset: meta.dola
43821
+ });
43822
+ }
43823
+ return entries;
43824
+ }
43825
+ function getInverseAbi() {
43826
+ return InverseOracleAbi;
43827
+ }
43828
+ var inverseFetcher = {
43829
+ getCalls: getInverseCalls,
43830
+ parse: parseInverseResults,
43831
+ getAbi: getInverseAbi
43832
+ };
43373
43833
  function getTellerCalls(chainId) {
43374
43834
  const pools = tellerPoolsByChain(chainId);
43375
43835
  if (pools.length === 0) return [];
@@ -45108,8 +45568,6 @@ function resolveDerivation(entry, groupDefault) {
45108
45568
  if (entry.baseAsset && !entry.staticBase) return "quoted";
45109
45569
  return groupDefault ?? "direct";
45110
45570
  }
45111
-
45112
- // src/prices/oracle-prices/fetchOraclePrices.ts
45113
45571
  function countFailures(data, offset, count) {
45114
45572
  let failures = 0;
45115
45573
  for (let i = offset; i < offset + count; i++) {
@@ -45221,6 +45679,9 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
45221
45679
  const multicallErrors = [];
45222
45680
  const active = onlyFetchers ? new Set(onlyFetchers.map((f) => f.toLowerCase())) : null;
45223
45681
  const isActive = (name) => !active || active.has(name);
45682
+ if (isActive("termmax") && termMaxConfigByChain(chainId)) {
45683
+ await fetchTermMaxMarkets(chainId).catch(() => []);
45684
+ }
45224
45685
  const aaveResults = isActive("aave") ? safeGetCalls(
45225
45686
  "aave",
45226
45687
  () => aaveFetcher.getCalls(chainId),
@@ -45290,6 +45751,11 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
45290
45751
  () => riverFetcher.getCalls(chainId),
45291
45752
  getCallsErrors
45292
45753
  ) : [];
45754
+ const inverseResults = isActive("inverse") ? safeGetCalls(
45755
+ "inverse",
45756
+ () => inverseFetcher.getCalls(chainId),
45757
+ getCallsErrors
45758
+ ) : [];
45293
45759
  const tellerResults = isActive("teller") ? safeGetCalls(
45294
45760
  "teller",
45295
45761
  () => tellerFetcher.getCalls(chainId),
@@ -45409,6 +45875,13 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
45409
45875
  getRiverAbi(),
45410
45876
  "direct"
45411
45877
  );
45878
+ const inverseGroup = buildGroup(
45879
+ "inverse",
45880
+ inverseResults,
45881
+ inverseFetcher.parse,
45882
+ getInverseAbi(),
45883
+ "direct"
45884
+ );
45412
45885
  const tellerGroup = buildGroup(
45413
45886
  "teller",
45414
45887
  tellerResults,
@@ -45473,6 +45946,7 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
45473
45946
  termGroup,
45474
45947
  liquityGroup,
45475
45948
  riverGroup,
45949
+ inverseGroup,
45476
45950
  tellerGroup,
45477
45951
  termMaxGroup,
45478
45952
  siloV2Group,
@@ -45520,6 +45994,7 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
45520
45994
  termData,
45521
45995
  liquityData,
45522
45996
  riverData,
45997
+ inverseData,
45523
45998
  tellerData,
45524
45999
  termMaxData,
45525
46000
  morphoGqlEntries,
@@ -45638,6 +46113,14 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
45638
46113
  allowFailure,
45639
46114
  rpcOverrides
45640
46115
  ),
46116
+ executeGroup(
46117
+ inverseGroup,
46118
+ chainId,
46119
+ chainBatchSize,
46120
+ retries,
46121
+ allowFailure,
46122
+ rpcOverrides
46123
+ ),
45641
46124
  executeGroup(
45642
46125
  tellerGroup,
45643
46126
  chainId,
@@ -45780,6 +46263,7 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
45780
46263
  parseTrackers(termGroup, termData.results);
45781
46264
  parseTrackers(liquityGroup, liquityData.results);
45782
46265
  parseTrackers(riverGroup, riverData.results);
46266
+ parseTrackers(inverseGroup, inverseData.results);
45783
46267
  if (siloV2GqlEntries != null) {
45784
46268
  const diag2 = {
45785
46269
  lender: "SILO_V2 (GraphQL)",
@@ -49307,7 +49791,7 @@ var Erc4626PreviewRedeemAbi = [
49307
49791
  ];
49308
49792
 
49309
49793
  // src/vaults/lst/readers/shared.ts
49310
- var ONE_E187 = 10n ** 18n;
49794
+ var ONE_E188 = 10n ** 18n;
49311
49795
  var rescaleDecimals = (v, fromDec, toDec) => toDec >= fromDec ? v * 10n ** BigInt(toDec - fromDec) : v / 10n ** BigInt(fromDec - toDec);
49312
49796
  var MULTICALL3_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11";
49313
49797
  var Multicall3BalanceAbi = [
@@ -49350,7 +49834,7 @@ var readerBeetsStS = (entry) => ({
49350
49834
  }
49351
49835
  const liquidity = toBigInt13(pool);
49352
49836
  return {
49353
- totalAssets: totalSupply * exchangeRate / ONE_E187,
49837
+ totalAssets: totalSupply * exchangeRate / ONE_E188,
49354
49838
  totalSupply,
49355
49839
  exchangeRate,
49356
49840
  liquidity
@@ -49383,7 +49867,7 @@ var readerBenqiSavax = (entry) => ({
49383
49867
  {
49384
49868
  address: entry.address,
49385
49869
  name: "getPooledAvaxByShares",
49386
- params: [ONE_E187]
49870
+ params: [ONE_E188]
49387
49871
  },
49388
49872
  { address: entry.address, name: "totalPooledAvax", params: [] }
49389
49873
  ],
@@ -49394,7 +49878,7 @@ var readerBenqiSavax = (entry) => ({
49394
49878
  if (totalSupply === void 0 || exchangeRate === void 0) {
49395
49879
  return void 0;
49396
49880
  }
49397
- const totalAssets = toBigInt13(totalPooled) ?? totalSupply * exchangeRate / ONE_E187;
49881
+ const totalAssets = toBigInt13(totalPooled) ?? totalSupply * exchangeRate / ONE_E188;
49398
49882
  return {
49399
49883
  totalAssets,
49400
49884
  totalSupply,
@@ -49413,7 +49897,7 @@ var readerBgtWrapper1to1 = (entry) => ({
49413
49897
  return {
49414
49898
  totalAssets: totalSupply,
49415
49899
  totalSupply,
49416
- exchangeRate: ONE_E187
49900
+ exchangeRate: ONE_E188
49417
49901
  };
49418
49902
  }
49419
49903
  });
@@ -49443,7 +49927,7 @@ var readerDineroBeraEth = (entry) => ({
49443
49927
  return void 0;
49444
49928
  }
49445
49929
  return {
49446
- totalAssets: totalSupply * exchangeRate / ONE_E187,
49930
+ totalAssets: totalSupply * exchangeRate / ONE_E188,
49447
49931
  totalSupply,
49448
49932
  exchangeRate
49449
49933
  };
@@ -49455,7 +49939,7 @@ var readerErc4626 = (entry) => ({
49455
49939
  calls: [
49456
49940
  { address: entry.address, name: "totalAssets", params: [] },
49457
49941
  { address: entry.address, name: "totalSupply", params: [] },
49458
- { address: entry.address, name: "convertToAssets", params: [ONE_E187] }
49942
+ { address: entry.address, name: "convertToAssets", params: [ONE_E188] }
49459
49943
  ],
49460
49944
  abis: [Erc4626ReadAbi, TotalSupplyAbi, Erc4626ReadAbi],
49461
49945
  parse: ([assets, supply, rate]) => {
@@ -49472,7 +49956,7 @@ var readerErc4626PreviewRedeem = (entry) => ({
49472
49956
  calls: [
49473
49957
  { address: entry.address, name: "totalAssets", params: [] },
49474
49958
  { address: entry.address, name: "totalSupply", params: [] },
49475
- { address: entry.address, name: "previewRedeem", params: [ONE_E187] }
49959
+ { address: entry.address, name: "previewRedeem", params: [ONE_E188] }
49476
49960
  ],
49477
49961
  abis: [Erc4626PreviewRedeemAbi, TotalSupplyAbi, Erc4626PreviewRedeemAbi],
49478
49962
  parse: ([assets, supply, rate]) => {
@@ -49552,7 +50036,7 @@ var readerEtherFiWeEth = (entry) => {
49552
50036
  }
49553
50037
  }
49554
50038
  return {
49555
- totalAssets: totalSupply * exchangeRate / ONE_E187,
50039
+ totalAssets: totalSupply * exchangeRate / ONE_E188,
49556
50040
  totalSupply,
49557
50041
  exchangeRate,
49558
50042
  liquidity
@@ -49585,7 +50069,7 @@ var readerHyperbeatBeHype = (entry) => {
49585
50069
  return {
49586
50070
  totalAssets: totalSupply,
49587
50071
  totalSupply,
49588
- exchangeRate: ONE_E187
50072
+ exchangeRate: ONE_E188
49589
50073
  };
49590
50074
  }
49591
50075
  };
@@ -49593,7 +50077,7 @@ var readerHyperbeatBeHype = (entry) => {
49593
50077
  return {
49594
50078
  calls: [
49595
50079
  { address: entry.address, name: "totalSupply", params: [] },
49596
- { address: stakingCore, name: "BeHYPEToHYPE", params: [ONE_E187] }
50080
+ { address: stakingCore, name: "BeHYPEToHYPE", params: [ONE_E188] }
49597
50081
  ],
49598
50082
  abis: [TotalSupplyAbi, HyperbeatStakingCoreAbi],
49599
50083
  parse: ([supply, rate]) => {
@@ -49603,7 +50087,7 @@ var readerHyperbeatBeHype = (entry) => {
49603
50087
  return void 0;
49604
50088
  }
49605
50089
  return {
49606
- totalAssets: totalSupply * exchangeRate / ONE_E187,
50090
+ totalAssets: totalSupply * exchangeRate / ONE_E188,
49607
50091
  totalSupply,
49608
50092
  exchangeRate
49609
50093
  };
@@ -49635,7 +50119,7 @@ var readerKelpRsEth = (entry) => {
49635
50119
  return {
49636
50120
  totalAssets: totalSupply,
49637
50121
  totalSupply,
49638
- exchangeRate: ONE_E187
50122
+ exchangeRate: ONE_E188
49639
50123
  };
49640
50124
  }
49641
50125
  };
@@ -49653,7 +50137,7 @@ var readerKelpRsEth = (entry) => {
49653
50137
  return void 0;
49654
50138
  }
49655
50139
  return {
49656
- totalAssets: totalSupply * exchangeRate / ONE_E187,
50140
+ totalAssets: totalSupply * exchangeRate / ONE_E188,
49657
50141
  totalSupply,
49658
50142
  exchangeRate
49659
50143
  };
@@ -49685,7 +50169,7 @@ var readerKinetiqKHype = (entry) => {
49685
50169
  return {
49686
50170
  totalAssets: totalSupply,
49687
50171
  totalSupply,
49688
- exchangeRate: ONE_E187
50172
+ exchangeRate: ONE_E188
49689
50173
  };
49690
50174
  }
49691
50175
  };
@@ -49693,7 +50177,7 @@ var readerKinetiqKHype = (entry) => {
49693
50177
  return {
49694
50178
  calls: [
49695
50179
  { address: entry.address, name: "totalSupply", params: [] },
49696
- { address: accountant, name: "kHYPEToHYPE", params: [ONE_E187] }
50180
+ { address: accountant, name: "kHYPEToHYPE", params: [ONE_E188] }
49697
50181
  ],
49698
50182
  abis: [TotalSupplyAbi, KinetiqStakingAccountantAbi],
49699
50183
  parse: ([supply, rate]) => {
@@ -49703,7 +50187,7 @@ var readerKinetiqKHype = (entry) => {
49703
50187
  return void 0;
49704
50188
  }
49705
50189
  return {
49706
- totalAssets: totalSupply * exchangeRate / ONE_E187,
50190
+ totalAssets: totalSupply * exchangeRate / ONE_E188,
49707
50191
  totalSupply,
49708
50192
  exchangeRate
49709
50193
  };
@@ -49743,7 +50227,7 @@ var readerLairStKaia = (entry) => ({
49743
50227
  if (totalSupply === void 0 || exchangeRate === void 0) {
49744
50228
  return void 0;
49745
50229
  }
49746
- const totalAssets = toBigInt13(totalStaking) ?? totalSupply * exchangeRate / ONE_E187;
50230
+ const totalAssets = toBigInt13(totalStaking) ?? totalSupply * exchangeRate / ONE_E188;
49747
50231
  return {
49748
50232
  totalAssets,
49749
50233
  totalSupply,
@@ -49777,7 +50261,7 @@ var readerLidoWstEth = (entry) => ({
49777
50261
  return void 0;
49778
50262
  }
49779
50263
  return {
49780
- totalAssets: totalSupply * exchangeRate / ONE_E187,
50264
+ totalAssets: totalSupply * exchangeRate / ONE_E188,
49781
50265
  totalSupply,
49782
50266
  exchangeRate
49783
50267
  };
@@ -49815,7 +50299,7 @@ var readerListaSlisBnb = (entry) => {
49815
50299
  return {
49816
50300
  totalAssets: totalSupply,
49817
50301
  totalSupply,
49818
- exchangeRate: ONE_E187
50302
+ exchangeRate: ONE_E188
49819
50303
  };
49820
50304
  }
49821
50305
  };
@@ -49823,7 +50307,7 @@ var readerListaSlisBnb = (entry) => {
49823
50307
  return {
49824
50308
  calls: [
49825
50309
  { address: entry.address, name: "totalSupply", params: [] },
49826
- { address: manager, name: "convertSnBnbToBnb", params: [ONE_E187] },
50310
+ { address: manager, name: "convertSnBnbToBnb", params: [ONE_E188] },
49827
50311
  { address: manager, name: "getTotalPooledBnb", params: [] }
49828
50312
  ],
49829
50313
  abis: [TotalSupplyAbi, ListaStakeManagerReadAbi, ListaStakeManagerReadAbi],
@@ -49834,7 +50318,7 @@ var readerListaSlisBnb = (entry) => {
49834
50318
  return void 0;
49835
50319
  }
49836
50320
  const pooledBnb = toBigInt13(pooled);
49837
- const totalAssets = pooledBnb ?? totalSupply * exchangeRate / ONE_E187;
50321
+ const totalAssets = pooledBnb ?? totalSupply * exchangeRate / ONE_E188;
49838
50322
  return { totalAssets, totalSupply, exchangeRate };
49839
50323
  }
49840
50324
  };
@@ -49864,7 +50348,7 @@ var readerMantleMEth = (entry) => {
49864
50348
  return {
49865
50349
  totalAssets: totalSupply,
49866
50350
  totalSupply,
49867
- exchangeRate: ONE_E187
50351
+ exchangeRate: ONE_E188
49868
50352
  };
49869
50353
  }
49870
50354
  };
@@ -49872,7 +50356,7 @@ var readerMantleMEth = (entry) => {
49872
50356
  return {
49873
50357
  calls: [
49874
50358
  { address: entry.address, name: "totalSupply", params: [] },
49875
- { address: staking, name: "mETHToETH", params: [ONE_E187] }
50359
+ { address: staking, name: "mETHToETH", params: [ONE_E188] }
49876
50360
  ],
49877
50361
  abis: [TotalSupplyAbi, MantleStakingAbi],
49878
50362
  parse: ([supply, rate]) => {
@@ -49882,7 +50366,7 @@ var readerMantleMEth = (entry) => {
49882
50366
  return void 0;
49883
50367
  }
49884
50368
  return {
49885
- totalAssets: totalSupply * exchangeRate / ONE_E187,
50369
+ totalAssets: totalSupply * exchangeRate / ONE_E188,
49886
50370
  totalSupply,
49887
50371
  exchangeRate
49888
50372
  };
@@ -49903,7 +50387,7 @@ var readerOffChain = (entry) => {
49903
50387
  return {
49904
50388
  totalAssets: rescaleDecimals(totalSupply, shareDec, underlyingDec),
49905
50389
  totalSupply,
49906
- exchangeRate: ONE_E187
50390
+ exchangeRate: ONE_E188
49907
50391
  };
49908
50392
  }
49909
50393
  };
@@ -49937,7 +50421,7 @@ var readerRenzoEzEth = (entry) => {
49937
50421
  return {
49938
50422
  totalAssets: totalSupply,
49939
50423
  totalSupply,
49940
- exchangeRate: ONE_E187
50424
+ exchangeRate: ONE_E188
49941
50425
  };
49942
50426
  }
49943
50427
  };
@@ -49956,7 +50440,7 @@ var readerRenzoEzEth = (entry) => {
49956
50440
  return {
49957
50441
  totalAssets: totalTvl,
49958
50442
  totalSupply,
49959
- exchangeRate: totalTvl * ONE_E187 / totalSupply
50443
+ exchangeRate: totalTvl * ONE_E188 / totalSupply
49960
50444
  };
49961
50445
  }
49962
50446
  };
@@ -50012,7 +50496,7 @@ var readerRocketReth = (entry) => {
50012
50496
  }
50013
50497
  const liquidity = depositPool ? toBigInt13(slice2[2]) : void 0;
50014
50498
  return {
50015
- totalAssets: totalSupply * exchangeRate / ONE_E187,
50499
+ totalAssets: totalSupply * exchangeRate / ONE_E188,
50016
50500
  totalSupply,
50017
50501
  exchangeRate,
50018
50502
  liquidity
@@ -50054,7 +50538,7 @@ var readerStaderEthx = (entry) => {
50054
50538
  return {
50055
50539
  totalAssets: totalSupply,
50056
50540
  totalSupply,
50057
- exchangeRate: ONE_E187
50541
+ exchangeRate: ONE_E188
50058
50542
  };
50059
50543
  }
50060
50544
  };
@@ -50072,7 +50556,7 @@ var readerStaderEthx = (entry) => {
50072
50556
  return void 0;
50073
50557
  }
50074
50558
  return {
50075
- totalAssets: totalSupply * exchangeRate / ONE_E187,
50559
+ totalAssets: totalSupply * exchangeRate / ONE_E188,
50076
50560
  totalSupply,
50077
50561
  exchangeRate
50078
50562
  };
@@ -50089,7 +50573,7 @@ var readerStaderMaticX = (entry) => {
50089
50573
  {
50090
50574
  address: rateAddress,
50091
50575
  name: "convertMaticXToMatic",
50092
- params: [ONE_E187],
50576
+ params: [ONE_E188],
50093
50577
  chainId: homeChainId
50094
50578
  }
50095
50579
  ],
@@ -50104,7 +50588,7 @@ var readerStaderMaticX = (entry) => {
50104
50588
  }
50105
50589
  const isCrossChain = homeContract !== void 0;
50106
50590
  return {
50107
- totalAssets: isCrossChain ? totalSupply * amountInMatic / ONE_E187 : totalPooledMatic ?? totalSupply * amountInMatic / ONE_E187,
50591
+ totalAssets: isCrossChain ? totalSupply * amountInMatic / ONE_E188 : totalPooledMatic ?? totalSupply * amountInMatic / ONE_E188,
50108
50592
  totalSupply,
50109
50593
  exchangeRate: amountInMatic
50110
50594
  };
@@ -50136,7 +50620,7 @@ var readerStakeWiseOsEth = (entry) => {
50136
50620
  return {
50137
50621
  totalAssets: totalSupply,
50138
50622
  totalSupply,
50139
- exchangeRate: ONE_E187
50623
+ exchangeRate: ONE_E188
50140
50624
  };
50141
50625
  }
50142
50626
  };
@@ -50144,7 +50628,7 @@ var readerStakeWiseOsEth = (entry) => {
50144
50628
  return {
50145
50629
  calls: [
50146
50630
  { address: entry.address, name: "totalSupply", params: [] },
50147
- { address: controller, name: "convertToAssets", params: [ONE_E187] }
50631
+ { address: controller, name: "convertToAssets", params: [ONE_E188] }
50148
50632
  ],
50149
50633
  abis: [TotalSupplyAbi, StakeWiseOsTokenAbi],
50150
50634
  parse: ([supply, rate]) => {
@@ -50154,7 +50638,7 @@ var readerStakeWiseOsEth = (entry) => {
50154
50638
  return void 0;
50155
50639
  }
50156
50640
  return {
50157
- totalAssets: totalSupply * exchangeRate / ONE_E187,
50641
+ totalAssets: totalSupply * exchangeRate / ONE_E188,
50158
50642
  totalSupply,
50159
50643
  exchangeRate
50160
50644
  };
@@ -50186,7 +50670,7 @@ var readerStCelo = (entry) => {
50186
50670
  return {
50187
50671
  totalAssets: totalSupply,
50188
50672
  totalSupply,
50189
- exchangeRate: ONE_E187
50673
+ exchangeRate: ONE_E188
50190
50674
  };
50191
50675
  }
50192
50676
  };
@@ -50194,7 +50678,7 @@ var readerStCelo = (entry) => {
50194
50678
  return {
50195
50679
  calls: [
50196
50680
  { address: entry.address, name: "totalSupply", params: [] },
50197
- { address: manager, name: "toCelo", params: [ONE_E187] }
50681
+ { address: manager, name: "toCelo", params: [ONE_E188] }
50198
50682
  ],
50199
50683
  abis: [TotalSupplyAbi, StCeloManagerAbi],
50200
50684
  parse: ([supply, rate]) => {
@@ -50204,7 +50688,7 @@ var readerStCelo = (entry) => {
50204
50688
  return void 0;
50205
50689
  }
50206
50690
  return {
50207
- totalAssets: totalSupply * exchangeRate / ONE_E187,
50691
+ totalAssets: totalSupply * exchangeRate / ONE_E188,
50208
50692
  totalSupply,
50209
50693
  exchangeRate
50210
50694
  };
@@ -50237,7 +50721,7 @@ var readerSwellGetRate = (entry) => ({
50237
50721
  return void 0;
50238
50722
  }
50239
50723
  return {
50240
- totalAssets: totalSupply * exchangeRate / ONE_E187,
50724
+ totalAssets: totalSupply * exchangeRate / ONE_E188,
50241
50725
  totalSupply,
50242
50726
  exchangeRate
50243
50727
  };
@@ -50268,7 +50752,7 @@ var readerValantisWstHype = (entry) => {
50268
50752
  return {
50269
50753
  totalAssets: totalSupply,
50270
50754
  totalSupply,
50271
- exchangeRate: ONE_E187
50755
+ exchangeRate: ONE_E188
50272
50756
  };
50273
50757
  }
50274
50758
  };
@@ -50286,7 +50770,7 @@ var readerValantisWstHype = (entry) => {
50286
50770
  return void 0;
50287
50771
  }
50288
50772
  return {
50289
- totalAssets: totalSupply * exchangeRate / ONE_E187,
50773
+ totalAssets: totalSupply * exchangeRate / ONE_E188,
50290
50774
  totalSupply,
50291
50775
  exchangeRate
50292
50776
  };
@@ -50320,7 +50804,7 @@ var readerVedaAccountant = (entry) => {
50320
50804
  return {
50321
50805
  totalAssets: rescaleDecimals(totalSupply, shareDec, underlyingDec),
50322
50806
  totalSupply,
50323
- exchangeRate: ONE_E187
50807
+ exchangeRate: ONE_E188
50324
50808
  };
50325
50809
  }
50326
50810
  };
@@ -50339,7 +50823,7 @@ var readerVedaAccountant = (entry) => {
50339
50823
  const exchangeRate = rawRate * scale;
50340
50824
  return {
50341
50825
  totalAssets: rescaleDecimals(
50342
- totalSupply * exchangeRate / ONE_E187,
50826
+ totalSupply * exchangeRate / ONE_E188,
50343
50827
  shareDec,
50344
50828
  underlyingDec
50345
50829
  ),
@@ -50375,9 +50859,9 @@ var readerAnkrRatio = (entry) => ({
50375
50859
  return void 0;
50376
50860
  }
50377
50861
  return {
50378
- totalAssets: totalSupply * ONE_E187 / r,
50862
+ totalAssets: totalSupply * ONE_E188 / r,
50379
50863
  totalSupply,
50380
- exchangeRate: ONE_E187 * ONE_E187 / r
50864
+ exchangeRate: ONE_E188 * ONE_E188 / r
50381
50865
  };
50382
50866
  }
50383
50867
  });
@@ -50421,7 +50905,7 @@ var readerCoreEarnRate = (entry) => {
50421
50905
  return {
50422
50906
  totalAssets: totalSupply * r / CORE_RATE_DENOM,
50423
50907
  totalSupply,
50424
- exchangeRate: r * ONE_E187 / CORE_RATE_DENOM
50908
+ exchangeRate: r * ONE_E188 / CORE_RATE_DENOM
50425
50909
  };
50426
50910
  }
50427
50911
  };
@@ -50443,7 +50927,7 @@ var readerCoreStakedRatio = (entry) => {
50443
50927
  return {
50444
50928
  totalAssets: totalStaked,
50445
50929
  totalSupply,
50446
- exchangeRate: totalStaked * ONE_E187 / totalSupply
50930
+ exchangeRate: totalStaked * ONE_E188 / totalSupply
50447
50931
  };
50448
50932
  }
50449
50933
  };
@@ -50474,7 +50958,7 @@ var readerStellaStDot = (entry) => ({
50474
50958
  {
50475
50959
  address: entry.address,
50476
50960
  name: "getPooledTokenByShares",
50477
- params: [ONE_E187]
50961
+ params: [ONE_E188]
50478
50962
  },
50479
50963
  { address: entry.address, name: "getTotalPooledToken", params: [] }
50480
50964
  ],
@@ -50485,7 +50969,7 @@ var readerStellaStDot = (entry) => ({
50485
50969
  if (totalSupply === void 0 || exchangeRate === void 0) {
50486
50970
  return void 0;
50487
50971
  }
50488
- const totalAssets = toBigInt13(pooled) ?? totalSupply * exchangeRate / ONE_E187;
50972
+ const totalAssets = toBigInt13(pooled) ?? totalSupply * exchangeRate / ONE_E188;
50489
50973
  return {
50490
50974
  totalAssets,
50491
50975
  totalSupply,
@@ -50523,7 +51007,7 @@ var readerKintsuSMon = (entry) => ({
50523
51007
  const totalAssets = toBigInt13(pooled);
50524
51008
  const totalSupply = toBigInt13(shares);
50525
51009
  if (totalAssets === void 0 || totalSupply === void 0) return void 0;
50526
- const exchangeRate = totalSupply > 0n ? totalAssets * ONE_E187 / totalSupply : ONE_E187;
51010
+ const exchangeRate = totalSupply > 0n ? totalAssets * ONE_E188 / totalSupply : ONE_E188;
50527
51011
  return { totalAssets, totalSupply, exchangeRate };
50528
51012
  }
50529
51013
  });
@@ -50959,7 +51443,7 @@ var getLstValidators = async (chainId, shareToken) => {
50959
51443
  };
50960
51444
 
50961
51445
  // src/vaults/lst/fetchPublic.ts
50962
- var ONE_E188 = 10n ** 18n;
51446
+ var ONE_E189 = 10n ** 18n;
50963
51447
  var ERC20_BALANCE_ABI = parseAbi([
50964
51448
  "function balanceOf(address) view returns (uint256)"
50965
51449
  ]);
@@ -51074,8 +51558,8 @@ var fetchLstShareTokens = async (chainId, multicallRetry, prices = {}, tokenList
51074
51558
  const underlyingUnit = 10n ** BigInt(underlyingDec);
51075
51559
  const totalAssetsFormatted = Number(state.totalAssets) / 10 ** underlyingDec;
51076
51560
  const totalAssetsUsd = priceUsd !== void 0 ? totalAssetsFormatted * priceUsd : 0;
51077
- const convertToAssets = state.exchangeRate * underlyingUnit / ONE_E188;
51078
- const convertToShares = state.exchangeRate > 0n ? ONE_E188 * shareUnit / state.exchangeRate : 0n;
51561
+ const convertToAssets = state.exchangeRate * underlyingUnit / ONE_E189;
51562
+ const convertToShares = state.exchangeRate > 0n ? ONE_E189 * shareUnit / state.exchangeRate : 0n;
51079
51563
  let liquidityRaw;
51080
51564
  if (state.liquidity !== void 0) {
51081
51565
  liquidityRaw = state.liquidity;
@@ -54132,7 +54616,7 @@ var NavOracleReadAbi = [
54132
54616
  ];
54133
54617
 
54134
54618
  // src/vaults/savings/readers/shared.ts
54135
- var ONE_E189 = 10n ** 18n;
54619
+ var ONE_E1810 = 10n ** 18n;
54136
54620
  var toBigInt15 = (v) => {
54137
54621
  if (v === void 0 || v === null) return void 0;
54138
54622
  if (typeof v === "bigint") return v;
@@ -54173,7 +54657,7 @@ var readerErc46262 = (entry) => {
54173
54657
  return {
54174
54658
  totalAssets,
54175
54659
  totalSupply,
54176
- exchangeRate: convertToAssetsRaw * ONE_E189 / underlyingUnit
54660
+ exchangeRate: convertToAssetsRaw * ONE_E1810 / underlyingUnit
54177
54661
  };
54178
54662
  }
54179
54663
  };
@@ -54242,6 +54726,17 @@ var NativeWithdrawQueueReadAbi = [
54242
54726
  }
54243
54727
  ];
54244
54728
 
54729
+ // src/vaults/savings/abis/yearnStrategy.ts
54730
+ var AvailableWithdrawLimitAbi = [
54731
+ {
54732
+ name: "availableWithdrawLimit",
54733
+ type: "function",
54734
+ stateMutability: "view",
54735
+ inputs: [{ type: "address", name: "owner" }],
54736
+ outputs: [{ type: "uint256" }]
54737
+ }
54738
+ ];
54739
+
54245
54740
  // src/vaults/savings/readers/erc4626Idle.ts
54246
54741
  var readerErc4626Idle = (entry) => {
54247
54742
  const shareUnit = 10n ** BigInt(entry.decimals);
@@ -54270,7 +54765,7 @@ var readerErc4626Idle = (entry) => {
54270
54765
  return {
54271
54766
  totalAssets,
54272
54767
  totalSupply,
54273
- exchangeRate: convertToAssetsRaw * ONE_E189 / underlyingUnit,
54768
+ exchangeRate: convertToAssetsRaw * ONE_E1810 / underlyingUnit,
54274
54769
  ...capacity !== void 0 ? {
54275
54770
  instantRedeemCapacity: capacity,
54276
54771
  instantRedeemEnabled: true,
@@ -54282,6 +54777,54 @@ var readerErc4626Idle = (entry) => {
54282
54777
  };
54283
54778
  };
54284
54779
 
54780
+ // src/vaults/savings/readers/withdrawLimit.ts
54781
+ var NEUTRAL_PROBE = "0x000000000000000000000000000000000000dead";
54782
+ var readerErc4626WithdrawLimit = (entry) => {
54783
+ const shareUnit = 10n ** BigInt(entry.decimals);
54784
+ const underlyingUnit = 10n ** BigInt(entry.underlyingDecimals ?? entry.decimals);
54785
+ return {
54786
+ calls: [
54787
+ { address: entry.address, name: "totalAssets", params: [] },
54788
+ { address: entry.address, name: "totalSupply", params: [] },
54789
+ {
54790
+ address: entry.address,
54791
+ name: "convertToAssets",
54792
+ params: [shareUnit]
54793
+ },
54794
+ {
54795
+ address: entry.address,
54796
+ name: "availableWithdrawLimit",
54797
+ params: [NEUTRAL_PROBE]
54798
+ }
54799
+ ],
54800
+ abis: [
54801
+ Erc4626ReadAbi2,
54802
+ TotalSupplyAbi2,
54803
+ Erc4626ReadAbi2,
54804
+ AvailableWithdrawLimitAbi
54805
+ ],
54806
+ parse: ([assets, supply, rate, withdrawLimit]) => {
54807
+ const totalAssets = toBigInt15(assets);
54808
+ const totalSupply = toBigInt15(supply);
54809
+ const convertToAssetsRaw = toBigInt15(rate);
54810
+ if (totalAssets === void 0 || totalSupply === void 0 || convertToAssetsRaw === void 0) {
54811
+ return void 0;
54812
+ }
54813
+ const capacity = toBigInt15(withdrawLimit);
54814
+ return {
54815
+ totalAssets,
54816
+ totalSupply,
54817
+ exchangeRate: convertToAssetsRaw * ONE_E1810 / underlyingUnit,
54818
+ ...capacity !== void 0 ? {
54819
+ instantRedeemCapacity: capacity,
54820
+ instantRedeemEnabled: true,
54821
+ withdrawFeeBps: 0
54822
+ } : {}
54823
+ };
54824
+ }
54825
+ };
54826
+ };
54827
+
54285
54828
  // src/vaults/savings/readers/navOracle.ts
54286
54829
  var readerNavOracle = (entry) => {
54287
54830
  const shareUnit = 10n ** BigInt(entry.decimals);
@@ -54303,7 +54846,7 @@ var readerNavOracle = (entry) => {
54303
54846
  const exchangeRate = toBigInt15(raw);
54304
54847
  if (exchangeRate === void 0 || exchangeRate <= 0n) return void 0;
54305
54848
  return {
54306
- totalAssets: totalSupply * exchangeRate * underlyingUnit / (ONE_E189 * shareUnit),
54849
+ totalAssets: totalSupply * exchangeRate * underlyingUnit / (ONE_E1810 * shareUnit),
54307
54850
  totalSupply,
54308
54851
  exchangeRate
54309
54852
  };
@@ -54317,7 +54860,7 @@ var readerNativeWnlp = (entry) => {
54317
54860
  return {
54318
54861
  calls: [
54319
54862
  { address, name: "totalSupply", params: [] },
54320
- { address, name: "getNlpByWnlp", params: [ONE_E189] },
54863
+ { address, name: "getNlpByWnlp", params: [ONE_E1810] },
54321
54864
  { address, name: "instantRedeemFeeBips", params: [] },
54322
54865
  { address, name: "instantRedeemEnabled", params: [] },
54323
54866
  // Falls back to the vault itself when no CreditVault is pinned —
@@ -54351,7 +54894,7 @@ var readerNativeWnlp = (entry) => {
54351
54894
  const windowSeconds = toBigInt15(window);
54352
54895
  const bips = toBigInt15(feeBips);
54353
54896
  return {
54354
- totalAssets: totalSupply * exchangeRate / ONE_E189,
54897
+ totalAssets: totalSupply * exchangeRate / ONE_E1810,
54355
54898
  totalSupply,
54356
54899
  exchangeRate,
54357
54900
  // `instantRedeemFeeBips` on-chain is already basis points, so it
@@ -54377,6 +54920,8 @@ var buildReader2 = (entry) => {
54377
54920
  return readerNavOracle(entry);
54378
54921
  case "erc4626-idle":
54379
54922
  return readerErc4626Idle(entry);
54923
+ case "erc4626-withdraw-limit":
54924
+ return readerErc4626WithdrawLimit(entry);
54380
54925
  case "erc4626":
54381
54926
  case void 0:
54382
54927
  return readerErc46262(entry);
@@ -54387,7 +54932,7 @@ var buildReader2 = (entry) => {
54387
54932
  var resolveYieldApr2 = async (entries) => (await resolveEntryApr(entries)).apr;
54388
54933
 
54389
54934
  // src/vaults/savings/fetchPublic.ts
54390
- var ONE_E1810 = 10n ** 18n;
54935
+ var ONE_E1811 = 10n ** 18n;
54391
54936
  var fetchSavingsVaults = async (chainId, multicallRetry, prices = {}, tokenList = {}) => {
54392
54937
  const entries = getSavingsRegistry(chainId);
54393
54938
  if (entries.length === 0) return {};
@@ -54436,8 +54981,8 @@ var fetchSavingsVaults = async (chainId, multicallRetry, prices = {}, tokenList
54436
54981
  1,
54437
54982
  Number(liquidityAmount * 1000000n / state.totalAssets) / 1e6
54438
54983
  ) : 1;
54439
- const convertToAssets = state.exchangeRate * underlyingUnit / ONE_E1810;
54440
- const convertToShares = state.exchangeRate > 0n ? ONE_E1810 * shareUnit / state.exchangeRate : 0n;
54984
+ const convertToAssets = state.exchangeRate * underlyingUnit / ONE_E1811;
54985
+ const convertToShares = state.exchangeRate > 0n ? ONE_E1811 * shareUnit / state.exchangeRate : 0n;
54441
54986
  const displayName = composeVaultDisplayName(
54442
54987
  entry.brand,
54443
54988
  entry.brand,
@@ -54455,6 +55000,7 @@ var fetchSavingsVaults = async (chainId, multicallRetry, prices = {}, tokenList
54455
55000
  displayName,
54456
55001
  brand: entry.brand,
54457
55002
  curatorName: entry.brand,
55003
+ description: entry.description,
54458
55004
  decimals: entry.decimals,
54459
55005
  assetDecimals: underlyingDec,
54460
55006
  totalAssets: state.totalAssets.toString(),
@@ -54467,11 +55013,12 @@ var fetchSavingsVaults = async (chainId, multicallRetry, prices = {}, tokenList
54467
55013
  depositRate,
54468
55014
  // Opt-IN, not opt-out: a new bespoke reader exists precisely
54469
55015
  // because its token is not a conforming vault, so the default for
54470
- // an unlisted reader must be `false`. `erc4626-idle` is the plain
54471
- // 4626 surface plus an inventory read, so it counts; Native's wNLP
54472
- // and Re's NAV-oracle tokens revert on `asset()`/`totalAssets()`/
54473
- // `convertToAssets()` and do not.
54474
- isErc4626: entry.reader === void 0 || entry.reader === "erc4626" || entry.reader === "erc4626-idle",
55016
+ // an unlisted reader must be `false`. `erc4626-idle` and
55017
+ // `erc4626-withdraw-limit` are the plain 4626 surface plus one
55018
+ // extra read (an inventory balance / the strategy's limit view),
55019
+ // so they count; Native's wNLP and Re's NAV-oracle tokens revert
55020
+ // on `asset()`/`totalAssets()`/`convertToAssets()` and do not.
55021
+ isErc4626: entry.reader === void 0 || entry.reader === "erc4626" || entry.reader === "erc4626-idle" || entry.reader === "erc4626-withdraw-limit",
54475
55022
  isRebasing: entry.isRebasing,
54476
55023
  isMintable: entry.isMintable,
54477
55024
  mintContract: entry.mintContract?.toLowerCase() ?? addressLc,
@@ -56768,7 +57315,7 @@ var readVaultSharePrices = async (chainId, addresses, multicallRetry) => {
56768
57315
  };
56769
57316
 
56770
57317
  // src/vaults/yield/annualize.ts
56771
- var YEAR_SECONDS6 = 365 * 24 * 60 * 60;
57318
+ var YEAR_SECONDS8 = 365 * 24 * 60 * 60;
56772
57319
  var SCALE = 10n ** 18n;
56773
57320
  var appendSnapshot = (points, snap, options) => {
56774
57321
  const maxPoints = options?.maxPoints ?? 90;
@@ -56797,7 +57344,7 @@ var computeVaultApr = (points, options) => {
56797
57344
  if (pThen === 0n) return void 0;
56798
57345
  const ratioScaled = BigInt(now.p) * SCALE / pThen;
56799
57346
  const ratio = Number(ratioScaled) / 1e18;
56800
- const apr = (ratio - 1) * (YEAR_SECONDS6 / windowSeconds);
57347
+ const apr = (ratio - 1) * (YEAR_SECONDS8 / windowSeconds);
56801
57348
  return {
56802
57349
  apr,
56803
57350
  sharePriceNow: now.p,