@1delta/margin-fetcher 5.0.50 → 5.0.51

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,13 +1,13 @@
1
1
  import { parseAbi, keccak256, encodeAbiParameters, formatEther, BaseError, erc20Abi, stringToHex, isAddress, pad, encodeFunctionData, formatUnits, getAddress, decodeFunctionResult, decodeAbiParameters, concat, AbiEncodingLengthMismatchError, concatHex, toBytes, slice, hexToString, InvalidAddressError, boolToHex, integerRegex, numberToHex, bytesRegex, BytesSizeMismatchError, arrayRegex, UnsupportedPackedAbiType } from './chunk-YILYOOYB.js';
2
2
  import './chunk-BYTNVMX7.js';
3
3
  import './chunk-PR4QN5HX.js';
4
- import { Lender, isExactly, isMidnight, isTerm, isTermMax, isTeller, isListaDao, isLiquityFamily, isRiver, isInverse, isDssType, isCompoundV3Type, isFluid, isGearboxV3, isLlamaLend, isFrankencoin, isResupply, isCurvance, isFraxlend, LIQUITY_FAMILY_LENDERS, isAaveType, isCompoundV3, isMultiMarket, isSiloV2Type, isSiloV3Type, isDolomite, hasCrossMarginRisk, isEulerType, isAaveV4Type, isInit, isMorphoType, isCompoundV2Type, isVenusType, isSumerType, AAVE_V3_LENDERS, AAVE_V2_LENDERS, isMorphoBlue, isAaveV2Type, isAaveV32Type, isAaveV3Type, isUsdd, isSky, isYLDR, isLista, hasSubAccounts, isTectonicType, isKineticType, isBenqiType } from '@1delta/lender-registry';
4
+ import { Lender, isExactly, isMidnight, isTerm, isTermMax, isTeller, isListaDao, isLiquityFamily, isRiver, isInverse, isDssType, isCompoundV3Type, isFluid, isGearboxV3, isLlamaLend, isFrankencoin, isResupply, isCurvance, isTwyne, isFraxlend, LIQUITY_FAMILY_LENDERS, isAaveType, isCompoundV3, isMultiMarket, isSiloV2Type, isSiloV3Type, isDolomite, hasCrossMarginRisk, isEulerType, isAaveV4Type, isInit, isMorphoType, isCompoundV2Type, isVenusType, isSumerType, AAVE_V3_LENDERS, AAVE_V2_LENDERS, isMorphoBlue, isAaveV2Type, isAaveV32Type, isAaveV3Type, isUsdd, isSky, isYLDR, isLista, hasSubAccounts, isTectonicType, isKineticType, isBenqiType } from '@1delta/lender-registry';
5
5
  export { hasCrossMarginRisk, 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, llamaLendLendersByChain, usddLendersByChain, skyLendersByChain, frankencoinLendersByChain, resupplyLendersByChain, curvanceLendersByChain, fraxlendLendersByChain, tellerConfigByChain, tellerPoolsByChain, termMaxConfigByChain, aaveReserves, compoundV3Reserves, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, termMaxApiBaseUrl, termMaxLenderKey, inverseConfigFor, inverseChainData, llamaLendConfigFor, llamaLendChainData, llamaLendApiBaseUrl, resupplyConfigFor, fraxlendConfigFor, dssConfigFor, dssChainData, dssDebtToken, dssDebtJoin, frankencoinConfigFor, frankencoinChainData, aaveOracles, morphoTypeMarkets, resolveMidnightApiBase, resolveTermApiBase, llamaLendMarketByVault, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, curvanceConfigFor, aaveTokens, morphoTypeVaults, eulerConfigs, gearboxMarketCompressor, gearboxMarketConfigurators, gearboxV3LenderKey, midnightMarketsByChain, parseAaveV4SpokeLenderKey, fraxlendPairsFor, 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, llamaLendLendersByChain, usddLendersByChain, skyLendersByChain, frankencoinLendersByChain, resupplyLendersByChain, curvanceLendersByChain, fraxlendLendersByChain, tellerConfigByChain, tellerPoolsByChain, termMaxConfigByChain, aaveReserves, compoundV3Reserves, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, termMaxApiBaseUrl, termMaxLenderKey, inverseConfigFor, inverseChainData, llamaLendConfigFor, llamaLendChainData, llamaLendApiBaseUrl, resupplyConfigFor, fraxlendConfigFor, dssConfigFor, dssChainData, dssDebtToken, dssDebtJoin, frankencoinConfigFor, frankencoinChainData, aaveOracles, morphoTypeMarkets, resolveMidnightApiBase, resolveTermApiBase, llamaLendMarketByVault, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, curvanceConfigFor, aaveTokens, morphoTypeVaults, listaCollateralProvider, eulerConfigs, gearboxMarketCompressor, gearboxMarketConfigurators, gearboxV3LenderKey, midnightMarketsByChain, twyneConfigFor, twyneChainData, parseAaveV4SpokeLenderKey, fraxlendPairsFor, gearboxAccountCompressor, compoundV2Tokens, exactlyMarketsByChain, aaveOraclesConfig, compoundV2Oracles, compoundV2TokenArray, compoundV2OraclesConfig, compoundV3OraclesData, compoundV3BaseData, compoundV2Reserves, aaveV4Oracles } from '@1delta/data-sdk';
7
7
  import lodash from 'lodash';
8
8
  import { Chain } from '@1delta/chain-registry';
9
9
  import { multicallRetryUniversal, getEvmClient, getEvmChain, getEvmClientUniversal } from '@1delta/providers';
10
- import { LiquityTroveManagerAbi, LiquityActivePoolAbi, LiquityStabilityPoolAbi, LiquityPriceFeedAbi, LiquitySortedTrovesAbi, RiverTroveManagerAbi, RiverStabilityPoolAbi, TellerMarketRegistryAbi, TellerV2Abi, InverseMarketAbi, InverseOracleAbi, InverseDbrAbi, Erc20Abi, LlamaLendControllerAbi, LlamaLendControllerV1Abi, LlamaLendControllerV2Abi, LlamaLendVaultAbi, LlamaLendAmmAbi, MetaMorphoAbi, FluidDexResolverAbi, ExactlyPreviewerAbi, ExactlyAuditorAbi, 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, UsddCdpManagerAbi, UsddProxyRegistryAbi, CurvanceProtocolReaderAbi, CurvanceCentralRegistryAbi, TermPriceConsumerAbi, CurvanceOracleManagerAbi, TermMaxOracleAggregatorV2Abi } from '@1delta/abis';
10
+ import { LiquityTroveManagerAbi, LiquityActivePoolAbi, LiquityStabilityPoolAbi, LiquityPriceFeedAbi, LiquitySortedTrovesAbi, RiverTroveManagerAbi, RiverStabilityPoolAbi, TellerMarketRegistryAbi, TellerV2Abi, InverseMarketAbi, InverseOracleAbi, InverseDbrAbi, Erc20Abi, LlamaLendControllerAbi, LlamaLendControllerV1Abi, LlamaLendControllerV2Abi, LlamaLendVaultAbi, LlamaLendAmmAbi, MetaMorphoAbi, FluidDexResolverAbi, ExactlyPreviewerAbi, ExactlyAuditorAbi, 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, TwyneCollateralVaultAbi, GearboxCreditAccountCompressorV310Abi, TwyneVaultManagerAbi, TwyneCollateralVaultFactoryAbi, AaveV2V3Abi, TwyneATokenWrapperAbi, UsddCdpManagerAbi, UsddProxyRegistryAbi, CurvanceProtocolReaderAbi, CurvanceCentralRegistryAbi, TermPriceConsumerAbi, CurvanceOracleManagerAbi, TermMaxOracleAggregatorV2Abi } from '@1delta/abis';
11
11
  export { MorphoLensAbi } from '@1delta/abis';
12
12
  import { prepareDebitDataMulticall, prepareLenderDebitMulticall, parseDebitDataResult, parseLenderDebitResult, getPermit2ContractAddress, getLstAcceptedInputs, getCompoundV3CometAddress as getCompoundV3CometAddress$1, getMorphoAddress, getAaveCollateralTokenAddress, getSiloHalfForUnderlying, bandLtvCurve, InitMarginAddresses } from '@1delta/calldata-sdk';
13
13
  import { proxyNativeFetch } from '@1delta/proxy-fetch';
@@ -10121,11 +10121,11 @@ async function resolveListaBrokers(chainId, marketKeys, getClient = getEvmClient
10121
10121
  const moolah = morphoPools()?.LISTA_DAO?.[chainId];
10122
10122
  const out = {};
10123
10123
  if (!moolah || marketKeys.length === 0) return out;
10124
- const cache4 = BROKER_CACHE[chainId] ??= {};
10124
+ const cache6 = BROKER_CACHE[chainId] ??= {};
10125
10125
  const missing = [];
10126
10126
  for (const key3 of marketKeys) {
10127
10127
  const id = toBytes32MarketId(key3);
10128
- if (cache4[id] === void 0) missing.push(id);
10128
+ if (cache6[id] === void 0) missing.push(id);
10129
10129
  }
10130
10130
  if (missing.length > 0) {
10131
10131
  try {
@@ -10141,15 +10141,15 @@ async function resolveListaBrokers(chainId, marketKeys, getClient = getEvmClient
10141
10141
  });
10142
10142
  results.forEach((r, i) => {
10143
10143
  const id = missing[i];
10144
- const addr3 = r.status === "success" && r.result ? r.result : zeroAddress;
10145
- cache4[id] = addr3.toLowerCase();
10144
+ const addr4 = r.status === "success" && r.result ? r.result : zeroAddress;
10145
+ cache6[id] = addr4.toLowerCase();
10146
10146
  });
10147
10147
  } catch {
10148
10148
  }
10149
10149
  }
10150
10150
  for (const key3 of marketKeys) {
10151
10151
  const id = toBytes32MarketId(key3);
10152
- const broker = cache4[id];
10152
+ const broker = cache6[id];
10153
10153
  if (broker && broker !== zeroAddress) out[id] = broker;
10154
10154
  }
10155
10155
  return out;
@@ -10170,7 +10170,7 @@ async function fetchListaFixedTerms(chainId, marketKeys) {
10170
10170
  args: []
10171
10171
  }))
10172
10172
  });
10173
- const cache4 = FIXED_TERMS_CACHE[chainId] ??= {};
10173
+ const cache6 = FIXED_TERMS_CACHE[chainId] ??= {};
10174
10174
  results.forEach((r, i) => {
10175
10175
  const id = ids[i];
10176
10176
  if (r.status !== "success" || !r.result) return;
@@ -10184,7 +10184,7 @@ async function fetchListaFixedTerms(chainId, marketKeys) {
10184
10184
  };
10185
10185
  });
10186
10186
  out[id] = terms;
10187
- cache4[id] = terms;
10187
+ cache6[id] = terms;
10188
10188
  });
10189
10189
  } catch {
10190
10190
  }
@@ -10420,6 +10420,15 @@ function resolveModeConfig(configs, mode) {
10420
10420
  const base = configs?.["0"];
10421
10421
  const op = base?.openParameter;
10422
10422
  if (!base || !op) return void 0;
10423
+ if (op.identityMapping && op.dimension === "collateralFactor") {
10424
+ const value = Number(mode);
10425
+ if (Number.isFinite(value) && value > 0) {
10426
+ const inDomain = "values" in op.domain ? op.domain.values.includes(value) : value >= op.domain.min && value <= op.domain.max;
10427
+ if (inDomain || value <= 1) {
10428
+ return { ...base, collateralFactor: value, borrowCollateralFactor: value };
10429
+ }
10430
+ }
10431
+ }
10423
10432
  const factor = op.curve?.[mode];
10424
10433
  if (factor == null || op.dimension !== "collateralFactor") return base;
10425
10434
  return {
@@ -17532,13 +17541,13 @@ function findVaultInfo(normalizedAddr, vaultData) {
17532
17541
  function buildAdjacencyList(vaultData) {
17533
17542
  const adj = /* @__PURE__ */ new Map();
17534
17543
  const knownVaults = /* @__PURE__ */ new Set();
17535
- for (const addr3 of vaultData.keys()) {
17536
- const norm = addr3.toLowerCase();
17544
+ for (const addr4 of vaultData.keys()) {
17545
+ const norm = addr4.toLowerCase();
17537
17546
  knownVaults.add(norm);
17538
17547
  adj.set(norm, /* @__PURE__ */ new Set());
17539
17548
  }
17540
- for (const [addr3, info] of vaultData) {
17541
- const from = addr3.toLowerCase();
17549
+ for (const [addr4, info] of vaultData) {
17550
+ const from = addr4.toLowerCase();
17542
17551
  const activeCollaterals = getActiveCollaterals(info.collateralLTVInfo);
17543
17552
  for (const to of activeCollaterals) {
17544
17553
  if (knownVaults.has(to) && from !== to) {
@@ -17581,8 +17590,8 @@ function findConnectedComponents(adj) {
17581
17590
  function deriveGovernor(vaultAddresses, vaultData) {
17582
17591
  const counts = /* @__PURE__ */ new Map();
17583
17592
  const zeroNorm = zeroAddress;
17584
- for (const addr3 of vaultAddresses) {
17585
- const info = findVaultInfo(addr3, vaultData);
17593
+ for (const addr4 of vaultAddresses) {
17594
+ const info = findVaultInfo(addr4, vaultData);
17586
17595
  if (!info) continue;
17587
17596
  const gov = info.governorAdmin?.toLowerCase();
17588
17597
  if (!gov || gov === zeroNorm) continue;
@@ -17607,8 +17616,8 @@ function deriveClusters(vaultData, includeSingletons = false) {
17607
17616
  if (!includeSingletons && component.length < 2) continue;
17608
17617
  if (!includeSingletons) {
17609
17618
  let hasActiveEdge = false;
17610
- for (const addr3 of component) {
17611
- const neighbors = adj.get(addr3);
17619
+ for (const addr4 of component) {
17620
+ const neighbors = adj.get(addr4);
17612
17621
  if (neighbors && neighbors.size > 0) {
17613
17622
  hasActiveEdge = true;
17614
17623
  break;
@@ -17617,9 +17626,9 @@ function deriveClusters(vaultData, includeSingletons = false) {
17617
17626
  if (!hasActiveEdge) continue;
17618
17627
  }
17619
17628
  const clusterVaultData = /* @__PURE__ */ new Map();
17620
- for (const addr3 of component) {
17621
- const info = findVaultInfo(addr3, vaultData);
17622
- if (info) clusterVaultData.set(addr3, info);
17629
+ for (const addr4 of component) {
17630
+ const info = findVaultInfo(addr4, vaultData);
17631
+ if (info) clusterVaultData.set(addr4, info);
17623
17632
  }
17624
17633
  clusters.push({
17625
17634
  governor: deriveGovernor(component, vaultData),
@@ -17644,21 +17653,21 @@ function toTokenAmount(raw, decimals) {
17644
17653
  }
17645
17654
  function identifyBorrowVaults(cluster) {
17646
17655
  const borrowVaults = /* @__PURE__ */ new Set();
17647
- for (const [addr3, info] of cluster.vaultData) {
17656
+ for (const [addr4, info] of cluster.vaultData) {
17648
17657
  const hasIRM = info.interestRateModel && info.interestRateModel.toLowerCase() !== zeroAddress;
17649
17658
  const hasActiveCollateral = (info.collateralLTVInfo ?? []).some(
17650
17659
  (ltv) => ltv.borrowLTV > 0n
17651
17660
  );
17652
17661
  if (hasIRM && hasActiveCollateral) {
17653
- borrowVaults.add(addr3.toLowerCase());
17662
+ borrowVaults.add(addr4.toLowerCase());
17654
17663
  }
17655
17664
  }
17656
17665
  return borrowVaults;
17657
17666
  }
17658
17667
  function buildReverseLTVIndex(cluster) {
17659
17668
  const index = /* @__PURE__ */ new Map();
17660
- for (const [addr3, info] of cluster.vaultData) {
17661
- const borrowVault = addr3.toLowerCase();
17669
+ for (const [addr4, info] of cluster.vaultData) {
17670
+ const borrowVault = addr4.toLowerCase();
17662
17671
  for (const ltv of info.collateralLTVInfo ?? []) {
17663
17672
  if (ltv.borrowLTV <= 0n) continue;
17664
17673
  const collateral = ltv.collateral.toLowerCase();
@@ -17709,8 +17718,8 @@ function buildTokenConfig(vaultAddr, reverseLTV, borrowVaults, vaultData) {
17709
17718
  }
17710
17719
  function buildEModes(borrowVaults, cluster) {
17711
17720
  const eModes = {};
17712
- for (const addr3 of borrowVaults) {
17713
- const info = findInfo(addr3, cluster.vaultData);
17721
+ for (const addr4 of borrowVaults) {
17722
+ const info = findInfo(addr4, cluster.vaultData);
17714
17723
  if (!info) continue;
17715
17724
  const activeLTVs = info.collateralLTVInfo.filter((l) => l.borrowLTV > 0n);
17716
17725
  const avgBorrowLTV = activeLTVs.length > 0 ? activeLTVs.reduce((sum3, l) => sum3 + ltvToNumber(l.borrowLTV), 0) / activeLTVs.length : 0;
@@ -17718,8 +17727,8 @@ function buildEModes(borrowVaults, cluster) {
17718
17727
  (sum3, l) => sum3 + ltvToNumber(l.liquidationLTV),
17719
17728
  0
17720
17729
  ) / activeLTVs.length : 0;
17721
- eModes[addr3] = {
17722
- category: addr3,
17730
+ eModes[addr4] = {
17731
+ category: addr4,
17723
17732
  label: `${info.assetSymbol} Borrow (${info.vaultSymbol})`,
17724
17733
  borrowCollateralFactor: avgBorrowLTV,
17725
17734
  collateralFactor: avgLiqLTV,
@@ -17752,11 +17761,11 @@ function buildMetadata(info) {
17752
17761
  }
17753
17762
  function buildTokenEntry(info, config, collateralActive, borrowVaults, opts) {
17754
17763
  if (!info.asset) return void 0;
17755
- const addr3 = info.asset.toLowerCase();
17756
- const tokenMeta = opts.tokenList?.[addr3];
17764
+ const addr4 = info.asset.toLowerCase();
17765
+ const tokenMeta = opts.tokenList?.[addr4];
17757
17766
  const asset = {
17758
17767
  chainId: opts.chainId,
17759
- address: addr3,
17768
+ address: addr4,
17760
17769
  name: tokenMeta?.name ?? info.assetName,
17761
17770
  symbol: tokenMeta?.symbol ?? info.assetSymbol,
17762
17771
  decimals: tokenMeta?.decimals ?? Number(info.assetDecimals)
@@ -17836,9 +17845,9 @@ function buildTokenEntry(info, config, collateralActive, borrowVaults, opts) {
17836
17845
  params: { metadata: buildMetadata(info) }
17837
17846
  };
17838
17847
  }
17839
- function findInfo(addr3, vaultData) {
17848
+ function findInfo(addr4, vaultData) {
17840
17849
  for (const [key3, value] of vaultData) {
17841
- if (key3.toLowerCase() === addr3) return value;
17850
+ if (key3.toLowerCase() === addr4) return value;
17842
17851
  }
17843
17852
  return void 0;
17844
17853
  }
@@ -17853,8 +17862,8 @@ function normalizeCluster(cluster, opts) {
17853
17862
  }
17854
17863
  const eModes = buildEModes(borrowVaults, cluster);
17855
17864
  const data = {};
17856
- for (const [addr3, info] of cluster.vaultData) {
17857
- const norm = addr3.toLowerCase();
17865
+ for (const [addr4, info] of cluster.vaultData) {
17866
+ const norm = addr4.toLowerCase();
17858
17867
  const config = buildTokenConfig(
17859
17868
  norm,
17860
17869
  reverseLTV,
@@ -17999,8 +18008,8 @@ var getEulerV2ReservesDataConverter = (lender, chainId, prices, additionalYields
17999
18008
  var BASE_CALLS_PER_RESERVE = 5;
18000
18009
  var CALLS_PER_SPOKE_TAIL = 1;
18001
18010
  var MAX_HUB_ASSETS = 25;
18002
- function isValidAddress(addr3) {
18003
- return !!addr3 && addr3 !== "0x" && addr3.length > 2;
18011
+ function isValidAddress(addr4) {
18012
+ return !!addr4 && addr4 !== "0x" && addr4.length > 2;
18004
18013
  }
18005
18014
  function getDynamicConfigCount(spokeEntry) {
18006
18015
  const max = spokeEntry?.dynamicConfigKeyMax ?? 0;
@@ -18344,8 +18353,8 @@ function normalizeAaveV4(spokeDataList, chainId, spokeLenderKeyArg, prices, addi
18344
18353
  }
18345
18354
 
18346
18355
  // src/lending/public-data/aave-v4-type/publicCallParse.ts
18347
- function isValidAddress2(addr3) {
18348
- return !!addr3 && addr3 !== "0x" && addr3.length > 2;
18356
+ function isValidAddress2(addr4) {
18357
+ return !!addr4 && addr4 !== "0x" && addr4.length > 2;
18349
18358
  }
18350
18359
  var getAaveV4ReservesDataConverter = (lender, chainId, prices, additionalYields, tokenList = {}) => {
18351
18360
  const expectedCalls = getAaveV4ExpectedCallCount(chainId, lender);
@@ -19246,7 +19255,7 @@ var getCachedFluidDexState = (chainId) => cache2[chainId]?.data;
19246
19255
 
19247
19256
  // src/lending/public-data/fluid/publicCallParse.ts
19248
19257
  var FLUID_EEE_LOWER = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
19249
- var normalizeUnderlying = (addr3) => addr3 === FLUID_EEE_LOWER ? zeroAddress : addr3;
19258
+ var normalizeUnderlying = (addr4) => addr4 === FLUID_EEE_LOWER ? zeroAddress : addr4;
19250
19259
  var FLUID_RATE_SCALE = 100;
19251
19260
  var scaleFluidRate = (raw) => {
19252
19261
  if (raw === void 0 || raw === null) return 0;
@@ -19930,9 +19939,9 @@ var getGearboxV3PublicDataConverter = (_lender, chainId, prices, additionalYield
19930
19939
  const underlyingPrice = prices[underlyingPriceKey] ?? 0;
19931
19940
  const debtByCm = {};
19932
19941
  for (const dp of pool.creditManagerDebtParams ?? []) {
19933
- const addr3 = (dp?.creditManager ?? "").toString().toLowerCase();
19934
- if (!addr3) continue;
19935
- debtByCm[addr3] = {
19942
+ const addr4 = (dp?.creditManager ?? "").toString().toLowerCase();
19943
+ if (!addr4) continue;
19944
+ debtByCm[addr4] = {
19936
19945
  borrowed: BigInt(dp.borrowed ?? 0),
19937
19946
  limit: BigInt(dp.limit ?? 0),
19938
19947
  available: BigInt(dp.available ?? 0)
@@ -20720,9 +20729,9 @@ function midnightLenderKey(marketId) {
20720
20729
  return "MORPHO_MIDNIGHT_" + marketId.slice(2).toUpperCase();
20721
20730
  }
20722
20731
  function currencyFor(address, decimals, tokens) {
20723
- const lower3 = address.toLowerCase();
20724
- return tokens[lower3] ?? {
20725
- address: lower3,
20732
+ const lower4 = address.toLowerCase();
20733
+ return tokens[lower4] ?? {
20734
+ address: lower4,
20726
20735
  symbol: "",
20727
20736
  name: "",
20728
20737
  decimals
@@ -21339,8 +21348,8 @@ function toFixedTermAuction(auction, now, matured = false) {
21339
21348
  };
21340
21349
  }
21341
21350
  function currencyFor2(address, decimals, tokens) {
21342
- const lower3 = address.toLowerCase();
21343
- return tokens[lower3] ?? { address: lower3, symbol: "", name: "", decimals };
21351
+ const lower4 = address.toLowerCase();
21352
+ return tokens[lower4] ?? { address: lower4, symbol: "", name: "", decimals };
21344
21353
  }
21345
21354
  function convertTermMarketsToResponse(raw, chainId, prices = {}, _additionalYields = {
21346
21355
  intrinsicYields: {},
@@ -21582,8 +21591,8 @@ function toHuman(raw, decimals) {
21582
21591
  return Number(raw) / 10 ** decimals;
21583
21592
  }
21584
21593
  function currencyFor3(address, decimals, symbol, tokens) {
21585
- const lower3 = address.toLowerCase();
21586
- return tokens[lower3] ?? { address: lower3, symbol, name: symbol, decimals };
21594
+ const lower4 = address.toLowerCase();
21595
+ return tokens[lower4] ?? { address: lower4, symbol, name: symbol, decimals };
21587
21596
  }
21588
21597
  function convertExactlyMarketsToResponse(raw, chainId, prices = {}, _additionalYields = {
21589
21598
  intrinsicYields: {},
@@ -21825,8 +21834,8 @@ function toHuman2(raw, decimals) {
21825
21834
  return Number(raw) / 10 ** decimals;
21826
21835
  }
21827
21836
  function currencyFor4(address, decimals, symbol, tokens) {
21828
- const lower3 = address.toLowerCase();
21829
- return tokens[lower3] ?? { address: lower3, symbol, name: symbol, decimals };
21837
+ const lower4 = address.toLowerCase();
21838
+ return tokens[lower4] ?? { address: lower4, symbol, name: symbol, decimals };
21830
21839
  }
21831
21840
  function convertLiquityMarketsToResponse(raw, chainId, prices = {}, _additionalYields = {
21832
21841
  intrinsicYields: {},
@@ -22126,8 +22135,8 @@ function toHuman3(raw, decimals) {
22126
22135
  return Number(raw) / 10 ** decimals;
22127
22136
  }
22128
22137
  function currencyFor5(address, decimals, symbol, tokens) {
22129
- const lower3 = address.toLowerCase();
22130
- return tokens[lower3] ?? { address: lower3, symbol, name: symbol, decimals };
22138
+ const lower4 = address.toLowerCase();
22139
+ return tokens[lower4] ?? { address: lower4, symbol, name: symbol, decimals };
22131
22140
  }
22132
22141
  function convertRiverMarketsToResponse(raw, chainId, prices = {}, _additionalYields = {
22133
22142
  intrinsicYields: {},
@@ -22356,7 +22365,7 @@ async function fetchTellerMarkets(chainId) {
22356
22365
  } catch {
22357
22366
  return { chainId, pools: [] };
22358
22367
  }
22359
- const big18 = (i) => {
22368
+ const big20 = (i) => {
22360
22369
  const r = results[i];
22361
22370
  if (typeof r === "bigint") return r;
22362
22371
  if (typeof r === "number") return BigInt(r);
@@ -22369,21 +22378,21 @@ async function fetchTellerMarkets(chainId) {
22369
22378
  }
22370
22379
  return null;
22371
22380
  };
22372
- const num16 = (i) => {
22373
- const b = big18(i);
22381
+ const num18 = (i) => {
22382
+ const b = big20(i);
22374
22383
  return b === null ? null : Number(b);
22375
22384
  };
22376
22385
  const pool0 = pools.map((config, i) => {
22377
22386
  const base = i * READS_PER_POOL;
22378
22387
  return {
22379
22388
  config,
22380
- available: big18(base),
22381
- committed: big18(base + 1),
22382
- minRateBps: num16(base + 2),
22383
- collateralPerPrincipal: big18(base + 3),
22384
- maxLoanDuration: num16(base + 4),
22385
- marketId: big18(base + 5),
22386
- totalAssets: big18(base + 6)
22389
+ available: big20(base),
22390
+ committed: big20(base + 1),
22391
+ minRateBps: num18(base + 2),
22392
+ collateralPerPrincipal: big20(base + 3),
22393
+ maxLoanDuration: num18(base + 4),
22394
+ marketId: big20(base + 5),
22395
+ totalAssets: big20(base + 6)
22387
22396
  };
22388
22397
  });
22389
22398
  const attByMarket = /* @__PURE__ */ new Map();
@@ -22496,6 +22505,9 @@ function parseFeeConfig(raw) {
22496
22505
  mintGtFeeRef: toBig4(raw.mintGtFeeRef)
22497
22506
  };
22498
22507
  }
22508
+ function isTermMaxSpecSeriesSymbol(symbol) {
22509
+ return /@\d{1,2}[A-Z]{3}\d{4}-\d+(\.\d+)?[CP]$/.test(String(symbol ?? ""));
22510
+ }
22499
22511
  function toUnix(iso) {
22500
22512
  if (typeof iso === "number") return Math.trunc(iso);
22501
22513
  const t = Date.parse(String(iso ?? ""));
@@ -22508,6 +22520,7 @@ function parseMarket(raw, assetDecimals) {
22508
22520
  const collateral = lower(c.collateralAddr);
22509
22521
  return {
22510
22522
  market: lower(c.marketAddr),
22523
+ routerAddr: c.routerAddr ? lower(c.routerAddr) : void 0,
22511
22524
  ft: lower(c.ftAddr),
22512
22525
  xt: lower(c.xtAddr),
22513
22526
  gt: lower(c.gtAddr),
@@ -22561,6 +22574,7 @@ function parseOrder(raw) {
22561
22574
  borrowCapacityAmount: toNum2(meta.borrowCapacityAmount)
22562
22575
  };
22563
22576
  }
22577
+ var TERMMAX_MIN_ADVERTISED_CAPACITY_USD = 10;
22564
22578
  function reduceTop2(orders) {
22565
22579
  let bestLendApr;
22566
22580
  let bestBorrowApr;
@@ -22573,12 +22587,12 @@ function reduceTop2(orders) {
22573
22587
  borrowDepthUsd += o.borrowCapacityUsd;
22574
22588
  lendDepthAmount += o.lendCapacityAmount;
22575
22589
  borrowDepthAmount += o.borrowCapacityAmount;
22576
- if (o.takerLendApr != null && o.takerLendApr > 0 && o.lendCapacityUsd > 0) {
22590
+ if (o.takerLendApr != null && o.takerLendApr > 0 && o.lendCapacityUsd >= TERMMAX_MIN_ADVERTISED_CAPACITY_USD) {
22577
22591
  if (bestLendApr === void 0 || o.takerLendApr > bestLendApr) {
22578
22592
  bestLendApr = o.takerLendApr;
22579
22593
  }
22580
22594
  }
22581
- if (o.takerBorrowApr != null && o.takerBorrowApr > 0 && o.borrowCapacityUsd > 0) {
22595
+ if (o.takerBorrowApr != null && o.takerBorrowApr > 0 && o.borrowCapacityUsd >= TERMMAX_MIN_ADVERTISED_CAPACITY_USD) {
22582
22596
  if (bestBorrowApr === void 0 || o.takerBorrowApr < bestBorrowApr) {
22583
22597
  bestBorrowApr = o.takerBorrowApr;
22584
22598
  }
@@ -22617,15 +22631,20 @@ var TermMaxApiSource = class {
22617
22631
  const data = json?.data ?? json;
22618
22632
  if (!data) return null;
22619
22633
  const assetDecimals = /* @__PURE__ */ new Map();
22634
+ const assetSymbols = /* @__PURE__ */ new Map();
22620
22635
  for (const a of Array.isArray(data.assetConfigs) ? data.assetConfigs : []) {
22621
- const addr3 = lower(a?.contractAddress ?? a?.assetAddress);
22636
+ const addr4 = lower(a?.contractAddress ?? a?.assetAddress);
22637
+ if (!addr4) continue;
22622
22638
  const dec2 = Number(a?.decimals ?? a?.assetDecimals);
22623
- if (addr3 && Number.isFinite(dec2)) assetDecimals.set(addr3, dec2);
22639
+ if (Number.isFinite(dec2)) assetDecimals.set(addr4, dec2);
22640
+ if (a?.symbol) assetSymbols.set(addr4, String(a.symbol));
22624
22641
  }
22625
22642
  const markets = [];
22626
22643
  for (const m of Array.isArray(data.markets) ? data.markets : []) {
22627
22644
  const parsed = parseMarket(m, assetDecimals);
22628
- if (parsed && parsed.isEnabled && !parsed.isMatured) markets.push(parsed);
22645
+ if (!parsed || !parsed.isEnabled || parsed.isMatured) continue;
22646
+ if (isTermMaxSpecSeriesSymbol(assetSymbols.get(parsed.ft))) continue;
22647
+ markets.push(parsed);
22629
22648
  }
22630
22649
  if (markets.length === 0) return [];
22631
22650
  const ordersByMarket = /* @__PURE__ */ new Map();
@@ -22722,8 +22741,8 @@ function tellerPoolFromLenderKey(lender) {
22722
22741
  return body.length === 40 ? "0x" + body.toLowerCase() : void 0;
22723
22742
  }
22724
22743
  function currencyFor6(address, decimals, symbol, tokens) {
22725
- const lower3 = address.toLowerCase();
22726
- return tokens[lower3] ?? { address: lower3, symbol, name: symbol, decimals };
22744
+ const lower4 = address.toLowerCase();
22745
+ return tokens[lower4] ?? { address: lower4, symbol, name: symbol, decimals };
22727
22746
  }
22728
22747
  function fmtDuration2(sec) {
22729
22748
  if (sec == null || sec <= 0) return "a short window";
@@ -22732,9 +22751,9 @@ function fmtDuration2(sec) {
22732
22751
  return `${Math.round(sec / 86400)} day${sec < 172800 ? "" : "s"}`;
22733
22752
  }
22734
22753
  function priceFor(address, chainId, tokens, prices) {
22735
- const lower3 = address.toLowerCase();
22736
- const token = tokens[lower3];
22737
- const key3 = toOracleKey(token?.assetGroup) || toGenericPriceKey(lower3, chainId);
22754
+ const lower4 = address.toLowerCase();
22755
+ const token = tokens[lower4];
22756
+ const key3 = toOracleKey(token?.assetGroup) || toGenericPriceKey(lower4, chainId);
22738
22757
  return prices[key3] ?? 0;
22739
22758
  }
22740
22759
  function convertTellerMarketsToResponse(raw, chainId, prices = {}, _additionalYields = {
@@ -23068,9 +23087,9 @@ function termMaxLtvToWad(v) {
23068
23087
  // src/lending/public-data/termmax/convertPublic.ts
23069
23088
  var nowSec4 = () => Math.floor(Date.now() / 1e3);
23070
23089
  function currencyFor7(address, decimals, tokens) {
23071
- const lower3 = address.toLowerCase();
23072
- return tokens[lower3] ?? {
23073
- address: lower3,
23090
+ const lower4 = address.toLowerCase();
23091
+ return tokens[lower4] ?? {
23092
+ address: lower4,
23074
23093
  symbol: "",
23075
23094
  name: "",
23076
23095
  decimals
@@ -23344,20 +23363,20 @@ async function fetchInverseMarkets(lender, chainId) {
23344
23363
  if (Object.keys(byAddr).length > 0) {
23345
23364
  const rows = markets.map((market) => {
23346
23365
  const m = byAddr[market.address.toLowerCase()];
23347
- const num16 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
23366
+ const num18 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
23348
23367
  return {
23349
23368
  market,
23350
- totalDebt: num16(m?.totalDebt),
23351
- dolaLiquidity: num16(m?.dolaLiquidity),
23352
- leftToBorrow: num16(m?.leftToBorrow),
23353
- price: num16(m?.price),
23369
+ totalDebt: num18(m?.totalDebt),
23370
+ dolaLiquidity: num18(m?.dolaLiquidity),
23371
+ leftToBorrow: num18(m?.leftToBorrow),
23372
+ price: num18(m?.price),
23354
23373
  borrowPaused: typeof m?.borrowPaused === "boolean" ? m.borrowPaused : null,
23355
- dailyBorrows: num16(m?.dailyBorrows),
23374
+ dailyBorrows: num18(m?.dailyBorrows),
23356
23375
  // The API serves it as a DECIMAL (`replenishmentIncentive: 0.1`),
23357
23376
  // unlike the on-chain bps — normalize here, and fall back to the
23358
23377
  // curated metadata value when the field is missing.
23359
23378
  replenishmentIncentiveBps: (() => {
23360
- const dec2 = num16(m?.replenishmentIncentive);
23379
+ const dec2 = num18(m?.replenishmentIncentive);
23361
23380
  if (dec2 !== null) return Math.round(dec2 * 1e4);
23362
23381
  const meta = Number(market.replenishmentIncentiveBps);
23363
23382
  return Number.isFinite(meta) ? meta : null;
@@ -23833,10 +23852,10 @@ async function fetchResupplyMarkets(lender, chainId) {
23833
23852
  } catch {
23834
23853
  dec2 = [];
23835
23854
  }
23836
- const addr3 = (v) => typeof v === "string" && /^0x[0-9a-fA-F]{40}$/.test(v) && !/^0x0+$/.test(v) ? v : void 0;
23855
+ const addr4 = (v) => typeof v === "string" && /^0x[0-9a-fA-F]{40}$/.test(v) && !/^0x0+$/.test(v) ? v : void 0;
23837
23856
  const wrapped = pending.map((_3, i) => {
23838
- const curve = addr3(dec2[i * 4 + 2]);
23839
- const frax = addr3(dec2[i * 4 + 3]);
23857
+ const curve = addr4(dec2[i * 4 + 2]);
23858
+ const frax = addr4(dec2[i * 4 + 3]);
23840
23859
  return {
23841
23860
  token: curve ?? frax,
23842
23861
  family: curve ? "curvelend" : frax ? "fraxlend" : void 0
@@ -23985,7 +24004,7 @@ async function fetchResupplyMarkets(lender, chainId) {
23985
24004
  return { lender, config, pairs, rsup };
23986
24005
  }
23987
24006
  async function readRewardContext(chainId, registry, utilities) {
23988
- const addr3 = (v) => typeof v === "string" && v.startsWith("0x") && !/^0x0+$/.test(v) ? v : void 0;
24007
+ const addr4 = (v) => typeof v === "string" && v.startsWith("0x") && !/^0x0+$/.test(v) ? v : void 0;
23989
24008
  try {
23990
24009
  const first = await multicallRetryUniversal({
23991
24010
  chain: chainId,
@@ -24001,9 +24020,9 @@ async function readRewardContext(chainId, registry, utilities) {
24001
24020
  ],
24002
24021
  allowFailure: true
24003
24022
  });
24004
- const rewardHandler = addr3(first[0]);
24005
- const govToken = addr3(first[1]);
24006
- const convexPoolUtil = utilities ? addr3(first[2]) : void 0;
24023
+ const rewardHandler = addr4(first[0]);
24024
+ const govToken = addr4(first[1]);
24025
+ const convexPoolUtil = utilities ? addr4(first[2]) : void 0;
24007
24026
  if (!rewardHandler || !govToken) return { convexPoolUtil };
24008
24027
  const [emissions] = await multicallRetryUniversal({
24009
24028
  chain: chainId,
@@ -24011,7 +24030,7 @@ async function readRewardContext(chainId, registry, utilities) {
24011
24030
  abi: ResupplyRewardHandlerAbi,
24012
24031
  allowFailure: true
24013
24032
  });
24014
- const pairEmissions = addr3(emissions);
24033
+ const pairEmissions = addr4(emissions);
24015
24034
  if (!pairEmissions) return { convexPoolUtil };
24016
24035
  const stream = await multicallRetryUniversal({
24017
24036
  chain: chainId,
@@ -24466,8 +24485,234 @@ function allowlist(config) {
24466
24485
  }
24467
24486
  return new Set(config.marketAllowlist.map((m) => m.toLowerCase()));
24468
24487
  }
24469
- var PAIR_READS = 15;
24488
+ var AAVE_EMODE_ABI = [
24489
+ {
24490
+ type: "function",
24491
+ name: "getEModeCategoryCollateralConfig",
24492
+ stateMutability: "view",
24493
+ inputs: [{ type: "uint8" }],
24494
+ outputs: [
24495
+ {
24496
+ type: "tuple",
24497
+ components: [
24498
+ { name: "ltv", type: "uint16" },
24499
+ { name: "liquidationThreshold", type: "uint16" },
24500
+ { name: "liquidationBonus", type: "uint16" }
24501
+ ]
24502
+ }
24503
+ ]
24504
+ }
24505
+ ];
24506
+ var EVK_ABI = [
24507
+ { type: "function", name: "totalAssets", stateMutability: "view", inputs: [], outputs: [{ type: "uint256" }] },
24508
+ { type: "function", name: "totalBorrows", stateMutability: "view", inputs: [], outputs: [{ type: "uint256" }] },
24509
+ { type: "function", name: "cash", stateMutability: "view", inputs: [], outputs: [{ type: "uint256" }] },
24510
+ { type: "function", name: "interestRate", stateMutability: "view", inputs: [], outputs: [{ type: "uint256" }] },
24511
+ { type: "function", name: "interestFee", stateMutability: "view", inputs: [], outputs: [{ type: "uint16" }] },
24512
+ { type: "function", name: "decimals", stateMutability: "view", inputs: [], outputs: [{ type: "uint8" }] },
24513
+ { type: "function", name: "symbol", stateMutability: "view", inputs: [], outputs: [{ type: "string" }] },
24514
+ { type: "function", name: "interestRateModel", stateMutability: "view", inputs: [], outputs: [{ type: "address" }] },
24515
+ {
24516
+ type: "function",
24517
+ name: "maxDeposit",
24518
+ stateMutability: "view",
24519
+ inputs: [{ type: "address" }],
24520
+ outputs: [{ type: "uint256" }]
24521
+ },
24522
+ {
24523
+ type: "function",
24524
+ name: "LTVLiquidation",
24525
+ stateMutability: "view",
24526
+ inputs: [{ type: "address" }],
24527
+ outputs: [{ type: "uint16" }]
24528
+ }
24529
+ ];
24530
+ var ERC20_ABI = [
24531
+ { type: "function", name: "decimals", stateMutability: "view", inputs: [], outputs: [{ type: "uint8" }] },
24532
+ {
24533
+ type: "function",
24534
+ name: "balanceOf",
24535
+ stateMutability: "view",
24536
+ inputs: [{ type: "address" }],
24537
+ outputs: [{ type: "uint256" }]
24538
+ }
24539
+ ];
24540
+ var RAY4 = 1e27;
24541
+ var ok = (v) => v !== void 0 && v !== null && v !== "0x";
24470
24542
  var big3 = (v) => {
24543
+ if (typeof v === "bigint") return v;
24544
+ if (typeof v === "number") return BigInt(v);
24545
+ if (typeof v === "string" && /^(0x[0-9a-fA-F]+|\d+)$/.test(v)) return BigInt(v);
24546
+ return void 0;
24547
+ };
24548
+ async function fetchTwyneMarkets(lender, chainId) {
24549
+ const config = twyneConfigFor(lender, chainId);
24550
+ const markets = twyneChainData(lender, chainId)?.markets ?? [];
24551
+ if (!config?.collateralVaultFactory || markets.length === 0) return void 0;
24552
+ const nowSec9 = Math.floor(Date.now() / 1e3);
24553
+ const perMarket = markets.flatMap((m) => [
24554
+ { address: m.intermediateVault, name: "totalAssets", args: [] },
24555
+ { address: m.intermediateVault, name: "totalBorrows", args: [] },
24556
+ { address: m.intermediateVault, name: "cash", args: [] },
24557
+ { address: m.intermediateVault, name: "interestRate", args: [] },
24558
+ { address: m.intermediateVault, name: "decimals", args: [] },
24559
+ { address: m.intermediateVault, name: "symbol", args: [] },
24560
+ { address: m.intermediateVault, name: "interestRateModel", args: [] },
24561
+ // Probed with a neutral address: EVK `maxDeposit` is cap headroom, not a
24562
+ // permission, and there is no per-account gate on these vaults.
24563
+ { address: m.intermediateVault, name: "maxDeposit", args: ["0x000000000000000000000000000000000000dEaD"] }
24564
+ ]);
24565
+ const creditReads = await multicallRetryUniversal({
24566
+ chain: chainId,
24567
+ calls: perMarket,
24568
+ abi: EVK_ABI,
24569
+ allowFailure: true
24570
+ });
24571
+ const bounds = await multicallRetryUniversal({
24572
+ chain: chainId,
24573
+ calls: markets.flatMap((m) => [
24574
+ { address: config.vaultManager, name: "maxTwyneLTVs", args: [m.intermediateVault] },
24575
+ { address: config.vaultManager, name: "externalLiqBuffers", args: [m.intermediateVault] }
24576
+ ]),
24577
+ abi: TwyneVaultManagerAbi,
24578
+ allowFailure: true
24579
+ });
24580
+ const [pausedRaw] = await multicallRetryUniversal({
24581
+ chain: chainId,
24582
+ calls: [{ address: config.collateralVaultFactory, name: "paused", args: [] }],
24583
+ abi: TwyneCollateralVaultFactoryAbi,
24584
+ allowFailure: true
24585
+ });
24586
+ const paused = Boolean(pausedRaw);
24587
+ const aaveMarkets = markets.filter((m) => m.vaultType === "AAVE_V3");
24588
+ const eulerMarkets = markets.filter((m) => m.vaultType === "EULER_V2");
24589
+ const aaveEmode = aaveMarkets.length ? await multicallRetryUniversal({
24590
+ chain: chainId,
24591
+ calls: aaveMarkets.map((m) => ({
24592
+ address: m.targetVault,
24593
+ name: "getEModeCategoryCollateralConfig",
24594
+ args: [m.categoryId ?? 0]
24595
+ })),
24596
+ abi: AAVE_EMODE_ABI,
24597
+ allowFailure: true
24598
+ }) : [];
24599
+ const aaveReserves6 = aaveMarkets.length ? await multicallRetryUniversal({
24600
+ chain: chainId,
24601
+ calls: aaveMarkets.flatMap((m) => [
24602
+ { address: m.targetVault, name: "getReserveData", args: [m.underlyingAsset] },
24603
+ { address: m.targetVault, name: "getReserveData", args: [m.targetAsset] }
24604
+ ]),
24605
+ abi: AaveV2V3Abi,
24606
+ allowFailure: true
24607
+ }) : [];
24608
+ const eulerReads = eulerMarkets.length ? await multicallRetryUniversal({
24609
+ chain: chainId,
24610
+ calls: eulerMarkets.flatMap((m) => [
24611
+ { address: m.targetVault, name: "LTVLiquidation", args: [m.collateralAsset] },
24612
+ { address: m.targetVault, name: "interestRate", args: [] },
24613
+ { address: m.targetVault, name: "cash", args: [] },
24614
+ // The collateral is an eToken, i.e. ANOTHER EVault — its supply rate
24615
+ // is what the collateral earns underneath, and it lives on a different
24616
+ // contract than the debt vault.
24617
+ { address: m.collateralAsset, name: "interestRate", args: [] },
24618
+ { address: m.collateralAsset, name: "totalAssets", args: [] },
24619
+ { address: m.collateralAsset, name: "totalBorrows", args: [] },
24620
+ { address: m.collateralAsset, name: "interestFee", args: [] }
24621
+ ]),
24622
+ abi: EVK_ABI,
24623
+ allowFailure: true
24624
+ }) : [];
24625
+ const scaleReads = await multicallRetryUniversal({
24626
+ chain: chainId,
24627
+ calls: markets.flatMap((m) => [
24628
+ { address: m.underlyingAsset, name: "decimals", args: [] },
24629
+ { address: m.targetAsset, name: "decimals", args: [] },
24630
+ // Aave only: what the pool can actually lend of the target asset.
24631
+ { address: m.targetAsset, name: "balanceOf", args: [m.aToken ?? m.targetVault] }
24632
+ ]),
24633
+ abi: ERC20_ABI,
24634
+ allowFailure: true
24635
+ });
24636
+ const wrapperReads = await multicallRetryUniversal({
24637
+ chain: chainId,
24638
+ calls: markets.map((m) => ({
24639
+ address: m.collateralAsset,
24640
+ name: "convertToAssets",
24641
+ args: [10n ** 18n]
24642
+ })),
24643
+ abi: TwyneATokenWrapperAbi,
24644
+ allowFailure: true
24645
+ });
24646
+ const out = [];
24647
+ markets.forEach((m, i) => {
24648
+ const c = i * 8;
24649
+ const creditTotalAssets = big3(creditReads[c]);
24650
+ const creditTotalBorrows = big3(creditReads[c + 1]);
24651
+ const creditCash = big3(creditReads[c + 2]);
24652
+ const creditRateSpy = big3(creditReads[c + 3]);
24653
+ if (creditTotalAssets === void 0 || creditCash === void 0 || creditRateSpy === void 0) return;
24654
+ const aaveIdx = aaveMarkets.indexOf(m);
24655
+ const eulerIdx = eulerMarkets.indexOf(m);
24656
+ let externalLiqLtv;
24657
+ let externalSupplyRate;
24658
+ let externalBorrowRate;
24659
+ let externalBorrowLiquidity;
24660
+ if (aaveIdx >= 0) {
24661
+ const emode = aaveEmode[aaveIdx];
24662
+ const collReserve = aaveReserves6[aaveIdx * 2];
24663
+ const debtReserve = aaveReserves6[aaveIdx * 2 + 1];
24664
+ if (ok(emode) && emode?.liquidationThreshold) externalLiqLtv = BigInt(emode.liquidationThreshold);
24665
+ if (ok(collReserve) && collReserve?.currentLiquidityRate !== void 0)
24666
+ externalSupplyRate = Number(collReserve.currentLiquidityRate) / RAY4;
24667
+ if (ok(debtReserve) && debtReserve?.currentVariableBorrowRate !== void 0)
24668
+ externalBorrowRate = Number(debtReserve.currentVariableBorrowRate) / RAY4;
24669
+ } else if (eulerIdx >= 0) {
24670
+ const e = eulerIdx * 7;
24671
+ externalLiqLtv = big3(eulerReads[e]);
24672
+ const spy = big3(eulerReads[e + 1]);
24673
+ if (spy !== void 0) externalBorrowRate = Number(spy) / RAY4 * 31536e3;
24674
+ externalBorrowLiquidity = big3(eulerReads[e + 2]);
24675
+ const collSpy = big3(eulerReads[e + 3]);
24676
+ const collAssets = big3(eulerReads[e + 4]);
24677
+ const collBorrows = big3(eulerReads[e + 5]);
24678
+ const collFeeBps = big3(eulerReads[e + 6]) ?? 0n;
24679
+ if (collSpy !== void 0 && collAssets && collAssets > 0n) {
24680
+ const util = Number(collBorrows ?? 0n) / Number(collAssets);
24681
+ externalSupplyRate = Number(collSpy) / RAY4 * 31536e3 * util * (1 - Number(collFeeBps) / 1e4);
24682
+ }
24683
+ }
24684
+ const s = i * 3;
24685
+ if (externalBorrowLiquidity === void 0) externalBorrowLiquidity = big3(scaleReads[s + 2]);
24686
+ out.push({
24687
+ market: m,
24688
+ creditTotalAssets,
24689
+ creditTotalBorrows: creditTotalBorrows ?? 0n,
24690
+ creditCash,
24691
+ creditRateSpy,
24692
+ creditDepositCapacity: big3(creditReads[c + 7]),
24693
+ creditDecimals: Number(creditReads[c + 4] ?? 18),
24694
+ creditSymbol: typeof creditReads[c + 5] === "string" ? creditReads[c + 5] : void 0,
24695
+ creditIrm: typeof creditReads[c + 6] === "string" ? creditReads[c + 6].toLowerCase() : m.creditIrm,
24696
+ externalLiqLtv,
24697
+ maxTwyneLiqLtv: big3(bounds[i * 2]) ?? (m.maxTwyneLiqLTV !== void 0 ? BigInt(m.maxTwyneLiqLTV) : void 0),
24698
+ externalLiqBuffer: big3(bounds[i * 2 + 1]) ?? (m.externalLiqBuffer !== void 0 ? BigInt(m.externalLiqBuffer) : void 0),
24699
+ externalSupplyRate,
24700
+ externalBorrowRate,
24701
+ externalBorrowLiquidity,
24702
+ collateralDecimals: Number(scaleReads[s] ?? 18),
24703
+ targetDecimals: Number(scaleReads[s + 1] ?? 18),
24704
+ collateralToUnderlying: big3(wrapperReads[i]),
24705
+ // Computed HERE, never read from the roster: a stored flag goes stale,
24706
+ // and two of the three live PT markets have already matured.
24707
+ collateralMatured: !!m.collateralMaturity && m.collateralMaturity <= nowSec9,
24708
+ paused
24709
+ });
24710
+ });
24711
+ if (out.length === 0) return void 0;
24712
+ return { lender, chainId, config, markets: out };
24713
+ }
24714
+ var PAIR_READS = 15;
24715
+ var big4 = (v) => {
24471
24716
  if (typeof v === "bigint") return v;
24472
24717
  if (typeof v === "number") return BigInt(v);
24473
24718
  if (typeof v === "string" && v !== "0x") {
@@ -24574,41 +24819,41 @@ async function fetchFraxlendPairs(lender, chainId) {
24574
24819
  decimals: dec(decimals),
24575
24820
  asset: asset.toLowerCase(),
24576
24821
  collateral: collateral.toLowerCase(),
24577
- maxLtv: big3(maxLtv),
24578
- ltvPrecision: big3(ltvPrec) || 100000n,
24579
- exchangePrecision: big3(exPrec) || 10n ** 18n,
24580
- liqPrecision: big3(liqPrec) || 100000n,
24822
+ maxLtv: big4(maxLtv),
24823
+ ltvPrecision: big4(ltvPrec) || 100000n,
24824
+ exchangePrecision: big4(exPrec) || 10n ** 18n,
24825
+ liqPrecision: big4(liqPrec) || 100000n,
24581
24826
  cleanLiquidationFee: 0n,
24582
24827
  dirtyLiquidationFee: 0n,
24583
24828
  protocolLiquidationFee: 0n,
24584
- depositLimit: big3(depositLimit),
24585
- borrowLimit: big3(borrowLimit),
24586
- totalAssetAmount: big3(
24829
+ depositLimit: big4(depositLimit),
24830
+ borrowLimit: big4(borrowLimit),
24831
+ totalAssetAmount: big4(
24587
24832
  totalAsset.amount ?? totalAsset[0]
24588
24833
  ),
24589
- totalAssetShares: big3(
24834
+ totalAssetShares: big4(
24590
24835
  totalAsset.shares ?? totalAsset[1]
24591
24836
  ),
24592
- totalBorrowAmount: big3(
24837
+ totalBorrowAmount: big4(
24593
24838
  totalBorrow.amount ?? totalBorrow[0]
24594
24839
  ),
24595
- totalBorrowShares: big3(
24840
+ totalBorrowShares: big4(
24596
24841
  totalBorrow.shares ?? totalBorrow[1]
24597
24842
  ),
24598
- totalCollateral: big3(totalCollateral),
24843
+ totalCollateral: big4(totalCollateral),
24599
24844
  oracle: str2(xrInfo[0], "").toLowerCase(),
24600
24845
  maxOracleDeviation: Number(xrInfo[1] ?? 0),
24601
- exchangeRateLastTimestamp: big3(xrInfo[2]),
24602
- lowExchangeRate: big3(xrInfo[3]),
24603
- highExchangeRate: big3(xrInfo[4]),
24604
- ratePerSec: big3(rateInfo.ratePerSec ?? rateInfo[3]),
24605
- fullUtilizationRate: big3(
24846
+ exchangeRateLastTimestamp: big4(xrInfo[2]),
24847
+ lowExchangeRate: big4(xrInfo[3]),
24848
+ highExchangeRate: big4(xrInfo[4]),
24849
+ ratePerSec: big4(rateInfo.ratePerSec ?? rateInfo[3]),
24850
+ fullUtilizationRate: big4(
24606
24851
  rateInfo.fullUtilizationRate ?? rateInfo[4]
24607
24852
  ),
24608
24853
  feeToProtocolRate: Number(
24609
24854
  rateInfo.feeToProtocolRate ?? rateInfo[1] ?? 0
24610
24855
  ),
24611
- rateLastTimestamp: big3(
24856
+ rateLastTimestamp: big4(
24612
24857
  rateInfo.lastTimestamp ?? rateInfo[2]
24613
24858
  ),
24614
24859
  rateContract: str2(rateContract, "").toLowerCase(),
@@ -24673,8 +24918,8 @@ function inverseKeyParts(key3) {
24673
24918
  return { lender: "INVERSE", market: "0x" + suffix.toLowerCase() };
24674
24919
  }
24675
24920
  function currencyFor8(address, decimals, symbol, tokens) {
24676
- const lower3 = address.toLowerCase();
24677
- return tokens[lower3] ?? { address: lower3, symbol, name: symbol, decimals };
24921
+ const lower4 = address.toLowerCase();
24922
+ return tokens[lower4] ?? { address: lower4, symbol, name: symbol, decimals };
24678
24923
  }
24679
24924
  function convertInverseMarketsToResponse(raw, chainId, prices = {}, _additionalYields = {
24680
24925
  intrinsicYields: {},
@@ -24863,8 +25108,8 @@ function llamaLendKeyParts(key3) {
24863
25108
  return { lender: "LLAMALEND", controller: "0x" + suffix.toLowerCase() };
24864
25109
  }
24865
25110
  function currencyFor9(address, decimals, symbol, tokens) {
24866
- const lower3 = address.toLowerCase();
24867
- return tokens[lower3] ?? { address: lower3, symbol, name: symbol, decimals };
25111
+ const lower4 = address.toLowerCase();
25112
+ return tokens[lower4] ?? { address: lower4, symbol, name: symbol, decimals };
24868
25113
  }
24869
25114
  var LLAMALEND_MIN_BANDS = 4;
24870
25115
  var LLAMALEND_MAX_BANDS = 50;
@@ -25212,8 +25457,8 @@ var SECONDS_PER_YEAR9 = 31536e3;
25212
25457
  var LTV_PRECISION = 1e5;
25213
25458
  var ONE2 = 10n ** 18n;
25214
25459
  function currencyFor10(address, decimals, symbol, tokens) {
25215
- const lower3 = address.toLowerCase();
25216
- return tokens[lower3] ?? { address: lower3, symbol, name: symbol, decimals };
25460
+ const lower4 = address.toLowerCase();
25461
+ return tokens[lower4] ?? { address: lower4, symbol, name: symbol, decimals };
25217
25462
  }
25218
25463
  function ratePerSecToApr(rate) {
25219
25464
  if (rate === null) return 0;
@@ -25221,9 +25466,9 @@ function ratePerSecToApr(rate) {
25221
25466
  }
25222
25467
  function buildRewardEntries(p, rsup, chainId, prices, tokens, collateralUsd, debtUsd) {
25223
25468
  const priceOf2 = (address) => {
25224
- const lower3 = address.toLowerCase();
25225
- const token = tokens[lower3];
25226
- const key3 = toOracleKey(token?.assetGroup) || toGenericPriceKey(lower3, chainId);
25469
+ const lower4 = address.toLowerCase();
25470
+ const token = tokens[lower4];
25471
+ const key3 = toOracleKey(token?.assetGroup) || toGenericPriceKey(lower4, chainId);
25227
25472
  return prices[key3] ?? 0;
25228
25473
  };
25229
25474
  const collateral = [];
@@ -25505,8 +25750,8 @@ function ratePerSecToApr2(rate) {
25505
25750
  return Number(rate) / 1e18 * SECONDS_PER_YEAR10 * 100;
25506
25751
  }
25507
25752
  function currencyFor11(address, decimals, symbol, name, tokens) {
25508
- const lower3 = address.toLowerCase();
25509
- return tokens[lower3] ?? { address: lower3, symbol, name, decimals };
25753
+ const lower4 = address.toLowerCase();
25754
+ return tokens[lower4] ?? { address: lower4, symbol, name, decimals };
25510
25755
  }
25511
25756
  var toFloat = (raw, decimals) => Number(raw) / 10 ** decimals;
25512
25757
  function convertCurvanceMarketsToResponse(raw, chainId, prices = {}, _additionalYields = {
@@ -25729,6 +25974,254 @@ function resolvePositionManagers(cfg, marketManager) {
25729
25974
  return void 0;
25730
25975
  }
25731
25976
 
25977
+ // src/lending/public-data/twyne/convertPublic.ts
25978
+ function twyneLenderKey(lender, chainId, intermediateVault, targetAsset) {
25979
+ return `${lender}_${chainId}_${intermediateVault.replace(/^0x/i, "").toUpperCase()}_${targetAsset.replace(/^0x/i, "").toUpperCase()}`;
25980
+ }
25981
+ var SECONDS_PER_YEAR11 = 31536e3;
25982
+ var BPS3 = 1e4;
25983
+ var RAY5 = 1e27;
25984
+ var toFloat2 = (v, dec2) => v === void 0 ? 0 : Number(v) / 10 ** dec2;
25985
+ function spyToApr(spy) {
25986
+ return Number(spy) / RAY5 * SECONDS_PER_YEAR11 * 100;
25987
+ }
25988
+ function currencyFor12(address, decimals, symbol, tokens) {
25989
+ const lower4 = address.toLowerCase();
25990
+ return tokens[lower4] ?? { address: lower4, symbol, name: symbol, decimals };
25991
+ }
25992
+ function convertTwyneMarketsToResponse(raw, chainId, prices = {}, _additionalYields = { intrinsicYields: {}, lenderRewards: {}, loaded: true }, tokens = {}) {
25993
+ const out = {};
25994
+ if (!raw?.config) return out;
25995
+ for (const row of raw.markets ?? []) {
25996
+ const m = row.market;
25997
+ if (row.externalLiqLtv === void 0 || row.maxTwyneLiqLtv === void 0) continue;
25998
+ const lenderKey = twyneLenderKey(raw.lender, chainId, m.intermediateVault, m.targetAsset);
25999
+ const entry = { data: {} };
26000
+ const buffer = row.externalLiqBuffer ?? BigInt(BPS3);
26001
+ const floorLtv = Number(row.externalLiqLtv * buffer) / (BPS3 * BPS3);
26002
+ const maxLtv = Number(row.maxTwyneLiqLtv) / BPS3;
26003
+ const extLtv = Number(row.externalLiqLtv) / BPS3;
26004
+ const collAddr = m.underlyingAsset.toLowerCase();
26005
+ const debtAddr = m.targetAsset.toLowerCase();
26006
+ const collToken = tokens[collAddr];
26007
+ const debtToken = tokens[debtAddr];
26008
+ const collPrice = prices[toOracleKey(collToken?.assetGroup) || toGenericPriceKey(collAddr, chainId)] || 0;
26009
+ const debtPrice = prices[toOracleKey(debtToken?.assetGroup) || toGenericPriceKey(debtAddr, chainId)] || 0;
26010
+ const creditTotal = toFloat2(row.creditTotalAssets, row.creditDecimals);
26011
+ const creditAvailable = toFloat2(row.creditCash, row.creditDecimals);
26012
+ const creditUtilization = row.creditTotalAssets > 0n ? Number(row.creditTotalBorrows) / Number(row.creditTotalAssets) : 0;
26013
+ const creditApr = spyToApr(row.creditRateSpy);
26014
+ const externalBorrowLiquidity = toFloat2(row.externalBorrowLiquidity, row.targetDecimals);
26015
+ const openHalted = row.paused || row.collateralMatured || creditAvailable <= 0;
26016
+ const collUid = createMarketUid(chainId, lenderKey, collAddr);
26017
+ entry.data[collUid] = {
26018
+ marketUid: collUid,
26019
+ name: m.symbol ?? collToken?.symbol ?? "collateral",
26020
+ poolId: m.intermediateVault.toLowerCase(),
26021
+ underlying: collAddr,
26022
+ asset: currencyFor12(collAddr, row.collateralDecimals, m.symbol ?? "", tokens),
26023
+ totalDeposits: creditTotal,
26024
+ totalDebtStable: 0,
26025
+ totalDebt: 0,
26026
+ totalLiquidity: creditAvailable,
26027
+ borrowLiquidity: 0,
26028
+ totalLiquidityUSD: creditAvailable * collPrice,
26029
+ borrowLiquidityUSD: 0,
26030
+ totalDepositsUSD: creditTotal * collPrice,
26031
+ totalDebtStableUSD: 0,
26032
+ totalDebtUSD: 0,
26033
+ utilization: creditUtilization,
26034
+ // What the collateral earns is the EXTERNAL protocol's supply rate — the
26035
+ // receipt token keeps earning underneath. Twyne adds nothing here; its
26036
+ // own rate is a COST, charged on reserved credit in this same asset.
26037
+ //
26038
+ // A ZERO HERE IS USUALLY CORRECT, not a decode failure: every live
26039
+ // Aave-side collateral (the PTs, wstETH) is a collateral-only reserve with
26040
+ // borrowing disabled, so Aave's `currentLiquidityRate` really is ~0. The
26041
+ // yield those assets pay is INTRINSIC — a PT's accretion to par, wstETH's
26042
+ // staking rate — and the stack joins it in as `intrinsicYield`. Do not
26043
+ // "fix" this by substituting the intrinsic rate here; that would
26044
+ // double-count it.
26045
+ depositRate: (row.externalSupplyRate ?? 0) * 100,
26046
+ variableBorrowRate: 0,
26047
+ stableBorrowRate: 0,
26048
+ rateModel: "twyne-curve",
26049
+ intrinsicYield: 0,
26050
+ rewards: void 0,
26051
+ decimals: row.collateralDecimals,
26052
+ config: {
26053
+ 0: {
26054
+ category: 0,
26055
+ // The floor of the band, i.e. the LTV a position gets with no credit
26056
+ // reserved. Anything higher is a per-position choice — see
26057
+ // `openParameter`, which carries the DOMAIN while `modes[posId]`
26058
+ // carries the value.
26059
+ borrowCollateralFactor: floorLtv,
26060
+ collateralFactor: floorLtv,
26061
+ borrowFactor: 1,
26062
+ liquidationPenalty: 0,
26063
+ closeFactor: 1,
26064
+ collateralDisabled: false,
26065
+ debtDisabled: true,
26066
+ /**
26067
+ * THE PARAMETER. Twyne has no per-market LTV: each position picks its
26068
+ * own `twyneLiqLTV` inside this band and may change it at any time.
26069
+ *
26070
+ * `identityMapping` is what makes a curve unnecessary — the chosen
26071
+ * value IS the liquidation threshold, so a consumer prices a position
26072
+ * straight from `modes[posId]`. Without it every position would be
26073
+ * priced at `default` (the FLOOR), i.e. as though it had bought no
26074
+ * extra LTV at all, which is the entire product missing.
26075
+ *
26076
+ * `immutableAfterOpen: false` and NO cooldown: unlike LlamaLend's band
26077
+ * count this is adjustable in place, and unlike Liquity's rate there
26078
+ * is no adjustment delay. The only friction is economic — raising it
26079
+ * reserves more credit and can fail when the credit vault is dry.
26080
+ */
26081
+ openParameter: {
26082
+ kind: "twyne-liq-ltv",
26083
+ dimension: "collateralFactor",
26084
+ domain: { min: floorLtv, max: maxLtv },
26085
+ default: floorLtv,
26086
+ immutableAfterOpen: false,
26087
+ identityMapping: true
26088
+ }
26089
+ }
26090
+ },
26091
+ closeFactor: 1,
26092
+ collateralActive: !openHalted,
26093
+ borrowingEnabled: false,
26094
+ depositsEnabled: !openHalted,
26095
+ hasStable: false,
26096
+ variableBorrowDisabled: true,
26097
+ isActive: !row.paused,
26098
+ isFrozen: row.paused
26099
+ };
26100
+ const debtUid = createMarketUid(chainId, lenderKey, debtAddr);
26101
+ entry.data[debtUid] = {
26102
+ marketUid: debtUid,
26103
+ name: debtToken?.symbol ?? "debt",
26104
+ poolId: m.intermediateVault.toLowerCase(),
26105
+ underlying: debtAddr,
26106
+ asset: currencyFor12(debtAddr, row.targetDecimals, debtToken?.symbol ?? "", tokens),
26107
+ // Borrower aggregates are NOT readable without an event replay — see the
26108
+ // header. Zero here means "not measured", and the descriptor says so.
26109
+ totalDeposits: 0,
26110
+ totalDebtStable: 0,
26111
+ totalDebt: 0,
26112
+ totalLiquidity: externalBorrowLiquidity,
26113
+ borrowLiquidity: externalBorrowLiquidity,
26114
+ totalLiquidityUSD: externalBorrowLiquidity * debtPrice,
26115
+ borrowLiquidityUSD: externalBorrowLiquidity * debtPrice,
26116
+ totalDepositsUSD: 0,
26117
+ totalDebtStableUSD: 0,
26118
+ totalDebtUSD: 0,
26119
+ utilization: 0,
26120
+ depositRate: 0,
26121
+ // THE market's borrow rate: the external protocol's. The Twyne credit leg
26122
+ // is charged on reserved credit in the COLLATERAL asset, so it cannot be
26123
+ // added to this number — its effective contribution is per-position.
26124
+ variableBorrowRate: (row.externalBorrowRate ?? 0) * 100,
26125
+ stableBorrowRate: 0,
26126
+ rateModel: "twyne-curve",
26127
+ intrinsicYield: 0,
26128
+ rewards: void 0,
26129
+ decimals: row.targetDecimals,
26130
+ config: {
26131
+ 0: {
26132
+ category: 0,
26133
+ borrowCollateralFactor: 0,
26134
+ collateralFactor: 0,
26135
+ borrowFactor: 1,
26136
+ liquidationPenalty: 0,
26137
+ closeFactor: 1,
26138
+ collateralDisabled: true,
26139
+ debtDisabled: openHalted
26140
+ }
26141
+ },
26142
+ closeFactor: 1,
26143
+ collateralActive: false,
26144
+ borrowingEnabled: !openHalted,
26145
+ depositsEnabled: false,
26146
+ hasStable: false,
26147
+ variableBorrowDisabled: openHalted,
26148
+ isActive: !row.paused,
26149
+ isFrozen: row.paused
26150
+ };
26151
+ entry.params = {
26152
+ market: {
26153
+ lender: lenderKey,
26154
+ name: m.name ?? `${m.symbol ?? "?"} / ${m.vaultType === "AAVE_V3" ? "Aave V3" : "Euler V2"}`,
26155
+ loanDecimals: row.targetDecimals,
26156
+ collateralDecimals: row.collateralDecimals,
26157
+ id: m.intermediateVault.toLowerCase(),
26158
+ // The FLOOR, in the protocol's own 1e4 scale. Never the ceiling: a
26159
+ // consumer rendering one number must render the conservative one.
26160
+ lltv: String(Math.round(floorLtv * BPS3)),
26161
+ oracle: raw.config.oracleRouter ?? zeroAddress,
26162
+ irm: row.creditIrm ?? zeroAddress,
26163
+ collateralAddress: collAddr,
26164
+ loanAddress: debtAddr,
26165
+ twyne: {
26166
+ vaultType: m.vaultType,
26167
+ intermediateVault: m.intermediateVault,
26168
+ targetVault: m.targetVault,
26169
+ targetAsset: debtAddr,
26170
+ /** The receipt token the collateral vault actually holds. */
26171
+ collateralAsset: m.collateralAsset,
26172
+ aToken: m.aToken,
26173
+ categoryId: m.categoryId,
26174
+ /**
26175
+ * THE LTV BAND. There is no per-market LTV: a position picks its own
26176
+ * `twyneLiqLTV` anywhere in `[floorLtv, maxLtv]` and can change it at
26177
+ * any time, and the EFFECTIVE threshold is clamped further at runtime
26178
+ * when the credit vault runs short. Consumers must treat this as a
26179
+ * domain, not a value — the value lives on the position.
26180
+ */
26181
+ floorLtv,
26182
+ maxLtv,
26183
+ /** The external protocol's own liquidation threshold, 1e4-scaled. */
26184
+ externalLiqLtv: extLtv,
26185
+ externalLiqBufferBps: Number(buffer),
26186
+ /**
26187
+ * What the borrower pays ON RESERVED CREDIT, in the COLLATERAL asset —
26188
+ * NOT on their debt. Its contribution to an effective borrow rate is
26189
+ * `creditApr * (reservedCreditValue / debtValue)`, which only exists
26190
+ * per position. Never add it to `variableBorrowRate`.
26191
+ */
26192
+ creditApr,
26193
+ creditRateSpy: row.creditRateSpy.toString(),
26194
+ creditUtilization,
26195
+ /** Credit still reservable. Zero ⇒ no new position can raise its LTV
26196
+ * above the floor, however healthy the market otherwise looks. */
26197
+ creditAvailable,
26198
+ creditTotal,
26199
+ creditIrm: row.creditIrm,
26200
+ /** Cap headroom for Credit-LPs, in collateral-asset units. */
26201
+ creditDepositCapacity: row.creditDepositCapacity === void 0 ? void 0 : row.creditDepositCapacity.toString(),
26202
+ /** Unix seconds; absent when the collateral has no maturity. */
26203
+ collateralMaturity: m.collateralMaturity,
26204
+ /** Computed at READ time. Two of the three live PT markets are past
26205
+ * it — a stored flag would be stale. */
26206
+ collateralMatured: row.collateralMatured,
26207
+ /** Factory-wide pause; blocks deposits, borrows and LTV changes. */
26208
+ paused: row.paused,
26209
+ /**
26210
+ * Borrower-side aggregates are absent, not zero. Positions are
26211
+ * per-borrower CONTRACTS and the factory only enumerates them per
26212
+ * borrower, so a protocol-wide total needs a `T_CollateralVaultCreated`
26213
+ * replay — too heavy for a public refresh. `totalDebt` on the rows
26214
+ * above is therefore 0 and means "not measured".
26215
+ */
26216
+ borrowerAggregatesAvailable: false
26217
+ }
26218
+ }
26219
+ };
26220
+ out[lenderKey] = entry;
26221
+ }
26222
+ return out;
26223
+ }
26224
+
25732
26225
  // src/lending/public-data/fraxlend/convertPublic.ts
25733
26226
  function fraxlendLenderKey(lender, chainId, pair) {
25734
26227
  return `${lender}_${chainId}_${pair.replace(/^0x/i, "").toUpperCase()}`;
@@ -25739,13 +26232,13 @@ function fraxlendKeyParts(key3) {
25739
26232
  if (!m) return void 0;
25740
26233
  return { lender: "FRAXLEND", chainId: m[1], pair: `0x${m[2].toLowerCase()}` };
25741
26234
  }
25742
- var SECONDS_PER_YEAR11 = 31536e3;
25743
- var ratePerSecToApr3 = (rate) => Number(rate) / 1e18 * SECONDS_PER_YEAR11 * 100;
25744
- var toFloat2 = (raw, decimals) => Number(raw) / 10 ** decimals;
26235
+ var SECONDS_PER_YEAR12 = 31536e3;
26236
+ var ratePerSecToApr3 = (rate) => Number(rate) / 1e18 * SECONDS_PER_YEAR12 * 100;
26237
+ var toFloat3 = (raw, decimals) => Number(raw) / 10 ** decimals;
25745
26238
  var MAX_UINT = (1n << 256n) - 1n;
25746
- function currencyFor12(address, decimals, symbol, name, tokens) {
25747
- const lower3 = address.toLowerCase();
25748
- return tokens[lower3] ?? { address: lower3, symbol, name, decimals };
26239
+ function currencyFor13(address, decimals, symbol, name, tokens) {
26240
+ const lower4 = address.toLowerCase();
26241
+ return tokens[lower4] ?? { address: lower4, symbol, name, decimals };
25749
26242
  }
25750
26243
  function fraxlendAssetPerCollateral(p, which = "high") {
25751
26244
  const rate = which === "high" ? p.highExchangeRate : p.lowExchangeRate;
@@ -25769,10 +26262,10 @@ function convertFraxlendPairsToResponse(raw, chainId, prices = {}, _additionalYi
25769
26262
  const assetPrice = prices[assetPriceKey] || 0;
25770
26263
  const assetPerColl = fraxlendAssetPerCollateral(p, "high");
25771
26264
  const collPrice = assetPerColl > 0 && assetPrice > 0 ? assetPerColl * assetPrice : prices[collPriceKey] || 0;
25772
- const totalDeposits = toFloat2(p.totalAssetAmount, p.assetDecimals);
25773
- const totalDebt = toFloat2(p.totalBorrowAmount, p.assetDecimals);
26265
+ const totalDeposits = toFloat3(p.totalAssetAmount, p.assetDecimals);
26266
+ const totalDebt = toFloat3(p.totalBorrowAmount, p.assetDecimals);
25774
26267
  const liquidity = Math.max(totalDeposits - totalDebt, 0);
25775
- const totalCollateral = toFloat2(p.totalCollateral, p.collateralDecimals);
26268
+ const totalCollateral = toFloat3(p.totalCollateral, p.collateralDecimals);
25776
26269
  const utilization = totalDeposits > 0 ? totalDebt / totalDeposits : 0;
25777
26270
  const borrowApr = ratePerSecToApr3(p.ratePerSec);
25778
26271
  const protocolCut = Math.min(Math.max(p.feeToProtocolRate / 1e5, 0), 1);
@@ -25781,8 +26274,8 @@ function convertFraxlendPairsToResponse(raw, chainId, prices = {}, _additionalYi
25781
26274
  const liquidationPenalty = p.liqPrecision > 0n && p.cleanLiquidationFee > 0n ? Number(p.cleanLiquidationFee) / Number(p.liqPrecision) : 0;
25782
26275
  const uncappedDeposit = p.depositLimit >= MAX_UINT / 2n;
25783
26276
  const uncappedBorrow = p.borrowLimit >= MAX_UINT / 2n;
25784
- const depositHeadroom = uncappedDeposit ? Number.POSITIVE_INFINITY : Math.max(toFloat2(p.depositLimit, p.assetDecimals) - totalDeposits, 0);
25785
- const borrowHeadroom = uncappedBorrow ? Number.POSITIVE_INFINITY : Math.max(toFloat2(p.borrowLimit, p.assetDecimals) - totalDebt, 0);
26277
+ const depositHeadroom = uncappedDeposit ? Number.POSITIVE_INFINITY : Math.max(toFloat3(p.depositLimit, p.assetDecimals) - totalDeposits, 0);
26278
+ const borrowHeadroom = uncappedBorrow ? Number.POSITIVE_INFINITY : Math.max(toFloat3(p.borrowLimit, p.assetDecimals) - totalDebt, 0);
25786
26279
  const depositsHalted = depositHeadroom <= 0;
25787
26280
  const borrowHalted = borrowHeadroom <= 0;
25788
26281
  const borrowLiquidity = borrowHalted ? 0 : Math.min(liquidity, borrowHeadroom);
@@ -25792,7 +26285,7 @@ function convertFraxlendPairsToResponse(raw, chainId, prices = {}, _additionalYi
25792
26285
  name: p.assetSymbol,
25793
26286
  poolId: p.pair.toLowerCase(),
25794
26287
  underlying: p.asset,
25795
- asset: currencyFor12(
26288
+ asset: currencyFor13(
25796
26289
  p.asset,
25797
26290
  p.assetDecimals,
25798
26291
  p.assetSymbol,
@@ -25845,7 +26338,7 @@ function convertFraxlendPairsToResponse(raw, chainId, prices = {}, _additionalYi
25845
26338
  name: p.collateralSymbol,
25846
26339
  poolId: p.pair.toLowerCase(),
25847
26340
  underlying: p.collateral,
25848
- asset: currencyFor12(
26341
+ asset: currencyFor13(
25849
26342
  p.collateral,
25850
26343
  p.collateralDecimals,
25851
26344
  p.collateralSymbol,
@@ -26015,12 +26508,12 @@ async function fetchDssMarkets(lender, chainId) {
26015
26508
  } catch {
26016
26509
  return { lender, config, chainData, markets: [] };
26017
26510
  }
26018
- const big18 = (v) => {
26511
+ const big20 = (v) => {
26019
26512
  if (typeof v === "bigint") return v;
26020
26513
  if (typeof v === "number") return BigInt(v);
26021
26514
  return null;
26022
26515
  };
26023
- const field13 = (res, name, idx) => big18(res?.[name] ?? res?.[idx]);
26516
+ const field13 = (res, name, idx) => big20(res?.[name] ?? res?.[idx]);
26024
26517
  let cursor = 0;
26025
26518
  const out = markets.map((market, i) => {
26026
26519
  const base = cursor;
@@ -26037,7 +26530,7 @@ async function fetchDssMarkets(lender, chainId) {
26037
26530
  dust: field13(vatIlk, "dust", 4),
26038
26531
  duty: field13(jugIlk, "duty", 0),
26039
26532
  mat: field13(spotIlk, "mat", 1),
26040
- joinBalance: joinReadIndex[i] >= 0 ? big18(results[joinReadIndex[i]]) : null
26533
+ joinBalance: joinReadIndex[i] >= 0 ? big20(results[joinReadIndex[i]]) : null
26041
26534
  };
26042
26535
  });
26043
26536
  return { lender, config, chainData, markets: out };
@@ -26059,15 +26552,15 @@ function dssKeyParts(key3) {
26059
26552
  return { lender: m[1], chainId: m[2], ilk: keySegmentToIlk(m[3]) };
26060
26553
  }
26061
26554
  var WAD10 = 1e18;
26062
- var RAY4 = 1e27;
26555
+ var RAY6 = 1e27;
26063
26556
  var RAD = 1e45;
26064
26557
  var YEAR_SECONDS2 = 31536e3;
26065
26558
  function toHuman4(raw, decimals) {
26066
26559
  return Number(raw) / 10 ** decimals;
26067
26560
  }
26068
- function currencyFor13(address, decimals, symbol, tokens) {
26069
- const lower3 = address.toLowerCase();
26070
- return tokens[lower3] ?? { address: lower3, symbol, name: symbol, decimals };
26561
+ function currencyFor14(address, decimals, symbol, tokens) {
26562
+ const lower4 = address.toLowerCase();
26563
+ return tokens[lower4] ?? { address: lower4, symbol, name: symbol, decimals };
26071
26564
  }
26072
26565
  function convertDssMarketsToResponse(raw, chainId, prices = {}, _additionalYields = {
26073
26566
  intrinsicYields: {},
@@ -26096,16 +26589,16 @@ function convertDssMarketsToResponse(raw, chainId, prices = {}, _additionalYield
26096
26589
  const collSymbol = collToken?.symbol ?? market.collSymbol ?? market.ilk.split("-")[0];
26097
26590
  const marketName2 = market.name ?? `${debtSymbol} / ${collSymbol}`;
26098
26591
  const collPriceKey = toOracleKey(collToken?.assetGroup) || toGenericPriceKey(collAddr, chainId);
26099
- const spotDerivedPrice = m.spot !== null && m.mat !== null ? Number(m.spot) / RAY4 * (Number(m.mat) / RAY4) : 0;
26592
+ const spotDerivedPrice = m.spot !== null && m.mat !== null ? Number(m.spot) / RAY6 * (Number(m.mat) / RAY6) : 0;
26100
26593
  const collPrice = spotDerivedPrice || (prices[collPriceKey] ?? 0);
26101
26594
  const totalDebt = m.Art !== null && m.rate !== null ? Number(m.Art * m.rate / BigInt(1e27)) / 10 ** debtDecimals : 0;
26102
26595
  const totalColl = m.joinBalance !== null ? toHuman4(m.joinBalance, collDecimals) : 0;
26103
- const mat = m.mat !== null ? Number(m.mat) / RAY4 : Number(market.mat) / RAY4 || 1.5;
26596
+ const mat = m.mat !== null ? Number(m.mat) / RAY6 : Number(market.mat) / RAY6 || 1.5;
26104
26597
  const ltv = mat > 0 ? 1 / mat : 0;
26105
26598
  const chop = market.chop ? Number(market.chop) / WAD10 : 0;
26106
26599
  const liqPenalty = chop > 1 ? chop - 1 : 0;
26107
26600
  const duty = m.duty !== null ? m.duty : BigInt(market.duty ?? 0);
26108
- const borrowApr = duty > BigInt(1e27) ? Number(duty - BigInt(10) ** BigInt(27)) / RAY4 * YEAR_SECONDS2 * 100 : 0;
26601
+ const borrowApr = duty > BigInt(1e27) ? Number(duty - BigInt(10) ** BigInt(27)) / RAY6 * YEAR_SECONDS2 * 100 : 0;
26109
26602
  const line = m.line !== null ? Number(m.line) / RAD : 0;
26110
26603
  let borrowLiquidity = Math.max(0, line - totalDebt);
26111
26604
  const offboarded = market.offboarded === true;
@@ -26117,7 +26610,7 @@ function convertDssMarketsToResponse(raw, chainId, prices = {}, _additionalYield
26117
26610
  name: "Collateral " + collSymbol,
26118
26611
  poolId: market.gemJoin?.toLowerCase(),
26119
26612
  underlying: collAddr,
26120
- asset: currencyFor13(collAddr, collDecimals, collSymbol, tokens),
26613
+ asset: currencyFor14(collAddr, collDecimals, collSymbol, tokens),
26121
26614
  totalDeposits: totalColl,
26122
26615
  totalDebtStable: 0,
26123
26616
  totalDebt: 0,
@@ -26161,7 +26654,7 @@ function convertDssMarketsToResponse(raw, chainId, prices = {}, _additionalYield
26161
26654
  name: debtSymbol,
26162
26655
  poolId: cfg.vat.toLowerCase(),
26163
26656
  underlying: debtAddr,
26164
- asset: currencyFor13(debtAddr, debtDecimals, debtSymbol, tokens),
26657
+ asset: currencyFor14(debtAddr, debtDecimals, debtSymbol, tokens),
26165
26658
  totalDeposits: 0,
26166
26659
  totalDebtStable: 0,
26167
26660
  totalDebt,
@@ -26311,26 +26804,26 @@ async function fetchFrankencoinMarkets(lender, chainId) {
26311
26804
  } catch {
26312
26805
  return { lender, config, chainData, markets: [] };
26313
26806
  }
26314
- const big18 = (v) => {
26807
+ const big20 = (v) => {
26315
26808
  if (typeof v === "bigint") return v;
26316
26809
  if (typeof v === "number") return BigInt(v);
26317
26810
  return null;
26318
26811
  };
26319
26812
  const out = markets.map((market, i) => {
26320
26813
  const base = i * READS_PER_MARKET3;
26321
- const expiration = big18(results[base + 7]);
26814
+ const expiration = big20(results[base + 7]);
26322
26815
  return {
26323
26816
  market,
26324
- price: big18(results[base]),
26325
- minted: big18(results[base + 1]),
26326
- availableForClones: big18(results[base + 2]),
26327
- annualInterestPPM: big18(results[base + 3]),
26328
- currentFeePPM: big18(results[base + 4]),
26329
- reserveContribution: big18(results[base + 5]),
26330
- challengedAmount: big18(results[base + 6]),
26817
+ price: big20(results[base]),
26818
+ minted: big20(results[base + 1]),
26819
+ availableForClones: big20(results[base + 2]),
26820
+ annualInterestPPM: big20(results[base + 3]),
26821
+ currentFeePPM: big20(results[base + 4]),
26822
+ reserveContribution: big20(results[base + 5]),
26823
+ challengedAmount: big20(results[base + 6]),
26331
26824
  expiration,
26332
26825
  isClosed: typeof results[base + 8] === "boolean" ? results[base + 8] : null,
26333
- collateralBalance: big18(results[base + 9])
26826
+ collateralBalance: big20(results[base + 9])
26334
26827
  };
26335
26828
  });
26336
26829
  return { lender, config, chainData, markets: out };
@@ -26352,9 +26845,9 @@ function frankencoinKeyParts(key3) {
26352
26845
  };
26353
26846
  }
26354
26847
  var PPM = 1e6;
26355
- function currencyFor14(address, decimals, symbol, tokens) {
26356
- const lower3 = address.toLowerCase();
26357
- return tokens[lower3] ?? { address: lower3, symbol, name: symbol, decimals };
26848
+ function currencyFor15(address, decimals, symbol, tokens) {
26849
+ const lower4 = address.toLowerCase();
26850
+ return tokens[lower4] ?? { address: lower4, symbol, name: symbol, decimals };
26358
26851
  }
26359
26852
  function convertFrankencoinMarketsToResponse(raw, chainId, prices = {}, _additionalYields = {
26360
26853
  intrinsicYields: {},
@@ -26403,7 +26896,7 @@ function convertFrankencoinMarketsToResponse(raw, chainId, prices = {}, _additio
26403
26896
  name: "Collateral " + collSymbol,
26404
26897
  poolId: market.position.toLowerCase(),
26405
26898
  underlying: collAddr,
26406
- asset: currencyFor14(collAddr, collDecimals, collSymbol, tokens),
26899
+ asset: currencyFor15(collAddr, collDecimals, collSymbol, tokens),
26407
26900
  totalDeposits: totalColl,
26408
26901
  totalDebtStable: 0,
26409
26902
  totalDebt: 0,
@@ -26450,7 +26943,7 @@ function convertFrankencoinMarketsToResponse(raw, chainId, prices = {}, _additio
26450
26943
  name: debtSymbol,
26451
26944
  poolId: cfg.mintingHub.toLowerCase(),
26452
26945
  underlying: debtAddr,
26453
- asset: currencyFor14(debtAddr, debtDecimals, debtSymbol, tokens),
26946
+ asset: currencyFor15(debtAddr, debtDecimals, debtSymbol, tokens),
26454
26947
  totalDeposits: 0,
26455
26948
  totalDebtStable: 0,
26456
26949
  totalDebt,
@@ -27174,6 +27667,7 @@ async function getLenderDataFromApi(lender, chainId, prices, additionalYields, i
27174
27667
  if (isLlamaLend(lender)) return await fetchLlamaLendMarkets(lender, chainId);
27175
27668
  if (isResupply(lender)) return await fetchResupplyMarkets(lender, chainId);
27176
27669
  if (isCurvance(lender)) return await fetchCurvanceMarkets(lender, chainId);
27670
+ if (isTwyne(lender)) return await fetchTwyneMarkets(lender, chainId);
27177
27671
  if (isFraxlend(lender)) return await fetchFraxlendPairs(lender, chainId);
27178
27672
  if (isTermMax(lender)) return await fetchTermMaxMarkets(chainId);
27179
27673
  if (isDssType(lender)) return await fetchDssMarkets(lender, chainId);
@@ -27256,6 +27750,14 @@ function convertLenderDataFromApi(lender, chainId, data, prices, additionalYield
27256
27750
  additionalYields,
27257
27751
  list
27258
27752
  );
27753
+ if (isTwyne(lender))
27754
+ return convertTwyneMarketsToResponse(
27755
+ data,
27756
+ chainId,
27757
+ prices,
27758
+ additionalYields,
27759
+ list
27760
+ );
27259
27761
  if (isCurvance(lender))
27260
27762
  return convertCurvanceMarketsToResponse(
27261
27763
  data,
@@ -27500,6 +28002,7 @@ function lenderApiOnly(lender, chainId) {
27500
28002
  if (isResupply(lender)) return true;
27501
28003
  if (isCurvance(lender)) return true;
27502
28004
  if (isFraxlend(lender)) return true;
28005
+ if (isTwyne(lender)) return true;
27503
28006
  if (isDssType(lender)) return true;
27504
28007
  if (isFrankencoin(lender)) return true;
27505
28008
  if (isLlamaLend(lender)) return true;
@@ -28463,8 +28966,8 @@ function getSubAccountAddress(owner, index) {
28463
28966
  const suffix = newLastByte.toString(16).padStart(2, "0");
28464
28967
  return (prefix + suffix).toLowerCase();
28465
28968
  }
28466
- function getSubAccountIndex(addr3, owner) {
28467
- const addrLastByte = parseInt(addr3.slice(40), 16);
28969
+ function getSubAccountIndex(addr4, owner) {
28970
+ const addrLastByte = parseInt(addr4.slice(40), 16);
28468
28971
  if (!owner) return addrLastByte;
28469
28972
  const ownerLastByte = parseInt(owner.slice(40), 16);
28470
28973
  return (addrLastByte ^ ownerLastByte) & 255;
@@ -29319,17 +29822,94 @@ var buildCurvanceUserCall = async (chainId, lender, account) => {
29319
29822
  ])
29320
29823
  ]);
29321
29824
  };
29825
+ var DISCOVERY_TTL_MS3 = 6e4;
29826
+ var TWYNE_READS_PER_VAULT = 9;
29827
+ var discoveryCache4 = /* @__PURE__ */ new Map();
29828
+ var discoveryKey3 = (chainId, lender, account) => `${chainId}:${lender}:${account.toLowerCase()}`;
29829
+ function getCachedTwyneDiscovery(chainId, lender, account) {
29830
+ return discoveryCache4.get(discoveryKey3(chainId, lender, account));
29831
+ }
29832
+ var lower2 = (a) => String(a).toLowerCase();
29833
+ var isAddress2 = (v) => typeof v === "string" && /^0x[0-9a-fA-F]{40}$/.test(v);
29834
+ async function discover(chainId, lender, account) {
29835
+ const key3 = discoveryKey3(chainId, lender, account);
29836
+ const cached = discoveryCache4.get(key3);
29837
+ if (cached && Date.now() - cached.at < DISCOVERY_TTL_MS3) return cached;
29838
+ const cfg = twyneConfigFor(lender, chainId);
29839
+ const empty = { vaults: [], at: Date.now() };
29840
+ if (!cfg?.collateralVaultFactory) return empty;
29841
+ const [listRaw] = await multicallRetryUniversal({
29842
+ chain: chainId,
29843
+ calls: [
29844
+ {
29845
+ address: cfg.collateralVaultFactory,
29846
+ name: "getCollateralVaults",
29847
+ args: [account]
29848
+ }
29849
+ ],
29850
+ abi: TwyneCollateralVaultFactoryAbi,
29851
+ allowFailure: true
29852
+ });
29853
+ const created = Array.isArray(listRaw) ? listRaw.filter(isAddress2).map(lower2) : [];
29854
+ if (created.length === 0) {
29855
+ discoveryCache4.set(key3, empty);
29856
+ return empty;
29857
+ }
29858
+ const refs = await multicallRetryUniversal({
29859
+ chain: chainId,
29860
+ calls: created.flatMap((v) => [
29861
+ { address: v, name: "intermediateVault", args: [] },
29862
+ { address: v, name: "targetAsset", args: [] },
29863
+ { address: v, name: "borrower", args: [] }
29864
+ ]),
29865
+ abi: TwyneCollateralVaultAbi,
29866
+ allowFailure: true
29867
+ });
29868
+ const known = new Set(
29869
+ (twyneChainData(lender, chainId)?.markets ?? []).map(
29870
+ (m) => `${lower2(m.intermediateVault)}|${lower2(m.targetAsset)}`
29871
+ )
29872
+ );
29873
+ const vaults = [];
29874
+ created.forEach((vault, i) => {
29875
+ const iv = refs[i * 3];
29876
+ const target = refs[i * 3 + 1];
29877
+ const owner = refs[i * 3 + 2];
29878
+ if (!isAddress2(iv) || !isAddress2(target)) return;
29879
+ if (isAddress2(owner) && lower2(owner) !== lower2(account)) return;
29880
+ if (!known.has(`${lower2(iv)}|${lower2(target)}`)) return;
29881
+ vaults.push({ vault, intermediateVault: lower2(iv), targetAsset: lower2(target) });
29882
+ });
29883
+ const result = { vaults, at: Date.now() };
29884
+ discoveryCache4.set(key3, result);
29885
+ return result;
29886
+ }
29887
+ async function buildTwyneUserCall(chainId, lender, account) {
29888
+ const { vaults } = await discover(chainId, lender, account);
29889
+ if (vaults.length === 0) return [];
29890
+ return vaults.flatMap(({ vault }) => [
29891
+ { address: vault, name: "totalAssetsDepositedOrReserved", args: [] },
29892
+ { address: vault, name: "maxRelease", args: [] },
29893
+ { address: vault, name: "maxRepay", args: [] },
29894
+ { address: vault, name: "twyneLiqLTV", args: [] },
29895
+ { address: vault, name: "canLiquidate", args: [] },
29896
+ { address: vault, name: "isExternallyLiquidated", args: [] },
29897
+ { address: vault, name: "canRebalance", args: [] },
29898
+ { address: vault, name: "asset", args: [] },
29899
+ { address: vault, name: "convertToAssets", args: [10n ** 18n] }
29900
+ ]);
29901
+ }
29322
29902
  var DSS_CALLS_PER_CDP = 1;
29323
29903
  var MAX_CDP_WALK = 64;
29324
29904
  var CACHE_TTL_MS2 = 5 * 6e4;
29325
- var discoveryCache4 = /* @__PURE__ */ new Map();
29905
+ var discoveryCache5 = /* @__PURE__ */ new Map();
29326
29906
  var cacheKey2 = (lender, chainId, account) => `${lender}:${chainId}:${account.toLowerCase()}`;
29327
29907
  var getCachedDssCdps = (lender, chainId, account) => {
29328
- const hit = discoveryCache4.get(cacheKey2(lender, chainId, account));
29908
+ const hit = discoveryCache5.get(cacheKey2(lender, chainId, account));
29329
29909
  if (!hit || Date.now() - hit.at > CACHE_TTL_MS2) return void 0;
29330
29910
  return hit;
29331
29911
  };
29332
- var big4 = (v) => {
29912
+ var big5 = (v) => {
29333
29913
  try {
29334
29914
  if (typeof v === "bigint") return v;
29335
29915
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -29341,7 +29921,7 @@ var field6 = (res, name, idx) => res?.[name] ?? res?.[idx];
29341
29921
  var buildDssUserCall = async (chainId, lender, account) => {
29342
29922
  const cfg = dssConfigFor(lender, chainId);
29343
29923
  const markets = dssChainData(lender, chainId)?.markets ?? [];
29344
- const stash = (d) => discoveryCache4.set(cacheKey2(lender, chainId, account), d);
29924
+ const stash = (d) => discoveryCache5.set(cacheKey2(lender, chainId, account), d);
29345
29925
  if (!cfg || markets.length === 0) {
29346
29926
  stash({ cdps: [], ilks: [], at: Date.now() });
29347
29927
  return [];
@@ -29360,7 +29940,7 @@ var buildDssUserCall = async (chainId, lender, account) => {
29360
29940
  ],
29361
29941
  allowFailure: false
29362
29942
  });
29363
- owners.push({ owner: account, count: big4(rawCount), cursor: big4(rawFirst) });
29943
+ owners.push({ owner: account, count: big5(rawCount), cursor: big5(rawFirst) });
29364
29944
  const proxy = String(rawProxy ?? zero2);
29365
29945
  if (proxy.toLowerCase() !== zero2) {
29366
29946
  const [pCount, pFirst] = await multicallRetryUniversal({
@@ -29372,7 +29952,7 @@ var buildDssUserCall = async (chainId, lender, account) => {
29372
29952
  ],
29373
29953
  allowFailure: false
29374
29954
  });
29375
- owners.push({ owner: proxy, count: big4(pCount), cursor: big4(pFirst) });
29955
+ owners.push({ owner: proxy, count: big5(pCount), cursor: big5(pFirst) });
29376
29956
  }
29377
29957
  } catch {
29378
29958
  return [];
@@ -29413,7 +29993,7 @@ var buildDssUserCall = async (chainId, lender, account) => {
29413
29993
  if (curated.has(ilk)) {
29414
29994
  cdps.push({ cdpId: cursor.toString(), urn: String(urn), ilk });
29415
29995
  }
29416
- cursor = big4(field6(link, "next", 1));
29996
+ cursor = big5(field6(link, "next", 1));
29417
29997
  }
29418
29998
  }
29419
29999
  } catch {
@@ -29438,7 +30018,7 @@ var buildDssUserCall = async (chainId, lender, account) => {
29438
30018
  };
29439
30019
  var FRANKENCOIN_CALLS_PER_POSITION = 6;
29440
30020
  var BOOK_TTL_MS = 5 * 6e4;
29441
- var DISCOVERY_TTL_MS3 = 5 * 6e4;
30021
+ var DISCOVERY_TTL_MS4 = 5 * 6e4;
29442
30022
  var API_BASE = "https://api.frankencoin.com";
29443
30023
  var bookCache;
29444
30024
  var fetchBook = async () => {
@@ -29462,23 +30042,23 @@ var fetchBook = async () => {
29462
30042
  bookCache = { at: Date.now(), entries };
29463
30043
  return entries;
29464
30044
  };
29465
- var discoveryCache5 = /* @__PURE__ */ new Map();
30045
+ var discoveryCache6 = /* @__PURE__ */ new Map();
29466
30046
  var cacheKey3 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
29467
30047
  var getCachedFrankencoinPositions = (chainId, account) => {
29468
- const hit = discoveryCache5.get(cacheKey3(chainId, account));
29469
- if (!hit || Date.now() - hit.at > DISCOVERY_TTL_MS3) return void 0;
30048
+ const hit = discoveryCache6.get(cacheKey3(chainId, account));
30049
+ if (!hit || Date.now() - hit.at > DISCOVERY_TTL_MS4) return void 0;
29470
30050
  return hit;
29471
30051
  };
29472
30052
  var buildFrankencoinUserCall = async (chainId, lender, account) => {
29473
30053
  const cfg = frankencoinConfigFor(lender, chainId);
29474
30054
  const markets = frankencoinChainData(lender, chainId)?.markets ?? [];
29475
- const stash = (d) => discoveryCache5.set(cacheKey3(chainId, account), d);
30055
+ const stash = (d) => discoveryCache6.set(cacheKey3(chainId, account), d);
29476
30056
  if (!cfg || markets.length === 0) {
29477
30057
  stash({ positions: [], at: Date.now() });
29478
30058
  return [];
29479
30059
  }
29480
30060
  const curated = new Set(markets.map((m) => m.position.toLowerCase()));
29481
- const lower3 = account.toLowerCase();
30061
+ const lower4 = account.toLowerCase();
29482
30062
  let book = [];
29483
30063
  try {
29484
30064
  book = await fetchBook();
@@ -29486,7 +30066,7 @@ var buildFrankencoinUserCall = async (chainId, lender, account) => {
29486
30066
  return [];
29487
30067
  }
29488
30068
  const positions = book.filter(
29489
- (e) => e.owner === lower3 && e.version === 2 && !e.closed && !e.denied && curated.has(e.original)
30069
+ (e) => e.owner === lower4 && e.version === 2 && !e.closed && !e.denied && curated.has(e.original)
29490
30070
  ).map((e) => ({ position: e.position, original: e.original }));
29491
30071
  stash({ positions, at: Date.now() });
29492
30072
  if (positions.length === 0) return [];
@@ -29509,10 +30089,10 @@ var buildFrankencoinUserCall = async (chainId, lender, account) => {
29509
30089
  };
29510
30090
  var TELLER_CALLS_PER_BID = 4;
29511
30091
  var CACHE_TTL_MS3 = 5 * 6e4;
29512
- var discoveryCache6 = /* @__PURE__ */ new Map();
30092
+ var discoveryCache7 = /* @__PURE__ */ new Map();
29513
30093
  var cacheKey4 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
29514
30094
  var getCachedTellerBids = (chainId, account) => {
29515
- const hit = discoveryCache6.get(cacheKey4(chainId, account));
30095
+ const hit = discoveryCache7.get(cacheKey4(chainId, account));
29516
30096
  if (!hit || Date.now() - hit.at > CACHE_TTL_MS3) return void 0;
29517
30097
  return hit;
29518
30098
  };
@@ -29553,7 +30133,7 @@ var buildTellerUserCall = async (chainId, _lender, account) => {
29553
30133
  return [];
29554
30134
  }
29555
30135
  if (ids.length === 0) {
29556
- discoveryCache6.set(cacheKey4(chainId, account), { bids: [], at: Date.now() });
30136
+ discoveryCache7.set(cacheKey4(chainId, account), { bids: [], at: Date.now() });
29557
30137
  return [];
29558
30138
  }
29559
30139
  const poolByAddr = /* @__PURE__ */ new Map();
@@ -29580,7 +30160,7 @@ var buildTellerUserCall = async (chainId, _lender, account) => {
29580
30160
  const pool = poolByAddr.get(lenderAddr);
29581
30161
  if (pool) kept.push({ bidId: id, pool });
29582
30162
  });
29583
- discoveryCache6.set(cacheKey4(chainId, account), { bids: kept, at: Date.now() });
30163
+ discoveryCache7.set(cacheKey4(chainId, account), { bids: kept, at: Date.now() });
29584
30164
  if (kept.length === 0) return [];
29585
30165
  const ts = nowSec5();
29586
30166
  const calls = [];
@@ -29606,10 +30186,10 @@ var buildTellerUserCall = async (chainId, _lender, account) => {
29606
30186
  };
29607
30187
  var TERMMAX_CALLS_PER_ACCOUNT = 1;
29608
30188
  var CACHE_TTL_MS4 = 5 * 6e4;
29609
- var discoveryCache7 = /* @__PURE__ */ new Map();
30189
+ var discoveryCache8 = /* @__PURE__ */ new Map();
29610
30190
  var cacheKey5 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
29611
30191
  var getCachedTermMaxDiscovery = (chainId, account) => {
29612
- const hit = discoveryCache7.get(cacheKey5(chainId, account));
30192
+ const hit = discoveryCache8.get(cacheKey5(chainId, account));
29613
30193
  if (!hit || Date.now() - hit.at > CACHE_TTL_MS4) return void 0;
29614
30194
  return hit;
29615
30195
  };
@@ -29625,11 +30205,11 @@ var buildTermMaxUserCall = async (chainId, _lender, account) => {
29625
30205
  }
29626
30206
  }
29627
30207
  if (markets.length === 0) {
29628
- discoveryCache7.set(cacheKey5(chainId, account), { markets: [], at: Date.now() });
30208
+ discoveryCache8.set(cacheKey5(chainId, account), { markets: [], at: Date.now() });
29629
30209
  return [];
29630
30210
  }
29631
30211
  markets = [...markets].sort((a, b) => a.market.localeCompare(b.market));
29632
- discoveryCache7.set(cacheKey5(chainId, account), { markets, at: Date.now() });
30212
+ discoveryCache8.set(cacheKey5(chainId, account), { markets, at: Date.now() });
29633
30213
  return [
29634
30214
  {
29635
30215
  address: proto.viewer,
@@ -29667,6 +30247,7 @@ async function buildUserCall(chainId, lender, account, params, getClient) {
29667
30247
  if (isResupply(lender)) return buildResupplyUserCall(chainId, lender, account);
29668
30248
  if (isFraxlend(lender)) return buildFraxlendUserCall(chainId, lender, account);
29669
30249
  if (isCurvance(lender)) return buildCurvanceUserCall(chainId, lender, account);
30250
+ if (isTwyne(lender)) return buildTwyneUserCall(chainId, lender, account);
29670
30251
  if (isDssType(lender)) return buildDssUserCall(chainId, lender, account);
29671
30252
  if (isFrankencoin(lender))
29672
30253
  return buildFrankencoinUserCall(chainId, lender, account);
@@ -31624,7 +32205,7 @@ function toBigInt8(v) {
31624
32205
  }
31625
32206
  }
31626
32207
  var FLUID_EEE_LOWER2 = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
31627
- var normalizeUnderlying2 = (addr3) => addr3 === FLUID_EEE_LOWER2 ? zeroAddress : addr3;
32208
+ var normalizeUnderlying2 = (addr4) => addr4 === FLUID_EEE_LOWER2 ? zeroAddress : addr4;
31628
32209
  function toBigInt9(v) {
31629
32210
  if (v === void 0 || v === null || v === "0x") return 0n;
31630
32211
  if (typeof v === "bigint") return v;
@@ -32068,8 +32649,8 @@ var WETH_BY_CHAIN = {
32068
32649
  // populated by the meta's native handling; kept as a hook. Default: identity.
32069
32650
  };
32070
32651
  function normalizeUnderlying3(token) {
32071
- const lower3 = token.toLowerCase();
32072
- return Object.values(WETH_BY_CHAIN).includes(lower3) ? zeroAddress : lower3;
32652
+ const lower4 = token.toLowerCase();
32653
+ return Object.values(WETH_BY_CHAIN).includes(lower4) ? zeroAddress : lower4;
32073
32654
  }
32074
32655
  function toBigInt11(v) {
32075
32656
  if (v === void 0 || v === null || v === "0x") return 0n;
@@ -32520,7 +33101,7 @@ var getExactlyUserDataConverter = (_lender, chainId, account, meta) => {
32520
33101
  expected
32521
33102
  ];
32522
33103
  };
32523
- var big5 = (v) => {
33104
+ var big6 = (v) => {
32524
33105
  try {
32525
33106
  if (typeof v === "bigint") return v;
32526
33107
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -32528,7 +33109,7 @@ var big5 = (v) => {
32528
33109
  }
32529
33110
  return 0n;
32530
33111
  };
32531
- var field7 = (res, name, idx) => big5(res?.[name] ?? res?.[idx]);
33112
+ var field7 = (res, name, idx) => big6(res?.[name] ?? res?.[idx]);
32532
33113
  var getLiquityUserDataConverter = (lender, chainId, account, meta) => {
32533
33114
  const cfg = liquityConfigFor(lender, chainId);
32534
33115
  const branches = liquityBranchesByChain(lender, chainId);
@@ -32649,11 +33230,11 @@ var getLiquityUserDataConverter = (lender, chainId, account, meta) => {
32649
33230
  };
32650
33231
  });
32651
33232
  const spBase = troves.length * 2;
32652
- const spDeposit = big5(slice2[spBase]);
32653
- const spYield = big5(slice2[spBase + 1]);
32654
- const spCollGain = big5(slice2[spBase + 2]);
32655
- const spStashed = big5(slice2[spBase + 3]);
32656
- const collSurplus = branch.collSurplusPool ? big5(slice2[spBase + 4]) : 0n;
33233
+ const spDeposit = big6(slice2[spBase]);
33234
+ const spYield = big6(slice2[spBase + 1]);
33235
+ const spCollGain = big6(slice2[spBase + 2]);
33236
+ const spStashed = big6(slice2[spBase + 3]);
33237
+ const collSurplus = branch.collSurplusPool ? big6(slice2[spBase + 4]) : 0n;
32657
33238
  const spStable = spDeposit + spYield;
32658
33239
  const spColl = spCollGain + spStashed + collSurplus;
32659
33240
  if (spStable > 0n || spColl > 0n) {
@@ -32732,7 +33313,7 @@ var getLiquityUserDataConverter = (lender, chainId, account, meta) => {
32732
33313
  expected
32733
33314
  ];
32734
33315
  };
32735
- var big6 = (v) => {
33316
+ var big7 = (v) => {
32736
33317
  try {
32737
33318
  if (typeof v === "bigint") return v;
32738
33319
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -32740,7 +33321,7 @@ var big6 = (v) => {
32740
33321
  }
32741
33322
  return 0n;
32742
33323
  };
32743
- var field8 = (res, name, idx) => big6(res?.[name] ?? res?.[idx]);
33324
+ var field8 = (res, name, idx) => big7(res?.[name] ?? res?.[idx]);
32744
33325
  var getRiverUserDataConverter = (lender, chainId, account, meta) => {
32745
33326
  const cfg = riverConfigFor(lender, chainId);
32746
33327
  const markets = riverChainData(lender, chainId)?.markets ?? [];
@@ -32752,13 +33333,13 @@ var getRiverUserDataConverter = (lender, chainId, account, meta) => {
32752
33333
  const debtAddr = cfg.debtToken.toLowerCase();
32753
33334
  const debtDecimals = cfg.debtDecimals ?? 18;
32754
33335
  const out = {};
32755
- const spDeposit = big6(data[markets.length * RIVER_CALLS_PER_MARKET]);
33336
+ const spDeposit = big7(data[markets.length * RIVER_CALLS_PER_MARKET]);
32756
33337
  markets.forEach((market, i) => {
32757
33338
  const base = i * RIVER_CALLS_PER_MARKET;
32758
33339
  const entire = data[base];
32759
33340
  if (isFailedCall(entire) || isFailedCall(data[base + 1])) return;
32760
- const status = Number(big6(data[base + 1]));
32761
- const surplus = big6(data[base + 2]);
33341
+ const status = Number(big7(data[base + 1]));
33342
+ const surplus = big7(data[base + 2]);
32762
33343
  const lenderKey = riverLenderKey(lender, chainId, market.index);
32763
33344
  const metaMap = meta?.[lenderKey];
32764
33345
  if (!metaMap) return;
@@ -32866,7 +33447,7 @@ var getRiverUserDataConverter = (lender, chainId, account, meta) => {
32866
33447
  expected
32867
33448
  ];
32868
33449
  };
32869
- var big7 = (v) => {
33450
+ var big8 = (v) => {
32870
33451
  try {
32871
33452
  if (typeof v === "bigint") return v;
32872
33453
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -32885,24 +33466,24 @@ var getInverseUserDataConverter = (lender, chainId, account, meta) => {
32885
33466
  const dolaAddr = cfg.dola.toLowerCase();
32886
33467
  const debtDecimals = cfg.debtDecimals ?? 18;
32887
33468
  const tailBase = markets.length * INVERSE_CALLS_PER_MARKET;
32888
- const dbrBalance = big7(data[tailBase]);
32889
- const dbrDeficit = big7(data[tailBase + 1]);
33469
+ const dbrBalance = big8(data[tailBase]);
33470
+ const dbrDeficit = big8(data[tailBase + 1]);
32890
33471
  const dbrSignedRaw = data[tailBase + 2];
32891
- const dbrSigned = isFailedCall(dbrSignedRaw) ? 0n : big7(dbrSignedRaw);
33472
+ const dbrSigned = isFailedCall(dbrSignedRaw) ? 0n : big8(dbrSignedRaw);
32892
33473
  const dbrTotalDebtRaw = data[tailBase + 3];
32893
- const dbrTotalDebt = isFailedCall(dbrTotalDebtRaw) ? 0n : big7(dbrTotalDebtRaw);
33474
+ const dbrTotalDebt = isFailedCall(dbrTotalDebtRaw) ? 0n : big8(dbrTotalDebtRaw);
32894
33475
  const dbrRunway = dbrTotalDebt > 0n ? dbrBalance * 31536000n / dbrTotalDebt : 0n;
32895
33476
  const nowSec9 = BigInt(Math.floor(Date.now() / 1e3));
32896
33477
  const out = {};
32897
33478
  markets.forEach((market, i) => {
32898
33479
  const base = i * INVERSE_CALLS_PER_MARKET;
32899
- const escrowBal = isFailedCall(data[base]) ? 0n : big7(data[base]);
33480
+ const escrowBal = isFailedCall(data[base]) ? 0n : big8(data[base]);
32900
33481
  const debtRaw = data[base + 1];
32901
33482
  if (isFailedCall(debtRaw)) return;
32902
- const debt = big7(debtRaw);
33483
+ const debt = big8(debtRaw);
32903
33484
  if (escrowBal === 0n && debt === 0n) return;
32904
- const creditLimit = isFailedCall(data[base + 2]) ? 0n : big7(data[base + 2]);
32905
- const withdrawalLimit = isFailedCall(data[base + 3]) ? 0n : big7(data[base + 3]);
33485
+ const creditLimit = isFailedCall(data[base + 2]) ? 0n : big8(data[base + 2]);
33486
+ const withdrawalLimit = isFailedCall(data[base + 3]) ? 0n : big8(data[base + 3]);
32906
33487
  const lenderKey = inverseLenderKey(lender, market.address);
32907
33488
  const metaMap = meta?.[lenderKey];
32908
33489
  if (!metaMap) return;
@@ -32988,7 +33569,7 @@ var getInverseUserDataConverter = (lender, chainId, account, meta) => {
32988
33569
  expected
32989
33570
  ];
32990
33571
  };
32991
- var big8 = (v) => {
33572
+ var big9 = (v) => {
32992
33573
  try {
32993
33574
  if (typeof v === "bigint") return v;
32994
33575
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -32998,7 +33579,7 @@ var big8 = (v) => {
32998
33579
  };
32999
33580
  var arrAt = (v, i) => {
33000
33581
  if (isFailedCall(v) || !Array.isArray(v)) return 0n;
33001
- return big8(v[i]);
33582
+ return big9(v[i]);
33002
33583
  };
33003
33584
  var getLlamaLendUserDataConverter = (lender, chainId, account, meta) => {
33004
33585
  const cfg = llamaLendConfigFor(lender, chainId);
@@ -33013,24 +33594,24 @@ var getLlamaLendUserDataConverter = (lender, chainId, account, meta) => {
33013
33594
  const base = i * LLAMALEND_CALLS_PER_MARKET;
33014
33595
  const stateRaw = data[base];
33015
33596
  if (isFailedCall(stateRaw) || !Array.isArray(stateRaw)) return;
33016
- const collateral = big8(stateRaw[0]);
33017
- const bandBorrowed = big8(stateRaw[1]);
33018
- const debt = big8(stateRaw[2]);
33019
- const bandCount = Number(big8(stateRaw[3]));
33597
+ const collateral = big9(stateRaw[0]);
33598
+ const bandBorrowed = big9(stateRaw[1]);
33599
+ const debt = big9(stateRaw[2]);
33600
+ const bandCount = Number(big9(stateRaw[3]));
33020
33601
  const vaultSharesRaw = data[base + 5];
33021
33602
  const gaugeSharesRaw = data[base + 6];
33022
- const vaultShares = isFailedCall(vaultSharesRaw) ? 0n : big8(vaultSharesRaw);
33023
- const gaugeShares = isFailedCall(gaugeSharesRaw) ? 0n : big8(gaugeSharesRaw);
33603
+ const vaultShares = isFailedCall(vaultSharesRaw) ? 0n : big9(vaultSharesRaw);
33604
+ const gaugeShares = isFailedCall(gaugeSharesRaw) ? 0n : big9(gaugeSharesRaw);
33024
33605
  const lendShares = vaultShares + gaugeShares;
33025
33606
  if (collateral === 0n && debt === 0n && bandBorrowed === 0n && lendShares === 0n)
33026
33607
  return;
33027
33608
  const healthRaw = data[base + 1];
33028
- const health = isFailedCall(healthRaw) ? 0n : big8(healthRaw);
33609
+ const health = isFailedCall(healthRaw) ? 0n : big9(healthRaw);
33029
33610
  const pricesRaw = data[base + 2];
33030
33611
  const priceUpper = arrAt(pricesRaw, 0);
33031
33612
  const priceLower = arrAt(pricesRaw, 1);
33032
33613
  const ticksRaw = data[base + 3];
33033
- const bands = isFailedCall(ticksRaw) || !Array.isArray(ticksRaw) ? void 0 : [Number(big8(ticksRaw[0])), Number(big8(ticksRaw[1]))];
33614
+ const bands = isFailedCall(ticksRaw) || !Array.isArray(ticksRaw) ? void 0 : [Number(big9(ticksRaw[0])), Number(big9(ticksRaw[1]))];
33034
33615
  const approvalRaw = data[base + 4];
33035
33616
  const delegated = isFailedCall(approvalRaw) ? false : approvalRaw === true;
33036
33617
  const lenderKey = llamaLendLenderKey(lender, market.controller);
@@ -33051,7 +33632,7 @@ var getLlamaLendUserDataConverter = (lender, chainId, account, meta) => {
33051
33632
  const loanOracle = loanMeta ? getOraclePrice(loanMeta) : 0;
33052
33633
  const loanHist = loanMeta?.price?.priceUsd24h ?? loanDisplay;
33053
33634
  const shareToAssetRaw = data[base + 7];
33054
- const shareToAsset = isFailedCall(shareToAssetRaw) ? 0n : big8(shareToAssetRaw);
33635
+ const shareToAsset = isFailedCall(shareToAssetRaw) ? 0n : big9(shareToAssetRaw);
33055
33636
  const lendAssets = shareToAsset === 0n ? 0n : lendShares * shareToAsset / 10n ** 18n;
33056
33637
  const lendStr = parseRawAmount(lendAssets.toString(), loanDecimals);
33057
33638
  const depositStr = parseRawAmount(
@@ -33140,7 +33721,7 @@ var getLlamaLendUserDataConverter = (lender, chainId, account, meta) => {
33140
33721
  expected
33141
33722
  ];
33142
33723
  };
33143
- var big9 = (v) => {
33724
+ var big10 = (v) => {
33144
33725
  try {
33145
33726
  if (typeof v === "bigint") return v;
33146
33727
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -33148,7 +33729,7 @@ var big9 = (v) => {
33148
33729
  }
33149
33730
  return 0n;
33150
33731
  };
33151
- var tupleAt = (v, i) => Array.isArray(v) ? big9(v[i]) : 0n;
33732
+ var tupleAt = (v, i) => Array.isArray(v) ? big10(v[i]) : 0n;
33152
33733
  var ONE4 = 10n ** 18n;
33153
33734
  function sharesToAmount(shares, totalAmount, totalShares) {
33154
33735
  if (totalShares === 0n || shares === 0n) return 0n;
@@ -33174,7 +33755,7 @@ var getResupplyUserDataConverter = (lender, chainId, account, meta) => {
33174
33755
  if (isFailedCall(accounting) || !Array.isArray(accounting)) return;
33175
33756
  const totalBorrowAmount = tupleAt(accounting, 1);
33176
33757
  const totalBorrowShares = tupleAt(accounting, 2);
33177
- const sharePrice = isFailedCall(data[base + 1]) ? 0n : big9(data[base + 1]);
33758
+ const sharePrice = isFailedCall(data[base + 1]) ? 0n : big10(data[base + 1]);
33178
33759
  const lenderKey = resupplyLenderKey(lender, chainId, pair);
33179
33760
  const metaMap = meta?.[lenderKey];
33180
33761
  if (!metaMap) return;
@@ -33272,7 +33853,7 @@ var getResupplyUserDataConverter = (lender, chainId, account, meta) => {
33272
33853
  expected
33273
33854
  ];
33274
33855
  };
33275
- var big10 = (v) => {
33856
+ var big11 = (v) => {
33276
33857
  try {
33277
33858
  if (typeof v === "bigint") return v;
33278
33859
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -33303,9 +33884,9 @@ var getFraxlendUserDataConverter = (lender, chainId, account, meta) => {
33303
33884
  const fTokenRaw = data[base + 2];
33304
33885
  const previewRaw = data[base + 3];
33305
33886
  if (isFailedCall(collRaw) || isFailedCall(sharesRaw)) return;
33306
- const collateral = big10(collRaw);
33307
- const borrowShares = big10(sharesRaw);
33308
- const fTokenShares = isFailedCall(fTokenRaw) ? 0n : big10(fTokenRaw);
33887
+ const collateral = big11(collRaw);
33888
+ const borrowShares = big11(sharesRaw);
33889
+ const fTokenShares = isFailedCall(fTokenRaw) ? 0n : big11(fTokenRaw);
33309
33890
  if (collateral === 0n && borrowShares === 0n && fTokenShares === 0n)
33310
33891
  return;
33311
33892
  let totalBorrowAmount = 0n;
@@ -33315,10 +33896,10 @@ var getFraxlendUserDataConverter = (lender, chainId, account, meta) => {
33315
33896
  if (!isFailedCall(previewRaw) && previewRaw) {
33316
33897
  const ta = previewRaw[4];
33317
33898
  const tb = previewRaw[5];
33318
- totalAssetAmount = big10(ta?.amount ?? ta?.[0]);
33319
- totalAssetShares = big10(ta?.shares ?? ta?.[1]);
33320
- totalBorrowAmount = big10(tb?.amount ?? tb?.[0]);
33321
- totalBorrowShares = big10(tb?.shares ?? tb?.[1]);
33899
+ totalAssetAmount = big11(ta?.amount ?? ta?.[0]);
33900
+ totalAssetShares = big11(ta?.shares ?? ta?.[1]);
33901
+ totalBorrowAmount = big11(tb?.amount ?? tb?.[0]);
33902
+ totalBorrowShares = big11(tb?.shares ?? tb?.[1]);
33322
33903
  }
33323
33904
  const debt = fraxlendToAmount(
33324
33905
  borrowShares,
@@ -33426,7 +34007,7 @@ var getFraxlendUserDataConverter = (lender, chainId, account, meta) => {
33426
34007
  ];
33427
34008
  };
33428
34009
  var WAD13 = 10n ** 18n;
33429
- var big11 = (v) => {
34010
+ var big12 = (v) => {
33430
34011
  try {
33431
34012
  if (typeof v === "bigint") return v;
33432
34013
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -33434,7 +34015,7 @@ var big11 = (v) => {
33434
34015
  }
33435
34016
  return 0n;
33436
34017
  };
33437
- var tupleAt2 = (v, i) => Array.isArray(v) ? big11(v[i]) : 0n;
34018
+ var tupleAt2 = (v, i) => Array.isArray(v) ? big12(v[i]) : 0n;
33438
34019
  var HOLD_PERIOD_SECONDS = 1200n;
33439
34020
  var getCurvanceUserDataConverter = (lender, chainId, account, meta) => {
33440
34021
  const cfg = curvanceConfigFor(lender, chainId);
@@ -33457,7 +34038,7 @@ var getCurvanceUserDataConverter = (lender, chainId, account, meta) => {
33457
34038
  const cooldownRaw = data[base];
33458
34039
  const status = data[base + 1];
33459
34040
  if (isFailedCall(status) || !Array.isArray(status)) continue;
33460
- const cooldownTimestamp = isFailedCall(cooldownRaw) ? 0n : big11(cooldownRaw);
34041
+ const cooldownTimestamp = isFailedCall(cooldownRaw) ? 0n : big12(cooldownRaw);
33461
34042
  const holdPeriodEndsAt = cooldownTimestamp > 0n ? cooldownTimestamp + HOLD_PERIOD_SECONDS : 0n;
33462
34043
  const holdPeriodActive = holdPeriodEndsAt > nowSeconds;
33463
34044
  const lenderKey = curvanceLenderKey(lender, chainId, p.marketManager);
@@ -33479,10 +34060,10 @@ var getCurvanceUserDataConverter = (lender, chainId, account, meta) => {
33479
34060
  let rows = 0;
33480
34061
  p.activeTokens.forEach(({ cToken, asset }, i) => {
33481
34062
  const tokenBase = base + CURVANCE_MARKET_READS + i * CURVANCE_READS_PER_TOKEN;
33482
- const shares = isFailedCall(data[tokenBase]) ? 0n : big11(data[tokenBase]);
33483
- const collateralShares = isFailedCall(data[tokenBase + 1]) ? 0n : big11(data[tokenBase + 1]);
33484
- const debtRaw = isFailedCall(data[tokenBase + 2]) ? 0n : big11(data[tokenBase + 2]);
33485
- const exchangeRate = isFailedCall(data[tokenBase + 3]) ? 0n : big11(data[tokenBase + 3]);
34063
+ const shares = isFailedCall(data[tokenBase]) ? 0n : big12(data[tokenBase]);
34064
+ const collateralShares = isFailedCall(data[tokenBase + 1]) ? 0n : big12(data[tokenBase + 1]);
34065
+ const debtRaw = isFailedCall(data[tokenBase + 2]) ? 0n : big12(data[tokenBase + 2]);
34066
+ const exchangeRate = isFailedCall(data[tokenBase + 3]) ? 0n : big12(data[tokenBase + 3]);
33486
34067
  info.tokens[cToken.toLowerCase()] = {
33487
34068
  shares: shares.toString(),
33488
34069
  collateralShares: collateralShares.toString(),
@@ -33541,8 +34122,152 @@ var getCurvanceUserDataConverter = (lender, chainId, account, meta) => {
33541
34122
  expected
33542
34123
  ];
33543
34124
  };
33544
- var RAY5 = 10n ** 27n;
33545
- var big12 = (v) => {
34125
+ var WAD14 = 10n ** 18n;
34126
+ var big13 = (v) => {
34127
+ try {
34128
+ if (typeof v === "bigint") return v;
34129
+ if (typeof v === "number" || typeof v === "string") return BigInt(v);
34130
+ } catch {
34131
+ }
34132
+ return 0n;
34133
+ };
34134
+ var getTwyneUserDataConverter = (lender, chainId, account, meta) => {
34135
+ const discovery = getCachedTwyneDiscovery(chainId, lender, account);
34136
+ const vaults = discovery?.vaults ?? [];
34137
+ const expected = vaults.length * TWYNE_READS_PER_VAULT;
34138
+ const markets = twyneChainData(lender, chainId)?.markets ?? [];
34139
+ return [
34140
+ (data) => {
34141
+ if (expected === 0) return void 0;
34142
+ if (!data || data.length < expected) return void 0;
34143
+ const byMarket = /* @__PURE__ */ new Map();
34144
+ vaults.forEach((ref, i) => {
34145
+ const base = i * TWYNE_READS_PER_VAULT;
34146
+ const totalRaw = data[base];
34147
+ if (isFailedCall(totalRaw)) return;
34148
+ const total = big13(totalRaw);
34149
+ const reserved = isFailedCall(data[base + 1]) ? 0n : big13(data[base + 1]);
34150
+ const debt = isFailedCall(data[base + 2]) ? 0n : big13(data[base + 2]);
34151
+ const liqLtv = isFailedCall(data[base + 3]) ? 0n : big13(data[base + 3]);
34152
+ const canLiquidate = isFailedCall(data[base + 4]) ? false : Boolean(data[base + 4]);
34153
+ const extLiquidated = isFailedCall(data[base + 5]) ? false : Boolean(data[base + 5]);
34154
+ const releasable = isFailedCall(data[base + 6]) ? 0n : big13(data[base + 6]);
34155
+ const scale3 = isFailedCall(data[base + 8]) ? WAD14 : big13(data[base + 8]) || WAD14;
34156
+ const userCollateral = total > reserved ? total - reserved : 0n;
34157
+ if (userCollateral === 0n && debt === 0n) return;
34158
+ const market = markets.find(
34159
+ (m) => m.intermediateVault.toLowerCase() === ref.intermediateVault && m.targetAsset.toLowerCase() === ref.targetAsset
34160
+ );
34161
+ if (!market) return;
34162
+ const lenderKey = twyneLenderKey(lender, chainId, ref.intermediateVault, ref.targetAsset);
34163
+ if (!byMarket.has(lenderKey)) {
34164
+ byMarket.set(lenderKey, {
34165
+ collAddr: market.underlyingAsset.toLowerCase(),
34166
+ debtAddr: market.targetAsset.toLowerCase(),
34167
+ rows: []
34168
+ });
34169
+ }
34170
+ byMarket.get(lenderKey).rows.push({
34171
+ coll: userCollateral * scale3 / WAD14,
34172
+ debt,
34173
+ info: {
34174
+ collateralVault: ref.vault,
34175
+ intermediateVault: ref.intermediateVault,
34176
+ totalAssetsDepositedOrReserved: total.toString(),
34177
+ reservedCredit: reserved.toString(),
34178
+ userCollateral: userCollateral.toString(),
34179
+ debt: debt.toString(),
34180
+ twyneLiqLtv: liqLtv.toString(),
34181
+ canLiquidate,
34182
+ isExternallyLiquidated: extLiquidated,
34183
+ releasableCredit: releasable.toString(),
34184
+ collateralToUnderlying: scale3.toString()
34185
+ }
34186
+ });
34187
+ });
34188
+ const out = {};
34189
+ for (const [lenderKey, market] of byMarket) {
34190
+ const metaMap = meta?.[lenderKey];
34191
+ if (!metaMap) continue;
34192
+ const collUid = createMarketUid(chainId, lenderKey, market.collAddr);
34193
+ const debtUid = createMarketUid(chainId, lenderKey, market.debtAddr);
34194
+ const collMeta = metaMap[collUid];
34195
+ const debtMeta = metaMap[debtUid];
34196
+ if (!collMeta && !debtMeta) continue;
34197
+ const collDecimals = collMeta?.asset?.decimals ?? 18;
34198
+ const debtDecimals = debtMeta?.asset?.decimals ?? 18;
34199
+ const collDisplay = collMeta ? getDisplayPrice(collMeta) : 0;
34200
+ const collOracle = collMeta ? getOraclePrice(collMeta) : 0;
34201
+ const collHist = collMeta?.price?.priceUsd24h ?? collDisplay;
34202
+ const debtDisplay = debtMeta ? getDisplayPrice(debtMeta) : 0;
34203
+ const debtOracle = debtMeta ? getOraclePrice(debtMeta) : 0;
34204
+ const debtHist = debtMeta?.price?.priceUsd24h ?? debtDisplay;
34205
+ const lendingPositions = {};
34206
+ const modes = {};
34207
+ const hist = {};
34208
+ for (const row of market.rows) {
34209
+ const id = row.info.collateralVault;
34210
+ const collStr = parseRawAmount(row.coll.toString(), collDecimals);
34211
+ const collNum = Number(collStr);
34212
+ const debtStr = parseRawAmount(row.debt.toString(), debtDecimals);
34213
+ const debtNum = Number(debtStr);
34214
+ lendingPositions[id] = {
34215
+ [collUid]: {
34216
+ marketUid: collUid,
34217
+ underlying: market.collAddr,
34218
+ deposits: collStr,
34219
+ debt: "0",
34220
+ debtStable: "0",
34221
+ depositsUSD: collNum * collDisplay,
34222
+ debtUSD: 0,
34223
+ debtStableUSD: 0,
34224
+ depositsUSDOracle: collNum * collOracle,
34225
+ debtUSDOracle: 0,
34226
+ debtStableUSDOracle: 0,
34227
+ stableBorrowRate: "0",
34228
+ collateralEnabled: true,
34229
+ claimableRewards: 0,
34230
+ twyneInfo: row.info
34231
+ },
34232
+ [debtUid]: {
34233
+ marketUid: debtUid,
34234
+ underlying: market.debtAddr,
34235
+ deposits: "0",
34236
+ debt: debtStr,
34237
+ debtStable: "0",
34238
+ depositsUSD: 0,
34239
+ debtUSD: debtNum * debtDisplay,
34240
+ debtStableUSD: 0,
34241
+ depositsUSDOracle: 0,
34242
+ debtUSDOracle: debtNum * debtOracle,
34243
+ debtStableUSDOracle: 0,
34244
+ stableBorrowRate: "0",
34245
+ collateralEnabled: false,
34246
+ claimableRewards: 0,
34247
+ twyneInfo: row.info
34248
+ }
34249
+ };
34250
+ modes[id] = Number(row.info.twyneLiqLtv) / 1e4;
34251
+ hist[id] = {
34252
+ totalDeposits24h: collNum * collHist,
34253
+ totalDebt24h: debtNum * debtHist
34254
+ };
34255
+ }
34256
+ if (Object.keys(lendingPositions).length === 0) continue;
34257
+ const userData = createMultiAccountTypeUserState(
34258
+ { chainId, account, lendingPositions, modes },
34259
+ metaMap,
34260
+ hist
34261
+ );
34262
+ if (userData && userData.data.length > 0) out[lenderKey] = userData;
34263
+ }
34264
+ return Object.keys(out).length > 0 ? out : void 0;
34265
+ },
34266
+ expected
34267
+ ];
34268
+ };
34269
+ var RAY7 = 10n ** 27n;
34270
+ var big14 = (v) => {
33546
34271
  try {
33547
34272
  if (typeof v === "bigint") return v;
33548
34273
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -33550,7 +34275,7 @@ var big12 = (v) => {
33550
34275
  }
33551
34276
  return 0n;
33552
34277
  };
33553
- var field9 = (res, name, idx) => big12(res?.[name] ?? res?.[idx]);
34278
+ var field9 = (res, name, idx) => big14(res?.[name] ?? res?.[idx]);
33554
34279
  var getDssUserDataConverter = (lender, chainId, account, meta) => {
33555
34280
  const cfg = dssConfigFor(lender, chainId);
33556
34281
  const markets = dssChainData(lender, chainId)?.markets ?? [];
@@ -33577,8 +34302,8 @@ var getDssUserDataConverter = (lender, chainId, account, meta) => {
33577
34302
  if (isFailedCall(res)) return;
33578
34303
  const ink = field9(res, "ink", 0);
33579
34304
  const art = field9(res, "art", 1);
33580
- const rate = rateByIlk.get(cdp.ilk) ?? RAY5;
33581
- const debt = art * rate / RAY5;
34305
+ const rate = rateByIlk.get(cdp.ilk) ?? RAY7;
34306
+ const debt = art * rate / RAY7;
33582
34307
  if (ink === 0n && debt === 0n) return;
33583
34308
  const market = markets.find((m) => m.ilk === cdp.ilk);
33584
34309
  if (!market) return;
@@ -33665,7 +34390,7 @@ var getDssUserDataConverter = (lender, chainId, account, meta) => {
33665
34390
  expected
33666
34391
  ];
33667
34392
  };
33668
- var big13 = (v) => {
34393
+ var big15 = (v) => {
33669
34394
  try {
33670
34395
  if (typeof v === "bigint") return v;
33671
34396
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -33695,11 +34420,11 @@ var getFrankencoinUserDataConverter = (lender, chainId, account, meta) => {
33695
34420
  const ownerRes = data[base];
33696
34421
  if (isFailedCall(ownerRes)) return;
33697
34422
  if (String(ownerRes).toLowerCase() !== lowerAccount) return;
33698
- const minted = big13(data[base + 1]);
33699
- const price2 = big13(data[base + 2]);
33700
- const expiration = big13(data[base + 3]);
33701
- const challenged = big13(data[base + 4]);
33702
- const coll = big13(data[base + 5]);
34423
+ const minted = big15(data[base + 1]);
34424
+ const price2 = big15(data[base + 2]);
34425
+ const expiration = big15(data[base + 3]);
34426
+ const challenged = big15(data[base + 4]);
34427
+ const coll = big15(data[base + 5]);
33703
34428
  if (minted === 0n && coll === 0n) return;
33704
34429
  const market = marketByOriginal.get(p.original);
33705
34430
  if (!market) return;
@@ -33800,7 +34525,7 @@ var getFrankencoinUserDataConverter = (lender, chainId, account, meta) => {
33800
34525
 
33801
34526
  // src/lending/user-data/teller/userCallParse.ts
33802
34527
  var nowSec7 = () => Math.floor(Date.now() / 1e3);
33803
- var big14 = (v) => {
34528
+ var big16 = (v) => {
33804
34529
  try {
33805
34530
  if (typeof v === "bigint") return v;
33806
34531
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -33822,7 +34547,7 @@ var getTellerUserDataConverter = (_lender, chainId, account, meta) => {
33822
34547
  const base = i * TELLER_CALLS_PER_BID;
33823
34548
  const bidRes = data[base];
33824
34549
  const owed = data[base + 1];
33825
- const collAmount = big14(data[base + 2]);
34550
+ const collAmount = big16(data[base + 2]);
33826
34551
  const defaulted = !!data[base + 3];
33827
34552
  if (isFailedCall(bidRes) || isFailedCall(owed) || !bidRes) return;
33828
34553
  const pool = b.pool;
@@ -33843,17 +34568,17 @@ var getTellerUserDataConverter = (_lender, chainId, account, meta) => {
33843
34568
  const collDisplay = collMeta ? getDisplayPrice(collMeta) : 0;
33844
34569
  const collOracle = collMeta ? getOraclePrice(collMeta) : 0;
33845
34570
  const collHist = collMeta?.price?.priceUsd24h ?? collDisplay;
33846
- const owedPrincipal = big14(field10(owed, "principal", 0));
33847
- const owedInterest = big14(field10(owed, "interest", 1));
34571
+ const owedPrincipal = big16(field10(owed, "principal", 0));
34572
+ const owedInterest = big16(field10(owed, "interest", 1));
33848
34573
  const owedTotal = owedPrincipal + owedInterest;
33849
34574
  if (owedTotal === 0n && collAmount === 0n) return;
33850
34575
  const loanDetails = field10(bidRes, "loanDetails", 5);
33851
34576
  const terms = field10(bidRes, "terms", 6);
33852
34577
  const acceptedTs = Number(
33853
- big14(field10(loanDetails, "acceptedTimestamp", 4))
34578
+ big16(field10(loanDetails, "acceptedTimestamp", 4))
33854
34579
  );
33855
- const loanDuration = Number(big14(field10(loanDetails, "loanDuration", 6)));
33856
- const aprBps = Number(big14(field10(terms, "APR", 2)));
34580
+ const loanDuration = Number(big16(field10(loanDetails, "loanDuration", 6)));
34581
+ const aprBps = Number(big16(field10(terms, "APR", 2)));
33857
34582
  const maturity = acceptedTs > 0 ? acceptedTs + loanDuration : void 0;
33858
34583
  const isMatured2 = defaulted || maturity !== void 0 && maturity < now;
33859
34584
  const collStr = parseRawAmount(collAmount.toString(), collDecimals);
@@ -34238,6 +34963,8 @@ function getUserDataConverter(lender, chainId, account, params, meta) {
34238
34963
  return getFraxlendUserDataConverter(lender, chainId, account, meta);
34239
34964
  if (isCurvance(lender))
34240
34965
  return getCurvanceUserDataConverter(lender, chainId, account, meta);
34966
+ if (isTwyne(lender))
34967
+ return getTwyneUserDataConverter(lender, chainId, account, meta);
34241
34968
  if (isDssType(lender))
34242
34969
  return getDssUserDataConverter(lender, chainId, account, meta);
34243
34970
  if (isFrankencoin(lender))
@@ -38905,6 +39632,7 @@ var getAbi2 = (lender) => {
38905
39632
  return [...ResupplyPairAbi, ...VAULT_CONVERT_ABI];
38906
39633
  if (isCurvance(lender))
38907
39634
  return [...CurvanceMarketManagerAbi, ...CurvanceCTokenAbi];
39635
+ if (isTwyne(lender)) return [...TwyneCollateralVaultAbi];
38908
39636
  if (isInit(lender)) return InitLensAbi;
38909
39637
  if (isEulerType(lender)) return accountLensAbi;
38910
39638
  if (isCompoundV2Type(lender))
@@ -41161,6 +41889,49 @@ var hbuhypeFetcher = {
41161
41889
  }
41162
41890
  }
41163
41891
  };
41892
+ var HYPERBEAT_VAULTS = [
41893
+ {
41894
+ address: "0x5e105266db42f78FA814322Bce7f388B4C2e61eb",
41895
+ key: "Hyperbeat USDT::hbUSDT"
41896
+ },
41897
+ {
41898
+ address: "0x057ced81348D57Aad579A672d521d7b4396E8a61",
41899
+ key: "Hyperbeat USDC::hbUSDC"
41900
+ },
41901
+ {
41902
+ address: "0x81e064d0eB539de7c3170EDF38C1A42CBd752A76",
41903
+ key: "Hyperbeat LST Vault::lstHYPE"
41904
+ },
41905
+ {
41906
+ address: "0x441794D6a8F9A3739F5D4E98a728937b33489D29",
41907
+ key: "Liquid HYPE Yield::liquidHYPE"
41908
+ }
41909
+ ];
41910
+ var HYPERBEAT_VAULT_APY_URL = (address) => `https://api.hyperbeat.org/api/v1/vaults/apy/${address}?limit=1`;
41911
+ var hyperbeatVaultsFetcher = {
41912
+ label: "HYPERBEAT_VAULTS",
41913
+ fetch: async () => {
41914
+ const out = {};
41915
+ await Promise.all(
41916
+ HYPERBEAT_VAULTS.map(async ({ address, key: key3 }) => {
41917
+ try {
41918
+ const response = await fetch(HYPERBEAT_VAULT_APY_URL(address));
41919
+ if (!response.ok) {
41920
+ throw new Error(`HTTP error! Status: ${response.status}`);
41921
+ }
41922
+ const result = await response.json();
41923
+ const apy = Number(
41924
+ result.current_apy?.apy_7d ?? result.current_apy?.apy ?? 0
41925
+ );
41926
+ out[key3] = apyToAprPercent(apy);
41927
+ } catch (e) {
41928
+ out[key3] = 0;
41929
+ }
41930
+ })
41931
+ );
41932
+ return out;
41933
+ }
41934
+ };
41164
41935
 
41165
41936
  // src/yields/intrinsic/fetchers/coinbase.ts
41166
41937
  var CBETH_URL = "https://api.exchange.coinbase.com/wrapped-assets/cbeth";
@@ -43769,7 +44540,7 @@ var hastraPrimeFetcher = {
43769
44540
  return { [HASTRA_PRIME_KEY]: Math.max(0, apr) };
43770
44541
  }
43771
44542
  };
43772
- var RAY6 = 10n ** 27n;
44543
+ var RAY8 = 10n ** 27n;
43773
44544
  var YEAR_SECONDS6 = 31536e3;
43774
44545
  var SPARK_VAULTS_V2 = [
43775
44546
  {
@@ -43846,8 +44617,8 @@ var SSR_ABI = [
43846
44617
  }
43847
44618
  ];
43848
44619
  var aprFromVsr = (vsr) => {
43849
- if (vsr <= RAY6) return 0;
43850
- const perSecond = Number(vsr - RAY6) / 1e27;
44620
+ if (vsr <= RAY8) return 0;
44621
+ const perSecond = Number(vsr - RAY8) / 1e27;
43851
44622
  return perSecond * YEAR_SECONDS6 * 100;
43852
44623
  };
43853
44624
  var chainsOf = (vaults) => [
@@ -43867,7 +44638,7 @@ var fetchChain = async (chainId, vaults) => {
43867
44638
  const out = {};
43868
44639
  vaults.forEach((v, i) => {
43869
44640
  const vsr = results[i];
43870
- if (typeof vsr !== "bigint" || vsr < RAY6) return;
44641
+ if (typeof vsr !== "bigint" || vsr < RAY8) return;
43871
44642
  const apr = aprFromVsr(vsr);
43872
44643
  out[sparkVaultV2Key(v.chainId, v.symbol)] = apr;
43873
44644
  if (v.assetGroup) out[v.assetGroup] = apr;
@@ -43881,7 +44652,7 @@ var fetchSusdcApr = async () => {
43881
44652
  calls: [{ address: SKY_SSR_SOURCE, name: "ssr", params: [] }],
43882
44653
  allowFailure: false
43883
44654
  });
43884
- if (typeof ssr !== "bigint" || ssr < RAY6) {
44655
+ if (typeof ssr !== "bigint" || ssr < RAY8) {
43885
44656
  throw new Error("Spark sUSDC: unreadable ssr()");
43886
44657
  }
43887
44658
  const apr = aprFromVsr(ssr);
@@ -44603,7 +45374,7 @@ var strataFetcher = {
44603
45374
  return out;
44604
45375
  }
44605
45376
  };
44606
- var RAY7 = 10n ** 27n;
45377
+ var RAY9 = 10n ** 27n;
44607
45378
  var YEAR_SECONDS11 = 31536e3;
44608
45379
  var DSR_ABI = [
44609
45380
  {
@@ -44630,8 +45401,8 @@ var USDD_EARN_APY_URL = "https://openapi.usdd.io/api/v1/external/earn-apy";
44630
45401
  var susddKey = (chainId) => `USDD::${chainId}::sUSDD`;
44631
45402
  var SUSDD_GROUP_KEY = "Savings Usdd::sUSDD";
44632
45403
  var aprFromDsr = (dsr) => {
44633
- if (dsr <= RAY7) return 0;
44634
- const perSecond = Number(dsr - RAY7) / 1e27;
45404
+ if (dsr <= RAY9) return 0;
45405
+ const perSecond = Number(dsr - RAY9) / 1e27;
44635
45406
  return perSecond * YEAR_SECONDS11 * 100;
44636
45407
  };
44637
45408
  var fetchChainDsr = async (chainId, pot) => {
@@ -44641,7 +45412,7 @@ var fetchChainDsr = async (chainId, pot) => {
44641
45412
  calls: [{ address: pot, name: "dsr", params: [] }],
44642
45413
  allowFailure: false
44643
45414
  });
44644
- if (typeof dsr !== "bigint" || dsr < RAY7) {
45415
+ if (typeof dsr !== "bigint" || dsr < RAY9) {
44645
45416
  throw new Error(`USDD: unreadable dsr() on chain ${chainId}`);
44646
45417
  }
44647
45418
  return aprFromDsr(dsr);
@@ -44749,7 +45520,7 @@ var fetchRatesFromApi = async () => {
44749
45520
  const perChain = body?.status?.[d.chainId];
44750
45521
  if (!perChain) continue;
44751
45522
  const entry = Object.entries(perChain).find(
44752
- ([addr3]) => addr3.toLowerCase() === d.module.toLowerCase()
45523
+ ([addr4]) => addr4.toLowerCase() === d.module.toLowerCase()
44753
45524
  )?.[1];
44754
45525
  const rate = entry?.rate;
44755
45526
  if (typeof rate === "number" && Number.isFinite(rate)) {
@@ -47448,6 +48219,121 @@ var SINGLE_CHAIN_ENTRIES = {
47448
48219
  yieldKey: zchfSavingsKey(Chain.BASE)
47449
48220
  }
47450
48221
  ],
48222
+ // HyperEVM — the four LIVE core Hyperbeat vaults (Vault-Infra
48223
+ // generation, audited by Nethermind + Certora). All facts below were
48224
+ // read on-chain / from Hyperbeat's own app config on 2026-08-18:
48225
+ //
48226
+ // - The share tokens are NOT ERC-4626 (bare upgradeable ERC-20s, a
48227
+ // renamed Midas mToken lineage) — hence the `hyperbeat-vault` reader
48228
+ // over each vault's Pricer/Depositor/WithdrawalQueue triplet.
48229
+ // - The Midas periphery the DOCS still list is RETIRED: both its
48230
+ // instant paths revert `Pausable: paused` and its NAV aggregators
48231
+ // last updated 2025-12-22. Never build against the docs' addresses.
48232
+ // - Exit is two-legged (`fee-or-queued`): `instantWithdraw` at the
48233
+ // queue's `instantWithdrawalFee` (30 bps live — the docs' 0.5% is
48234
+ // the retired stack), capped by the queue's own baseAsset balance
48235
+ // (ops-topped, often 0); or a free `createWithdrawalRequest`
48236
+ // processed by ops and PAID OUT AUTOMATICALLY — no claim step, but
48237
+ // cancellable while pending.
48238
+ // - Deposits are permissionless and uncapped (`isPaused` false,
48239
+ // `depositCap` 0 = uncapped, no fee), via the Depositor
48240
+ // (`mintContract`) — NOT the share token.
48241
+ // - Solvency is deliberately ABSENT: strategies custody assets across
48242
+ // HyperEVM protocols and Hyperliquid (HyperCore) strategist
48243
+ // accounts, and the Pricer's rate is operator-published with no
48244
+ // on-chain solvency invariant (the Native/Maple trust class).
48245
+ //
48246
+ // Deliberately NOT listed: hbXAUt, wVLP, dnHYPE, dnPUMP — all flagged
48247
+ // `windingDown` in Hyperbeat's app config; nLP (Native's wNLP — the
48248
+ // `native` provider's surface); hbHYPE/hbBTC (Upshift-era, already
48249
+ // served by the LST registry / upshift provider).
48250
+ "999": [
48251
+ {
48252
+ reader: "hyperbeat-vault",
48253
+ address: "0x5e105266db42f78fa814322bce7f388b4c2e61eb",
48254
+ underlying: "0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb",
48255
+ // USDT0
48256
+ symbol: "hbUSDT",
48257
+ brand: "Hyperbeat",
48258
+ description: "hbUSDT deploys USDT0 across HyperEVM protocols and Hyperliquid strategist accounts for market-neutral stablecoin yield (20% performance fee, already netted in the rate). The share price is published by the vault's own Pricer with no on-chain solvency invariant. Exit is two-legged: instant at a 0.3% fee capped by the queue's live inventory, or a free withdrawal request processed within ~1 day and paid out automatically.",
48259
+ decimals: 18,
48260
+ underlyingDecimals: 6,
48261
+ isRebasing: false,
48262
+ isMintable: true,
48263
+ mintContract: "0x6261f30144b259c74243d5f5d9230941186ac936",
48264
+ withdrawalMode: "fee-or-queued",
48265
+ withdrawalCooldownSeconds: 86400,
48266
+ withdrawQueue: "0x240e0b2cb615ded2fe90fde265b15988dc45b1c6",
48267
+ inventoryContract: "0x240e0b2cb615ded2fe90fde265b15988dc45b1c6",
48268
+ priceOracle: "0x3636a26ec1d512c5ecff42f7adaa5ce7964c6579",
48269
+ yieldFetcher: hyperbeatVaultsFetcher,
48270
+ yieldKey: "Hyperbeat USDT::hbUSDT"
48271
+ },
48272
+ {
48273
+ reader: "hyperbeat-vault",
48274
+ address: "0x057ced81348d57aad579a672d521d7b4396e8a61",
48275
+ underlying: "0xb88339cb7199b77e23db6e890353e22632ba630f",
48276
+ // USDC
48277
+ symbol: "hbUSDC",
48278
+ brand: "Hyperbeat",
48279
+ description: "hbUSDC deploys USDC across HyperEVM protocols and Hyperliquid strategist accounts for market-neutral stablecoin yield (20% performance fee, already netted in the rate). The share price is published by the vault's own Pricer with no on-chain solvency invariant. Exit is two-legged: instant at a 0.3% fee capped by the queue's live inventory, or a free withdrawal request processed within ~1 day and paid out automatically.",
48280
+ decimals: 18,
48281
+ underlyingDecimals: 6,
48282
+ isRebasing: false,
48283
+ isMintable: true,
48284
+ mintContract: "0x929df52b0c3315d03922e12e54b46157395be4d0",
48285
+ withdrawalMode: "fee-or-queued",
48286
+ withdrawalCooldownSeconds: 86400,
48287
+ withdrawQueue: "0x10024239474120ce410dd7ce203793c81d438be3",
48288
+ inventoryContract: "0x10024239474120ce410dd7ce203793c81d438be3",
48289
+ priceOracle: "0xe0995a641d454c149e6c808baa37cb2b38763316",
48290
+ yieldFetcher: hyperbeatVaultsFetcher,
48291
+ yieldKey: "Hyperbeat USDC::hbUSDC"
48292
+ },
48293
+ {
48294
+ reader: "hyperbeat-vault",
48295
+ address: "0x81e064d0eb539de7c3170edf38c1a42cbd752a76",
48296
+ underlying: "0x5555555555555555555555555555555555555555",
48297
+ // WHYPE
48298
+ symbol: "lstHYPE",
48299
+ brand: "Hyperbeat",
48300
+ description: "lstHYPE deploys WHYPE across HyperEVM protocols and Hyperliquid strategist accounts (20% performance fee, already netted in the rate). The rate is HYPE-denominated and the share price is published by the vault's own Pricer with no on-chain solvency invariant. Exit is two-legged: instant at a 0.3% fee capped by the queue's live inventory, or a free withdrawal request processed within ~3 days and paid out automatically.",
48301
+ decimals: 18,
48302
+ isRebasing: false,
48303
+ isMintable: true,
48304
+ mintContract: "0x205ac1e0380b0b9cce691bd4c6f3c14258ae9201",
48305
+ withdrawalMode: "fee-or-queued",
48306
+ withdrawalCooldownSeconds: 259200,
48307
+ withdrawQueue: "0x8b04cd6561abf2de78112da30ccb919fe8d09d98",
48308
+ inventoryContract: "0x8b04cd6561abf2de78112da30ccb919fe8d09d98",
48309
+ priceOracle: "0x5ed0ec0b0643dab621dc814c8d058e161b9b884b",
48310
+ yieldFetcher: hyperbeatVaultsFetcher,
48311
+ yieldKey: "Hyperbeat LST Vault::lstHYPE"
48312
+ },
48313
+ {
48314
+ // Underlying is beHYPE — itself a yield-bearing LST share, so this
48315
+ // row's rate is the STRATEGY leg only, in beHYPE terms; beHYPE's
48316
+ // staking yield is a separate leg carried by its own assetGroup.
48317
+ reader: "hyperbeat-vault",
48318
+ address: "0x441794d6a8f9a3739f5d4e98a728937b33489d29",
48319
+ underlying: "0xd8fc8f0b03eba61f64d08b0bef69d80916e5dda9",
48320
+ // beHYPE
48321
+ symbol: "liquidHYPE",
48322
+ brand: "Hyperbeat",
48323
+ description: "liquidHYPE deploys beHYPE (Hyperbeat x ether.fi staked HYPE) across HyperEVM strategies; the rate shown is the strategy leg in beHYPE terms and comes ON TOP of beHYPE's own staking yield. The share price is published by the vault's own Pricer with no on-chain solvency invariant. Exit is two-legged: instant at a 0.3% fee capped by the queue's live inventory, or a free withdrawal request processed within ~3 days and paid out automatically.",
48324
+ decimals: 18,
48325
+ isRebasing: false,
48326
+ isMintable: true,
48327
+ mintContract: "0x5bfb09dd155c0ec3f375b266a7353c0ba64f9d60",
48328
+ withdrawalMode: "fee-or-queued",
48329
+ withdrawalCooldownSeconds: 259200,
48330
+ withdrawQueue: "0xa03e0e3b7e6204c9a8d237c4fbd30793555a84fe",
48331
+ inventoryContract: "0xa03e0e3b7e6204c9a8d237c4fbd30793555a84fe",
48332
+ priceOracle: "0x90a0a650f0c403a92ae22f162b3e61818d6f8f11",
48333
+ yieldFetcher: hyperbeatVaultsFetcher,
48334
+ yieldKey: "Liquid HYPE Yield::liquidHYPE"
48335
+ }
48336
+ ],
47451
48337
  "43114": [
47452
48338
  {
47453
48339
  address: "0x06d47f3fb376649c3a9dafe069b3d6e35572219e",
@@ -47764,13 +48650,13 @@ var gmxFetcher = {
47764
48650
  fetch: async () => {
47765
48651
  const { apy } = await fetchGmxRawData(GMX_CHAIN, GMX_DEFAULT_APY_PERIOD);
47766
48652
  const rData = {};
47767
- for (const [addr3, d] of Object.entries(apy.markets ?? {})) {
47768
- const a = addr3.toLowerCase();
48653
+ for (const [addr4, d] of Object.entries(apy.markets ?? {})) {
48654
+ const a = addr4.toLowerCase();
47769
48655
  if (a === gmx_eth_usd_address) rData[gmx_eth_usd] = apyToApr(d.apy) * 100;
47770
48656
  if (a === gmx_btc_usd_address) rData[gmx_btc_usd] = apyToApr(d.apy) * 100;
47771
48657
  }
47772
- for (const [addr3, d] of Object.entries(apy.glvs ?? {})) {
47773
- const a = addr3.toLowerCase();
48658
+ for (const [addr4, d] of Object.entries(apy.glvs ?? {})) {
48659
+ const a = addr4.toLowerCase();
47774
48660
  if (a === glv_wbtc_usdc_address)
47775
48661
  rData[glv_wbtc_usdc] = apyToApr(d.apy) * 100;
47776
48662
  if (a === glv_weth_usdc_address)
@@ -48709,7 +49595,7 @@ var DLEND_POOLS = [
48709
49595
  }
48710
49596
  ];
48711
49597
  var ZERO_ADDRESS7 = "0x0000000000000000000000000000000000000000";
48712
- var SECONDS_PER_YEAR12 = 31536e3;
49598
+ var SECONDS_PER_YEAR13 = 31536e3;
48713
49599
  var ABI = [
48714
49600
  {
48715
49601
  name: "getReservesList",
@@ -48850,7 +49736,7 @@ function rebateApr(params) {
48850
49736
  if (nowSeconds >= Number(distributionEnd)) return 0;
48851
49737
  if (emissionPerSecond <= 0n || balanceTotalSupply <= 0n) return 0;
48852
49738
  if (!(rewardPrice > 0) || !(assetPrice > 0)) return 0;
48853
- const rewardsPerYearUsd = scale(emissionPerSecond, rewardDecimals) * SECONDS_PER_YEAR12 * rewardPrice;
49739
+ const rewardsPerYearUsd = scale(emissionPerSecond, rewardDecimals) * SECONDS_PER_YEAR13 * rewardPrice;
48854
49740
  const baseUsd = scale(balanceTotalSupply, balanceDecimals) * assetPrice;
48855
49741
  if (!(baseUsd > 0)) return 0;
48856
49742
  return rewardsPerYearUsd / baseUsd * 100;
@@ -49038,8 +49924,8 @@ var dtrinityRebateRewardFetcher = {
49038
49924
  return { byLender: merged };
49039
49925
  }
49040
49926
  };
49041
- var SECONDS_PER_YEAR13 = 31536e3;
49042
- var WAD14 = 10n ** 18n;
49927
+ var SECONDS_PER_YEAR14 = 31536e3;
49928
+ var WAD15 = 10n ** 18n;
49043
49929
  var ZERO2 = "0x0000000000000000000000000000000000000000";
49044
49930
  var UNBOOSTED_FACTOR = 0.4;
49045
49931
  var MAX_BOOST = 2.5;
@@ -49146,7 +50032,7 @@ function crvGaugeApr(params) {
49146
50032
  return 0;
49147
50033
  }
49148
50034
  if (!(crvPriceUsd > 0) || !(assetPriceUsd > 0)) return 0;
49149
- const crvPerYear = scale2(inflationRate, 18) * scale2(relativeWeight, 18) * SECONDS_PER_YEAR13;
50035
+ const crvPerYear = scale2(inflationRate, 18) * scale2(relativeWeight, 18) * SECONDS_PER_YEAR14;
49150
50036
  const stakedUsd = scale2(workingSupply, 18) * scale2(pricePerShare, 18) * assetPriceUsd;
49151
50037
  if (!(stakedUsd > 0)) return 0;
49152
50038
  return crvPerYear * crvPriceUsd / stakedUsd * 100 * UNBOOSTED_FACTOR;
@@ -49165,7 +50051,7 @@ function extraRewardApr(params) {
49165
50051
  if (nowSeconds >= Number(periodFinish)) return 0;
49166
50052
  if (rate <= 0n || totalSupply <= 0n) return 0;
49167
50053
  if (!(rewardPriceUsd > 0) || !(assetPriceUsd > 0)) return 0;
49168
- const rewardPerYearUsd = scale2(rate, rewardDecimals) * SECONDS_PER_YEAR13 * rewardPriceUsd;
50054
+ const rewardPerYearUsd = scale2(rate, rewardDecimals) * SECONDS_PER_YEAR14 * rewardPriceUsd;
49169
50055
  const stakedUsd = scale2(totalSupply, 18) * scale2(pricePerShare, 18) * assetPriceUsd;
49170
50056
  if (!(stakedUsd > 0)) return 0;
49171
50057
  return rewardPerYearUsd / stakedUsd * 100;
@@ -49257,7 +50143,7 @@ async function fetchForChain(chainId, nowSeconds) {
49257
50143
  { address: m.gauge, name: "totalSupply", params: [] },
49258
50144
  { address: m.gauge, name: "is_killed", params: [] },
49259
50145
  { address: m.gauge, name: "reward_count", params: [] },
49260
- { address: m.vault, name: "convertToAssets", params: [WAD14] },
50146
+ { address: m.vault, name: "convertToAssets", params: [WAD15] },
49261
50147
  isL1 ? {
49262
50148
  address: GAUGE_CONTROLLER,
49263
50149
  name: "gauge_relative_weight",
@@ -49273,7 +50159,7 @@ async function fetchForChain(chainId, nowSeconds) {
49273
50159
  abi: GAUGE_ABI,
49274
50160
  allowFailure: true
49275
50161
  });
49276
- const big18 = (v) => {
50162
+ const big20 = (v) => {
49277
50163
  try {
49278
50164
  if (typeof v === "bigint") return v;
49279
50165
  if (typeof v === "string" && v !== "0x") return BigInt(v);
@@ -49287,15 +50173,15 @@ async function fetchForChain(chainId, nowSeconds) {
49287
50173
  const b = i * STRIDE;
49288
50174
  return {
49289
50175
  market: m,
49290
- inflationRate: big18(r1[b]),
49291
- workingSupply: big18(r1[b + 1]),
49292
- totalSupply: big18(r1[b + 2]),
50176
+ inflationRate: big20(r1[b]),
50177
+ workingSupply: big20(r1[b + 1]),
50178
+ totalSupply: big20(r1[b + 2]),
49293
50179
  isKilled: r1[b + 3] === true,
49294
- rewardCount: Number(big18(r1[b + 4])),
49295
- pricePerShare: big18(r1[b + 5]),
50180
+ rewardCount: Number(big20(r1[b + 4])),
50181
+ pricePerShare: big20(r1[b + 5]),
49296
50182
  // Off L1 the child gauge's own rate is already market-scoped, so the
49297
50183
  // weight is the identity.
49298
- relativeWeight: isL1 ? big18(r1[b + 6]) : WAD14
50184
+ relativeWeight: isL1 ? big20(r1[b + 6]) : WAD15
49299
50185
  };
49300
50186
  });
49301
50187
  const tokenCalls = state.flatMap(
@@ -49388,7 +50274,7 @@ async function fetchForChain(chainId, nowSeconds) {
49388
50274
  const decoded = decodeRewardData(data);
49389
50275
  if (!decoded) continue;
49390
50276
  const { periodFinish, rate } = decoded;
49391
- const decimals = typeof decRaw === "number" ? decRaw : Number(big18(decRaw) || 18n);
50277
+ const decimals = typeof decRaw === "number" ? decRaw : Number(big20(decRaw) || 18n);
49392
50278
  const rewardPrice = priceOf(prices, chainId, token);
49393
50279
  const apr = extraRewardApr({
49394
50280
  rate,
@@ -50402,8 +51288,8 @@ function getDssCalls(chainId) {
50402
51288
  }
50403
51289
  return results;
50404
51290
  }
50405
- var RAY8 = 1e27;
50406
- var big15 = (v) => {
51291
+ var RAY10 = 1e27;
51292
+ var big17 = (v) => {
50407
51293
  try {
50408
51294
  if (typeof v === "bigint") return v;
50409
51295
  if (v == null || v === "0x") return 0n;
@@ -50415,18 +51301,18 @@ var big15 = (v) => {
50415
51301
  var field12 = (res, name, idx) => {
50416
51302
  const v = res?.[name];
50417
51303
  if (typeof v === "bigint" || typeof v === "number" || typeof v === "string") {
50418
- return big15(v);
51304
+ return big17(v);
50419
51305
  }
50420
- return big15(res?.[idx]);
51306
+ return big17(res?.[idx]);
50421
51307
  };
50422
51308
  function parseDssResults(data, meta, context) {
50423
51309
  const { chainId } = context;
50424
51310
  const key3 = dssLenderKey(meta.lender, chainId, meta.ilk);
50425
51311
  const entries = [];
50426
51312
  const spot = field12(data?.[0], "spot", 2);
50427
- const mat = big15(meta.mat);
51313
+ const mat = big17(meta.mat);
50428
51314
  if (spot > 0n && mat > 0n) {
50429
- const collUSD = Number(spot) / RAY8 * (Number(mat) / RAY8);
51315
+ const collUSD = Number(spot) / RAY10 * (Number(mat) / RAY10);
50430
51316
  if (collUSD > 0 && collUSD < 1e9) {
50431
51317
  entries.push({
50432
51318
  asset: meta.collToken,
@@ -50503,10 +51389,10 @@ function parseCurvanceResults(data, meta, context) {
50503
51389
  meta.assets.forEach((asset, i) => {
50504
51390
  const lowerRes = data?.[i * READS_PER_ASSET];
50505
51391
  const upperRes = data?.[i * READS_PER_ASSET + 1];
50506
- const lower3 = decode(lowerRes);
51392
+ const lower4 = decode(lowerRes);
50507
51393
  const upper = decode(upperRes);
50508
- if (!lower3 || lower3.errorCode !== 0n) return;
50509
- const priceUSD = Number(lower3.price) / 1e18;
51394
+ if (!lower4 || lower4.errorCode !== 0n) return;
51395
+ const priceUSD = Number(lower4.price) / 1e18;
50510
51396
  if (!(priceUSD > 0 && priceUSD < 1e9)) return;
50511
51397
  const upperUSD = upper && upper.errorCode === 0n ? Number(upper.price) / 1e18 : void 0;
50512
51398
  const spreadBps = upperUSD && upperUSD > priceUSD ? Math.round((upperUSD - priceUSD) / priceUSD * 1e4) : 0;
@@ -50697,9 +51583,9 @@ function parseTellerResults(data, meta, context) {
50697
51583
  const principal = meta.principal;
50698
51584
  const collateral = meta.collateral;
50699
51585
  const lenderKey = tellerLenderKey(meta.pool);
50700
- const usdOf = (addr3) => {
50701
- const key3 = tokenList?.[addr3]?.assetGroup ?? `${chainId}-${addr3}`;
50702
- return usdPrices[key3] ?? usdPrices[addr3];
51586
+ const usdOf = (addr4) => {
51587
+ const key3 = tokenList?.[addr4]?.assetGroup ?? `${chainId}-${addr4}`;
51588
+ return usdPrices[key3] ?? usdPrices[addr4];
50703
51589
  };
50704
51590
  const principalUSD = usdOf(principal);
50705
51591
  const collateralUSD = usdOf(collateral);
@@ -50803,9 +51689,9 @@ function parseFraxlendResults(data, meta, context) {
50803
51689
  const asset = assetRaw.toLowerCase();
50804
51690
  const collateral = collateralRaw.toLowerCase();
50805
51691
  const lenderKey = fraxlendLenderKey("FRAXLEND", chainId, meta.pair);
50806
- const usdOf = (addr3) => {
50807
- const key3 = tokenList?.[addr3]?.assetGroup ?? `${chainId}-${addr3}`;
50808
- return usdPrices[key3] ?? usdPrices[addr3];
51692
+ const usdOf = (addr4) => {
51693
+ const key3 = tokenList?.[addr4]?.assetGroup ?? `${chainId}-${addr4}`;
51694
+ return usdPrices[key3] ?? usdPrices[addr4];
50809
51695
  };
50810
51696
  const assetUSD = usdOf(asset);
50811
51697
  if (!assetUSD) return entries;
@@ -51346,8 +52232,8 @@ var priceLensAbi = [
51346
52232
  // src/prices/oracle-prices/fetchers/euler.ts
51347
52233
  var MAX_VIRTUAL_ADDRESS = 65535;
51348
52234
  var MAX_SANE_PRICE_USD = 1e7;
51349
- function isUsdUnitOfAccount(addr3) {
51350
- const numeric = parseInt(addr3, 16);
52235
+ function isUsdUnitOfAccount(addr4) {
52236
+ const numeric = parseInt(addr4, 16);
51351
52237
  return numeric <= MAX_VIRTUAL_ADDRESS;
51352
52238
  }
51353
52239
  var PRICE_LENS_ADDRESS = "0x6392892f3C57c658d2c748fc64c6fe57680E889F";
@@ -51905,7 +52791,7 @@ var siloV3Fetcher = {
51905
52791
  getAbi: getSiloV3Abi
51906
52792
  };
51907
52793
  var FLUID_EEE_LOWER3 = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
51908
- var normalizeUnderlying4 = (addr3) => addr3 === FLUID_EEE_LOWER3 ? zeroAddress : addr3;
52794
+ var normalizeUnderlying4 = (addr4) => addr4 === FLUID_EEE_LOWER3 ? zeroAddress : addr4;
51909
52795
  function priceColInDebt(raw, colDec, debtDec) {
51910
52796
  return formatMorphoPrice(raw, debtDec, colDec + 9);
51911
52797
  }
@@ -53622,9 +54508,9 @@ function rejectOutliers(candidates, guard = DEFAULT_OUTLIER_GUARD) {
53622
54508
  const reference = consensusReference(candidates, guard);
53623
54509
  if (reference === void 0) return candidates;
53624
54510
  const upper = reference * guard.rejectFactor;
53625
- const lower3 = reference / guard.rejectFactor;
54511
+ const lower4 = reference / guard.rejectFactor;
53626
54512
  const kept = candidates.filter(
53627
- (c) => c.priceUSD <= upper && c.priceUSD >= lower3
54513
+ (c) => c.priceUSD <= upper && c.priceUSD >= lower4
53628
54514
  );
53629
54515
  return kept.length > 0 ? kept : candidates;
53630
54516
  }
@@ -54385,7 +55271,7 @@ var composeVaultDisplayName = (brand, curatorName, asset, fallbackName) => {
54385
55271
 
54386
55272
  // src/vaults/fluid/publicCallParse.ts
54387
55273
  var FLUID_EEE_LOWER4 = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
54388
- var normalizeUnderlying5 = (addr3) => addr3 === FLUID_EEE_LOWER4 ? zeroAddress : addr3;
55274
+ var normalizeUnderlying5 = (addr4) => addr4 === FLUID_EEE_LOWER4 ? zeroAddress : addr4;
54389
55275
  var FLUID_RATE_SCALE2 = 100;
54390
55276
  var scaleFluidRate2 = (raw) => {
54391
55277
  if (raw === void 0 || raw === null) return 0;
@@ -54626,10 +55512,10 @@ function deriveConvertToAssets(totalAssetsRaw, totalSupplyRaw, shareDecimals) {
54626
55512
 
54627
55513
  // src/vaults/gearbox/publicCallParse.ts
54628
55514
  var WETH_MAINNET = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2";
54629
- var normalizeUnderlying6 = (addr3, chainId) => {
54630
- const lower3 = addr3.toLowerCase();
54631
- if (chainId === "1" && lower3 === WETH_MAINNET) return zeroAddress;
54632
- return lower3;
55515
+ var normalizeUnderlying6 = (addr4, chainId) => {
55516
+ const lower4 = addr4.toLowerCase();
55517
+ if (chainId === "1" && lower4 === WETH_MAINNET) return zeroAddress;
55518
+ return lower4;
54633
55519
  };
54634
55520
  var RAY_TO_PERCENT2 = 1e25;
54635
55521
  var scaleRate = (raw) => {
@@ -55088,9 +55974,9 @@ var VAULT_V2_ADAPTER_ABI = parseAbi([
55088
55974
  ]);
55089
55975
  var PHASE1_ABI = [...MetaMorphoAbi, ...VAULT_V2_PHASE1_ABI];
55090
55976
  var FEE_SCALE = 1e18;
55091
- var isHex40 = (addr3) => typeof addr3 === "string" && /^0x[0-9a-f]{40}$/i.test(addr3);
55977
+ var isHex40 = (addr4) => typeof addr4 === "string" && /^0x[0-9a-f]{40}$/i.test(addr4);
55092
55978
  var isHex64 = (v) => typeof v === "string" && /^0x[0-9a-f]{64}$/i.test(v);
55093
- var lcOrUndefined = (addr3) => isHex40(addr3) ? addr3.toLowerCase() : void 0;
55979
+ var lcOrUndefined = (addr4) => isHex40(addr4) ? addr4.toLowerCase() : void 0;
55094
55980
  var toNumberSafe = (raw, fallback = 0) => {
55095
55981
  if (raw === void 0 || raw === null) return fallback;
55096
55982
  const n = Number(raw);
@@ -55461,6 +56347,7 @@ function parseVault3(entry, results, chainId, prices, tokenList, marketIds, rate
55461
56347
  const onchainName = toStringSafe(nameRaw).trim();
55462
56348
  const fallbackName = onchainName || (entry.name ?? "").trim();
55463
56349
  const symbol = toStringSafe(symbolRaw);
56350
+ const curatorName = (entry.curatorName ?? "").trim() || void 0;
55464
56351
  const fee = v2FeePercent !== void 0 ? v2FeePercent : toNumberSafe(feeRaw) / FEE_SCALE * 100;
55465
56352
  const timelock = toNumberSafe(timelockRaw);
55466
56353
  const { depositRate, exposures, liquidityFormatted } = v2Allocation ?? computeVaultAllocation(
@@ -55482,10 +56369,11 @@ function parseVault3(entry, results, chainId, prices, tokenList, marketIds, rate
55482
56369
  name: fallbackName,
55483
56370
  displayName: composeVaultDisplayName(
55484
56371
  "Morpho",
55485
- void 0,
56372
+ curatorName,
55486
56373
  assetMeta,
55487
56374
  fallbackName
55488
56375
  ),
56376
+ curatorName,
55489
56377
  decimals,
55490
56378
  totalAssets,
55491
56379
  totalSupply,
@@ -55541,6 +56429,7 @@ var STOP_WORDS = /* @__PURE__ */ new Set([
55541
56429
  "prime",
55542
56430
  "staked",
55543
56431
  "core",
56432
+ "rwa",
55544
56433
  "lista",
55545
56434
  // protocol brand; a bare "Lista …" vault has no distinct curator
55546
56435
  "moolah"
@@ -55591,18 +56480,23 @@ var ASSET_TOKENS = /* @__PURE__ */ new Set([
55591
56480
  ]);
55592
56481
  function curatorNameFromVaultName(name, assetSymbol) {
55593
56482
  if (!name) return void 0;
56483
+ if (/\b(test|testing|fake)\b/i.test(name)) return void 0;
55594
56484
  const cleaned = name.replace(/\([^)]*\)\s*$/, "").trim();
55595
56485
  if (!cleaned) return void 0;
55596
56486
  const tokens = cleaned.split(/[\s/]+/).flatMap((t) => t.split("-")).filter(Boolean);
55597
56487
  const asset = (assetSymbol ?? "").toLowerCase();
55598
56488
  const out = [];
56489
+ let terminated = false;
55599
56490
  for (const tok of tokens) {
55600
56491
  const tl = tok.toLowerCase();
55601
- if (STOP_WORDS.has(tl)) break;
55602
- if (asset && tl === asset || ASSET_TOKENS.has(tl)) break;
56492
+ if (STOP_WORDS.has(tl) || asset && tl === asset || ASSET_TOKENS.has(tl) || tl.includes("usd")) {
56493
+ terminated = true;
56494
+ break;
56495
+ }
55603
56496
  out.push(tok);
55604
56497
  if (out.length >= 3) break;
55605
56498
  }
56499
+ if (!terminated || out.length === tokens.length) return void 0;
55606
56500
  const curator = out.join(" ").trim();
55607
56501
  return curator.length >= 2 ? curator : void 0;
55608
56502
  }
@@ -55628,11 +56522,11 @@ var PHASE1_CALLS2 = [
55628
56522
  var PHASE1_PER_VAULT2 = PHASE1_CALLS2.length;
55629
56523
  var WITHDRAW_QUEUE_LENGTH_INDEX2 = 8;
55630
56524
  var FEE_SCALE2 = 1e18;
55631
- var isHex402 = (addr3) => typeof addr3 === "string" && /^0x[0-9a-f]{40}$/i.test(addr3);
55632
- var lcOrUndefined2 = (addr3) => {
55633
- if (!isHex402(addr3)) return void 0;
55634
- const lower3 = addr3.toLowerCase();
55635
- return lower3 === zeroAddress ? void 0 : lower3;
56525
+ var isHex402 = (addr4) => typeof addr4 === "string" && /^0x[0-9a-f]{40}$/i.test(addr4);
56526
+ var lcOrUndefined2 = (addr4) => {
56527
+ if (!isHex402(addr4)) return void 0;
56528
+ const lower4 = addr4.toLowerCase();
56529
+ return lower4 === zeroAddress ? void 0 : lower4;
55636
56530
  };
55637
56531
  var isHex642 = (val) => typeof val === "string" && /^0x[0-9a-f]{64}$/i.test(val);
55638
56532
  var toNumberSafe2 = (raw, fallback = 0) => {
@@ -56032,6 +56926,7 @@ function parseVault5(v, chainId, prices, tokenList, exposures, liquidityFormatte
56032
56926
  const fee = Number.isFinite(feeRaw) ? feeRaw / PERFORMANCE_FEE_SCALE : 0;
56033
56927
  const apiTotalAssetsUsd = Number(v.totalAssetsUsd ?? 0) || 0;
56034
56928
  const totalAssetsUsd = apiTotalAssetsUsd || totalAssetsFormatted * priceUsd;
56929
+ const curatorName = curatorNameFromVaultName(v.name, assetMeta?.symbol);
56035
56930
  return {
56036
56931
  address,
56037
56932
  underlying: assetAddr,
@@ -56039,10 +56934,11 @@ function parseVault5(v, chainId, prices, tokenList, exposures, liquidityFormatte
56039
56934
  name: v.name ?? "",
56040
56935
  displayName: composeVaultDisplayName(
56041
56936
  "Silo",
56042
- void 0,
56937
+ curatorName,
56043
56938
  assetMeta,
56044
56939
  v.name ?? void 0
56045
56940
  ),
56941
+ curatorName,
56046
56942
  decimals,
56047
56943
  protocolVersion: v.protocol?.protocolVersion ?? "",
56048
56944
  protocolId: (v.protocolId ?? v.protocol?.id ?? "").toLowerCase(),
@@ -56152,6 +57048,54 @@ var fetchSiloVaults = async (chainId, prices = {}, tokenList = {}, options) => {
56152
57048
  }
56153
57049
  return out;
56154
57050
  };
57051
+
57052
+ // src/vaults/euler-earn/entityLabels.ts
57053
+ var LABELS_BASE = "https://raw.githubusercontent.com/euler-xyz/euler-labels/master";
57054
+ var TTL_MS3 = 30 * 60 * 1e3;
57055
+ var cache3 = /* @__PURE__ */ new Map();
57056
+ var inflight4 = /* @__PURE__ */ new Map();
57057
+ async function fetchChainEntities(chainId) {
57058
+ const res = await fetch(`${LABELS_BASE}/${chainId}/entities.json`);
57059
+ if (!res.ok) throw new Error(`euler-labels ${chainId}: HTTP ${res.status}`);
57060
+ const json = await res.json();
57061
+ const byAddress = /* @__PURE__ */ new Map();
57062
+ for (const entity of Object.values(json ?? {})) {
57063
+ const name = String(entity?.name ?? "").trim();
57064
+ if (!name) continue;
57065
+ for (const addr4 of Object.keys(entity?.addresses ?? {})) {
57066
+ const lower4 = addr4.toLowerCase();
57067
+ if (!/^0x[0-9a-f]{40}$/.test(lower4)) continue;
57068
+ if (!byAddress.has(lower4)) byAddress.set(lower4, /* @__PURE__ */ new Set());
57069
+ byAddress.get(lower4).add(name);
57070
+ }
57071
+ }
57072
+ const map = /* @__PURE__ */ new Map();
57073
+ for (const [addr4, names] of byAddress) {
57074
+ if (names.size === 1) map.set(addr4, [...names][0]);
57075
+ }
57076
+ return map;
57077
+ }
57078
+ async function fetchEulerEntityNames(chainId) {
57079
+ const hit = cache3.get(chainId);
57080
+ if (hit && Date.now() - hit.at <= TTL_MS3) return hit.map;
57081
+ const running = inflight4.get(chainId);
57082
+ if (running) return running;
57083
+ const p = fetchChainEntities(chainId).then((map) => {
57084
+ cache3.set(chainId, { at: Date.now(), map });
57085
+ return map;
57086
+ }).catch(() => {
57087
+ return hit?.map ?? /* @__PURE__ */ new Map();
57088
+ }).finally(() => {
57089
+ inflight4.delete(chainId);
57090
+ });
57091
+ inflight4.set(chainId, p);
57092
+ return p;
57093
+ }
57094
+ function eulerEntityCuratorName(entityNames, curator, owner) {
57095
+ return (curator ? entityNames.get(curator.toLowerCase()) : void 0) ?? (owner ? entityNames.get(owner.toLowerCase()) : void 0);
57096
+ }
57097
+
57098
+ // src/vaults/euler-earn/fetchFromSubgraph.ts
56155
57099
  var DECIMALS_ABI = [
56156
57100
  {
56157
57101
  name: "decimals",
@@ -56299,7 +57243,7 @@ function computeRealLiquidity(strategies, totalAssetsRaw, evkIndex) {
56299
57243
  const result = idle + withdrawable;
56300
57244
  return result > totalAssets ? totalAssets : result;
56301
57245
  }
56302
- function parseVault6(v, chainId, prices, tokenList, evkIndex, shareDecimalsByVault) {
57246
+ function parseVault6(v, chainId, prices, tokenList, evkIndex, shareDecimalsByVault, entityNames) {
56303
57247
  const address = (v?.id ?? "").toLowerCase();
56304
57248
  const assetAddr = (v?.asset ?? "").toLowerCase();
56305
57249
  if (!address || !assetAddr) return null;
@@ -56350,7 +57294,13 @@ function parseVault6(v, chainId, prices, tokenList, evkIndex, shareDecimalsByVau
56350
57294
  fee,
56351
57295
  owner: readAddress2(v.owner),
56352
57296
  curator: readAddress2(v.curator),
56353
- curatorName: curatorNameFromVaultName(v.name, assetMeta?.symbol),
57297
+ // Euler's entity registry names the curator by ADDRESS — authoritative
57298
+ // when it hits; the vault-name parse only covers what it misses.
57299
+ curatorName: eulerEntityCuratorName(
57300
+ entityNames,
57301
+ readAddress2(v.curator),
57302
+ readAddress2(v.owner)
57303
+ ) ?? curatorNameFromVaultName(v.name, assetMeta?.symbol),
56354
57304
  guardian: readAddress2(v.guardian),
56355
57305
  feeRecipient: v.feeReceiver?.toLowerCase() || void 0,
56356
57306
  asset: assetMeta,
@@ -56425,9 +57375,10 @@ async function fetchEulerEarnVaultsFromSubgraph(chainId, prices = {}, tokenList
56425
57375
  const id = v?.id;
56426
57376
  if (id) vaultAddrs.push(id);
56427
57377
  }
56428
- const [evkIndex, shareDecimalsByVault] = await Promise.all([
57378
+ const [evkIndex, shareDecimalsByVault, entityNames] = await Promise.all([
56429
57379
  fetchEvkIndex(url, [...assets]),
56430
- fetchShareDecimals(chainId, vaultAddrs, multicallRetry)
57380
+ fetchShareDecimals(chainId, vaultAddrs, multicallRetry),
57381
+ fetchEulerEntityNames(chainId)
56431
57382
  ]);
56432
57383
  const out = {};
56433
57384
  for (const v of items) {
@@ -56437,7 +57388,8 @@ async function fetchEulerEarnVaultsFromSubgraph(chainId, prices = {}, tokenList
56437
57388
  prices,
56438
57389
  tokenList,
56439
57390
  evkIndex,
56440
- shareDecimalsByVault
57391
+ shareDecimalsByVault,
57392
+ entityNames
56441
57393
  );
56442
57394
  if (parsed) out[parsed.address] = parsed;
56443
57395
  }
@@ -56473,7 +57425,7 @@ async function getJson3(url) {
56473
57425
  clearTimeout(timer);
56474
57426
  }
56475
57427
  }
56476
- function mapApiDetail(d, chainId, prices, tokenList, shareDecimalsByVault) {
57428
+ function mapApiDetail(d, chainId, prices, tokenList, shareDecimalsByVault, entityNames) {
56477
57429
  const address = (d.address ?? "").toLowerCase();
56478
57430
  const underlying = (d.asset?.address ?? "").toLowerCase();
56479
57431
  if (!address || !underlying) return null;
@@ -56499,6 +57451,8 @@ function mapApiDetail(d, chainId, prices, tokenList, shareDecimalsByVault) {
56499
57451
  const priceUsd = prices[oracleKey] ?? prices[underlying] ?? 0;
56500
57452
  const totalAssetsUsd = priceUsd ? totalAssetsFormatted * priceUsd : Number(d.totalSupplyUsd ?? 0);
56501
57453
  const liquidityUsd = priceUsd ? liquidityFormatted * priceUsd : Number(d.availableAssetsUsd ?? 0);
57454
+ const owner = (d.governance?.owner ?? d.management?.owner ?? d.owner)?.toLowerCase();
57455
+ const curator = (d.governance?.curator ?? d.management?.curator ?? d.curator)?.toLowerCase();
56502
57456
  return {
56503
57457
  address,
56504
57458
  underlying,
@@ -56515,13 +57469,12 @@ function mapApiDetail(d, chainId, prices, tokenList, shareDecimalsByVault) {
56515
57469
  // The API doesn't surface the performance fee on this endpoint; the
56516
57470
  // headline APY is already net, so 0 here only affects fee display.
56517
57471
  fee: 0,
56518
- // owner/curator/guardian/feeRecipient + timelock live under
56519
- // `governance`/`management` in the current API; fall back to the legacy
56520
- // flat fields for older snapshots.
56521
57472
  timelock: Number(d.governance?.timelock ?? d.management?.timelockSeconds ?? 0) || void 0,
56522
- owner: (d.governance?.owner ?? d.management?.owner ?? d.owner)?.toLowerCase(),
56523
- curator: (d.governance?.curator ?? d.management?.curator ?? d.curator)?.toLowerCase(),
56524
- curatorName: curatorNameFromVaultName(d.name, assetMeta?.symbol),
57473
+ owner,
57474
+ curator,
57475
+ // Euler's own entity registry names the curator by ADDRESS — authoritative
57476
+ // when it hits; the vault-name parse only covers what it misses.
57477
+ curatorName: eulerEntityCuratorName(entityNames, curator, owner) ?? curatorNameFromVaultName(d.name, assetMeta?.symbol),
56525
57478
  guardian: (d.governance?.guardian ?? d.management?.guardian ?? d.guardian)?.toLowerCase(),
56526
57479
  feeRecipient: (d.governance?.feeReceiver ?? d.management?.feeRecipient ?? d.feeReceiver)?.toLowerCase() || void 0,
56527
57480
  asset: assetMeta,
@@ -56555,13 +57508,16 @@ async function fetchEulerEarnVaultsFromApi(chainId, prices = {}, tokenList = {},
56555
57508
  if (!list) return void 0;
56556
57509
  const rows = list.data ?? [];
56557
57510
  if (rows.length === 0) return {};
56558
- const details = await mapWithConcurrency(
56559
- rows,
56560
- DETAIL_CONCURRENCY,
56561
- (row) => getJson3(
56562
- `${EULER_DATA_API_BASE2}/earn/vaults/${chainId}/${row.address}?include=strategies`
56563
- ).then((d) => d?.data)
56564
- );
57511
+ const [details, entityNames] = await Promise.all([
57512
+ mapWithConcurrency(
57513
+ rows,
57514
+ DETAIL_CONCURRENCY,
57515
+ (row) => getJson3(
57516
+ `${EULER_DATA_API_BASE2}/earn/vaults/${chainId}/${row.address}?include=strategies`
57517
+ ).then((d) => d?.data)
57518
+ ),
57519
+ fetchEulerEntityNames(chainId)
57520
+ ]);
56565
57521
  const vaultAddrs = details.map((d) => d?.address).filter((a) => !!a);
56566
57522
  const shareDecimalsByVault = await fetchShareDecimals(
56567
57523
  chainId,
@@ -56571,7 +57527,14 @@ async function fetchEulerEarnVaultsFromApi(chainId, prices = {}, tokenList = {},
56571
57527
  const out = {};
56572
57528
  for (const d of details) {
56573
57529
  if (!d) continue;
56574
- const v = mapApiDetail(d, chainId, prices, tokenList, shareDecimalsByVault);
57530
+ const v = mapApiDetail(
57531
+ d,
57532
+ chainId,
57533
+ prices,
57534
+ tokenList,
57535
+ shareDecimalsByVault,
57536
+ entityNames
57537
+ );
56575
57538
  if (v) out[v.address] = v;
56576
57539
  }
56577
57540
  return out;
@@ -56603,7 +57566,7 @@ var num4 = (v) => {
56603
57566
  const n = Number(v);
56604
57567
  return Number.isFinite(n) ? n : 0;
56605
57568
  };
56606
- var big16 = (v) => {
57569
+ var big18 = (v) => {
56607
57570
  try {
56608
57571
  if (v === void 0 || v === null || v === "") return "0";
56609
57572
  const s = String(v);
@@ -56612,7 +57575,7 @@ var big16 = (v) => {
56612
57575
  return "0";
56613
57576
  }
56614
57577
  };
56615
- var lower2 = (v) => String(v ?? "").toLowerCase();
57578
+ var lower3 = (v) => String(v ?? "").toLowerCase();
56616
57579
  async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, fetchImpl = fetch) {
56617
57580
  const url = `${termMaxApiBase(chainId)}/vault/list?chainId=${chainId}`;
56618
57581
  let rows;
@@ -56630,8 +57593,8 @@ async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, f
56630
57593
  }
56631
57594
  const out = {};
56632
57595
  for (const r of rows) {
56633
- const address = lower2(r?.vaultAddress);
56634
- const underlying = lower2(r?.asset?.contractAddress);
57596
+ const address = lower3(r?.vaultAddress);
57597
+ const underlying = lower3(r?.asset?.contractAddress);
56635
57598
  if (!address || !underlying) continue;
56636
57599
  if (r.isEnabled === false) continue;
56637
57600
  const assetDecimals = num4(r?.asset?.decimals) || 18;
@@ -56639,12 +57602,12 @@ async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, f
56639
57602
  const assetEntry = tokenList[underlying];
56640
57603
  const priceKey = toOracleKey(assetEntry?.assetGroup) || toGenericPriceKey(underlying, chainId);
56641
57604
  const priceUsd = prices[priceKey];
56642
- const totalAssets = big16(r.totalAssets);
56643
- const totalSupply = big16(r.totalSupplyAmt);
57605
+ const totalAssets = big18(r.totalAssets);
57606
+ const totalSupply = big18(r.totalSupplyAmt);
56644
57607
  const totalAssetsFormatted = Number(totalAssets) / scale3;
56645
57608
  const supplyRate = num4(r.apr) * 100;
56646
57609
  const rewardsRate = num4(r?.incentiveData?.TMX_APR) * 100;
56647
- const rawLiquidity = BigInt(big16(r.redeemableAmt ?? r.idleFunds ?? "0"));
57610
+ const rawLiquidity = BigInt(big18(r.redeemableAmt ?? r.idleFunds ?? "0"));
56648
57611
  const totalAssetsBig = BigInt(totalAssets);
56649
57612
  const liquidity = (rawLiquidity > totalAssetsBig ? totalAssetsBig : rawLiquidity).toString();
56650
57613
  const liquidityFormatted = Number(liquidity) / scale3;
@@ -56667,10 +57630,10 @@ async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, f
56667
57630
  // 1e8-scaled upstream (10000000 = 10%).
56668
57631
  fee: num4(r.performanceFeeRate) / 1e6,
56669
57632
  timelock: num4(r.timeLockSeconds) || void 0,
56670
- curator: r?.curator?.curatorAddress ? lower2(r.curator.curatorAddress) : void 0,
57633
+ curator: r?.curator?.curatorAddress ? lower3(r.curator.curatorAddress) : void 0,
56671
57634
  // The API is the ONLY source for this — do not derive it from `name`.
56672
57635
  curatorName: r?.curator?.name || void 0,
56673
- guardian: r?.guardianAddress ? lower2(r.guardianAddress) : void 0,
57636
+ guardian: r?.guardianAddress ? lower3(r.guardianAddress) : void 0,
56674
57637
  asset: assetEntry,
56675
57638
  priceUsd,
56676
57639
  totalAssetsFormatted,
@@ -56680,8 +57643,8 @@ async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, f
56680
57643
  liquidityUsd: priceUsd ? liquidityFormatted * priceUsd : 0,
56681
57644
  version: r.version,
56682
57645
  isPaused: r.isPaused === true || void 0,
56683
- supplyCap: r.capacity ? big16(r.capacity) : void 0,
56684
- basePool: r.poolAddress ? lower2(r.poolAddress) : void 0
57646
+ supplyCap: r.capacity ? big18(r.capacity) : void 0,
57647
+ basePool: r.poolAddress ? lower3(r.poolAddress) : void 0
56685
57648
  };
56686
57649
  }
56687
57650
  return out;
@@ -56736,7 +57699,7 @@ var Erc20DecimalsBalanceAbi = [
56736
57699
 
56737
57700
  // src/vaults/termmax/fetchFromChain.ts
56738
57701
  var DECIMAL_BASE2 = 100000000n;
56739
- var big17 = (v) => {
57702
+ var big19 = (v) => {
56740
57703
  if (v === void 0 || v === null || v === "0x") return 0n;
56741
57704
  try {
56742
57705
  return typeof v === "bigint" ? v : BigInt(v);
@@ -56800,7 +57763,7 @@ var fetchTermMaxVaultsFromChain = async (chainId, multicallRetry, prices = {}, t
56800
57763
  vaults.forEach((address, i) => {
56801
57764
  const at = (k) => res[i * READS_PER_VAULT + VAULT_READS.indexOf(k)];
56802
57765
  const asset = addr(at("asset"));
56803
- const totalAssets = big17(at("totalAssets"));
57766
+ const totalAssets = big19(at("totalAssets"));
56804
57767
  if (!asset || totalAssets === 0n) return;
56805
57768
  rows.push({
56806
57769
  address,
@@ -56809,11 +57772,11 @@ var fetchTermMaxVaultsFromChain = async (chainId, multicallRetry, prices = {}, t
56809
57772
  decimals: num5(at("decimals")) ?? 18,
56810
57773
  asset,
56811
57774
  totalAssets,
56812
- totalSupply: big17(at("totalSupply")),
56813
- annualizedInterest: big17(at("annualizedInterest")),
56814
- accretingPrincipal: big17(at("accretingPrincipal")),
56815
- performanceFeeRate: big17(at("performanceFeeRate")),
56816
- aprRaw: at("apr") != null ? big17(at("apr")) : void 0,
57775
+ totalSupply: big19(at("totalSupply")),
57776
+ annualizedInterest: big19(at("annualizedInterest")),
57777
+ accretingPrincipal: big19(at("accretingPrincipal")),
57778
+ performanceFeeRate: big19(at("performanceFeeRate")),
57779
+ aprRaw: at("apr") != null ? big19(at("apr")) : void 0,
56817
57780
  curator: addr(at("curator")),
56818
57781
  guardian: addr(at("guardian")),
56819
57782
  timelock: num5(at("timelock")),
@@ -56834,7 +57797,7 @@ var fetchTermMaxVaultsFromChain = async (chainId, multicallRetry, prices = {}, t
56834
57797
  const out = {};
56835
57798
  rows.forEach((r, i) => {
56836
57799
  const assetDecimals = num5(res2[i * 2]) ?? r.decimals;
56837
- const idle = big17(res2[i * 2 + 1]);
57800
+ const idle = big19(res2[i * 2 + 1]);
56838
57801
  const assetEntry = tokenList[r.asset];
56839
57802
  const priceKey = toOracleKey(assetEntry?.assetGroup) || toGenericPriceKey(r.asset, chainId);
56840
57803
  const priceUsd = prices[priceKey];
@@ -62355,6 +63318,40 @@ var FrankencoinSavingsReadAbi = [
62355
63318
  }
62356
63319
  ];
62357
63320
 
63321
+ // src/vaults/savings/abis/hyperbeat.ts
63322
+ var HyperbeatPricerReadAbi = [
63323
+ {
63324
+ inputs: [],
63325
+ name: "getRate",
63326
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
63327
+ stateMutability: "view",
63328
+ type: "function"
63329
+ },
63330
+ {
63331
+ inputs: [],
63332
+ name: "decimals",
63333
+ outputs: [{ internalType: "uint8", name: "", type: "uint8" }],
63334
+ stateMutability: "view",
63335
+ type: "function"
63336
+ }
63337
+ ];
63338
+ var HyperbeatQueueReadAbi = [
63339
+ {
63340
+ inputs: [],
63341
+ name: "instantWithdrawalFee",
63342
+ outputs: [{ internalType: "uint64", name: "", type: "uint64" }],
63343
+ stateMutability: "view",
63344
+ type: "function"
63345
+ },
63346
+ {
63347
+ inputs: [],
63348
+ name: "isInstantWithdrawalPaused",
63349
+ outputs: [{ internalType: "bool", name: "", type: "bool" }],
63350
+ stateMutability: "view",
63351
+ type: "function"
63352
+ }
63353
+ ];
63354
+
62358
63355
  // src/vaults/savings/abis/yearnStrategy.ts
62359
63356
  var AvailableWithdrawLimitAbi = [
62360
63357
  {
@@ -62544,6 +63541,57 @@ var readerFrankencoinSavings = (entry) => ({
62544
63541
  }
62545
63542
  });
62546
63543
 
63544
+ // src/vaults/savings/readers/hyperbeatVault.ts
63545
+ var readerHyperbeatVault = (entry) => {
63546
+ const { address, underlying, priceOracle, withdrawQueue } = entry;
63547
+ const pricer = priceOracle ?? address;
63548
+ const queue = withdrawQueue ?? address;
63549
+ const shareUnit = 10n ** BigInt(entry.decimals);
63550
+ const underlyingUnit = 10n ** BigInt(entry.underlyingDecimals ?? entry.decimals);
63551
+ return {
63552
+ calls: [
63553
+ { address, name: "totalSupply", params: [] },
63554
+ { address: pricer, name: "getRate", params: [] },
63555
+ { address: pricer, name: "decimals", params: [] },
63556
+ { address: underlying, name: "balanceOf", params: [queue] },
63557
+ { address: queue, name: "instantWithdrawalFee", params: [] },
63558
+ { address: queue, name: "isInstantWithdrawalPaused", params: [] }
63559
+ ],
63560
+ abis: [
63561
+ TotalSupplyAbi2,
63562
+ HyperbeatPricerReadAbi,
63563
+ HyperbeatPricerReadAbi,
63564
+ BalanceOfAbi,
63565
+ HyperbeatQueueReadAbi,
63566
+ HyperbeatQueueReadAbi
63567
+ ],
63568
+ parse: ([supply, rate, rateDecimals, inventory, fee, instantPaused]) => {
63569
+ const totalSupply = toBigInt16(supply);
63570
+ const rawRate = toBigInt16(rate);
63571
+ const rateDec = toBigInt16(rateDecimals);
63572
+ if (totalSupply === void 0 || rawRate === void 0 || rateDec === void 0 || rawRate === 0n) {
63573
+ return void 0;
63574
+ }
63575
+ const exchangeRate = rateDec <= 18n ? rawRate * 10n ** (18n - rateDec) : rawRate / 10n ** (rateDec - 18n);
63576
+ const capacity = toBigInt16(inventory);
63577
+ const feeRaw = toBigInt16(fee);
63578
+ return {
63579
+ // totalSupply is in raw share units; convert to raw underlying.
63580
+ totalAssets: totalSupply * exchangeRate * underlyingUnit / (shareUnit * ONE_E1813),
63581
+ totalSupply,
63582
+ exchangeRate,
63583
+ // `instantWithdrawalFee` is over a base of 10 000, so the raw
63584
+ // value maps 1:1 onto bps (30 on all four vaults = 0.30% — the
63585
+ // docs' 0.5% describes the retired Midas stack).
63586
+ withdrawFeeBps: feeRaw !== void 0 ? Number(feeRaw) : void 0,
63587
+ instantRedeemEnabled: typeof instantPaused === "boolean" ? !instantPaused : void 0,
63588
+ instantRedeemCapacity: capacity,
63589
+ withdrawQueue: queue.toLowerCase()
63590
+ };
63591
+ }
63592
+ };
63593
+ };
63594
+
62547
63595
  // src/vaults/savings/readers/navOracle.ts
62548
63596
  var readerNavOracle = (entry) => {
62549
63597
  const shareUnit = 10n ** BigInt(entry.decimals);
@@ -62721,6 +63769,8 @@ var buildReader2 = (entry) => {
62721
63769
  return readerNavOracle(entry);
62722
63770
  case "frankencoin-savings":
62723
63771
  return readerFrankencoinSavings(entry);
63772
+ case "hyperbeat-vault":
63773
+ return readerHyperbeatVault(entry);
62724
63774
  case "yieldbasis-lt":
62725
63775
  return readerYieldBasisLt(entry);
62726
63776
  case "wren-nav":
@@ -63150,9 +64200,9 @@ async function fetchAaveEarnApiVaults(chainId, targets) {
63150
64200
  const target = Number(chainId);
63151
64201
  const byAddress = /* @__PURE__ */ new Map();
63152
64202
  const keep = (it) => {
63153
- const addr3 = it?.address?.toLowerCase();
63154
- if (!addr3 || Number(it.chainId) !== target) return;
63155
- if (!byAddress.has(addr3)) byAddress.set(addr3, it);
64203
+ const addr4 = it?.address?.toLowerCase();
64204
+ if (!addr4 || Number(it.chainId) !== target) return;
64205
+ if (!byAddress.has(addr4)) byAddress.set(addr4, it);
63156
64206
  };
63157
64207
  for (const owner of targets.owners) {
63158
64208
  let cursor = null;
@@ -63842,7 +64892,7 @@ var SYNC_REDEMPTION_PROVIDERS = /* @__PURE__ */ new Set([
63842
64892
  ]);
63843
64893
  var ASYNC_REDEMPTION_PROVIDERS = /* @__PURE__ */ new Set(["lagoon", "upshift"]);
63844
64894
  var classifyRedemption = (provider, v) => {
63845
- if (provider === "pendle") return void 0;
64895
+ if (provider === "pendle" || provider === "spectra") return void 0;
63846
64896
  if (ASYNC_REDEMPTION_PROVIDERS.has(provider)) return "async";
63847
64897
  if (SYNC_REDEMPTION_PROVIDERS.has(provider)) return "sync";
63848
64898
  if (provider === "lst") return "async";
@@ -64029,6 +65079,7 @@ var stampVaultClassification = (data, chainId, tokenList = {}) => {
64029
65079
  stampBag(data.upshift, "upshift");
64030
65080
  stampBag(data.yearn, "yearn");
64031
65081
  stampBag(data.pendle, "pendle");
65082
+ stampBag(data.spectra, "spectra");
64032
65083
  stampBag(data.hypercore, "hypercore", false);
64033
65084
  stampBag(data.gmx, "gmx", false);
64034
65085
  };
@@ -64574,23 +65625,23 @@ var priceGmMarkets = async (chainId, multicallRetry, markets, prices) => {
64574
65625
  const indexMax = price(prices, m.indexToken)?.max;
64575
65626
  if (Array.isArray(dsRes) && longMax != null && shortMax != null) {
64576
65627
  const base = i * SLOTS;
64577
- const big18 = (j) => typeof dsRes[base + j] === "bigint" ? dsRes[base + j] : 0n;
65628
+ const big20 = (j) => typeof dsRes[base + j] === "bigint" ? dsRes[base + j] : 0n;
64578
65629
  const cap = computeDepositCapacityUsd(
64579
- [info?.longTokenAmount, longMax, big18(0), big18(2)],
64580
- [info?.shortTokenAmount, shortMax, big18(1), big18(3)]
65630
+ [info?.longTokenAmount, longMax, big20(0), big20(2)],
65631
+ [info?.shortTokenAmount, shortMax, big20(1), big20(3)]
64581
65632
  );
64582
65633
  if (cap != null) value.depositCapacityUsd = cap;
64583
65634
  if (indexMax != null) {
64584
65635
  const divisor = m.longToken.toLowerCase() === m.shortToken.toLowerCase() ? 2n : 1n;
64585
- const reservedUsdLong = (big18(4) + big18(5)) / divisor * indexMax;
64586
- const reservedUsdShort = (big18(6) + big18(7)) / divisor;
65636
+ const reservedUsdLong = (big20(4) + big20(5)) / divisor * indexMax;
65637
+ const reservedUsdShort = (big20(6) + big20(7)) / divisor;
64587
65638
  const liq = computeLiquidityUsd(
64588
65639
  info?.longTokenUsd,
64589
65640
  info?.shortTokenUsd,
64590
65641
  reservedUsdLong,
64591
65642
  reservedUsdShort,
64592
- big18(8),
64593
- big18(9)
65643
+ big20(8),
65644
+ big20(9)
64594
65645
  );
64595
65646
  if (liq != null)
64596
65647
  value.liquidityUsd = Math.max(0, Math.min(liq, value.tvlUsd));
@@ -64669,17 +65720,17 @@ var priceGlvVaults = async (chainId, multicallRetry, glvTokens, prices, marketIn
64669
65720
  const sp = price(prices, short);
64670
65721
  if (!lp || !sp) return;
64671
65722
  const indexPrices = [];
64672
- let ok = true;
65723
+ let ok2 = true;
64673
65724
  for (const m of markets) {
64674
65725
  const idx = marketIndexToken.get(m.toLowerCase());
64675
65726
  const ip = idx ? price(prices, idx) : void 0;
64676
65727
  if (!ip) {
64677
- ok = false;
65728
+ ok2 = false;
64678
65729
  break;
64679
65730
  }
64680
65731
  indexPrices.push(ip);
64681
65732
  }
64682
- if (!ok) return;
65733
+ if (!ok2) return;
64683
65734
  calls.push({
64684
65735
  address: c.glvReader,
64685
65736
  name: "getGlvTokenPrice",
@@ -64789,21 +65840,21 @@ var fetchGmxExecutionFees = async (chainId, multicallRetry, gasPriceWei) => {
64789
65840
  } catch {
64790
65841
  return void 0;
64791
65842
  }
64792
- const big18 = (i) => typeof res[i] === "bigint" ? res[i] : 0n;
64793
- const base = big18(0);
64794
- const mult = big18(1);
65843
+ const big20 = (i) => typeof res[i] === "bigint" ? res[i] : 0n;
65844
+ const base = big20(0);
65845
+ const mult = big20(1);
64795
65846
  if (base === 0n && mult === 0n) return void 0;
64796
65847
  const PRECISION = 10n ** 30n;
64797
65848
  const adjusted = (opGas) => base + opGas * mult / PRECISION;
64798
65849
  const fee = (opGas) => (adjusted(opGas) * gasPriceWei).toString();
64799
- const glvExtra = big18(6) * GLV_NOMINAL_MARKET_COUNT;
65850
+ const glvExtra = big20(6) * GLV_NOMINAL_MARKET_COUNT;
64800
65851
  return {
64801
65852
  chainId,
64802
65853
  gasPriceWei: gasPriceWei.toString(),
64803
- deposit: fee(big18(2)),
64804
- withdrawal: fee(big18(3)),
64805
- glvDeposit: fee(big18(4) + glvExtra),
64806
- glvWithdrawal: fee(big18(5) + glvExtra)
65854
+ deposit: fee(big20(2)),
65855
+ withdrawal: fee(big20(3)),
65856
+ glvDeposit: fee(big20(4) + glvExtra),
65857
+ glvWithdrawal: fee(big20(5) + glvExtra)
64807
65858
  };
64808
65859
  };
64809
65860
 
@@ -64904,8 +65955,8 @@ var fetchGmxVaults = async (chainId, multicallRetry, options) => {
64904
65955
  marketIndexToken
64905
65956
  )
64906
65957
  ]);
64907
- for (const [addr3, v] of gmValues) {
64908
- const e = out[addr3];
65958
+ for (const [addr4, v] of gmValues) {
65959
+ const e = out[addr4];
64909
65960
  if (e) {
64910
65961
  e.priceUsd = v.priceUsd;
64911
65962
  e.tvlUsd = v.tvlUsd;
@@ -64913,12 +65964,12 @@ var fetchGmxVaults = async (chainId, multicallRetry, options) => {
64913
65964
  e.depositCapacityUsd = v.depositCapacityUsd;
64914
65965
  }
64915
65966
  }
64916
- for (const [addr3, v] of glv.values) {
64917
- const e = out[addr3];
65967
+ for (const [addr4, v] of glv.values) {
65968
+ const e = out[addr4];
64918
65969
  if (!e) continue;
64919
65970
  e.priceUsd = v.priceUsd;
64920
65971
  e.tvlUsd = v.tvlUsd;
64921
- const markets2 = glv.glvMarkets.get(addr3) ?? [];
65972
+ const markets2 = glv.glvMarkets.get(addr4) ?? [];
64922
65973
  let liqSum = 0;
64923
65974
  let tvlSum = 0;
64924
65975
  for (const m of markets2) {
@@ -64930,7 +65981,7 @@ var fetchGmxVaults = async (chainId, multicallRetry, options) => {
64930
65981
  }
64931
65982
  if (tvlSum > 0 && v.tvlUsd != null)
64932
65983
  e.liquidityUsd = v.tvlUsd * (liqSum / tvlSum);
64933
- const caps = glv.glvCaps.get(addr3) ?? [];
65984
+ const caps = glv.glvCaps.get(addr4) ?? [];
64934
65985
  let capacity = 0;
64935
65986
  let known = false;
64936
65987
  for (const cap of caps) {
@@ -65221,7 +66272,7 @@ async function getJson4(url, label) {
65221
66272
  }
65222
66273
  return response.json();
65223
66274
  }
65224
- function cache3(slot, build, store) {
66275
+ function cache4(slot, build, store) {
65225
66276
  const now = Date.now();
65226
66277
  if (slot && now - slot.at < CACHE_TTL_MS6) return slot.promise;
65227
66278
  const promise = build();
@@ -65231,7 +66282,7 @@ function cache3(slot, build, store) {
65231
66282
  return promise;
65232
66283
  }
65233
66284
  function fetchPendleApiMarkets() {
65234
- return cache3(
66285
+ return cache4(
65235
66286
  marketsCache,
65236
66287
  async () => (await getJson4(PENDLE_MARKETS_URL, "markets"))?.markets ?? [],
65237
66288
  (c) => {
@@ -65241,7 +66292,7 @@ function fetchPendleApiMarkets() {
65241
66292
  }
65242
66293
  var assetKey = (chainId, address) => `${chainId}-${address.toLowerCase()}`;
65243
66294
  function fetchPendleApiAssets() {
65244
- return cache3(
66295
+ return cache4(
65245
66296
  assetsCache,
65246
66297
  async () => {
65247
66298
  const json = await getJson4(PENDLE_ASSETS_URL, "assets");
@@ -65424,6 +66475,255 @@ var fetchPendlePtMarkets = async (chainId, multicallRetry, prices = {}, tokenLis
65424
66475
  return out;
65425
66476
  };
65426
66477
 
66478
+ // src/vaults/spectra/api.ts
66479
+ var SPECTRA_NETWORKS = {
66480
+ "1": "mainnet",
66481
+ "10": "optimism",
66482
+ "14": "flare",
66483
+ "56": "bsc",
66484
+ "143": "monad",
66485
+ "146": "sonic",
66486
+ "999": "hyperevm",
66487
+ "8453": "base",
66488
+ "42161": "arbitrum",
66489
+ "43114": "avalanche",
66490
+ "43111": "hemi",
66491
+ "747474": "katana"
66492
+ };
66493
+ var spectraNetwork = (chainId) => SPECTRA_NETWORKS[String(chainId)];
66494
+ var hasSpectraMarkets = (chainId) => spectraNetwork(chainId) !== void 0;
66495
+ var spectraPoolsUrl = (network) => `https://app.spectra.finance/api/v1/${network}/pools`;
66496
+ var addr2 = (v) => typeof v === "string" && /^0x[0-9a-fA-F]{40}$/.test(v) ? v.toLowerCase() : void 0;
66497
+ var spectraAddress = addr2;
66498
+ function isLiveSpectraMarket(market, nowSecs = Math.floor(Date.now() / 1e3)) {
66499
+ const maturity = market?.maturity;
66500
+ if (typeof maturity !== "number" || !Number.isFinite(maturity)) return false;
66501
+ return maturity > nowSecs;
66502
+ }
66503
+ function pickPool(pools) {
66504
+ if (!Array.isArray(pools) || pools.length === 0) return void 0;
66505
+ let best;
66506
+ let bestDepth = -Infinity;
66507
+ for (const p of pools) {
66508
+ if (!p) continue;
66509
+ const depth = (typeof p.liquidity?.usd === "number" ? p.liquidity.usd : null) ?? (typeof p.liquidity?.underlying === "number" ? p.liquidity.underlying : null) ?? 0;
66510
+ if (depth > bestDepth) {
66511
+ bestDepth = depth;
66512
+ best = p;
66513
+ }
66514
+ }
66515
+ return best ?? pools[0] ?? void 0;
66516
+ }
66517
+ function parseCurveFee(raw) {
66518
+ if (typeof raw !== "string" || !/^\d+$/.test(raw)) return void 0;
66519
+ const n = Number(raw) / 1e10;
66520
+ return Number.isFinite(n) && n >= 0 && n < 1 ? n : void 0;
66521
+ }
66522
+ var SPECTRA_RATE_MIN_PERCENT = -99;
66523
+ var SPECTRA_RATE_MAX_PERCENT = 1e3;
66524
+ function sanePercent(v) {
66525
+ if (typeof v !== "number" || !Number.isFinite(v)) return void 0;
66526
+ if (v < SPECTRA_RATE_MIN_PERCENT || v > SPECTRA_RATE_MAX_PERCENT)
66527
+ return void 0;
66528
+ return v;
66529
+ }
66530
+ var PT_RATE_ONE = 1e27;
66531
+ function parsePtRate(raw) {
66532
+ if (typeof raw !== "string" || !/^\d+$/.test(raw)) return void 0;
66533
+ const n = Number(raw) / PT_RATE_ONE;
66534
+ if (!Number.isFinite(n) || n < 0 || n > 1.000001) return void 0;
66535
+ return n;
66536
+ }
66537
+ var CACHE_TTL_MS7 = 6e4;
66538
+ var cache5 = /* @__PURE__ */ new Map();
66539
+ function clearSpectraMarketsCache() {
66540
+ cache5.clear();
66541
+ }
66542
+ function fetchSpectraApiMarkets(chainId) {
66543
+ const network = spectraNetwork(chainId);
66544
+ if (!network) return Promise.resolve([]);
66545
+ const now = Date.now();
66546
+ const hit = cache5.get(network);
66547
+ if (hit && now - hit.at < CACHE_TTL_MS7) return hit.promise;
66548
+ const promise = (async () => {
66549
+ const response = await fetch(spectraPoolsUrl(network), {
66550
+ headers: { Accept: "application/json" }
66551
+ });
66552
+ if (!response.ok) {
66553
+ throw new Error(
66554
+ `Spectra pools API failed for ${network}: ${response.status} - ${response.statusText}`
66555
+ );
66556
+ }
66557
+ const json = await response.json();
66558
+ return Array.isArray(json) ? json : [];
66559
+ })();
66560
+ cache5.set(network, { at: now, promise });
66561
+ promise.catch(() => {
66562
+ if (cache5.get(network)?.promise === promise) cache5.delete(network);
66563
+ });
66564
+ return promise;
66565
+ }
66566
+
66567
+ // src/vaults/spectra/fetchPublic.ts
66568
+ var SECONDS_PER_DAY3 = 86400;
66569
+ var num12 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
66570
+ function resolveToken2(address, apiToken, tokenList, decimalsOnChain) {
66571
+ const listed = address ? tokenList[address] : void 0;
66572
+ const apiDecimals = typeof apiToken?.decimals === "number" && Number.isFinite(apiToken.decimals) ? apiToken.decimals : void 0;
66573
+ return {
66574
+ decimals: listed?.decimals ?? apiDecimals ?? (address ? decimalsOnChain.get(address) : void 0),
66575
+ symbol: listed?.symbol ?? apiToken?.symbol ?? void 0,
66576
+ name: listed?.name ?? apiToken?.name ?? void 0,
66577
+ logoURI: listed?.logoURI ?? apiToken?.logoURI ?? void 0,
66578
+ assetGroup: listed?.assetGroup
66579
+ };
66580
+ }
66581
+ function parseMarket3(m, chainId, prices, tokenList, decimalsOnChain, nowSecs) {
66582
+ const ptAddress = spectraAddress(m.address);
66583
+ const underlyingAddress = spectraAddress(m.underlying?.address);
66584
+ if (!ptAddress || !underlyingAddress) return null;
66585
+ const maturity = num12(m.maturity);
66586
+ if (maturity === null) return null;
66587
+ const pool = pickPool(m.pools);
66588
+ if (!pool) return null;
66589
+ const ptRate = parsePtRate(m.rate);
66590
+ if (ptRate === void 0 || ptRate <= 0) return null;
66591
+ const impliedApyPercent = sanePercent(pool.impliedApy);
66592
+ if (impliedApyPercent === void 0) return null;
66593
+ const ptMeta = resolveToken2(
66594
+ ptAddress,
66595
+ // The market object IS the PT's token record — `name`/`symbol`/`decimals`
66596
+ // at the root describe the PrincipalToken, not the underlying.
66597
+ {
66598
+ address: m.address,
66599
+ name: m.name,
66600
+ symbol: m.symbol,
66601
+ decimals: m.decimals
66602
+ },
66603
+ tokenList,
66604
+ decimalsOnChain
66605
+ );
66606
+ const assetMeta = resolveToken2(
66607
+ underlyingAddress,
66608
+ m.underlying,
66609
+ tokenList,
66610
+ decimalsOnChain
66611
+ );
66612
+ const decimals = ptMeta.decimals;
66613
+ const assetDecimals = assetMeta.decimals;
66614
+ if (decimals === void 0 || assetDecimals === void 0) return null;
66615
+ const supplyRate = apyToAprPercent(impliedApyPercent);
66616
+ const priceKey = toOracleKey(assetMeta.assetGroup ?? null) || toGenericPriceKey(underlyingAddress, chainId);
66617
+ const priceUsd = prices[priceKey] ?? prices[underlyingAddress];
66618
+ const totalAssetsUnderlying = num12(m.tvl?.underlying) ?? void 0;
66619
+ const totalAssetsUsd = num12(m.tvl?.usd) ?? (totalAssetsUnderlying !== void 0 && priceUsd !== void 0 ? totalAssetsUnderlying * priceUsd : 0);
66620
+ const liquidityUnderlying = num12(pool.liquidity?.underlying);
66621
+ const liquidityUsd = num12(pool.liquidity?.usd) ?? (liquidityUnderlying !== null && priceUsd !== void 0 ? liquidityUnderlying * priceUsd : 0);
66622
+ const ptPriceKey = toOracleKey(ptMeta.assetGroup ?? null) || toGenericPriceKey(ptAddress, chainId);
66623
+ const ptPriceUsd = prices[ptPriceKey] ?? prices[ptAddress] ?? num12(pool.ptPrice?.usd) ?? void 0;
66624
+ const secondsToExpiry = Math.max(maturity - nowSecs, 0);
66625
+ return {
66626
+ address: ptAddress,
66627
+ marketAddress: spectraAddress(pool.address),
66628
+ underlying: underlyingAddress,
66629
+ ytAddress: spectraAddress(m.yt?.address),
66630
+ ibtAddress: spectraAddress(m.ibt?.address),
66631
+ baseIbtAddress: spectraAddress(m.baseIbt?.address),
66632
+ symbol: ptMeta.symbol ?? `PT-${assetMeta.symbol ?? ""}`,
66633
+ name: ptMeta.name ?? `Principal Token ${assetMeta.symbol ?? ""}`,
66634
+ decimals,
66635
+ assetDecimals,
66636
+ expiry: maturity,
66637
+ expiryIso: new Date(maturity * 1e3).toISOString(),
66638
+ secondsToExpiry,
66639
+ daysToExpiry: Math.round(secondsToExpiry / SECONDS_PER_DAY3 * 100) / 100,
66640
+ supplyRate,
66641
+ rewardsRate: 0,
66642
+ depositRate: supplyRate,
66643
+ impliedApyPercent,
66644
+ executableApyPercent: sanePercent(pool.ptApy),
66645
+ underlyingApyPercent: sanePercent(m.ibt?.apr?.total),
66646
+ feeRate: parseCurveFee(pool.feeRate),
66647
+ totalAssetsUsd,
66648
+ totalAssetsFormatted: totalAssetsUsd,
66649
+ liquidityUsd,
66650
+ totalAssetsUnderlying,
66651
+ ptRate,
66652
+ principalWriteDownBps: Math.max(0, Math.round((1 - ptRate) * 1e4)),
66653
+ isMintable: true,
66654
+ withdrawalMode: "market-sale",
66655
+ // Pre-seeded from Spectra's own icon CDN. `stampVaultClassification`
66656
+ // overwrites it when the token list resolves something and leaves it alone
66657
+ // otherwise, so a row still renders an icon with no token list.
66658
+ logoURI: ptMeta.logoURI,
66659
+ // Prefer the curated token-list entry (it carries `assetGroup`, tags and
66660
+ // everything else downstream reads); synthesize from Spectra's own record
66661
+ // otherwise, so `stampVaultClassification` still has a symbol to read for
66662
+ // the stable/volatile call.
66663
+ asset: tokenList[underlyingAddress] ?? (assetMeta.symbol ? {
66664
+ chainId,
66665
+ address: underlyingAddress,
66666
+ symbol: assetMeta.symbol,
66667
+ name: assetMeta.name,
66668
+ decimals: assetDecimals,
66669
+ logoURI: assetMeta.logoURI
66670
+ } : void 0),
66671
+ priceUsd,
66672
+ ptPriceUsd,
66673
+ ptPriceUnderlying: num12(pool.ptPrice?.underlying) ?? void 0,
66674
+ categoryIds: Array.isArray(m.tags) ? m.tags : void 0,
66675
+ protocol: m.ibt?.protocol ?? void 0
66676
+ };
66677
+ }
66678
+ var fetchSpectraPtMarkets = async (chainId, multicallRetry, prices = {}, tokenList = {}, options = {}) => {
66679
+ if (!hasSpectraMarkets(chainId)) return {};
66680
+ const nowSecs = options.nowSecs ?? Math.floor(Date.now() / 1e3);
66681
+ const all = await fetchSpectraApiMarkets(chainId);
66682
+ const candidates = all.filter(
66683
+ (m) => !!m && (options.includeExpired === true || isLiveSpectraMarket(m, nowSecs))
66684
+ );
66685
+ if (candidates.length === 0) return {};
66686
+ const unresolved = /* @__PURE__ */ new Set();
66687
+ for (const m of candidates) {
66688
+ const pairs = [
66689
+ [spectraAddress(m.address), m.decimals],
66690
+ [spectraAddress(m.underlying?.address), m.underlying?.decimals]
66691
+ ];
66692
+ for (const [address, apiDecimals] of pairs) {
66693
+ if (!address) continue;
66694
+ if (tokenList[address]?.decimals !== void 0) continue;
66695
+ if (typeof apiDecimals === "number" && Number.isFinite(apiDecimals))
66696
+ continue;
66697
+ unresolved.add(address);
66698
+ }
66699
+ }
66700
+ let decimalsOnChain = /* @__PURE__ */ new Map();
66701
+ if (unresolved.size > 0) {
66702
+ try {
66703
+ decimalsOnChain = await fetchAssetDecimals(
66704
+ chainId,
66705
+ [...unresolved],
66706
+ multicallRetry
66707
+ );
66708
+ } catch {
66709
+ decimalsOnChain = /* @__PURE__ */ new Map();
66710
+ }
66711
+ }
66712
+ const out = {};
66713
+ for (const m of candidates) {
66714
+ const parsed = parseMarket3(
66715
+ m,
66716
+ chainId,
66717
+ prices,
66718
+ tokenList,
66719
+ decimalsOnChain,
66720
+ nowSecs
66721
+ );
66722
+ if (parsed) out[parsed.address] = parsed;
66723
+ }
66724
+ return out;
66725
+ };
66726
+
65427
66727
  // src/vaults/yield/sharePrice.ts
65428
66728
  var VAULT_SHARE_PRICE_PROBE = 10n ** 18n;
65429
66729
  var ConvertToAssetsAbi = [
@@ -65503,11 +66803,11 @@ function buildVaultLookup(data) {
65503
66803
  const addEntries = (bag, provider) => {
65504
66804
  if (!bag) return;
65505
66805
  for (const v of Object.values(bag)) {
65506
- const addr3 = v.address.toLowerCase();
65507
- if (map.has(addr3)) continue;
65508
- map.set(addr3, {
66806
+ const addr4 = v.address.toLowerCase();
66807
+ if (map.has(addr4)) continue;
66808
+ map.set(addr4, {
65509
66809
  provider,
65510
- address: addr3,
66810
+ address: addr4,
65511
66811
  underlying: v.underlying.toLowerCase(),
65512
66812
  symbol: v.symbol,
65513
66813
  name: v.name,
@@ -66272,6 +67572,29 @@ var TERM_PROFILES = [
66272
67572
  ]
66273
67573
  }
66274
67574
  }),
67575
+ P({
67576
+ id: "twyne.credit-delegation@v1",
67577
+ name: "Twyne credit delegation",
67578
+ family: "twyne",
67579
+ supply: {
67580
+ description: "You deposit a receipt token you already hold \u2014 an Euler eToken, or a Twyne wrapper around an Aave aToken \u2014 and keep earning that token\u2019s own yield while borrowers pay you a fee for the borrowing power you were not using.",
67581
+ implications: [
67582
+ "Your capital never leaves the underlying lending market; only the right to borrow against it is delegated.",
67583
+ "You are FIRST-LOSS on that delegation. Twyne liquidates a failing borrower first and you lose nothing \u2014 but if nobody does so in time and Aave or Euler liquidates instead, the shortfall comes out of the delegated credit.",
67584
+ "You can withdraw whenever credit is not reserved. A fully utilised credit vault cannot be exited until a borrower releases credit."
67585
+ ]
67586
+ },
67587
+ borrow: {
67588
+ description: "Borrow against collateral that stays in Aave or Euler, at a higher liquidation LTV than that market allows on its own, by reserving other lenders\u2019 unused borrowing power.",
67589
+ implications: [
67590
+ "There is no single liquidation LTV here: you pick one for THIS position, inside the band the market allows, and you can change it at any time. Higher means more credit reserved and more paid for it.",
67591
+ "You pay TWO interest legs on different bases \u2014 the underlying market\u2019s borrow rate on your debt, plus Twyne\u2019s rate on the RESERVED CREDIT, charged in the collateral asset. The second is small precisely because it applies only to the extra slice.",
67592
+ "Liquidation does not auction your collateral. A liquidator takes over your vault and must make it healthy in the same transaction; below the safety line you keep your entire remaining equity, and their cut grows only as the position deteriorates.",
67593
+ "If no Twyne liquidator acts in time, the underlying market liquidates the whole position at its own penalty \u2014 and the vault is then frozen, so it can only be wound up.",
67594
+ 'Reserved credit is not yours: it is not withdrawable, and "withdraw everything" means your own collateral, not the vault\u2019s balance.'
67595
+ ]
67596
+ }
67597
+ }),
66275
67598
  P({
66276
67599
  id: "morpho.blue@v1",
66277
67600
  name: "Morpho Blue isolated market",
@@ -66448,6 +67771,7 @@ var VAULT_PROVIDER_PROFILE = {
66448
67771
  savings: "vault.savings@v1",
66449
67772
  lst: "vault.lst@v1",
66450
67773
  pendle: "vault.fixed-maturity@v1",
67774
+ spectra: "vault.fixed-maturity@v1",
66451
67775
  lagoon: "vault.request@v1",
66452
67776
  upshift: "vault.request@v1",
66453
67777
  yearn: "vault.strategy@v1",
@@ -67142,6 +68466,37 @@ var VAULT_PROVIDER_TRAITS = {
67142
68466
  hasDecomposableBacking: false,
67143
68467
  hasUtilization: false
67144
68468
  },
68469
+ // Spectra PTs are the same instrument as Pendle's, so the traits agree
68470
+ // where the economics agree — with one deliberate divergence below.
68471
+ spectra: {
68472
+ rateKind: "fixed-term",
68473
+ // Same call as Pendle, and for the same reason: no borrower, no
68474
+ // leverage, no tranching on the Spectra side, so the fixed-rate promise
68475
+ // itself carries no credit risk. The IBT it redeems into is only as good
68476
+ // as the protocol behind it, and that passes straight through to the PT
68477
+ // holder — a property of the underlying, stated in the profile.
68478
+ //
68479
+ // **The divergence from Pendle is that Spectra makes the failure mode
68480
+ // legible.** `ptRate` starts at par and is written DOWN whenever the IBT
68481
+ // loses value ("The `ptRate` can only decrease" — their own docs work the
68482
+ // example where a halved IBT returns half the deposit). Pendle carries
68483
+ // the identical exposure through its SY and publishes no equivalent
68484
+ // number. So this is not a weaker claim than Pendle's, it is the same
68485
+ // claim with a live check attached: the row ships `ptRate` and
68486
+ // `principalWriteDownBps`, and a market written down to zero is dropped
68487
+ // outright rather than served as a bond.
68488
+ solvency: "overcollateralized",
68489
+ rateSource: "derived",
68490
+ rateWindow: { kind: "forward" },
68491
+ defaultExitMode: "market-sale",
68492
+ priceRisk: "market-price",
68493
+ counterpartyKind: "p2p",
68494
+ reportsPerformanceFee: false,
68495
+ reportsGovernance: false,
68496
+ reportsExposures: false,
68497
+ hasDecomposableBacking: false,
68498
+ hasUtilization: false
68499
+ },
67145
68500
  lagoon: {
67146
68501
  rateKind: "variable-managed",
67147
68502
  rateSource: "api",
@@ -67891,7 +69246,8 @@ var VAULT_PROVIDER_BRANDS = {
67891
69246
  yearn: "Yearn",
67892
69247
  hypercore: "HyperLiquid",
67893
69248
  gmx: "GMX",
67894
- pendle: "Pendle"
69249
+ pendle: "Pendle",
69250
+ spectra: "Spectra"
67895
69251
  };
67896
69252
  function isInstanceSegment(seg) {
67897
69253
  if (/^\d+$/.test(seg)) return true;
@@ -68108,7 +69464,7 @@ function resolveEarnIdentity(venue, brand, publishedProtocol) {
68108
69464
  }
68109
69465
 
68110
69466
  // src/earn/normalize.ts
68111
- function num12(v) {
69467
+ function num13(v) {
68112
69468
  if (v == null || v === "") return void 0;
68113
69469
  const n = typeof v === "number" ? v : Number(v);
68114
69470
  return Number.isFinite(n) ? n : void 0;
@@ -68118,7 +69474,7 @@ function str6(v) {
68118
69474
  if (typeof v === "number" && Number.isFinite(v)) return String(v);
68119
69475
  return void 0;
68120
69476
  }
68121
- function addr2(v) {
69477
+ function addr3(v) {
68122
69478
  return str6(v)?.toLowerCase();
68123
69479
  }
68124
69480
  function yieldProfile(v) {
@@ -68164,6 +69520,7 @@ var RATE_SOURCE = {
68164
69520
  yearn: "api",
68165
69521
  "aave-earn": "api",
68166
69522
  pendle: "api",
69523
+ spectra: "api",
68167
69524
  lista: "chain",
68168
69525
  fluid: "chain",
68169
69526
  gearbox: "chain",
@@ -68189,6 +69546,8 @@ var RATE_KIND = {
68189
69546
  // to maturity — the same promise TermMax's FT makes, reached by a different
68190
69547
  // mechanism (an AMM discount rather than a quoted curve).
68191
69548
  pendle: "fixed-term",
69549
+ // Same instrument, same promise: the discount at purchase IS the rate.
69550
+ spectra: "fixed-term",
68192
69551
  savings: "variable-managed",
68193
69552
  lst: "variable-managed",
68194
69553
  lagoon: "variable-managed",
@@ -68202,8 +69561,8 @@ function resolveExitMode2(provider, meta, tvl, liq) {
68202
69561
  if (declared) return declared;
68203
69562
  const fallback = vaultTraits(provider)?.defaultExitMode ?? "instant";
68204
69563
  if (fallback !== "instant-capped") return fallback;
68205
- const total = num12(tvl?.totalAssetsFormatted) ?? num12(tvl?.totalAssetsUsd);
68206
- const available = num12(liq?.liquidityFormatted) ?? num12(liq?.liquidityUsd);
69564
+ const total = num13(tvl?.totalAssetsFormatted) ?? num13(tvl?.totalAssetsUsd);
69565
+ const available = num13(liq?.liquidityFormatted) ?? num13(liq?.liquidityUsd);
68207
69566
  if (total === void 0 || available === void 0) return "instant-capped";
68208
69567
  if (total <= 0) return "instant";
68209
69568
  return available >= total ? "instant" : "instant-capped";
@@ -68238,8 +69597,8 @@ function earnMarketFromVault(row, chainId, opts = {}) {
68238
69597
  const rates = row.rates ?? {};
68239
69598
  const tvl = row.tvl ?? {};
68240
69599
  const liq = row.liquidity ?? {};
68241
- const shareDecimals = num12(row.decimals) ?? 18;
68242
- const assetDecimals = num12(row.assetDecimals) ?? num12(row.underlyingInfo?.asset?.decimals) ?? shareDecimals;
69600
+ const shareDecimals = num13(row.decimals) ?? 18;
69601
+ const assetDecimals = num13(row.assetDecimals) ?? num13(row.underlyingInfo?.asset?.decimals) ?? shareDecimals;
68243
69602
  const toPercent2 = (v) => ratePercent(v, provider, opts.fractionRateProviders);
68244
69603
  const rewards = toPercent2(rates.rewardsRate);
68245
69604
  const deposit = toPercent2(rates.depositRate);
@@ -68321,7 +69680,7 @@ function earnMarketFromVault(row, chainId, opts = {}) {
68321
69680
  symbol: str6(row.underlyingInfo?.asset?.symbol) ?? "",
68322
69681
  decimals: assetDecimals,
68323
69682
  assetGroup: str6(info.assetGroup),
68324
- priceUsd: num12(row.underlyingInfo?.prices?.priceUsd)
69683
+ priceUsd: num13(row.underlyingInfo?.prices?.priceUsd)
68325
69684
  },
68326
69685
  // The vault IS a share token by construction; carry it so a withdraw in
68327
69686
  // share units can be built without a second lookup.
@@ -68351,8 +69710,8 @@ function earnMarketFromVault(row, chainId, opts = {}) {
68351
69710
  exit: {
68352
69711
  mode: exitMode,
68353
69712
  settlement: str6(meta.redemptionType),
68354
- cooldownSecs: num12(meta.withdrawalCooldownSeconds),
68355
- feeBps: num12(meta.withdrawFeeBps)
69713
+ cooldownSecs: num13(meta.withdrawalCooldownSeconds),
69714
+ feeBps: num13(meta.withdrawFeeBps)
68356
69715
  },
68357
69716
  availability,
68358
69717
  risk: {
@@ -68362,12 +69721,12 @@ function earnMarketFromVault(row, chainId, opts = {}) {
68362
69721
  // since the surface was written and never populated — a tranche's
68363
69722
  // first-loss position is the term most worth surfacing on a rate list.
68364
69723
  counterparty: str6(meta.solvency),
68365
- score: num12(row.rating?.score),
69724
+ score: num13(row.rating?.score),
68366
69725
  label: str6(row.rating?.level),
68367
69726
  illiquid: isIlliquid({
68368
69727
  exitMode,
68369
- tvlUsd: num12(tvl.totalAssetsUsd),
68370
- liquidityUsd: num12(liq.liquidityUsd)
69728
+ tvlUsd: num13(tvl.totalAssetsUsd),
69729
+ liquidityUsd: num13(liq.liquidityUsd)
68371
69730
  })
68372
69731
  },
68373
69732
  // Filled by `capabilities.ts` — kept required on the type so a normalizer
@@ -68379,7 +69738,7 @@ function earnMarketFromVault(row, chainId, opts = {}) {
68379
69738
  return market;
68380
69739
  }
68381
69740
  function ratePercent(value, provider, fractionProviders = FRACTION_RATE_PROVIDERS) {
68382
- const n = num12(value);
69741
+ const n = num13(value);
68383
69742
  if (n === void 0) return void 0;
68384
69743
  return fractionProviders.has(provider) ? n * 100 : n;
68385
69744
  }
@@ -68434,7 +69793,7 @@ function vaultDisplayName(row, info) {
68434
69793
  return str6(row.name) ?? str6(info.name) ?? str6(row.displayName) ?? str6(share?.name) ?? str6(share?.symbol) ?? str6(info.symbol) ?? str6(row.symbol);
68435
69794
  }
68436
69795
  function resolveMaturity(meta) {
68437
- const expiry = num12(meta.expiry) ?? num12(meta.maturity);
69796
+ const expiry = num13(meta.expiry) ?? num13(meta.maturity);
68438
69797
  if (expiry === void 0 || expiry <= 0) return void 0;
68439
69798
  const nowSecs = Math.floor(Date.now() / 1e3);
68440
69799
  return {
@@ -68457,8 +69816,8 @@ function amount(raw, formatted, usd, decimals) {
68457
69816
  const rawStr = raw != null ? String(raw) : void 0;
68458
69817
  return {
68459
69818
  raw: rawStr,
68460
- formatted: num12(formatted) ?? formatRaw(rawStr, decimals),
68461
- usd: num12(usd)
69819
+ formatted: num13(formatted) ?? formatRaw(rawStr, decimals),
69820
+ usd: num13(usd)
68462
69821
  };
68463
69822
  }
68464
69823
  function withCuratorEntity(id, entity) {
@@ -68471,7 +69830,7 @@ function sum(a, b) {
68471
69830
  }
68472
69831
 
68473
69832
  // src/terms/vault/input.ts
68474
- var num13 = (v) => {
69833
+ var num14 = (v) => {
68475
69834
  if (typeof v === "number") return Number.isFinite(v) ? v : void 0;
68476
69835
  if (typeof v === "string" && v.trim() !== "") {
68477
69836
  const n = Number(v);
@@ -68490,27 +69849,27 @@ var fromRaw = (raw, decimals) => {
68490
69849
  function sdkRates(row, provider) {
68491
69850
  if (!SDK_FRACTION_RATE_PROVIDERS.has(provider)) {
68492
69851
  return {
68493
- supplyRate: num13(row.supplyRate),
68494
- rewardsRate: num13(row.rewardsRate),
68495
- totalRate: num13(row.depositRate)
69852
+ supplyRate: num14(row.supplyRate),
69853
+ rewardsRate: num14(row.rewardsRate),
69854
+ totalRate: num14(row.depositRate)
68496
69855
  };
68497
69856
  }
68498
- const pct2 = (v) => {
68499
- const n = num13(v);
69857
+ const pct3 = (v) => {
69858
+ const n = num14(v);
68500
69859
  return n === void 0 ? void 0 : n * 100;
68501
69860
  };
68502
69861
  return {
68503
69862
  // GMX splits fee APY from incentive APR; HyperCore reports one number.
68504
- supplyRate: pct2(row.baseApy ?? row.apr),
68505
- rewardsRate: pct2(row.bonusApr),
68506
- totalRate: pct2(row.apy ?? row.apr)
69863
+ supplyRate: pct3(row.baseApy ?? row.apr),
69864
+ rewardsRate: pct3(row.bonusApr),
69865
+ totalRate: pct3(row.apy ?? row.apr)
68507
69866
  };
68508
69867
  }
68509
69868
  function toVaultTermInput(vault, provider, chainId) {
68510
69869
  const row = vault;
68511
69870
  const address = str7(row.address)?.toLowerCase();
68512
69871
  if (!address) return void 0;
68513
- const assetDecimals = num13(row.assetDecimals) ?? num13(row.decimals);
69872
+ const assetDecimals = num14(row.assetDecimals) ?? num14(row.decimals);
68514
69873
  const asset = row.asset;
68515
69874
  return {
68516
69875
  provider,
@@ -68536,22 +69895,22 @@ function toVaultTermInput(vault, provider, chainId) {
68536
69895
  // GMX / HyperCore / Pendle report USD only and set the token-denominated
68537
69896
  // fields to their USD figure — `totalAssetsFormatted` is the cross-provider
68538
69897
  // magnitude either way, so prefer it over re-deriving from raw.
68539
- totalAssets: num13(row.totalAssetsFormatted) ?? fromRaw(row.totalAssets, assetDecimals),
68540
- totalAssetsUsd: num13(row.totalAssetsUsd) ?? num13(row.tvlUsd),
68541
- liquidity: num13(row.liquidityFormatted) ?? fromRaw(row.liquidity, assetDecimals),
68542
- liquidityUsd: num13(row.liquidityUsd),
68543
- instantLiquidityRatio: num13(row.instantLiquidityRatio),
69898
+ totalAssets: num14(row.totalAssetsFormatted) ?? fromRaw(row.totalAssets, assetDecimals),
69899
+ totalAssetsUsd: num14(row.totalAssetsUsd) ?? num14(row.tvlUsd),
69900
+ liquidity: num14(row.liquidityFormatted) ?? fromRaw(row.liquidity, assetDecimals),
69901
+ liquidityUsd: num14(row.liquidityUsd),
69902
+ instantLiquidityRatio: num14(row.instantLiquidityRatio),
68544
69903
  totalBorrowed: fromRaw(row.totalBorrowed, assetDecimals),
68545
69904
  expectedLiquidity: fromRaw(row.expectedLiquidity, assetDecimals),
68546
69905
  withdrawalMode: str7(row.withdrawalMode),
68547
- withdrawalCooldownSeconds: num13(row.withdrawalCooldownSeconds),
68548
- withdrawFeeBps: num13(row.withdrawFeeBps),
68549
- fee: num13(row.fee),
68550
- managementFee: num13(row.managementFee),
68551
- swapFeeRate: num13(row.feeRate),
68552
- redemptionDiscountBps: num13(row.redemptionDiscountBps),
69906
+ withdrawalCooldownSeconds: num14(row.withdrawalCooldownSeconds),
69907
+ withdrawFeeBps: num14(row.withdrawFeeBps),
69908
+ fee: num14(row.fee),
69909
+ managementFee: num14(row.managementFee),
69910
+ swapFeeRate: num14(row.feeRate),
69911
+ redemptionDiscountBps: num14(row.redemptionDiscountBps),
68553
69912
  instantRedeemEnabled: bool2(row.instantRedeemEnabled),
68554
- yieldWarmupSeconds: num13(row.yieldWarmupSeconds),
69913
+ yieldWarmupSeconds: num14(row.yieldWarmupSeconds),
68555
69914
  accrual: str7(row.accrual),
68556
69915
  needsDepositApproval: bool2(row.needsDepositApproval),
68557
69916
  isMintable: bool2(row.isMintable),
@@ -68562,8 +69921,8 @@ function toVaultTermInput(vault, provider, chainId) {
68562
69921
  withdrawalsPaused: bool2(row.isWithdrawalPaused),
68563
69922
  isClosed: bool2(row.isClosed),
68564
69923
  whitelisted: bool2(row.whitelisted),
68565
- expiry: num13(row.expiry),
68566
- timelock: num13(row.timelock),
69924
+ expiry: num14(row.expiry),
69925
+ timelock: num14(row.timelock),
68567
69926
  owner: str7(row.owner),
68568
69927
  curator: str7(row.curator),
68569
69928
  guardian: str7(row.guardian),
@@ -68605,18 +69964,18 @@ function vaultTermInputFromEarnMarket(m) {
68605
69964
  totalAssetsUsd: m.tvl.usd,
68606
69965
  liquidity: m.liquidity?.formatted,
68607
69966
  liquidityUsd: m.liquidity?.usd,
68608
- instantLiquidityRatio: num13(meta.instantLiquidityRatio),
68609
- totalBorrowed: num13(meta.totalBorrowed),
68610
- expectedLiquidity: num13(meta.expectedLiquidity),
69967
+ instantLiquidityRatio: num14(meta.instantLiquidityRatio),
69968
+ totalBorrowed: num14(meta.totalBorrowed),
69969
+ expectedLiquidity: num14(meta.expectedLiquidity),
68611
69970
  withdrawalMode: m.exit.mode,
68612
69971
  withdrawalCooldownSeconds: m.exit.cooldownSecs,
68613
69972
  withdrawFeeBps: m.exit.feeBps,
68614
69973
  fee: m.rate.fee,
68615
- managementFee: num13(meta.managementFee),
68616
- swapFeeRate: num13(meta.feeRate),
68617
- redemptionDiscountBps: num13(meta.redemptionDiscountBps),
69974
+ managementFee: num14(meta.managementFee),
69975
+ swapFeeRate: num14(meta.feeRate),
69976
+ redemptionDiscountBps: num14(meta.redemptionDiscountBps),
68618
69977
  instantRedeemEnabled: bool2(meta.instantRedeemEnabled),
68619
- yieldWarmupSeconds: num13(meta.yieldWarmupSeconds),
69978
+ yieldWarmupSeconds: num14(meta.yieldWarmupSeconds),
68620
69979
  accrual: str7(meta.accrual),
68621
69980
  needsDepositApproval: bool2(meta.needsDepositApproval),
68622
69981
  // `canDeposit` already folds in the cap, the pause and the gate, so it is
@@ -68630,7 +69989,7 @@ function vaultTermInputFromEarnMarket(m) {
68630
69989
  isClosed: bool2(meta.isClosed),
68631
69990
  whitelisted: bool2(meta.whitelisted),
68632
69991
  expiry: m.maturity?.maturity,
68633
- timelock: num13(meta.timelock),
69992
+ timelock: num14(meta.timelock),
68634
69993
  owner: str7(meta.owner),
68635
69994
  curator: str7(meta.curator),
68636
69995
  guardian: str7(meta.guardian),
@@ -68642,13 +70001,13 @@ function vaultTermInputFromEarnMarket(m) {
68642
70001
  };
68643
70002
  }
68644
70003
  function originRates(rates) {
68645
- const supply = num13(rates.supplyRate);
68646
- const rewards = num13(rates.rewardsRate);
68647
- const deposit = num13(rates.depositRate);
70004
+ const supply = num14(rates.supplyRate);
70005
+ const rewards = num14(rates.rewardsRate);
70006
+ const deposit = num14(rates.depositRate);
68648
70007
  return {
68649
70008
  supplyRate: supply ?? (deposit !== void 0 && rewards !== void 0 ? deposit - rewards : deposit),
68650
70009
  rewardsRate: rewards,
68651
- totalRate: num13(rates.totalRate) ?? deposit
70010
+ totalRate: num14(rates.totalRate) ?? deposit
68652
70011
  };
68653
70012
  }
68654
70013
  function vaultTermInputFromSourceRow(row, chainId) {
@@ -68661,7 +70020,7 @@ function vaultTermInputFromSourceRow(row, chainId) {
68661
70020
  const liq = row.liquidity ?? {};
68662
70021
  const info = row.vaultInfo ?? {};
68663
70022
  const assetInfo = row.underlyingInfo?.asset;
68664
- const assetDecimals = num13(row.assetDecimals) ?? num13(assetInfo?.decimals) ?? num13(row.decimals);
70023
+ const assetDecimals = num14(row.assetDecimals) ?? num14(assetInfo?.decimals) ?? num14(row.decimals);
68665
70024
  return {
68666
70025
  provider,
68667
70026
  chainId,
@@ -68682,22 +70041,22 @@ function vaultTermInputFromSourceRow(row, chainId) {
68682
70041
  ...originRates(rates),
68683
70042
  isForwardApr: bool2(meta.isForwardApr),
68684
70043
  aprWindow: str7(meta.aprWindow),
68685
- totalAssets: num13(tvl.totalAssetsFormatted) ?? fromRaw(tvl.totalAssets, assetDecimals),
68686
- totalAssetsUsd: num13(tvl.totalAssetsUsd),
68687
- liquidity: num13(liq.liquidityFormatted) ?? fromRaw(liq.liquidity, assetDecimals),
68688
- liquidityUsd: num13(liq.liquidityUsd),
68689
- instantLiquidityRatio: num13(meta.instantLiquidityRatio),
70044
+ totalAssets: num14(tvl.totalAssetsFormatted) ?? fromRaw(tvl.totalAssets, assetDecimals),
70045
+ totalAssetsUsd: num14(tvl.totalAssetsUsd),
70046
+ liquidity: num14(liq.liquidityFormatted) ?? fromRaw(liq.liquidity, assetDecimals),
70047
+ liquidityUsd: num14(liq.liquidityUsd),
70048
+ instantLiquidityRatio: num14(meta.instantLiquidityRatio),
68690
70049
  totalBorrowed: fromRaw(meta.totalBorrowed, assetDecimals),
68691
70050
  expectedLiquidity: fromRaw(meta.expectedLiquidity, assetDecimals),
68692
70051
  withdrawalMode: str7(meta.withdrawalMode),
68693
- withdrawalCooldownSeconds: num13(meta.withdrawalCooldownSeconds),
68694
- withdrawFeeBps: num13(meta.withdrawFeeBps),
68695
- fee: num13(rates.fee),
68696
- managementFee: num13(meta.managementFee),
68697
- swapFeeRate: num13(meta.feeRate),
68698
- redemptionDiscountBps: num13(meta.redemptionDiscountBps),
70052
+ withdrawalCooldownSeconds: num14(meta.withdrawalCooldownSeconds),
70053
+ withdrawFeeBps: num14(meta.withdrawFeeBps),
70054
+ fee: num14(rates.fee),
70055
+ managementFee: num14(meta.managementFee),
70056
+ swapFeeRate: num14(meta.feeRate),
70057
+ redemptionDiscountBps: num14(meta.redemptionDiscountBps),
68699
70058
  instantRedeemEnabled: bool2(meta.instantRedeemEnabled),
68700
- yieldWarmupSeconds: num13(meta.yieldWarmupSeconds),
70059
+ yieldWarmupSeconds: num14(meta.yieldWarmupSeconds),
68701
70060
  accrual: str7(meta.accrual),
68702
70061
  needsDepositApproval: bool2(meta.needsDepositApproval),
68703
70062
  isMintable: bool2(meta.isMintable),
@@ -68708,8 +70067,8 @@ function vaultTermInputFromSourceRow(row, chainId) {
68708
70067
  withdrawalsPaused: bool2(meta.isWithdrawalPaused),
68709
70068
  isClosed: bool2(meta.isClosed),
68710
70069
  whitelisted: bool2(meta.whitelisted),
68711
- expiry: num13(meta.expiry) ?? num13(meta.maturity),
68712
- timelock: num13(meta.timelock),
70070
+ expiry: num14(meta.expiry) ?? num14(meta.maturity),
70071
+ timelock: num14(meta.timelock),
68713
70072
  owner: str7(meta.owner),
68714
70073
  curator: str7(meta.curator),
68715
70074
  guardian: str7(meta.guardian),
@@ -68746,6 +70105,7 @@ function stampVaultTermSheets(data, chainId) {
68746
70105
  stampBag(data.upshift, "upshift");
68747
70106
  stampBag(data.yearn, "yearn");
68748
70107
  stampBag(data.pendle, "pendle");
70108
+ stampBag(data.spectra, "spectra");
68749
70109
  stampBag(data.hypercore, "hypercore");
68750
70110
  stampBag(data.gmx, "gmx");
68751
70111
  }
@@ -68767,7 +70127,8 @@ var VAULT_PROVIDERS = [
68767
70127
  "yearn",
68768
70128
  "hypercore",
68769
70129
  "gmx",
68770
- "pendle"
70130
+ "pendle",
70131
+ "spectra"
68771
70132
  ];
68772
70133
  var HYPERCORE_PROVIDER_CHAIN = "999";
68773
70134
  var getVaultPublicDataAll = async (chainId, providers, multicallRetry, prices = {}, tokenList = {}, options) => {
@@ -68960,6 +70321,20 @@ var getVaultPublicDataAll = async (chainId, providers, multicallRetry, prices =
68960
70321
  })
68961
70322
  );
68962
70323
  }
70324
+ if (requested.has("spectra") && hasSpectraMarkets(chainId)) {
70325
+ tasks.push(
70326
+ fetchSpectraPtMarkets(chainId, multicallRetry, prices, tokenList, {
70327
+ includeExpired: options?.spectraIncludeExpired
70328
+ }).then((res) => {
70329
+ out.spectra = res;
70330
+ }).catch((e) => {
70331
+ warn8(
70332
+ `[vaults] spectra fetch failed for chain ${chainId}:`,
70333
+ e?.message ?? e
70334
+ );
70335
+ })
70336
+ );
70337
+ }
68963
70338
  if (requested.has("gmx") && getGmxApiHost(chainId)) {
68964
70339
  tasks.push(
68965
70340
  fetchGmxVaults(chainId, multicallRetry).then((res) => {
@@ -69292,32 +70667,32 @@ async function fetchTokenMetadata(chain, addrs) {
69292
70667
  const results = await client.multicall({
69293
70668
  allowFailure: false,
69294
70669
  batchSize: 300,
69295
- contracts: addrs.map((addr3) => [
70670
+ contracts: addrs.map((addr4) => [
69296
70671
  {
69297
70672
  abi: ERC20MetadataAbi,
69298
70673
  functionName: "name",
69299
- address: addr3,
70674
+ address: addr4,
69300
70675
  args: []
69301
70676
  },
69302
70677
  {
69303
70678
  abi: ERC20MetadataAbi,
69304
70679
  functionName: "symbol",
69305
- address: addr3,
70680
+ address: addr4,
69306
70681
  args: []
69307
70682
  },
69308
70683
  {
69309
70684
  abi: ERC20MetadataAbi,
69310
70685
  functionName: "decimals",
69311
- address: addr3,
70686
+ address: addr4,
69312
70687
  args: []
69313
70688
  }
69314
70689
  ]).flat()
69315
70690
  });
69316
- addrs.forEach((addr3, i) => {
70691
+ addrs.forEach((addr4, i) => {
69317
70692
  const name = results[i * 3];
69318
70693
  const symbol = results[i * 3 + 1];
69319
70694
  const decimals = results[i * 3 + 2];
69320
- const address = addr3.toLowerCase();
70695
+ const address = addr4.toLowerCase();
69321
70696
  tokens[address] = {
69322
70697
  chainId: String(chain),
69323
70698
  decimals,
@@ -69532,7 +70907,7 @@ async function fetchTokenBalances(chainId, account, tokens, options = {}) {
69532
70907
  }
69533
70908
 
69534
70909
  // src/terms/input.ts
69535
- var num14 = (v) => {
70910
+ var num15 = (v) => {
69536
70911
  if (v == null) return void 0;
69537
70912
  const n = typeof v === "string" ? Number(v) : v;
69538
70913
  return Number.isFinite(n) ? n : void 0;
@@ -69563,12 +70938,12 @@ function toTermSheetInput(row, ctx = {}) {
69563
70938
  {
69564
70939
  category: v?.category ?? k,
69565
70940
  label: v?.label,
69566
- borrowCollateralFactor: num14(v?.borrowCollateralFactor),
69567
- collateralFactor: num14(v?.collateralFactor),
69568
- borrowFactor: num14(v?.borrowFactor),
69569
- liquidationPenalty: num14(v?.liquidationPenalty),
69570
- closeFactor: num14(v?.closeFactor),
69571
- targetHealthFactor: num14(v?.targetHealthFactor),
70941
+ borrowCollateralFactor: num15(v?.borrowCollateralFactor),
70942
+ collateralFactor: num15(v?.collateralFactor),
70943
+ borrowFactor: num15(v?.borrowFactor),
70944
+ liquidationPenalty: num15(v?.liquidationPenalty),
70945
+ closeFactor: num15(v?.closeFactor),
70946
+ targetHealthFactor: num15(v?.targetHealthFactor),
69572
70947
  collateralDisabled: v?.collateralDisabled === true,
69573
70948
  debtDisabled: v?.debtDisabled === true
69574
70949
  }
@@ -69576,11 +70951,11 @@ function toTermSheetInput(row, ctx = {}) {
69576
70951
  ) : void 0;
69577
70952
  const rewards = pick2(row, "rewards")?.map((r) => ({
69578
70953
  asset: r?.asset,
69579
- depositRate: num14(r?.depositRate),
69580
- variableBorrowRate: num14(r?.variableBorrowRate),
69581
- stableBorrowRate: num14(r?.stableBorrowRate),
70954
+ depositRate: num15(r?.depositRate),
70955
+ variableBorrowRate: num15(r?.variableBorrowRate),
70956
+ stableBorrowRate: num15(r?.stableBorrowRate),
69582
70957
  kind: r?.kind,
69583
- endsAt: num14(r?.endsAt),
70958
+ endsAt: num15(r?.endsAt),
69584
70959
  claim: r?.claim
69585
70960
  }));
69586
70961
  return {
@@ -69593,29 +70968,29 @@ function toTermSheetInput(row, ctx = {}) {
69593
70968
  "underlyingInfo.asset"
69594
70969
  ),
69595
70970
  underlying: pick2(row, "underlying"),
69596
- decimals: num14(pick2(row, "decimals")),
69597
- depositRate: num14(pick2(row, "depositRate")),
69598
- variableBorrowRate: num14(pick2(row, "variableBorrowRate")),
69599
- stableBorrowRate: num14(pick2(row, "stableBorrowRate")),
69600
- intrinsicYield: num14(pick2(row, "intrinsicYield")),
70971
+ decimals: num15(pick2(row, "decimals")),
70972
+ depositRate: num15(pick2(row, "depositRate")),
70973
+ variableBorrowRate: num15(pick2(row, "variableBorrowRate")),
70974
+ stableBorrowRate: num15(pick2(row, "stableBorrowRate")),
70975
+ intrinsicYield: num15(pick2(row, "intrinsicYield")),
69601
70976
  rewards,
69602
70977
  rateModel: pick2(row, "rateModel"),
69603
- originationFee: num14(pick2(row, "originationFee")),
69604
- totalDeposits: num14(pick2(row, "totalDeposits")),
69605
- totalDebt: num14(pick2(row, "totalDebt")),
69606
- totalDebtStable: num14(pick2(row, "totalDebtStable")),
69607
- totalLiquidity: num14(pick2(row, "totalLiquidity")),
69608
- borrowLiquidity: num14(pick2(row, "borrowLiquidity")),
69609
- totalDepositsUsd: num14(pick2(row, "totalDepositsUSD", "totalDepositsUsd")),
69610
- totalDebtUsd: num14(pick2(row, "totalDebtUSD", "totalDebtUsd")),
69611
- totalLiquidityUsd: num14(pick2(row, "totalLiquidityUSD", "totalLiquidityUsd")),
69612
- utilization: num14(pick2(row, "utilization")),
69613
- irmTotalDeposits: num14(pick2(row, "irmTotalDeposits")),
69614
- irmTotalDebt: num14(pick2(row, "irmTotalDebt")),
69615
- lockupRatio: num14(pick2(row, "lockupRatio")),
70978
+ originationFee: num15(pick2(row, "originationFee")),
70979
+ totalDeposits: num15(pick2(row, "totalDeposits")),
70980
+ totalDebt: num15(pick2(row, "totalDebt")),
70981
+ totalDebtStable: num15(pick2(row, "totalDebtStable")),
70982
+ totalLiquidity: num15(pick2(row, "totalLiquidity")),
70983
+ borrowLiquidity: num15(pick2(row, "borrowLiquidity")),
70984
+ totalDepositsUsd: num15(pick2(row, "totalDepositsUSD", "totalDepositsUsd")),
70985
+ totalDebtUsd: num15(pick2(row, "totalDebtUSD", "totalDebtUsd")),
70986
+ totalLiquidityUsd: num15(pick2(row, "totalLiquidityUSD", "totalLiquidityUsd")),
70987
+ utilization: num15(pick2(row, "utilization")),
70988
+ irmTotalDeposits: num15(pick2(row, "irmTotalDeposits")),
70989
+ irmTotalDebt: num15(pick2(row, "irmTotalDebt")),
70990
+ lockupRatio: num15(pick2(row, "lockupRatio")),
69616
70991
  minBorrow: pick2(row, "minBorrow", "caps.minBorrow") ?? void 0,
69617
- supplyCap: num14(pick2(row, "supplyCap", "caps.supplyCap")),
69618
- borrowCap: num14(pick2(row, "borrowCap", "caps.borrowCap")),
70992
+ supplyCap: num15(pick2(row, "supplyCap", "caps.supplyCap")),
70993
+ borrowCap: num15(pick2(row, "borrowCap", "caps.borrowCap")),
69619
70994
  debtCeiling: pick2(row, "debtCeiling", "caps.debtCeiling"),
69620
70995
  isActive: pick2(row, "isActive", "flags.isActive"),
69621
70996
  isFrozen: pick2(row, "isFrozen", "flags.isFrozen"),
@@ -69641,8 +71016,8 @@ function toTermSheetInput(row, ctx = {}) {
69641
71016
  "flags.variableBorrowDisabled"
69642
71017
  ),
69643
71018
  config,
69644
- closeFactor: num14(pick2(row, "closeFactor")),
69645
- targetHealthFactor: num14(pick2(row, "targetHealthFactor")),
71019
+ closeFactor: num15(pick2(row, "closeFactor")),
71020
+ targetHealthFactor: num15(pick2(row, "targetHealthFactor")),
69646
71021
  fixedTerm: pick2(row, "fixedTerm") ?? ctx.fixedTerm,
69647
71022
  terms: pick2(row, "terms"),
69648
71023
  market: resolveMarketDescriptors(row, ctx.market)
@@ -71014,6 +72389,107 @@ var curvanceAdapter = {
71014
72389
  function numOrUndef(v) {
71015
72390
  return typeof v === "number" && Number.isFinite(v) ? v : void 0;
71016
72391
  }
72392
+ var num16 = (v) => typeof v === "number" && Number.isFinite(v) ? v : void 0;
72393
+ var pct2 = (v) => `${(v * 100).toFixed(2)} %`;
72394
+ var twyneAdapter = {
72395
+ id: "twyne",
72396
+ matches: isTwyne,
72397
+ profileId: () => "twyne.credit-delegation@v1",
72398
+ build: (input) => {
72399
+ const tw = input.market?.twyne ?? {};
72400
+ const floorLtv = num16(tw.floorLtv);
72401
+ const maxLtv = num16(tw.maxLtv);
72402
+ const externalLiqLtv = num16(tw.externalLiqLtv);
72403
+ const creditApr = num16(tw.creditApr);
72404
+ const maturity = num16(tw.collateralMaturity);
72405
+ const matured = tw.collateralMatured === true;
72406
+ const creditAvailable = num16(tw.creditAvailable);
72407
+ const vaultType = typeof tw.vaultType === "string" ? tw.vaultType : void 0;
72408
+ const externalName = vaultType === "AAVE_V3" ? "Aave V3" : vaultType === "EULER_V2" ? "Euler V2" : "the external market";
72409
+ const creditExhausted = creditAvailable != null && creditAvailable <= 0;
72410
+ const bandNote = floorLtv != null && maxLtv != null ? `You choose this position's liquidation LTV anywhere between ${pct2(floorLtv)} and ${pct2(maxLtv)}, and you can change it later. The higher you set it, the more credit the position reserves and the more you pay for it.` : void 0;
72411
+ return {
72412
+ constraints: {
72413
+ // The position is a CONTRACT the borrower deploys, and they may own
72414
+ // several per market — each with its own collateral, debt and LTV.
72415
+ positionModel: "sub-account",
72416
+ positionIdMeaning: "the address of the collateral vault you deployed \u2014 one contract per position, and you can own several in the same market",
72417
+ crossMargin: false
72418
+ },
72419
+ supply: {
72420
+ info: {
72421
+ description: "Credit-LPs deposit a receipt token they already hold (an Euler eToken, or a Twyne wrapper around an Aave aToken) and keep earning that token\u2019s own yield, plus a delegation fee paid by borrowers who reserve their idle borrowing power."
72422
+ },
72423
+ // Credit-LPs are FIRST-LOSS for the fallback-liquidation gap. Neither
72424
+ // of these is left to default: `overcollateralized` would read as a
72425
+ // guarantee that does not exist here, and `protected: true` would say
72426
+ // the principal cannot be impaired, which is exactly what the delegation
72427
+ // risk is.
72428
+ counterparty: { solvency: "tranched-junior" },
72429
+ principal: { protected: false, risks: ["first-loss", "bad-debt"] },
72430
+ exit: {
72431
+ partialAllowed: true
72432
+ }
72433
+ },
72434
+ borrow: {
72435
+ debtShape: "accruing",
72436
+ info: {
72437
+ description: [
72438
+ `Your collateral stays in ${externalName}; Twyne only reserves other lenders\u2019 unused borrowing power so the same collateral supports a larger loan.`,
72439
+ bandNote,
72440
+ creditApr != null ? `On top of ${externalName}\u2019s borrow rate you pay ${creditApr.toFixed(3)} % a year on the RESERVED CREDIT only \u2014 not on your debt \u2014 and it is charged in the collateral asset.` : void 0
72441
+ ].filter(Boolean).join(" ")
72442
+ },
72443
+ availability: {
72444
+ // A matured PT still services existing positions but must not take
72445
+ // new ones, and an exhausted credit vault cannot grant extra LTV.
72446
+ ...matured || creditExhausted ? { canOpen: false } : {},
72447
+ canClose: true
72448
+ },
72449
+ exit: {
72450
+ partialAllowed: true
72451
+ },
72452
+ liquidation: {
72453
+ // Neither 'pool' nor an auction: the liquidator inherits the position.
72454
+ model: "inheritance",
72455
+ trigger: "price",
72456
+ penalties: [
72457
+ {
72458
+ id: "twyne-inheritance",
72459
+ label: "Twyne liquidation (by inheritance)",
72460
+ value: 0,
72461
+ description: "A liquidator takes over your vault and must make it healthy in the same transaction. Nothing is auctioned. While your LTV is still below the protocol\u2019s safety line you keep your entire remaining equity; the liquidator\u2019s cut grows from zero only as the position gets worse, and reaches all of your equity at the maximum LTV."
72462
+ },
72463
+ {
72464
+ id: "external-fallback",
72465
+ label: `${externalName} fallback liquidation`,
72466
+ value: 0,
72467
+ description: `If no Twyne liquidator acts in time, ${externalName} liquidates the whole position at its own threshold and its own penalty. After that the vault is frozen: it can only be wound up, not repaid, topped up or closed.`
72468
+ }
72469
+ ],
72470
+ ...externalLiqLtv != null ? {
72471
+ description: `Twyne liquidates first, above your chosen LTV. ${externalName}\u2019s own threshold of ${pct2(externalLiqLtv)} is the backstop, and reaching it is the bad case.`
72472
+ } : {}
72473
+ },
72474
+ // The collateral has a maturity even though the loan does not — a PT
72475
+ // stops accreting at expiry and the external threshold ramps out from
72476
+ // under it, so this is a date the borrower has to act on.
72477
+ ...maturity ? {
72478
+ maturity: {
72479
+ kind: "fixed-date",
72480
+ maturity,
72481
+ maturityIso: new Date(maturity * 1e3).toISOString(),
72482
+ ...matured ? {
72483
+ description: "This market\u2019s collateral has already matured. Existing positions can still be repaid and closed, but no new borrowing should be opened against it."
72484
+ } : {
72485
+ description: "The collateral is a fixed-maturity token. The loan itself has no end date, but the collateral stops accreting at maturity and the underlying market\u2019s risk parameters move as that date approaches."
72486
+ }
72487
+ }
72488
+ } : {}
72489
+ }
72490
+ };
72491
+ }
72492
+ };
71017
72493
  var fraxlendAdapter = {
71018
72494
  id: "fraxlend",
71019
72495
  matches: isFraxlend,
@@ -71099,6 +72575,7 @@ var TERM_ADAPTERS = [
71099
72575
  frankencoinAdapter,
71100
72576
  resupplyAdapter,
71101
72577
  curvanceAdapter,
72578
+ twyneAdapter,
71102
72579
  fraxlendAdapter,
71103
72580
  morphoBlueAdapter
71104
72581
  ];
@@ -71298,8 +72775,8 @@ function enrichTermSheet(sheet, index) {
71298
72775
  if (!exp) continue;
71299
72776
  for (const item of exp.items) {
71300
72777
  const chain = item.asset.chainId;
71301
- const addr3 = item.asset.address;
71302
- const q = quality?.[chain]?.[addr3];
72778
+ const addr4 = item.asset.address;
72779
+ const q = quality?.[chain]?.[addr4];
71303
72780
  if (q) {
71304
72781
  item.quality = {
71305
72782
  riskScore: q.riskScore,
@@ -71541,8 +73018,6 @@ function validateTermSheet(sheet) {
71541
73018
  function validateTermSheets(sheets) {
71542
73019
  return sheets.flatMap((s) => validateTermSheet(s));
71543
73020
  }
71544
-
71545
- // src/earn/fromPool.ts
71546
73021
  var FIXED_TERM_PREFIXES = [
71547
73022
  "EXACTLY",
71548
73023
  "TELLER",
@@ -71581,10 +73056,40 @@ function venueGroupKey(chainId, venue) {
71581
73056
  return `${chainId}::${venue}`;
71582
73057
  }
71583
73058
  function resolveBasket(row) {
73059
+ const provider = listaCollateralProvider(
73060
+ row.chainId ?? "",
73061
+ str6(row.params?.market?.collateralProvider)
73062
+ );
73063
+ if (provider?.kind === "smart-lp" && provider.coins) {
73064
+ const rowAsset = addr3(row.underlying) ?? addr3(row.asset?.address);
73065
+ if (rowAsset && rowAsset === provider.collateralToken.toLowerCase()) {
73066
+ return {
73067
+ // The row's asset IS the receipt — one row for the whole position,
73068
+ // the opposite of Fluid's per-leg rows.
73069
+ rowAsset: "positionUnit",
73070
+ // `dex.coins(i)` order, NOT the collateral symbol's order:
73071
+ // "USDT & USDe-SmartLP" is [USDe, USDT].
73072
+ legs: provider.coins.map((c) => ({
73073
+ address: c.address.toLowerCase(),
73074
+ symbol: c.symbol,
73075
+ decimals: c.decimals
73076
+ })),
73077
+ autoBalanced: true,
73078
+ ...provider.dexLp ? {
73079
+ positionUnit: {
73080
+ kind: "lpToken",
73081
+ address: provider.dexLp.toLowerCase(),
73082
+ decimals: provider.collateralDecimals
73083
+ }
73084
+ } : {},
73085
+ pool: "lista-smartlp"
73086
+ };
73087
+ }
73088
+ }
71584
73089
  if (row.autoBalanced !== true) return void 0;
71585
73090
  const f = row.fluid;
71586
73091
  if (f && f.isSmartCol !== true) return void 0;
71587
- const legs = (f?.collateralPair ?? []).map((a) => addr2(a)).filter((a) => !!a).map((address) => ({ address }));
73092
+ const legs = (f?.collateralPair ?? []).map((a) => addr3(a)).filter((a) => !!a).map((address) => ({ address }));
71588
73093
  return {
71589
73094
  // Fluid emits one row PER LEG of the pool, so this row is a leg and a
71590
73095
  // consumer that sums the listing without deduping counts the position
@@ -71609,19 +73114,19 @@ function earnMarketFromPool(row, fallbackChainId, venueCollaterals) {
71609
73114
  if (!chainId || !venue) return void 0;
71610
73115
  const flags = row.flags ?? {};
71611
73116
  const assetInfo = row.underlyingInfo?.asset ?? row.asset ?? {};
71612
- const underlying = addr2(assetInfo.address) ?? addr2(row.underlying) ?? addr2(row.poolId);
73117
+ const underlying = addr3(assetInfo.address) ?? addr3(row.underlying) ?? addr3(row.poolId);
71613
73118
  if (!underlying) return void 0;
71614
- const decimals = num12(assetInfo.decimals) ?? num12(row.decimals) ?? 18;
71615
- const priceUsd = num12(row.underlyingInfo?.prices?.priceUsd) ?? num12(row.price);
71616
- const base = num12(row.depositRate);
71617
- const intrinsic = num12(row.intrinsicYield);
73119
+ const decimals = num13(assetInfo.decimals) ?? num13(row.decimals) ?? 18;
73120
+ const priceUsd = num13(row.underlyingInfo?.prices?.priceUsd) ?? num13(row.price);
73121
+ const base = num13(row.depositRate);
73122
+ const intrinsic = num13(row.intrinsicYield);
71618
73123
  const rewards = sumRewardAprs(row.rewards);
71619
73124
  const marketOwn = sum2(base, rewards);
71620
73125
  const rate = {
71621
73126
  // Prefer our own sum over the origin's `apr`, because `apr` is documented
71622
73127
  // as `depositRate + intrinsicYield` and therefore EXCLUDES incentives —
71623
73128
  // using it as the headline would under-report every incentivized market.
71624
- total: sum2(base, intrinsic, rewards) ?? num12(row.apr) ?? 0,
73129
+ total: sum2(base, intrinsic, rewards) ?? num13(row.apr) ?? 0,
71625
73130
  base,
71626
73131
  rewards,
71627
73132
  intrinsic,
@@ -71689,7 +73194,7 @@ function earnMarketFromPool(row, fallbackChainId, venueCollaterals) {
71689
73194
  row.totalLiquidityUSD ?? row.totalLiquidityUsd
71690
73195
  ),
71691
73196
  depositCapacity: void 0,
71692
- utilization: num12(row.utilization),
73197
+ utilization: num13(row.utilization),
71693
73198
  // Lending withdrawals are same-block, bounded by available liquidity —
71694
73199
  // which is exactly `instant-capped`, not `instant`. A pool at 100 %
71695
73200
  // utilization cannot be exited, and calling that `instant` is the kind of
@@ -71697,12 +73202,12 @@ function earnMarketFromPool(row, fallbackChainId, venueCollaterals) {
71697
73202
  exit: { mode: "instant-capped", settlement: "sync" },
71698
73203
  availability,
71699
73204
  risk: {
71700
- score: num12(row.risk?.score),
73205
+ score: num13(row.risk?.score),
71701
73206
  label: str6(row.risk?.label),
71702
73207
  illiquid: isIlliquid({
71703
73208
  exitMode: "instant-capped",
71704
- tvlUsd: num12(row.totalDepositsUSD ?? row.totalDepositsUsd),
71705
- liquidityUsd: num12(row.totalLiquidityUSD ?? row.totalLiquidityUsd)
73209
+ tvlUsd: num13(row.totalDepositsUSD ?? row.totalDepositsUsd),
73210
+ liquidityUsd: num13(row.totalLiquidityUSD ?? row.totalLiquidityUsd)
71706
73211
  })
71707
73212
  },
71708
73213
  ...basket ? { basket } : {},
@@ -71713,7 +73218,7 @@ function earnMarketFromPool(row, fallbackChainId, venueCollaterals) {
71713
73218
  // reads them — two markets on the same pair at the same LLTV differ by
71714
73219
  // nothing else, and one may price its collateral off a feed that ignores
71715
73220
  // a depeg in it.
71716
- oracle: addr2(row.oracleInfo?.feeds?.find((f) => f?.oracle)?.oracle),
73221
+ oracle: addr3(row.oracleInfo?.feeds?.find((f) => f?.oracle)?.oracle),
71717
73222
  oracleDescription: str6(
71718
73223
  row.oracleInfo?.feeds?.find((f) => f?.priceDescription)?.priceDescription
71719
73224
  ),
@@ -71766,9 +73271,9 @@ function resolveAvailability2(row, flags, totalRate) {
71766
73271
  };
71767
73272
  }
71768
73273
  function isSupplyCapFull(row) {
71769
- const cap = num12(row.caps?.supplyCap) ?? num12(row.supplyCap);
73274
+ const cap = num13(row.caps?.supplyCap) ?? num13(row.supplyCap);
71770
73275
  if (cap === void 0 || cap <= 0) return false;
71771
- const deposits = num12(row.totalDeposits);
73276
+ const deposits = num13(row.totalDeposits);
71772
73277
  if (deposits === void 0) return false;
71773
73278
  return deposits >= cap;
71774
73279
  }
@@ -71777,7 +73282,7 @@ function sumRewardAprs(rewards) {
71777
73282
  let total = 0;
71778
73283
  let seen = false;
71779
73284
  for (const r of rewards) {
71780
- const apr = num12(r?.depositRate);
73285
+ const apr = num13(r?.depositRate);
71781
73286
  if (apr === void 0) continue;
71782
73287
  total += apr;
71783
73288
  seen = true;
@@ -71785,7 +73290,7 @@ function sumRewardAprs(rewards) {
71785
73290
  return seen ? total : void 0;
71786
73291
  }
71787
73292
  function amount2(formatted, usd) {
71788
- return { formatted: num12(formatted), usd: num12(usd) };
73293
+ return { formatted: num13(formatted), usd: num13(usd) };
71789
73294
  }
71790
73295
  function sum2(...parts) {
71791
73296
  const present = parts.filter((p) => p !== void 0);
@@ -71818,7 +73323,7 @@ function lendingCapabilities(row) {
71818
73323
  }
71819
73324
  return caps;
71820
73325
  }
71821
- var SWAP_ROUTED_PROVIDERS = /* @__PURE__ */ new Set(["pendle"]);
73326
+ var SWAP_ROUTED_PROVIDERS = /* @__PURE__ */ new Set(["pendle", "spectra"]);
71822
73327
  function swapRoutedCapabilities(row) {
71823
73328
  const caps = [];
71824
73329
  if (row.availability.canDeposit) {
@@ -71868,7 +73373,7 @@ function vaultCapabilities(row) {
71868
73373
  caps.push({
71869
73374
  action: "withdraw",
71870
73375
  requires: withdrawRequires(provider),
71871
- feeBps: num12(meta.withdrawFeeBps) ?? row.exit.feeBps
73376
+ feeBps: num13(meta.withdrawFeeBps) ?? row.exit.feeBps
71872
73377
  });
71873
73378
  }
71874
73379
  caps.push({
@@ -71977,7 +73482,7 @@ function legEarnUid(marketUid) {
71977
73482
  if (isVaultVenue(parts[0])) return void 0;
71978
73483
  return marketUid;
71979
73484
  }
71980
- function num15(v) {
73485
+ function num17(v) {
71981
73486
  const n = typeof v === "number" ? v : Number(v);
71982
73487
  return Number.isFinite(n) ? n : 0;
71983
73488
  }
@@ -71999,10 +73504,10 @@ function legAsset(pos) {
71999
73504
  };
72000
73505
  }
72001
73506
  function toLeg(pos) {
72002
- const depositsUsd = num15(pos.depositsUSD);
72003
- const debtUsd = num15(pos.debtUSD) + num15(pos.debtStableUSD);
72004
- const hasSupply = depositsUsd !== 0 || num15(pos.deposits) !== 0;
72005
- const hasDebt = debtUsd !== 0 || num15(pos.debt) !== 0 || num15(pos.debtStable) !== 0;
73507
+ const depositsUsd = num17(pos.depositsUSD);
73508
+ const debtUsd = num17(pos.debtUSD) + num17(pos.debtStableUSD);
73509
+ const hasSupply = depositsUsd !== 0 || num17(pos.deposits) !== 0;
73510
+ const hasDebt = debtUsd !== 0 || num17(pos.debt) !== 0 || num17(pos.debtStable) !== 0;
72006
73511
  return {
72007
73512
  earnUid: legEarnUid(pos.marketUid),
72008
73513
  marketUid: pos.marketUid,
@@ -72042,12 +73547,12 @@ function earnPositionFromLenderEntry(entry) {
72042
73547
  (s) => s.legs.some((l) => l.side !== "none") || s.netUsd !== 0
72043
73548
  );
72044
73549
  const crossMargin = active.length <= 1;
72045
- const suppliedUsd = num15(entry.balanceData?.deposits);
72046
- const borrowedUsd = num15(entry.balanceData?.debt);
73550
+ const suppliedUsd = num17(entry.balanceData?.deposits);
73551
+ const borrowedUsd = num17(entry.balanceData?.debt);
72047
73552
  const aprBreakdown = {
72048
- market: num15(entry.aprData?.apr),
72049
- rewards: num15(entry.aprData?.rewardApr),
72050
- intrinsic: num15(entry.aprData?.intrinsicApr)
73553
+ market: num17(entry.aprData?.apr),
73554
+ rewards: num17(entry.aprData?.rewardApr),
73555
+ intrinsic: num17(entry.aprData?.intrinsicApr)
72051
73556
  };
72052
73557
  return {
72053
73558
  positionUid: buildLendingPositionUid(entry.lender, entry.chainId),
@@ -72061,15 +73566,15 @@ function earnPositionFromLenderEntry(entry) {
72061
73566
  ...entry.lenderInfo?.logoUri ? { logoURI: entry.lenderInfo.logoUri } : {},
72062
73567
  suppliedUsd,
72063
73568
  borrowedUsd,
72064
- netUsd: num15(entry.balanceData?.nav),
73569
+ netUsd: num17(entry.balanceData?.nav),
72065
73570
  apr: aprBreakdown.market + aprBreakdown.rewards + aprBreakdown.intrinsic,
72066
73571
  aprBreakdown,
72067
- depositApr: num15(entry.aprData?.depositApr),
72068
- borrowApr: num15(entry.aprData?.borrowApr),
73572
+ depositApr: num17(entry.aprData?.depositApr),
73573
+ borrowApr: num17(entry.aprData?.borrowApr),
72069
73574
  // Only a cross-margin account HAS one health factor. Publishing the first
72070
73575
  // sub-account's as the row's would be a number about a different position.
72071
73576
  health: crossMargin ? active[0]?.health ?? null : null,
72072
- leverage: num15(entry.leverage),
73577
+ leverage: num17(entry.leverage),
72073
73578
  crossMargin,
72074
73579
  legs: subAccounts.flatMap((s) => s.legs),
72075
73580
  subAccounts: active,
@@ -72151,6 +73656,6 @@ function earnPositionTotals(items) {
72151
73656
  };
72152
73657
  }
72153
73658
 
72154
- export { ApiBookSource, DEFAULT_MIDNIGHT_API, DEFAULT_OUTLIER_GUARD, DEFAULT_PROFILE_ID, DEFAULT_STALE_REJECT_SECONDS, DEFAULT_TERMMAX_API, EARN_DESCRIPTIONS, EARN_LABELS, EMPTY_BALANCE, EXACTLY_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, STABLECOIN_SYMBOLS, STCELO_MANAGER_ADDRESS, TELLER_CALLS_PER_BID, TERMMAX_CALLS_PER_ACCOUNT, DECIMAL_BASE as TERMMAX_DECIMAL_BASE, TERMMAX_LIQUIDATION_PENALTY, TERMMAX_LIQUIDATION_WINDOW_SECS, TERMMAX_LIQUIDATOR_BONUS, 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, 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, convertDssMarketsToResponse, convertExactlyMarketsToResponse, 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, fetchDolomiteAccountNumbers, fetchDssMarkets, fetchEulerEarnVaults, fetchEulerEarnVaultsFromSubgraph, fetchEulerSubAccountIndexes, fetchExactlyMarkets, fetchFlashLiquidityForChain, fetchFluidDexState, fetchFluidFTokens, 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, fetchTellerMarkets, fetchTermMarkets, fetchTermMaxMarkets, fetchTokenBalances, fetchTokenMetadata, fetchUpshiftApiVaults, fetchUpshiftVaults, fetchUsddMarkets, fetchYearnApiVaults, fetchYearnVaults, 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, hasUpshiftVaults, hasYearnVaults, ilkToKeySegment, implausibleRatePercent, inverseKeyParts, inverseLenderKey, isBoundNeed, isFailedCall, isIlliquid, isLendingPosition, isLiveMarket as isLivePendleMarket, isStablecoinSymbol, isVaultPosition, isVaultVenue, isYearnV3, keySegmentToIlk, keysFromMaps, lenderApiOnly, lenderFamily, liquityCandidateTroveIds, liquityKeyParts, liquityLenderKey, llamaLendKeyParts, llamaLendLenderKey, mergeDeep, multicall3Abi2 as multicall3Abi, nanTo, needsLenderApproval, needsTokenApproval, noOpResult, normalizeToBytes, parseBalanceFetcherResult, parseEarnUid, parseMergedResult, parseMulticallRpcResponses, parseExpirySeconds as parsePendleExpirySeconds, parseRawRpcBatchResponses, parseRawRpcResponses, parseTermMaxLtv, parseTokenBalanceResult, pct, assetKey as pendleAssetKey, 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, savingsAddresses, savingsBalanceKind, selectAssetGroupPrices, shortDate, splitChainScopedAddress as splitPendleChainScopedAddress, stampCapabilities, stampEarnSubtitles, stampVaultClassification, stampVaultTermSheets, stripLeadingBrand, supplyDescription, supplyFindings, supplyHeadline, swapRoutedProvidersArePriceConsistent, tellerBpsToPercent, tellerImpliedLtv, tellerLenderKey, tellerPoolFromLenderKey, 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, tickToAprNumber, tickToPrice, toDigest, toTermSheetInput, toVaultTermInput, trancheFromCounterparty, tryParseEarnUid, unflattenLenderData, updateFeedStats, usdValue, usddIlkBytes32, usddKeyParts, usddLenderKey, validateTermSheet, validateTermSheets, validateUserData, vaultSharesToAssets, vaultTermInputFromEarnMarket, vaultTermInputFromSourceRow, vaultTraits, vaultVenue, venueBrand, venueBrandKey, withMaturityLabel, withTrancheLabel };
73659
+ export { ApiBookSource, DEFAULT_MIDNIGHT_API, DEFAULT_OUTLIER_GUARD, DEFAULT_PROFILE_ID, DEFAULT_STALE_REJECT_SECONDS, DEFAULT_TERMMAX_API, EARN_DESCRIPTIONS, EARN_LABELS, EMPTY_BALANCE, EXACTLY_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, TERMMAX_CALLS_PER_ACCOUNT, DECIMAL_BASE as TERMMAX_DECIMAL_BASE, TERMMAX_LIQUIDATION_PENALTY, TERMMAX_LIQUIDATION_WINDOW_SECS, TERMMAX_LIQUIDATOR_BONUS, 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, convertDssMarketsToResponse, convertExactlyMarketsToResponse, 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, fetchDolomiteAccountNumbers, fetchDssMarkets, fetchEulerEarnVaults, fetchEulerEarnVaultsFromSubgraph, fetchEulerSubAccountIndexes, fetchExactlyMarkets, fetchFlashLiquidityForChain, fetchFluidDexState, fetchFluidFTokens, 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, fetchTokenBalances, fetchTokenMetadata, fetchUpshiftApiVaults, fetchUpshiftVaults, fetchUsddMarkets, fetchYearnApiVaults, fetchYearnVaults, 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, isStablecoinSymbol, isVaultPosition, isVaultVenue, isYearnV3, keySegmentToIlk, keysFromMaps, lenderApiOnly, lenderFamily, liquityCandidateTroveIds, liquityKeyParts, liquityLenderKey, llamaLendKeyParts, llamaLendLenderKey, mergeDeep, multicall3Abi2 as multicall3Abi, nanTo, needsLenderApproval, needsTokenApproval, noOpResult, normalizeToBytes, 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, selectAssetGroupPrices, shortDate, spectraAddress, spectraNetwork, spectraPoolsUrl, splitChainScopedAddress as splitPendleChainScopedAddress, stampCapabilities, stampEarnSubtitles, stampVaultClassification, stampVaultTermSheets, stripLeadingBrand, supplyDescription, supplyFindings, supplyHeadline, swapRoutedProvidersArePriceConsistent, tellerBpsToPercent, tellerImpliedLtv, tellerLenderKey, tellerPoolFromLenderKey, 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, tickToAprNumber, tickToPrice, toDigest, toTermSheetInput, toVaultTermInput, trancheFromCounterparty, tryParseEarnUid, unflattenLenderData, updateFeedStats, usdValue, usddIlkBytes32, usddKeyParts, usddLenderKey, validateTermSheet, validateTermSheets, validateUserData, vaultSharesToAssets, vaultTermInputFromEarnMarket, vaultTermInputFromSourceRow, vaultTraits, vaultVenue, venueBrand, venueBrandKey, withMaturityLabel, withTrancheLabel };
72155
73660
  //# sourceMappingURL=index.js.map
72156
73661
  //# sourceMappingURL=index.js.map