@1delta/margin-fetcher 5.0.50 → 5.0.52

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"
@@ -55589,20 +56478,39 @@ var ASSET_TOKENS = /* @__PURE__ */ new Set([
55589
56478
  "plume",
55590
56479
  "s"
55591
56480
  ]);
56481
+ var isAssetToken = (tl, asset) => {
56482
+ if (asset && tl === asset || ASSET_TOKENS.has(tl) || tl.includes("usd")) {
56483
+ return true;
56484
+ }
56485
+ const unwrapped = tl.replace(/^(cb|wst|ws|w|st)/, "");
56486
+ return unwrapped !== tl && ASSET_TOKENS.has(unwrapped);
56487
+ };
55592
56488
  function curatorNameFromVaultName(name, assetSymbol) {
55593
56489
  if (!name) return void 0;
55594
- const cleaned = name.replace(/\([^)]*\)\s*$/, "").trim();
56490
+ if (/\b(test|testing|fake)\b/i.test(name)) return void 0;
56491
+ const by = /\bby\s+(.{2,})$/i.exec(name);
56492
+ if (by) {
56493
+ const suffix = by[1].trim().split(/\s+/).slice(0, 3).join(" ");
56494
+ if (suffix.length >= 2 && !isAssetToken(suffix.toLowerCase(), (assetSymbol ?? "").toLowerCase())) {
56495
+ return suffix;
56496
+ }
56497
+ }
56498
+ const cleaned = name.replace(/\([^)]*\)\s*$/, "").split(":")[0].trim();
55595
56499
  if (!cleaned) return void 0;
55596
56500
  const tokens = cleaned.split(/[\s/]+/).flatMap((t) => t.split("-")).filter(Boolean);
55597
56501
  const asset = (assetSymbol ?? "").toLowerCase();
55598
56502
  const out = [];
56503
+ let terminated = false;
55599
56504
  for (const tok of tokens) {
55600
56505
  const tl = tok.toLowerCase();
55601
- if (STOP_WORDS.has(tl)) break;
55602
- if (asset && tl === asset || ASSET_TOKENS.has(tl)) break;
56506
+ if (STOP_WORDS.has(tl) || isAssetToken(tl, asset)) {
56507
+ terminated = true;
56508
+ break;
56509
+ }
55603
56510
  out.push(tok);
55604
56511
  if (out.length >= 3) break;
55605
56512
  }
56513
+ if (!terminated || out.length === tokens.length) return void 0;
55606
56514
  const curator = out.join(" ").trim();
55607
56515
  return curator.length >= 2 ? curator : void 0;
55608
56516
  }
@@ -55628,11 +56536,11 @@ var PHASE1_CALLS2 = [
55628
56536
  var PHASE1_PER_VAULT2 = PHASE1_CALLS2.length;
55629
56537
  var WITHDRAW_QUEUE_LENGTH_INDEX2 = 8;
55630
56538
  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;
56539
+ var isHex402 = (addr4) => typeof addr4 === "string" && /^0x[0-9a-f]{40}$/i.test(addr4);
56540
+ var lcOrUndefined2 = (addr4) => {
56541
+ if (!isHex402(addr4)) return void 0;
56542
+ const lower4 = addr4.toLowerCase();
56543
+ return lower4 === zeroAddress ? void 0 : lower4;
55636
56544
  };
55637
56545
  var isHex642 = (val) => typeof val === "string" && /^0x[0-9a-f]{64}$/i.test(val);
55638
56546
  var toNumberSafe2 = (raw, fallback = 0) => {
@@ -56032,6 +56940,7 @@ function parseVault5(v, chainId, prices, tokenList, exposures, liquidityFormatte
56032
56940
  const fee = Number.isFinite(feeRaw) ? feeRaw / PERFORMANCE_FEE_SCALE : 0;
56033
56941
  const apiTotalAssetsUsd = Number(v.totalAssetsUsd ?? 0) || 0;
56034
56942
  const totalAssetsUsd = apiTotalAssetsUsd || totalAssetsFormatted * priceUsd;
56943
+ const curatorName = curatorNameFromVaultName(v.name, assetMeta?.symbol);
56035
56944
  return {
56036
56945
  address,
56037
56946
  underlying: assetAddr,
@@ -56039,10 +56948,11 @@ function parseVault5(v, chainId, prices, tokenList, exposures, liquidityFormatte
56039
56948
  name: v.name ?? "",
56040
56949
  displayName: composeVaultDisplayName(
56041
56950
  "Silo",
56042
- void 0,
56951
+ curatorName,
56043
56952
  assetMeta,
56044
56953
  v.name ?? void 0
56045
56954
  ),
56955
+ curatorName,
56046
56956
  decimals,
56047
56957
  protocolVersion: v.protocol?.protocolVersion ?? "",
56048
56958
  protocolId: (v.protocolId ?? v.protocol?.id ?? "").toLowerCase(),
@@ -56152,6 +57062,54 @@ var fetchSiloVaults = async (chainId, prices = {}, tokenList = {}, options) => {
56152
57062
  }
56153
57063
  return out;
56154
57064
  };
57065
+
57066
+ // src/vaults/euler-earn/entityLabels.ts
57067
+ var LABELS_BASE = "https://raw.githubusercontent.com/euler-xyz/euler-labels/master";
57068
+ var TTL_MS3 = 30 * 60 * 1e3;
57069
+ var cache3 = /* @__PURE__ */ new Map();
57070
+ var inflight4 = /* @__PURE__ */ new Map();
57071
+ async function fetchChainEntities(chainId) {
57072
+ const res = await fetch(`${LABELS_BASE}/${chainId}/entities.json`);
57073
+ if (!res.ok) throw new Error(`euler-labels ${chainId}: HTTP ${res.status}`);
57074
+ const json = await res.json();
57075
+ const byAddress = /* @__PURE__ */ new Map();
57076
+ for (const entity of Object.values(json ?? {})) {
57077
+ const name = String(entity?.name ?? "").trim();
57078
+ if (!name) continue;
57079
+ for (const addr4 of Object.keys(entity?.addresses ?? {})) {
57080
+ const lower4 = addr4.toLowerCase();
57081
+ if (!/^0x[0-9a-f]{40}$/.test(lower4)) continue;
57082
+ if (!byAddress.has(lower4)) byAddress.set(lower4, /* @__PURE__ */ new Set());
57083
+ byAddress.get(lower4).add(name);
57084
+ }
57085
+ }
57086
+ const map = /* @__PURE__ */ new Map();
57087
+ for (const [addr4, names] of byAddress) {
57088
+ if (names.size === 1) map.set(addr4, [...names][0]);
57089
+ }
57090
+ return map;
57091
+ }
57092
+ async function fetchEulerEntityNames(chainId) {
57093
+ const hit = cache3.get(chainId);
57094
+ if (hit && Date.now() - hit.at <= TTL_MS3) return hit.map;
57095
+ const running = inflight4.get(chainId);
57096
+ if (running) return running;
57097
+ const p = fetchChainEntities(chainId).then((map) => {
57098
+ cache3.set(chainId, { at: Date.now(), map });
57099
+ return map;
57100
+ }).catch(() => {
57101
+ return hit?.map ?? /* @__PURE__ */ new Map();
57102
+ }).finally(() => {
57103
+ inflight4.delete(chainId);
57104
+ });
57105
+ inflight4.set(chainId, p);
57106
+ return p;
57107
+ }
57108
+ function eulerEntityCuratorName(entityNames, curator, owner) {
57109
+ return (curator ? entityNames.get(curator.toLowerCase()) : void 0) ?? (owner ? entityNames.get(owner.toLowerCase()) : void 0);
57110
+ }
57111
+
57112
+ // src/vaults/euler-earn/fetchFromSubgraph.ts
56155
57113
  var DECIMALS_ABI = [
56156
57114
  {
56157
57115
  name: "decimals",
@@ -56299,7 +57257,7 @@ function computeRealLiquidity(strategies, totalAssetsRaw, evkIndex) {
56299
57257
  const result = idle + withdrawable;
56300
57258
  return result > totalAssets ? totalAssets : result;
56301
57259
  }
56302
- function parseVault6(v, chainId, prices, tokenList, evkIndex, shareDecimalsByVault) {
57260
+ function parseVault6(v, chainId, prices, tokenList, evkIndex, shareDecimalsByVault, entityNames) {
56303
57261
  const address = (v?.id ?? "").toLowerCase();
56304
57262
  const assetAddr = (v?.asset ?? "").toLowerCase();
56305
57263
  if (!address || !assetAddr) return null;
@@ -56350,7 +57308,13 @@ function parseVault6(v, chainId, prices, tokenList, evkIndex, shareDecimalsByVau
56350
57308
  fee,
56351
57309
  owner: readAddress2(v.owner),
56352
57310
  curator: readAddress2(v.curator),
56353
- curatorName: curatorNameFromVaultName(v.name, assetMeta?.symbol),
57311
+ // Euler's entity registry names the curator by ADDRESS — authoritative
57312
+ // when it hits; the vault-name parse only covers what it misses.
57313
+ curatorName: eulerEntityCuratorName(
57314
+ entityNames,
57315
+ readAddress2(v.curator),
57316
+ readAddress2(v.owner)
57317
+ ) ?? curatorNameFromVaultName(v.name, assetMeta?.symbol),
56354
57318
  guardian: readAddress2(v.guardian),
56355
57319
  feeRecipient: v.feeReceiver?.toLowerCase() || void 0,
56356
57320
  asset: assetMeta,
@@ -56425,9 +57389,10 @@ async function fetchEulerEarnVaultsFromSubgraph(chainId, prices = {}, tokenList
56425
57389
  const id = v?.id;
56426
57390
  if (id) vaultAddrs.push(id);
56427
57391
  }
56428
- const [evkIndex, shareDecimalsByVault] = await Promise.all([
57392
+ const [evkIndex, shareDecimalsByVault, entityNames] = await Promise.all([
56429
57393
  fetchEvkIndex(url, [...assets]),
56430
- fetchShareDecimals(chainId, vaultAddrs, multicallRetry)
57394
+ fetchShareDecimals(chainId, vaultAddrs, multicallRetry),
57395
+ fetchEulerEntityNames(chainId)
56431
57396
  ]);
56432
57397
  const out = {};
56433
57398
  for (const v of items) {
@@ -56437,7 +57402,8 @@ async function fetchEulerEarnVaultsFromSubgraph(chainId, prices = {}, tokenList
56437
57402
  prices,
56438
57403
  tokenList,
56439
57404
  evkIndex,
56440
- shareDecimalsByVault
57405
+ shareDecimalsByVault,
57406
+ entityNames
56441
57407
  );
56442
57408
  if (parsed) out[parsed.address] = parsed;
56443
57409
  }
@@ -56473,7 +57439,7 @@ async function getJson3(url) {
56473
57439
  clearTimeout(timer);
56474
57440
  }
56475
57441
  }
56476
- function mapApiDetail(d, chainId, prices, tokenList, shareDecimalsByVault) {
57442
+ function mapApiDetail(d, chainId, prices, tokenList, shareDecimalsByVault, entityNames) {
56477
57443
  const address = (d.address ?? "").toLowerCase();
56478
57444
  const underlying = (d.asset?.address ?? "").toLowerCase();
56479
57445
  if (!address || !underlying) return null;
@@ -56499,6 +57465,8 @@ function mapApiDetail(d, chainId, prices, tokenList, shareDecimalsByVault) {
56499
57465
  const priceUsd = prices[oracleKey] ?? prices[underlying] ?? 0;
56500
57466
  const totalAssetsUsd = priceUsd ? totalAssetsFormatted * priceUsd : Number(d.totalSupplyUsd ?? 0);
56501
57467
  const liquidityUsd = priceUsd ? liquidityFormatted * priceUsd : Number(d.availableAssetsUsd ?? 0);
57468
+ const owner = (d.governance?.owner ?? d.management?.owner ?? d.owner)?.toLowerCase();
57469
+ const curator = (d.governance?.curator ?? d.management?.curator ?? d.curator)?.toLowerCase();
56502
57470
  return {
56503
57471
  address,
56504
57472
  underlying,
@@ -56515,13 +57483,12 @@ function mapApiDetail(d, chainId, prices, tokenList, shareDecimalsByVault) {
56515
57483
  // The API doesn't surface the performance fee on this endpoint; the
56516
57484
  // headline APY is already net, so 0 here only affects fee display.
56517
57485
  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
57486
  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),
57487
+ owner,
57488
+ curator,
57489
+ // Euler's own entity registry names the curator by ADDRESS — authoritative
57490
+ // when it hits; the vault-name parse only covers what it misses.
57491
+ curatorName: eulerEntityCuratorName(entityNames, curator, owner) ?? curatorNameFromVaultName(d.name, assetMeta?.symbol),
56525
57492
  guardian: (d.governance?.guardian ?? d.management?.guardian ?? d.guardian)?.toLowerCase(),
56526
57493
  feeRecipient: (d.governance?.feeReceiver ?? d.management?.feeRecipient ?? d.feeReceiver)?.toLowerCase() || void 0,
56527
57494
  asset: assetMeta,
@@ -56555,13 +57522,16 @@ async function fetchEulerEarnVaultsFromApi(chainId, prices = {}, tokenList = {},
56555
57522
  if (!list) return void 0;
56556
57523
  const rows = list.data ?? [];
56557
57524
  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
- );
57525
+ const [details, entityNames] = await Promise.all([
57526
+ mapWithConcurrency(
57527
+ rows,
57528
+ DETAIL_CONCURRENCY,
57529
+ (row) => getJson3(
57530
+ `${EULER_DATA_API_BASE2}/earn/vaults/${chainId}/${row.address}?include=strategies`
57531
+ ).then((d) => d?.data)
57532
+ ),
57533
+ fetchEulerEntityNames(chainId)
57534
+ ]);
56565
57535
  const vaultAddrs = details.map((d) => d?.address).filter((a) => !!a);
56566
57536
  const shareDecimalsByVault = await fetchShareDecimals(
56567
57537
  chainId,
@@ -56571,7 +57541,14 @@ async function fetchEulerEarnVaultsFromApi(chainId, prices = {}, tokenList = {},
56571
57541
  const out = {};
56572
57542
  for (const d of details) {
56573
57543
  if (!d) continue;
56574
- const v = mapApiDetail(d, chainId, prices, tokenList, shareDecimalsByVault);
57544
+ const v = mapApiDetail(
57545
+ d,
57546
+ chainId,
57547
+ prices,
57548
+ tokenList,
57549
+ shareDecimalsByVault,
57550
+ entityNames
57551
+ );
56575
57552
  if (v) out[v.address] = v;
56576
57553
  }
56577
57554
  return out;
@@ -56603,7 +57580,7 @@ var num4 = (v) => {
56603
57580
  const n = Number(v);
56604
57581
  return Number.isFinite(n) ? n : 0;
56605
57582
  };
56606
- var big16 = (v) => {
57583
+ var big18 = (v) => {
56607
57584
  try {
56608
57585
  if (v === void 0 || v === null || v === "") return "0";
56609
57586
  const s = String(v);
@@ -56612,7 +57589,7 @@ var big16 = (v) => {
56612
57589
  return "0";
56613
57590
  }
56614
57591
  };
56615
- var lower2 = (v) => String(v ?? "").toLowerCase();
57592
+ var lower3 = (v) => String(v ?? "").toLowerCase();
56616
57593
  async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, fetchImpl = fetch) {
56617
57594
  const url = `${termMaxApiBase(chainId)}/vault/list?chainId=${chainId}`;
56618
57595
  let rows;
@@ -56630,8 +57607,8 @@ async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, f
56630
57607
  }
56631
57608
  const out = {};
56632
57609
  for (const r of rows) {
56633
- const address = lower2(r?.vaultAddress);
56634
- const underlying = lower2(r?.asset?.contractAddress);
57610
+ const address = lower3(r?.vaultAddress);
57611
+ const underlying = lower3(r?.asset?.contractAddress);
56635
57612
  if (!address || !underlying) continue;
56636
57613
  if (r.isEnabled === false) continue;
56637
57614
  const assetDecimals = num4(r?.asset?.decimals) || 18;
@@ -56639,12 +57616,12 @@ async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, f
56639
57616
  const assetEntry = tokenList[underlying];
56640
57617
  const priceKey = toOracleKey(assetEntry?.assetGroup) || toGenericPriceKey(underlying, chainId);
56641
57618
  const priceUsd = prices[priceKey];
56642
- const totalAssets = big16(r.totalAssets);
56643
- const totalSupply = big16(r.totalSupplyAmt);
57619
+ const totalAssets = big18(r.totalAssets);
57620
+ const totalSupply = big18(r.totalSupplyAmt);
56644
57621
  const totalAssetsFormatted = Number(totalAssets) / scale3;
56645
57622
  const supplyRate = num4(r.apr) * 100;
56646
57623
  const rewardsRate = num4(r?.incentiveData?.TMX_APR) * 100;
56647
- const rawLiquidity = BigInt(big16(r.redeemableAmt ?? r.idleFunds ?? "0"));
57624
+ const rawLiquidity = BigInt(big18(r.redeemableAmt ?? r.idleFunds ?? "0"));
56648
57625
  const totalAssetsBig = BigInt(totalAssets);
56649
57626
  const liquidity = (rawLiquidity > totalAssetsBig ? totalAssetsBig : rawLiquidity).toString();
56650
57627
  const liquidityFormatted = Number(liquidity) / scale3;
@@ -56667,10 +57644,10 @@ async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, f
56667
57644
  // 1e8-scaled upstream (10000000 = 10%).
56668
57645
  fee: num4(r.performanceFeeRate) / 1e6,
56669
57646
  timelock: num4(r.timeLockSeconds) || void 0,
56670
- curator: r?.curator?.curatorAddress ? lower2(r.curator.curatorAddress) : void 0,
57647
+ curator: r?.curator?.curatorAddress ? lower3(r.curator.curatorAddress) : void 0,
56671
57648
  // The API is the ONLY source for this — do not derive it from `name`.
56672
57649
  curatorName: r?.curator?.name || void 0,
56673
- guardian: r?.guardianAddress ? lower2(r.guardianAddress) : void 0,
57650
+ guardian: r?.guardianAddress ? lower3(r.guardianAddress) : void 0,
56674
57651
  asset: assetEntry,
56675
57652
  priceUsd,
56676
57653
  totalAssetsFormatted,
@@ -56680,8 +57657,8 @@ async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, f
56680
57657
  liquidityUsd: priceUsd ? liquidityFormatted * priceUsd : 0,
56681
57658
  version: r.version,
56682
57659
  isPaused: r.isPaused === true || void 0,
56683
- supplyCap: r.capacity ? big16(r.capacity) : void 0,
56684
- basePool: r.poolAddress ? lower2(r.poolAddress) : void 0
57660
+ supplyCap: r.capacity ? big18(r.capacity) : void 0,
57661
+ basePool: r.poolAddress ? lower3(r.poolAddress) : void 0
56685
57662
  };
56686
57663
  }
56687
57664
  return out;
@@ -56736,7 +57713,7 @@ var Erc20DecimalsBalanceAbi = [
56736
57713
 
56737
57714
  // src/vaults/termmax/fetchFromChain.ts
56738
57715
  var DECIMAL_BASE2 = 100000000n;
56739
- var big17 = (v) => {
57716
+ var big19 = (v) => {
56740
57717
  if (v === void 0 || v === null || v === "0x") return 0n;
56741
57718
  try {
56742
57719
  return typeof v === "bigint" ? v : BigInt(v);
@@ -56800,7 +57777,7 @@ var fetchTermMaxVaultsFromChain = async (chainId, multicallRetry, prices = {}, t
56800
57777
  vaults.forEach((address, i) => {
56801
57778
  const at = (k) => res[i * READS_PER_VAULT + VAULT_READS.indexOf(k)];
56802
57779
  const asset = addr(at("asset"));
56803
- const totalAssets = big17(at("totalAssets"));
57780
+ const totalAssets = big19(at("totalAssets"));
56804
57781
  if (!asset || totalAssets === 0n) return;
56805
57782
  rows.push({
56806
57783
  address,
@@ -56809,11 +57786,11 @@ var fetchTermMaxVaultsFromChain = async (chainId, multicallRetry, prices = {}, t
56809
57786
  decimals: num5(at("decimals")) ?? 18,
56810
57787
  asset,
56811
57788
  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,
57789
+ totalSupply: big19(at("totalSupply")),
57790
+ annualizedInterest: big19(at("annualizedInterest")),
57791
+ accretingPrincipal: big19(at("accretingPrincipal")),
57792
+ performanceFeeRate: big19(at("performanceFeeRate")),
57793
+ aprRaw: at("apr") != null ? big19(at("apr")) : void 0,
56817
57794
  curator: addr(at("curator")),
56818
57795
  guardian: addr(at("guardian")),
56819
57796
  timelock: num5(at("timelock")),
@@ -56834,7 +57811,7 @@ var fetchTermMaxVaultsFromChain = async (chainId, multicallRetry, prices = {}, t
56834
57811
  const out = {};
56835
57812
  rows.forEach((r, i) => {
56836
57813
  const assetDecimals = num5(res2[i * 2]) ?? r.decimals;
56837
- const idle = big17(res2[i * 2 + 1]);
57814
+ const idle = big19(res2[i * 2 + 1]);
56838
57815
  const assetEntry = tokenList[r.asset];
56839
57816
  const priceKey = toOracleKey(assetEntry?.assetGroup) || toGenericPriceKey(r.asset, chainId);
56840
57817
  const priceUsd = prices[priceKey];
@@ -62355,6 +63332,40 @@ var FrankencoinSavingsReadAbi = [
62355
63332
  }
62356
63333
  ];
62357
63334
 
63335
+ // src/vaults/savings/abis/hyperbeat.ts
63336
+ var HyperbeatPricerReadAbi = [
63337
+ {
63338
+ inputs: [],
63339
+ name: "getRate",
63340
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
63341
+ stateMutability: "view",
63342
+ type: "function"
63343
+ },
63344
+ {
63345
+ inputs: [],
63346
+ name: "decimals",
63347
+ outputs: [{ internalType: "uint8", name: "", type: "uint8" }],
63348
+ stateMutability: "view",
63349
+ type: "function"
63350
+ }
63351
+ ];
63352
+ var HyperbeatQueueReadAbi = [
63353
+ {
63354
+ inputs: [],
63355
+ name: "instantWithdrawalFee",
63356
+ outputs: [{ internalType: "uint64", name: "", type: "uint64" }],
63357
+ stateMutability: "view",
63358
+ type: "function"
63359
+ },
63360
+ {
63361
+ inputs: [],
63362
+ name: "isInstantWithdrawalPaused",
63363
+ outputs: [{ internalType: "bool", name: "", type: "bool" }],
63364
+ stateMutability: "view",
63365
+ type: "function"
63366
+ }
63367
+ ];
63368
+
62358
63369
  // src/vaults/savings/abis/yearnStrategy.ts
62359
63370
  var AvailableWithdrawLimitAbi = [
62360
63371
  {
@@ -62544,6 +63555,57 @@ var readerFrankencoinSavings = (entry) => ({
62544
63555
  }
62545
63556
  });
62546
63557
 
63558
+ // src/vaults/savings/readers/hyperbeatVault.ts
63559
+ var readerHyperbeatVault = (entry) => {
63560
+ const { address, underlying, priceOracle, withdrawQueue } = entry;
63561
+ const pricer = priceOracle ?? address;
63562
+ const queue = withdrawQueue ?? address;
63563
+ const shareUnit = 10n ** BigInt(entry.decimals);
63564
+ const underlyingUnit = 10n ** BigInt(entry.underlyingDecimals ?? entry.decimals);
63565
+ return {
63566
+ calls: [
63567
+ { address, name: "totalSupply", params: [] },
63568
+ { address: pricer, name: "getRate", params: [] },
63569
+ { address: pricer, name: "decimals", params: [] },
63570
+ { address: underlying, name: "balanceOf", params: [queue] },
63571
+ { address: queue, name: "instantWithdrawalFee", params: [] },
63572
+ { address: queue, name: "isInstantWithdrawalPaused", params: [] }
63573
+ ],
63574
+ abis: [
63575
+ TotalSupplyAbi2,
63576
+ HyperbeatPricerReadAbi,
63577
+ HyperbeatPricerReadAbi,
63578
+ BalanceOfAbi,
63579
+ HyperbeatQueueReadAbi,
63580
+ HyperbeatQueueReadAbi
63581
+ ],
63582
+ parse: ([supply, rate, rateDecimals, inventory, fee, instantPaused]) => {
63583
+ const totalSupply = toBigInt16(supply);
63584
+ const rawRate = toBigInt16(rate);
63585
+ const rateDec = toBigInt16(rateDecimals);
63586
+ if (totalSupply === void 0 || rawRate === void 0 || rateDec === void 0 || rawRate === 0n) {
63587
+ return void 0;
63588
+ }
63589
+ const exchangeRate = rateDec <= 18n ? rawRate * 10n ** (18n - rateDec) : rawRate / 10n ** (rateDec - 18n);
63590
+ const capacity = toBigInt16(inventory);
63591
+ const feeRaw = toBigInt16(fee);
63592
+ return {
63593
+ // totalSupply is in raw share units; convert to raw underlying.
63594
+ totalAssets: totalSupply * exchangeRate * underlyingUnit / (shareUnit * ONE_E1813),
63595
+ totalSupply,
63596
+ exchangeRate,
63597
+ // `instantWithdrawalFee` is over a base of 10 000, so the raw
63598
+ // value maps 1:1 onto bps (30 on all four vaults = 0.30% — the
63599
+ // docs' 0.5% describes the retired Midas stack).
63600
+ withdrawFeeBps: feeRaw !== void 0 ? Number(feeRaw) : void 0,
63601
+ instantRedeemEnabled: typeof instantPaused === "boolean" ? !instantPaused : void 0,
63602
+ instantRedeemCapacity: capacity,
63603
+ withdrawQueue: queue.toLowerCase()
63604
+ };
63605
+ }
63606
+ };
63607
+ };
63608
+
62547
63609
  // src/vaults/savings/readers/navOracle.ts
62548
63610
  var readerNavOracle = (entry) => {
62549
63611
  const shareUnit = 10n ** BigInt(entry.decimals);
@@ -62721,6 +63783,8 @@ var buildReader2 = (entry) => {
62721
63783
  return readerNavOracle(entry);
62722
63784
  case "frankencoin-savings":
62723
63785
  return readerFrankencoinSavings(entry);
63786
+ case "hyperbeat-vault":
63787
+ return readerHyperbeatVault(entry);
62724
63788
  case "yieldbasis-lt":
62725
63789
  return readerYieldBasisLt(entry);
62726
63790
  case "wren-nav":
@@ -63150,9 +64214,9 @@ async function fetchAaveEarnApiVaults(chainId, targets) {
63150
64214
  const target = Number(chainId);
63151
64215
  const byAddress = /* @__PURE__ */ new Map();
63152
64216
  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);
64217
+ const addr4 = it?.address?.toLowerCase();
64218
+ if (!addr4 || Number(it.chainId) !== target) return;
64219
+ if (!byAddress.has(addr4)) byAddress.set(addr4, it);
63156
64220
  };
63157
64221
  for (const owner of targets.owners) {
63158
64222
  let cursor = null;
@@ -63842,7 +64906,7 @@ var SYNC_REDEMPTION_PROVIDERS = /* @__PURE__ */ new Set([
63842
64906
  ]);
63843
64907
  var ASYNC_REDEMPTION_PROVIDERS = /* @__PURE__ */ new Set(["lagoon", "upshift"]);
63844
64908
  var classifyRedemption = (provider, v) => {
63845
- if (provider === "pendle") return void 0;
64909
+ if (provider === "pendle" || provider === "spectra") return void 0;
63846
64910
  if (ASYNC_REDEMPTION_PROVIDERS.has(provider)) return "async";
63847
64911
  if (SYNC_REDEMPTION_PROVIDERS.has(provider)) return "sync";
63848
64912
  if (provider === "lst") return "async";
@@ -64029,6 +65093,7 @@ var stampVaultClassification = (data, chainId, tokenList = {}) => {
64029
65093
  stampBag(data.upshift, "upshift");
64030
65094
  stampBag(data.yearn, "yearn");
64031
65095
  stampBag(data.pendle, "pendle");
65096
+ stampBag(data.spectra, "spectra");
64032
65097
  stampBag(data.hypercore, "hypercore", false);
64033
65098
  stampBag(data.gmx, "gmx", false);
64034
65099
  };
@@ -64574,23 +65639,23 @@ var priceGmMarkets = async (chainId, multicallRetry, markets, prices) => {
64574
65639
  const indexMax = price(prices, m.indexToken)?.max;
64575
65640
  if (Array.isArray(dsRes) && longMax != null && shortMax != null) {
64576
65641
  const base = i * SLOTS;
64577
- const big18 = (j) => typeof dsRes[base + j] === "bigint" ? dsRes[base + j] : 0n;
65642
+ const big20 = (j) => typeof dsRes[base + j] === "bigint" ? dsRes[base + j] : 0n;
64578
65643
  const cap = computeDepositCapacityUsd(
64579
- [info?.longTokenAmount, longMax, big18(0), big18(2)],
64580
- [info?.shortTokenAmount, shortMax, big18(1), big18(3)]
65644
+ [info?.longTokenAmount, longMax, big20(0), big20(2)],
65645
+ [info?.shortTokenAmount, shortMax, big20(1), big20(3)]
64581
65646
  );
64582
65647
  if (cap != null) value.depositCapacityUsd = cap;
64583
65648
  if (indexMax != null) {
64584
65649
  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;
65650
+ const reservedUsdLong = (big20(4) + big20(5)) / divisor * indexMax;
65651
+ const reservedUsdShort = (big20(6) + big20(7)) / divisor;
64587
65652
  const liq = computeLiquidityUsd(
64588
65653
  info?.longTokenUsd,
64589
65654
  info?.shortTokenUsd,
64590
65655
  reservedUsdLong,
64591
65656
  reservedUsdShort,
64592
- big18(8),
64593
- big18(9)
65657
+ big20(8),
65658
+ big20(9)
64594
65659
  );
64595
65660
  if (liq != null)
64596
65661
  value.liquidityUsd = Math.max(0, Math.min(liq, value.tvlUsd));
@@ -64669,17 +65734,17 @@ var priceGlvVaults = async (chainId, multicallRetry, glvTokens, prices, marketIn
64669
65734
  const sp = price(prices, short);
64670
65735
  if (!lp || !sp) return;
64671
65736
  const indexPrices = [];
64672
- let ok = true;
65737
+ let ok2 = true;
64673
65738
  for (const m of markets) {
64674
65739
  const idx = marketIndexToken.get(m.toLowerCase());
64675
65740
  const ip = idx ? price(prices, idx) : void 0;
64676
65741
  if (!ip) {
64677
- ok = false;
65742
+ ok2 = false;
64678
65743
  break;
64679
65744
  }
64680
65745
  indexPrices.push(ip);
64681
65746
  }
64682
- if (!ok) return;
65747
+ if (!ok2) return;
64683
65748
  calls.push({
64684
65749
  address: c.glvReader,
64685
65750
  name: "getGlvTokenPrice",
@@ -64789,21 +65854,21 @@ var fetchGmxExecutionFees = async (chainId, multicallRetry, gasPriceWei) => {
64789
65854
  } catch {
64790
65855
  return void 0;
64791
65856
  }
64792
- const big18 = (i) => typeof res[i] === "bigint" ? res[i] : 0n;
64793
- const base = big18(0);
64794
- const mult = big18(1);
65857
+ const big20 = (i) => typeof res[i] === "bigint" ? res[i] : 0n;
65858
+ const base = big20(0);
65859
+ const mult = big20(1);
64795
65860
  if (base === 0n && mult === 0n) return void 0;
64796
65861
  const PRECISION = 10n ** 30n;
64797
65862
  const adjusted = (opGas) => base + opGas * mult / PRECISION;
64798
65863
  const fee = (opGas) => (adjusted(opGas) * gasPriceWei).toString();
64799
- const glvExtra = big18(6) * GLV_NOMINAL_MARKET_COUNT;
65864
+ const glvExtra = big20(6) * GLV_NOMINAL_MARKET_COUNT;
64800
65865
  return {
64801
65866
  chainId,
64802
65867
  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)
65868
+ deposit: fee(big20(2)),
65869
+ withdrawal: fee(big20(3)),
65870
+ glvDeposit: fee(big20(4) + glvExtra),
65871
+ glvWithdrawal: fee(big20(5) + glvExtra)
64807
65872
  };
64808
65873
  };
64809
65874
 
@@ -64904,8 +65969,8 @@ var fetchGmxVaults = async (chainId, multicallRetry, options) => {
64904
65969
  marketIndexToken
64905
65970
  )
64906
65971
  ]);
64907
- for (const [addr3, v] of gmValues) {
64908
- const e = out[addr3];
65972
+ for (const [addr4, v] of gmValues) {
65973
+ const e = out[addr4];
64909
65974
  if (e) {
64910
65975
  e.priceUsd = v.priceUsd;
64911
65976
  e.tvlUsd = v.tvlUsd;
@@ -64913,12 +65978,12 @@ var fetchGmxVaults = async (chainId, multicallRetry, options) => {
64913
65978
  e.depositCapacityUsd = v.depositCapacityUsd;
64914
65979
  }
64915
65980
  }
64916
- for (const [addr3, v] of glv.values) {
64917
- const e = out[addr3];
65981
+ for (const [addr4, v] of glv.values) {
65982
+ const e = out[addr4];
64918
65983
  if (!e) continue;
64919
65984
  e.priceUsd = v.priceUsd;
64920
65985
  e.tvlUsd = v.tvlUsd;
64921
- const markets2 = glv.glvMarkets.get(addr3) ?? [];
65986
+ const markets2 = glv.glvMarkets.get(addr4) ?? [];
64922
65987
  let liqSum = 0;
64923
65988
  let tvlSum = 0;
64924
65989
  for (const m of markets2) {
@@ -64930,7 +65995,7 @@ var fetchGmxVaults = async (chainId, multicallRetry, options) => {
64930
65995
  }
64931
65996
  if (tvlSum > 0 && v.tvlUsd != null)
64932
65997
  e.liquidityUsd = v.tvlUsd * (liqSum / tvlSum);
64933
- const caps = glv.glvCaps.get(addr3) ?? [];
65998
+ const caps = glv.glvCaps.get(addr4) ?? [];
64934
65999
  let capacity = 0;
64935
66000
  let known = false;
64936
66001
  for (const cap of caps) {
@@ -65221,7 +66286,7 @@ async function getJson4(url, label) {
65221
66286
  }
65222
66287
  return response.json();
65223
66288
  }
65224
- function cache3(slot, build, store) {
66289
+ function cache4(slot, build, store) {
65225
66290
  const now = Date.now();
65226
66291
  if (slot && now - slot.at < CACHE_TTL_MS6) return slot.promise;
65227
66292
  const promise = build();
@@ -65231,7 +66296,7 @@ function cache3(slot, build, store) {
65231
66296
  return promise;
65232
66297
  }
65233
66298
  function fetchPendleApiMarkets() {
65234
- return cache3(
66299
+ return cache4(
65235
66300
  marketsCache,
65236
66301
  async () => (await getJson4(PENDLE_MARKETS_URL, "markets"))?.markets ?? [],
65237
66302
  (c) => {
@@ -65241,7 +66306,7 @@ function fetchPendleApiMarkets() {
65241
66306
  }
65242
66307
  var assetKey = (chainId, address) => `${chainId}-${address.toLowerCase()}`;
65243
66308
  function fetchPendleApiAssets() {
65244
- return cache3(
66309
+ return cache4(
65245
66310
  assetsCache,
65246
66311
  async () => {
65247
66312
  const json = await getJson4(PENDLE_ASSETS_URL, "assets");
@@ -65424,6 +66489,255 @@ var fetchPendlePtMarkets = async (chainId, multicallRetry, prices = {}, tokenLis
65424
66489
  return out;
65425
66490
  };
65426
66491
 
66492
+ // src/vaults/spectra/api.ts
66493
+ var SPECTRA_NETWORKS = {
66494
+ "1": "mainnet",
66495
+ "10": "optimism",
66496
+ "14": "flare",
66497
+ "56": "bsc",
66498
+ "143": "monad",
66499
+ "146": "sonic",
66500
+ "999": "hyperevm",
66501
+ "8453": "base",
66502
+ "42161": "arbitrum",
66503
+ "43114": "avalanche",
66504
+ "43111": "hemi",
66505
+ "747474": "katana"
66506
+ };
66507
+ var spectraNetwork = (chainId) => SPECTRA_NETWORKS[String(chainId)];
66508
+ var hasSpectraMarkets = (chainId) => spectraNetwork(chainId) !== void 0;
66509
+ var spectraPoolsUrl = (network) => `https://app.spectra.finance/api/v1/${network}/pools`;
66510
+ var addr2 = (v) => typeof v === "string" && /^0x[0-9a-fA-F]{40}$/.test(v) ? v.toLowerCase() : void 0;
66511
+ var spectraAddress = addr2;
66512
+ function isLiveSpectraMarket(market, nowSecs = Math.floor(Date.now() / 1e3)) {
66513
+ const maturity = market?.maturity;
66514
+ if (typeof maturity !== "number" || !Number.isFinite(maturity)) return false;
66515
+ return maturity > nowSecs;
66516
+ }
66517
+ function pickPool(pools) {
66518
+ if (!Array.isArray(pools) || pools.length === 0) return void 0;
66519
+ let best;
66520
+ let bestDepth = -Infinity;
66521
+ for (const p of pools) {
66522
+ if (!p) continue;
66523
+ const depth = (typeof p.liquidity?.usd === "number" ? p.liquidity.usd : null) ?? (typeof p.liquidity?.underlying === "number" ? p.liquidity.underlying : null) ?? 0;
66524
+ if (depth > bestDepth) {
66525
+ bestDepth = depth;
66526
+ best = p;
66527
+ }
66528
+ }
66529
+ return best ?? pools[0] ?? void 0;
66530
+ }
66531
+ function parseCurveFee(raw) {
66532
+ if (typeof raw !== "string" || !/^\d+$/.test(raw)) return void 0;
66533
+ const n = Number(raw) / 1e10;
66534
+ return Number.isFinite(n) && n >= 0 && n < 1 ? n : void 0;
66535
+ }
66536
+ var SPECTRA_RATE_MIN_PERCENT = -99;
66537
+ var SPECTRA_RATE_MAX_PERCENT = 1e3;
66538
+ function sanePercent(v) {
66539
+ if (typeof v !== "number" || !Number.isFinite(v)) return void 0;
66540
+ if (v < SPECTRA_RATE_MIN_PERCENT || v > SPECTRA_RATE_MAX_PERCENT)
66541
+ return void 0;
66542
+ return v;
66543
+ }
66544
+ var PT_RATE_ONE = 1e27;
66545
+ function parsePtRate(raw) {
66546
+ if (typeof raw !== "string" || !/^\d+$/.test(raw)) return void 0;
66547
+ const n = Number(raw) / PT_RATE_ONE;
66548
+ if (!Number.isFinite(n) || n < 0 || n > 1.000001) return void 0;
66549
+ return n;
66550
+ }
66551
+ var CACHE_TTL_MS7 = 6e4;
66552
+ var cache5 = /* @__PURE__ */ new Map();
66553
+ function clearSpectraMarketsCache() {
66554
+ cache5.clear();
66555
+ }
66556
+ function fetchSpectraApiMarkets(chainId) {
66557
+ const network = spectraNetwork(chainId);
66558
+ if (!network) return Promise.resolve([]);
66559
+ const now = Date.now();
66560
+ const hit = cache5.get(network);
66561
+ if (hit && now - hit.at < CACHE_TTL_MS7) return hit.promise;
66562
+ const promise = (async () => {
66563
+ const response = await fetch(spectraPoolsUrl(network), {
66564
+ headers: { Accept: "application/json" }
66565
+ });
66566
+ if (!response.ok) {
66567
+ throw new Error(
66568
+ `Spectra pools API failed for ${network}: ${response.status} - ${response.statusText}`
66569
+ );
66570
+ }
66571
+ const json = await response.json();
66572
+ return Array.isArray(json) ? json : [];
66573
+ })();
66574
+ cache5.set(network, { at: now, promise });
66575
+ promise.catch(() => {
66576
+ if (cache5.get(network)?.promise === promise) cache5.delete(network);
66577
+ });
66578
+ return promise;
66579
+ }
66580
+
66581
+ // src/vaults/spectra/fetchPublic.ts
66582
+ var SECONDS_PER_DAY3 = 86400;
66583
+ var num12 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
66584
+ function resolveToken2(address, apiToken, tokenList, decimalsOnChain) {
66585
+ const listed = address ? tokenList[address] : void 0;
66586
+ const apiDecimals = typeof apiToken?.decimals === "number" && Number.isFinite(apiToken.decimals) ? apiToken.decimals : void 0;
66587
+ return {
66588
+ decimals: listed?.decimals ?? apiDecimals ?? (address ? decimalsOnChain.get(address) : void 0),
66589
+ symbol: listed?.symbol ?? apiToken?.symbol ?? void 0,
66590
+ name: listed?.name ?? apiToken?.name ?? void 0,
66591
+ logoURI: listed?.logoURI ?? apiToken?.logoURI ?? void 0,
66592
+ assetGroup: listed?.assetGroup
66593
+ };
66594
+ }
66595
+ function parseMarket3(m, chainId, prices, tokenList, decimalsOnChain, nowSecs) {
66596
+ const ptAddress = spectraAddress(m.address);
66597
+ const underlyingAddress = spectraAddress(m.underlying?.address);
66598
+ if (!ptAddress || !underlyingAddress) return null;
66599
+ const maturity = num12(m.maturity);
66600
+ if (maturity === null) return null;
66601
+ const pool = pickPool(m.pools);
66602
+ if (!pool) return null;
66603
+ const ptRate = parsePtRate(m.rate);
66604
+ if (ptRate === void 0 || ptRate <= 0) return null;
66605
+ const impliedApyPercent = sanePercent(pool.impliedApy);
66606
+ if (impliedApyPercent === void 0) return null;
66607
+ const ptMeta = resolveToken2(
66608
+ ptAddress,
66609
+ // The market object IS the PT's token record — `name`/`symbol`/`decimals`
66610
+ // at the root describe the PrincipalToken, not the underlying.
66611
+ {
66612
+ address: m.address,
66613
+ name: m.name,
66614
+ symbol: m.symbol,
66615
+ decimals: m.decimals
66616
+ },
66617
+ tokenList,
66618
+ decimalsOnChain
66619
+ );
66620
+ const assetMeta = resolveToken2(
66621
+ underlyingAddress,
66622
+ m.underlying,
66623
+ tokenList,
66624
+ decimalsOnChain
66625
+ );
66626
+ const decimals = ptMeta.decimals;
66627
+ const assetDecimals = assetMeta.decimals;
66628
+ if (decimals === void 0 || assetDecimals === void 0) return null;
66629
+ const supplyRate = apyToAprPercent(impliedApyPercent);
66630
+ const priceKey = toOracleKey(assetMeta.assetGroup ?? null) || toGenericPriceKey(underlyingAddress, chainId);
66631
+ const priceUsd = prices[priceKey] ?? prices[underlyingAddress];
66632
+ const totalAssetsUnderlying = num12(m.tvl?.underlying) ?? void 0;
66633
+ const totalAssetsUsd = num12(m.tvl?.usd) ?? (totalAssetsUnderlying !== void 0 && priceUsd !== void 0 ? totalAssetsUnderlying * priceUsd : 0);
66634
+ const liquidityUnderlying = num12(pool.liquidity?.underlying);
66635
+ const liquidityUsd = num12(pool.liquidity?.usd) ?? (liquidityUnderlying !== null && priceUsd !== void 0 ? liquidityUnderlying * priceUsd : 0);
66636
+ const ptPriceKey = toOracleKey(ptMeta.assetGroup ?? null) || toGenericPriceKey(ptAddress, chainId);
66637
+ const ptPriceUsd = prices[ptPriceKey] ?? prices[ptAddress] ?? num12(pool.ptPrice?.usd) ?? void 0;
66638
+ const secondsToExpiry = Math.max(maturity - nowSecs, 0);
66639
+ return {
66640
+ address: ptAddress,
66641
+ marketAddress: spectraAddress(pool.address),
66642
+ underlying: underlyingAddress,
66643
+ ytAddress: spectraAddress(m.yt?.address),
66644
+ ibtAddress: spectraAddress(m.ibt?.address),
66645
+ baseIbtAddress: spectraAddress(m.baseIbt?.address),
66646
+ symbol: ptMeta.symbol ?? `PT-${assetMeta.symbol ?? ""}`,
66647
+ name: ptMeta.name ?? `Principal Token ${assetMeta.symbol ?? ""}`,
66648
+ decimals,
66649
+ assetDecimals,
66650
+ expiry: maturity,
66651
+ expiryIso: new Date(maturity * 1e3).toISOString(),
66652
+ secondsToExpiry,
66653
+ daysToExpiry: Math.round(secondsToExpiry / SECONDS_PER_DAY3 * 100) / 100,
66654
+ supplyRate,
66655
+ rewardsRate: 0,
66656
+ depositRate: supplyRate,
66657
+ impliedApyPercent,
66658
+ executableApyPercent: sanePercent(pool.ptApy),
66659
+ underlyingApyPercent: sanePercent(m.ibt?.apr?.total),
66660
+ feeRate: parseCurveFee(pool.feeRate),
66661
+ totalAssetsUsd,
66662
+ totalAssetsFormatted: totalAssetsUsd,
66663
+ liquidityUsd,
66664
+ totalAssetsUnderlying,
66665
+ ptRate,
66666
+ principalWriteDownBps: Math.max(0, Math.round((1 - ptRate) * 1e4)),
66667
+ isMintable: true,
66668
+ withdrawalMode: "market-sale",
66669
+ // Pre-seeded from Spectra's own icon CDN. `stampVaultClassification`
66670
+ // overwrites it when the token list resolves something and leaves it alone
66671
+ // otherwise, so a row still renders an icon with no token list.
66672
+ logoURI: ptMeta.logoURI,
66673
+ // Prefer the curated token-list entry (it carries `assetGroup`, tags and
66674
+ // everything else downstream reads); synthesize from Spectra's own record
66675
+ // otherwise, so `stampVaultClassification` still has a symbol to read for
66676
+ // the stable/volatile call.
66677
+ asset: tokenList[underlyingAddress] ?? (assetMeta.symbol ? {
66678
+ chainId,
66679
+ address: underlyingAddress,
66680
+ symbol: assetMeta.symbol,
66681
+ name: assetMeta.name,
66682
+ decimals: assetDecimals,
66683
+ logoURI: assetMeta.logoURI
66684
+ } : void 0),
66685
+ priceUsd,
66686
+ ptPriceUsd,
66687
+ ptPriceUnderlying: num12(pool.ptPrice?.underlying) ?? void 0,
66688
+ categoryIds: Array.isArray(m.tags) ? m.tags : void 0,
66689
+ protocol: m.ibt?.protocol ?? void 0
66690
+ };
66691
+ }
66692
+ var fetchSpectraPtMarkets = async (chainId, multicallRetry, prices = {}, tokenList = {}, options = {}) => {
66693
+ if (!hasSpectraMarkets(chainId)) return {};
66694
+ const nowSecs = options.nowSecs ?? Math.floor(Date.now() / 1e3);
66695
+ const all = await fetchSpectraApiMarkets(chainId);
66696
+ const candidates = all.filter(
66697
+ (m) => !!m && (options.includeExpired === true || isLiveSpectraMarket(m, nowSecs))
66698
+ );
66699
+ if (candidates.length === 0) return {};
66700
+ const unresolved = /* @__PURE__ */ new Set();
66701
+ for (const m of candidates) {
66702
+ const pairs = [
66703
+ [spectraAddress(m.address), m.decimals],
66704
+ [spectraAddress(m.underlying?.address), m.underlying?.decimals]
66705
+ ];
66706
+ for (const [address, apiDecimals] of pairs) {
66707
+ if (!address) continue;
66708
+ if (tokenList[address]?.decimals !== void 0) continue;
66709
+ if (typeof apiDecimals === "number" && Number.isFinite(apiDecimals))
66710
+ continue;
66711
+ unresolved.add(address);
66712
+ }
66713
+ }
66714
+ let decimalsOnChain = /* @__PURE__ */ new Map();
66715
+ if (unresolved.size > 0) {
66716
+ try {
66717
+ decimalsOnChain = await fetchAssetDecimals(
66718
+ chainId,
66719
+ [...unresolved],
66720
+ multicallRetry
66721
+ );
66722
+ } catch {
66723
+ decimalsOnChain = /* @__PURE__ */ new Map();
66724
+ }
66725
+ }
66726
+ const out = {};
66727
+ for (const m of candidates) {
66728
+ const parsed = parseMarket3(
66729
+ m,
66730
+ chainId,
66731
+ prices,
66732
+ tokenList,
66733
+ decimalsOnChain,
66734
+ nowSecs
66735
+ );
66736
+ if (parsed) out[parsed.address] = parsed;
66737
+ }
66738
+ return out;
66739
+ };
66740
+
65427
66741
  // src/vaults/yield/sharePrice.ts
65428
66742
  var VAULT_SHARE_PRICE_PROBE = 10n ** 18n;
65429
66743
  var ConvertToAssetsAbi = [
@@ -65503,11 +66817,11 @@ function buildVaultLookup(data) {
65503
66817
  const addEntries = (bag, provider) => {
65504
66818
  if (!bag) return;
65505
66819
  for (const v of Object.values(bag)) {
65506
- const addr3 = v.address.toLowerCase();
65507
- if (map.has(addr3)) continue;
65508
- map.set(addr3, {
66820
+ const addr4 = v.address.toLowerCase();
66821
+ if (map.has(addr4)) continue;
66822
+ map.set(addr4, {
65509
66823
  provider,
65510
- address: addr3,
66824
+ address: addr4,
65511
66825
  underlying: v.underlying.toLowerCase(),
65512
66826
  symbol: v.symbol,
65513
66827
  name: v.name,
@@ -66272,6 +67586,29 @@ var TERM_PROFILES = [
66272
67586
  ]
66273
67587
  }
66274
67588
  }),
67589
+ P({
67590
+ id: "twyne.credit-delegation@v1",
67591
+ name: "Twyne credit delegation",
67592
+ family: "twyne",
67593
+ supply: {
67594
+ 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.",
67595
+ implications: [
67596
+ "Your capital never leaves the underlying lending market; only the right to borrow against it is delegated.",
67597
+ "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.",
67598
+ "You can withdraw whenever credit is not reserved. A fully utilised credit vault cannot be exited until a borrower releases credit."
67599
+ ]
67600
+ },
67601
+ borrow: {
67602
+ 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.",
67603
+ implications: [
67604
+ "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.",
67605
+ "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.",
67606
+ "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.",
67607
+ "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.",
67608
+ 'Reserved credit is not yours: it is not withdrawable, and "withdraw everything" means your own collateral, not the vault\u2019s balance.'
67609
+ ]
67610
+ }
67611
+ }),
66275
67612
  P({
66276
67613
  id: "morpho.blue@v1",
66277
67614
  name: "Morpho Blue isolated market",
@@ -66448,6 +67785,7 @@ var VAULT_PROVIDER_PROFILE = {
66448
67785
  savings: "vault.savings@v1",
66449
67786
  lst: "vault.lst@v1",
66450
67787
  pendle: "vault.fixed-maturity@v1",
67788
+ spectra: "vault.fixed-maturity@v1",
66451
67789
  lagoon: "vault.request@v1",
66452
67790
  upshift: "vault.request@v1",
66453
67791
  yearn: "vault.strategy@v1",
@@ -67142,6 +68480,37 @@ var VAULT_PROVIDER_TRAITS = {
67142
68480
  hasDecomposableBacking: false,
67143
68481
  hasUtilization: false
67144
68482
  },
68483
+ // Spectra PTs are the same instrument as Pendle's, so the traits agree
68484
+ // where the economics agree — with one deliberate divergence below.
68485
+ spectra: {
68486
+ rateKind: "fixed-term",
68487
+ // Same call as Pendle, and for the same reason: no borrower, no
68488
+ // leverage, no tranching on the Spectra side, so the fixed-rate promise
68489
+ // itself carries no credit risk. The IBT it redeems into is only as good
68490
+ // as the protocol behind it, and that passes straight through to the PT
68491
+ // holder — a property of the underlying, stated in the profile.
68492
+ //
68493
+ // **The divergence from Pendle is that Spectra makes the failure mode
68494
+ // legible.** `ptRate` starts at par and is written DOWN whenever the IBT
68495
+ // loses value ("The `ptRate` can only decrease" — their own docs work the
68496
+ // example where a halved IBT returns half the deposit). Pendle carries
68497
+ // the identical exposure through its SY and publishes no equivalent
68498
+ // number. So this is not a weaker claim than Pendle's, it is the same
68499
+ // claim with a live check attached: the row ships `ptRate` and
68500
+ // `principalWriteDownBps`, and a market written down to zero is dropped
68501
+ // outright rather than served as a bond.
68502
+ solvency: "overcollateralized",
68503
+ rateSource: "derived",
68504
+ rateWindow: { kind: "forward" },
68505
+ defaultExitMode: "market-sale",
68506
+ priceRisk: "market-price",
68507
+ counterpartyKind: "p2p",
68508
+ reportsPerformanceFee: false,
68509
+ reportsGovernance: false,
68510
+ reportsExposures: false,
68511
+ hasDecomposableBacking: false,
68512
+ hasUtilization: false
68513
+ },
67145
68514
  lagoon: {
67146
68515
  rateKind: "variable-managed",
67147
68516
  rateSource: "api",
@@ -67891,7 +69260,8 @@ var VAULT_PROVIDER_BRANDS = {
67891
69260
  yearn: "Yearn",
67892
69261
  hypercore: "HyperLiquid",
67893
69262
  gmx: "GMX",
67894
- pendle: "Pendle"
69263
+ pendle: "Pendle",
69264
+ spectra: "Spectra"
67895
69265
  };
67896
69266
  function isInstanceSegment(seg) {
67897
69267
  if (/^\d+$/.test(seg)) return true;
@@ -68108,7 +69478,7 @@ function resolveEarnIdentity(venue, brand, publishedProtocol) {
68108
69478
  }
68109
69479
 
68110
69480
  // src/earn/normalize.ts
68111
- function num12(v) {
69481
+ function num13(v) {
68112
69482
  if (v == null || v === "") return void 0;
68113
69483
  const n = typeof v === "number" ? v : Number(v);
68114
69484
  return Number.isFinite(n) ? n : void 0;
@@ -68118,7 +69488,7 @@ function str6(v) {
68118
69488
  if (typeof v === "number" && Number.isFinite(v)) return String(v);
68119
69489
  return void 0;
68120
69490
  }
68121
- function addr2(v) {
69491
+ function addr3(v) {
68122
69492
  return str6(v)?.toLowerCase();
68123
69493
  }
68124
69494
  function yieldProfile(v) {
@@ -68164,6 +69534,7 @@ var RATE_SOURCE = {
68164
69534
  yearn: "api",
68165
69535
  "aave-earn": "api",
68166
69536
  pendle: "api",
69537
+ spectra: "api",
68167
69538
  lista: "chain",
68168
69539
  fluid: "chain",
68169
69540
  gearbox: "chain",
@@ -68189,6 +69560,8 @@ var RATE_KIND = {
68189
69560
  // to maturity — the same promise TermMax's FT makes, reached by a different
68190
69561
  // mechanism (an AMM discount rather than a quoted curve).
68191
69562
  pendle: "fixed-term",
69563
+ // Same instrument, same promise: the discount at purchase IS the rate.
69564
+ spectra: "fixed-term",
68192
69565
  savings: "variable-managed",
68193
69566
  lst: "variable-managed",
68194
69567
  lagoon: "variable-managed",
@@ -68202,8 +69575,8 @@ function resolveExitMode2(provider, meta, tvl, liq) {
68202
69575
  if (declared) return declared;
68203
69576
  const fallback = vaultTraits(provider)?.defaultExitMode ?? "instant";
68204
69577
  if (fallback !== "instant-capped") return fallback;
68205
- const total = num12(tvl?.totalAssetsFormatted) ?? num12(tvl?.totalAssetsUsd);
68206
- const available = num12(liq?.liquidityFormatted) ?? num12(liq?.liquidityUsd);
69578
+ const total = num13(tvl?.totalAssetsFormatted) ?? num13(tvl?.totalAssetsUsd);
69579
+ const available = num13(liq?.liquidityFormatted) ?? num13(liq?.liquidityUsd);
68207
69580
  if (total === void 0 || available === void 0) return "instant-capped";
68208
69581
  if (total <= 0) return "instant";
68209
69582
  return available >= total ? "instant" : "instant-capped";
@@ -68238,8 +69611,8 @@ function earnMarketFromVault(row, chainId, opts = {}) {
68238
69611
  const rates = row.rates ?? {};
68239
69612
  const tvl = row.tvl ?? {};
68240
69613
  const liq = row.liquidity ?? {};
68241
- const shareDecimals = num12(row.decimals) ?? 18;
68242
- const assetDecimals = num12(row.assetDecimals) ?? num12(row.underlyingInfo?.asset?.decimals) ?? shareDecimals;
69614
+ const shareDecimals = num13(row.decimals) ?? 18;
69615
+ const assetDecimals = num13(row.assetDecimals) ?? num13(row.underlyingInfo?.asset?.decimals) ?? shareDecimals;
68243
69616
  const toPercent2 = (v) => ratePercent(v, provider, opts.fractionRateProviders);
68244
69617
  const rewards = toPercent2(rates.rewardsRate);
68245
69618
  const deposit = toPercent2(rates.depositRate);
@@ -68321,7 +69694,7 @@ function earnMarketFromVault(row, chainId, opts = {}) {
68321
69694
  symbol: str6(row.underlyingInfo?.asset?.symbol) ?? "",
68322
69695
  decimals: assetDecimals,
68323
69696
  assetGroup: str6(info.assetGroup),
68324
- priceUsd: num12(row.underlyingInfo?.prices?.priceUsd)
69697
+ priceUsd: num13(row.underlyingInfo?.prices?.priceUsd)
68325
69698
  },
68326
69699
  // The vault IS a share token by construction; carry it so a withdraw in
68327
69700
  // share units can be built without a second lookup.
@@ -68351,8 +69724,8 @@ function earnMarketFromVault(row, chainId, opts = {}) {
68351
69724
  exit: {
68352
69725
  mode: exitMode,
68353
69726
  settlement: str6(meta.redemptionType),
68354
- cooldownSecs: num12(meta.withdrawalCooldownSeconds),
68355
- feeBps: num12(meta.withdrawFeeBps)
69727
+ cooldownSecs: num13(meta.withdrawalCooldownSeconds),
69728
+ feeBps: num13(meta.withdrawFeeBps)
68356
69729
  },
68357
69730
  availability,
68358
69731
  risk: {
@@ -68362,12 +69735,12 @@ function earnMarketFromVault(row, chainId, opts = {}) {
68362
69735
  // since the surface was written and never populated — a tranche's
68363
69736
  // first-loss position is the term most worth surfacing on a rate list.
68364
69737
  counterparty: str6(meta.solvency),
68365
- score: num12(row.rating?.score),
69738
+ score: num13(row.rating?.score),
68366
69739
  label: str6(row.rating?.level),
68367
69740
  illiquid: isIlliquid({
68368
69741
  exitMode,
68369
- tvlUsd: num12(tvl.totalAssetsUsd),
68370
- liquidityUsd: num12(liq.liquidityUsd)
69742
+ tvlUsd: num13(tvl.totalAssetsUsd),
69743
+ liquidityUsd: num13(liq.liquidityUsd)
68371
69744
  })
68372
69745
  },
68373
69746
  // Filled by `capabilities.ts` — kept required on the type so a normalizer
@@ -68379,7 +69752,7 @@ function earnMarketFromVault(row, chainId, opts = {}) {
68379
69752
  return market;
68380
69753
  }
68381
69754
  function ratePercent(value, provider, fractionProviders = FRACTION_RATE_PROVIDERS) {
68382
- const n = num12(value);
69755
+ const n = num13(value);
68383
69756
  if (n === void 0) return void 0;
68384
69757
  return fractionProviders.has(provider) ? n * 100 : n;
68385
69758
  }
@@ -68434,7 +69807,7 @@ function vaultDisplayName(row, info) {
68434
69807
  return str6(row.name) ?? str6(info.name) ?? str6(row.displayName) ?? str6(share?.name) ?? str6(share?.symbol) ?? str6(info.symbol) ?? str6(row.symbol);
68435
69808
  }
68436
69809
  function resolveMaturity(meta) {
68437
- const expiry = num12(meta.expiry) ?? num12(meta.maturity);
69810
+ const expiry = num13(meta.expiry) ?? num13(meta.maturity);
68438
69811
  if (expiry === void 0 || expiry <= 0) return void 0;
68439
69812
  const nowSecs = Math.floor(Date.now() / 1e3);
68440
69813
  return {
@@ -68457,8 +69830,8 @@ function amount(raw, formatted, usd, decimals) {
68457
69830
  const rawStr = raw != null ? String(raw) : void 0;
68458
69831
  return {
68459
69832
  raw: rawStr,
68460
- formatted: num12(formatted) ?? formatRaw(rawStr, decimals),
68461
- usd: num12(usd)
69833
+ formatted: num13(formatted) ?? formatRaw(rawStr, decimals),
69834
+ usd: num13(usd)
68462
69835
  };
68463
69836
  }
68464
69837
  function withCuratorEntity(id, entity) {
@@ -68471,7 +69844,7 @@ function sum(a, b) {
68471
69844
  }
68472
69845
 
68473
69846
  // src/terms/vault/input.ts
68474
- var num13 = (v) => {
69847
+ var num14 = (v) => {
68475
69848
  if (typeof v === "number") return Number.isFinite(v) ? v : void 0;
68476
69849
  if (typeof v === "string" && v.trim() !== "") {
68477
69850
  const n = Number(v);
@@ -68490,27 +69863,27 @@ var fromRaw = (raw, decimals) => {
68490
69863
  function sdkRates(row, provider) {
68491
69864
  if (!SDK_FRACTION_RATE_PROVIDERS.has(provider)) {
68492
69865
  return {
68493
- supplyRate: num13(row.supplyRate),
68494
- rewardsRate: num13(row.rewardsRate),
68495
- totalRate: num13(row.depositRate)
69866
+ supplyRate: num14(row.supplyRate),
69867
+ rewardsRate: num14(row.rewardsRate),
69868
+ totalRate: num14(row.depositRate)
68496
69869
  };
68497
69870
  }
68498
- const pct2 = (v) => {
68499
- const n = num13(v);
69871
+ const pct3 = (v) => {
69872
+ const n = num14(v);
68500
69873
  return n === void 0 ? void 0 : n * 100;
68501
69874
  };
68502
69875
  return {
68503
69876
  // 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)
69877
+ supplyRate: pct3(row.baseApy ?? row.apr),
69878
+ rewardsRate: pct3(row.bonusApr),
69879
+ totalRate: pct3(row.apy ?? row.apr)
68507
69880
  };
68508
69881
  }
68509
69882
  function toVaultTermInput(vault, provider, chainId) {
68510
69883
  const row = vault;
68511
69884
  const address = str7(row.address)?.toLowerCase();
68512
69885
  if (!address) return void 0;
68513
- const assetDecimals = num13(row.assetDecimals) ?? num13(row.decimals);
69886
+ const assetDecimals = num14(row.assetDecimals) ?? num14(row.decimals);
68514
69887
  const asset = row.asset;
68515
69888
  return {
68516
69889
  provider,
@@ -68536,22 +69909,22 @@ function toVaultTermInput(vault, provider, chainId) {
68536
69909
  // GMX / HyperCore / Pendle report USD only and set the token-denominated
68537
69910
  // fields to their USD figure — `totalAssetsFormatted` is the cross-provider
68538
69911
  // 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),
69912
+ totalAssets: num14(row.totalAssetsFormatted) ?? fromRaw(row.totalAssets, assetDecimals),
69913
+ totalAssetsUsd: num14(row.totalAssetsUsd) ?? num14(row.tvlUsd),
69914
+ liquidity: num14(row.liquidityFormatted) ?? fromRaw(row.liquidity, assetDecimals),
69915
+ liquidityUsd: num14(row.liquidityUsd),
69916
+ instantLiquidityRatio: num14(row.instantLiquidityRatio),
68544
69917
  totalBorrowed: fromRaw(row.totalBorrowed, assetDecimals),
68545
69918
  expectedLiquidity: fromRaw(row.expectedLiquidity, assetDecimals),
68546
69919
  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),
69920
+ withdrawalCooldownSeconds: num14(row.withdrawalCooldownSeconds),
69921
+ withdrawFeeBps: num14(row.withdrawFeeBps),
69922
+ fee: num14(row.fee),
69923
+ managementFee: num14(row.managementFee),
69924
+ swapFeeRate: num14(row.feeRate),
69925
+ redemptionDiscountBps: num14(row.redemptionDiscountBps),
68553
69926
  instantRedeemEnabled: bool2(row.instantRedeemEnabled),
68554
- yieldWarmupSeconds: num13(row.yieldWarmupSeconds),
69927
+ yieldWarmupSeconds: num14(row.yieldWarmupSeconds),
68555
69928
  accrual: str7(row.accrual),
68556
69929
  needsDepositApproval: bool2(row.needsDepositApproval),
68557
69930
  isMintable: bool2(row.isMintable),
@@ -68562,8 +69935,8 @@ function toVaultTermInput(vault, provider, chainId) {
68562
69935
  withdrawalsPaused: bool2(row.isWithdrawalPaused),
68563
69936
  isClosed: bool2(row.isClosed),
68564
69937
  whitelisted: bool2(row.whitelisted),
68565
- expiry: num13(row.expiry),
68566
- timelock: num13(row.timelock),
69938
+ expiry: num14(row.expiry),
69939
+ timelock: num14(row.timelock),
68567
69940
  owner: str7(row.owner),
68568
69941
  curator: str7(row.curator),
68569
69942
  guardian: str7(row.guardian),
@@ -68605,18 +69978,18 @@ function vaultTermInputFromEarnMarket(m) {
68605
69978
  totalAssetsUsd: m.tvl.usd,
68606
69979
  liquidity: m.liquidity?.formatted,
68607
69980
  liquidityUsd: m.liquidity?.usd,
68608
- instantLiquidityRatio: num13(meta.instantLiquidityRatio),
68609
- totalBorrowed: num13(meta.totalBorrowed),
68610
- expectedLiquidity: num13(meta.expectedLiquidity),
69981
+ instantLiquidityRatio: num14(meta.instantLiquidityRatio),
69982
+ totalBorrowed: num14(meta.totalBorrowed),
69983
+ expectedLiquidity: num14(meta.expectedLiquidity),
68611
69984
  withdrawalMode: m.exit.mode,
68612
69985
  withdrawalCooldownSeconds: m.exit.cooldownSecs,
68613
69986
  withdrawFeeBps: m.exit.feeBps,
68614
69987
  fee: m.rate.fee,
68615
- managementFee: num13(meta.managementFee),
68616
- swapFeeRate: num13(meta.feeRate),
68617
- redemptionDiscountBps: num13(meta.redemptionDiscountBps),
69988
+ managementFee: num14(meta.managementFee),
69989
+ swapFeeRate: num14(meta.feeRate),
69990
+ redemptionDiscountBps: num14(meta.redemptionDiscountBps),
68618
69991
  instantRedeemEnabled: bool2(meta.instantRedeemEnabled),
68619
- yieldWarmupSeconds: num13(meta.yieldWarmupSeconds),
69992
+ yieldWarmupSeconds: num14(meta.yieldWarmupSeconds),
68620
69993
  accrual: str7(meta.accrual),
68621
69994
  needsDepositApproval: bool2(meta.needsDepositApproval),
68622
69995
  // `canDeposit` already folds in the cap, the pause and the gate, so it is
@@ -68630,7 +70003,7 @@ function vaultTermInputFromEarnMarket(m) {
68630
70003
  isClosed: bool2(meta.isClosed),
68631
70004
  whitelisted: bool2(meta.whitelisted),
68632
70005
  expiry: m.maturity?.maturity,
68633
- timelock: num13(meta.timelock),
70006
+ timelock: num14(meta.timelock),
68634
70007
  owner: str7(meta.owner),
68635
70008
  curator: str7(meta.curator),
68636
70009
  guardian: str7(meta.guardian),
@@ -68642,13 +70015,13 @@ function vaultTermInputFromEarnMarket(m) {
68642
70015
  };
68643
70016
  }
68644
70017
  function originRates(rates) {
68645
- const supply = num13(rates.supplyRate);
68646
- const rewards = num13(rates.rewardsRate);
68647
- const deposit = num13(rates.depositRate);
70018
+ const supply = num14(rates.supplyRate);
70019
+ const rewards = num14(rates.rewardsRate);
70020
+ const deposit = num14(rates.depositRate);
68648
70021
  return {
68649
70022
  supplyRate: supply ?? (deposit !== void 0 && rewards !== void 0 ? deposit - rewards : deposit),
68650
70023
  rewardsRate: rewards,
68651
- totalRate: num13(rates.totalRate) ?? deposit
70024
+ totalRate: num14(rates.totalRate) ?? deposit
68652
70025
  };
68653
70026
  }
68654
70027
  function vaultTermInputFromSourceRow(row, chainId) {
@@ -68661,7 +70034,7 @@ function vaultTermInputFromSourceRow(row, chainId) {
68661
70034
  const liq = row.liquidity ?? {};
68662
70035
  const info = row.vaultInfo ?? {};
68663
70036
  const assetInfo = row.underlyingInfo?.asset;
68664
- const assetDecimals = num13(row.assetDecimals) ?? num13(assetInfo?.decimals) ?? num13(row.decimals);
70037
+ const assetDecimals = num14(row.assetDecimals) ?? num14(assetInfo?.decimals) ?? num14(row.decimals);
68665
70038
  return {
68666
70039
  provider,
68667
70040
  chainId,
@@ -68682,22 +70055,22 @@ function vaultTermInputFromSourceRow(row, chainId) {
68682
70055
  ...originRates(rates),
68683
70056
  isForwardApr: bool2(meta.isForwardApr),
68684
70057
  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),
70058
+ totalAssets: num14(tvl.totalAssetsFormatted) ?? fromRaw(tvl.totalAssets, assetDecimals),
70059
+ totalAssetsUsd: num14(tvl.totalAssetsUsd),
70060
+ liquidity: num14(liq.liquidityFormatted) ?? fromRaw(liq.liquidity, assetDecimals),
70061
+ liquidityUsd: num14(liq.liquidityUsd),
70062
+ instantLiquidityRatio: num14(meta.instantLiquidityRatio),
68690
70063
  totalBorrowed: fromRaw(meta.totalBorrowed, assetDecimals),
68691
70064
  expectedLiquidity: fromRaw(meta.expectedLiquidity, assetDecimals),
68692
70065
  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),
70066
+ withdrawalCooldownSeconds: num14(meta.withdrawalCooldownSeconds),
70067
+ withdrawFeeBps: num14(meta.withdrawFeeBps),
70068
+ fee: num14(rates.fee),
70069
+ managementFee: num14(meta.managementFee),
70070
+ swapFeeRate: num14(meta.feeRate),
70071
+ redemptionDiscountBps: num14(meta.redemptionDiscountBps),
68699
70072
  instantRedeemEnabled: bool2(meta.instantRedeemEnabled),
68700
- yieldWarmupSeconds: num13(meta.yieldWarmupSeconds),
70073
+ yieldWarmupSeconds: num14(meta.yieldWarmupSeconds),
68701
70074
  accrual: str7(meta.accrual),
68702
70075
  needsDepositApproval: bool2(meta.needsDepositApproval),
68703
70076
  isMintable: bool2(meta.isMintable),
@@ -68708,8 +70081,8 @@ function vaultTermInputFromSourceRow(row, chainId) {
68708
70081
  withdrawalsPaused: bool2(meta.isWithdrawalPaused),
68709
70082
  isClosed: bool2(meta.isClosed),
68710
70083
  whitelisted: bool2(meta.whitelisted),
68711
- expiry: num13(meta.expiry) ?? num13(meta.maturity),
68712
- timelock: num13(meta.timelock),
70084
+ expiry: num14(meta.expiry) ?? num14(meta.maturity),
70085
+ timelock: num14(meta.timelock),
68713
70086
  owner: str7(meta.owner),
68714
70087
  curator: str7(meta.curator),
68715
70088
  guardian: str7(meta.guardian),
@@ -68746,6 +70119,7 @@ function stampVaultTermSheets(data, chainId) {
68746
70119
  stampBag(data.upshift, "upshift");
68747
70120
  stampBag(data.yearn, "yearn");
68748
70121
  stampBag(data.pendle, "pendle");
70122
+ stampBag(data.spectra, "spectra");
68749
70123
  stampBag(data.hypercore, "hypercore");
68750
70124
  stampBag(data.gmx, "gmx");
68751
70125
  }
@@ -68767,7 +70141,8 @@ var VAULT_PROVIDERS = [
68767
70141
  "yearn",
68768
70142
  "hypercore",
68769
70143
  "gmx",
68770
- "pendle"
70144
+ "pendle",
70145
+ "spectra"
68771
70146
  ];
68772
70147
  var HYPERCORE_PROVIDER_CHAIN = "999";
68773
70148
  var getVaultPublicDataAll = async (chainId, providers, multicallRetry, prices = {}, tokenList = {}, options) => {
@@ -68960,6 +70335,20 @@ var getVaultPublicDataAll = async (chainId, providers, multicallRetry, prices =
68960
70335
  })
68961
70336
  );
68962
70337
  }
70338
+ if (requested.has("spectra") && hasSpectraMarkets(chainId)) {
70339
+ tasks.push(
70340
+ fetchSpectraPtMarkets(chainId, multicallRetry, prices, tokenList, {
70341
+ includeExpired: options?.spectraIncludeExpired
70342
+ }).then((res) => {
70343
+ out.spectra = res;
70344
+ }).catch((e) => {
70345
+ warn8(
70346
+ `[vaults] spectra fetch failed for chain ${chainId}:`,
70347
+ e?.message ?? e
70348
+ );
70349
+ })
70350
+ );
70351
+ }
68963
70352
  if (requested.has("gmx") && getGmxApiHost(chainId)) {
68964
70353
  tasks.push(
68965
70354
  fetchGmxVaults(chainId, multicallRetry).then((res) => {
@@ -69292,32 +70681,32 @@ async function fetchTokenMetadata(chain, addrs) {
69292
70681
  const results = await client.multicall({
69293
70682
  allowFailure: false,
69294
70683
  batchSize: 300,
69295
- contracts: addrs.map((addr3) => [
70684
+ contracts: addrs.map((addr4) => [
69296
70685
  {
69297
70686
  abi: ERC20MetadataAbi,
69298
70687
  functionName: "name",
69299
- address: addr3,
70688
+ address: addr4,
69300
70689
  args: []
69301
70690
  },
69302
70691
  {
69303
70692
  abi: ERC20MetadataAbi,
69304
70693
  functionName: "symbol",
69305
- address: addr3,
70694
+ address: addr4,
69306
70695
  args: []
69307
70696
  },
69308
70697
  {
69309
70698
  abi: ERC20MetadataAbi,
69310
70699
  functionName: "decimals",
69311
- address: addr3,
70700
+ address: addr4,
69312
70701
  args: []
69313
70702
  }
69314
70703
  ]).flat()
69315
70704
  });
69316
- addrs.forEach((addr3, i) => {
70705
+ addrs.forEach((addr4, i) => {
69317
70706
  const name = results[i * 3];
69318
70707
  const symbol = results[i * 3 + 1];
69319
70708
  const decimals = results[i * 3 + 2];
69320
- const address = addr3.toLowerCase();
70709
+ const address = addr4.toLowerCase();
69321
70710
  tokens[address] = {
69322
70711
  chainId: String(chain),
69323
70712
  decimals,
@@ -69532,7 +70921,7 @@ async function fetchTokenBalances(chainId, account, tokens, options = {}) {
69532
70921
  }
69533
70922
 
69534
70923
  // src/terms/input.ts
69535
- var num14 = (v) => {
70924
+ var num15 = (v) => {
69536
70925
  if (v == null) return void 0;
69537
70926
  const n = typeof v === "string" ? Number(v) : v;
69538
70927
  return Number.isFinite(n) ? n : void 0;
@@ -69563,12 +70952,12 @@ function toTermSheetInput(row, ctx = {}) {
69563
70952
  {
69564
70953
  category: v?.category ?? k,
69565
70954
  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),
70955
+ borrowCollateralFactor: num15(v?.borrowCollateralFactor),
70956
+ collateralFactor: num15(v?.collateralFactor),
70957
+ borrowFactor: num15(v?.borrowFactor),
70958
+ liquidationPenalty: num15(v?.liquidationPenalty),
70959
+ closeFactor: num15(v?.closeFactor),
70960
+ targetHealthFactor: num15(v?.targetHealthFactor),
69572
70961
  collateralDisabled: v?.collateralDisabled === true,
69573
70962
  debtDisabled: v?.debtDisabled === true
69574
70963
  }
@@ -69576,11 +70965,11 @@ function toTermSheetInput(row, ctx = {}) {
69576
70965
  ) : void 0;
69577
70966
  const rewards = pick2(row, "rewards")?.map((r) => ({
69578
70967
  asset: r?.asset,
69579
- depositRate: num14(r?.depositRate),
69580
- variableBorrowRate: num14(r?.variableBorrowRate),
69581
- stableBorrowRate: num14(r?.stableBorrowRate),
70968
+ depositRate: num15(r?.depositRate),
70969
+ variableBorrowRate: num15(r?.variableBorrowRate),
70970
+ stableBorrowRate: num15(r?.stableBorrowRate),
69582
70971
  kind: r?.kind,
69583
- endsAt: num14(r?.endsAt),
70972
+ endsAt: num15(r?.endsAt),
69584
70973
  claim: r?.claim
69585
70974
  }));
69586
70975
  return {
@@ -69593,29 +70982,29 @@ function toTermSheetInput(row, ctx = {}) {
69593
70982
  "underlyingInfo.asset"
69594
70983
  ),
69595
70984
  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")),
70985
+ decimals: num15(pick2(row, "decimals")),
70986
+ depositRate: num15(pick2(row, "depositRate")),
70987
+ variableBorrowRate: num15(pick2(row, "variableBorrowRate")),
70988
+ stableBorrowRate: num15(pick2(row, "stableBorrowRate")),
70989
+ intrinsicYield: num15(pick2(row, "intrinsicYield")),
69601
70990
  rewards,
69602
70991
  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")),
70992
+ originationFee: num15(pick2(row, "originationFee")),
70993
+ totalDeposits: num15(pick2(row, "totalDeposits")),
70994
+ totalDebt: num15(pick2(row, "totalDebt")),
70995
+ totalDebtStable: num15(pick2(row, "totalDebtStable")),
70996
+ totalLiquidity: num15(pick2(row, "totalLiquidity")),
70997
+ borrowLiquidity: num15(pick2(row, "borrowLiquidity")),
70998
+ totalDepositsUsd: num15(pick2(row, "totalDepositsUSD", "totalDepositsUsd")),
70999
+ totalDebtUsd: num15(pick2(row, "totalDebtUSD", "totalDebtUsd")),
71000
+ totalLiquidityUsd: num15(pick2(row, "totalLiquidityUSD", "totalLiquidityUsd")),
71001
+ utilization: num15(pick2(row, "utilization")),
71002
+ irmTotalDeposits: num15(pick2(row, "irmTotalDeposits")),
71003
+ irmTotalDebt: num15(pick2(row, "irmTotalDebt")),
71004
+ lockupRatio: num15(pick2(row, "lockupRatio")),
69616
71005
  minBorrow: pick2(row, "minBorrow", "caps.minBorrow") ?? void 0,
69617
- supplyCap: num14(pick2(row, "supplyCap", "caps.supplyCap")),
69618
- borrowCap: num14(pick2(row, "borrowCap", "caps.borrowCap")),
71006
+ supplyCap: num15(pick2(row, "supplyCap", "caps.supplyCap")),
71007
+ borrowCap: num15(pick2(row, "borrowCap", "caps.borrowCap")),
69619
71008
  debtCeiling: pick2(row, "debtCeiling", "caps.debtCeiling"),
69620
71009
  isActive: pick2(row, "isActive", "flags.isActive"),
69621
71010
  isFrozen: pick2(row, "isFrozen", "flags.isFrozen"),
@@ -69641,8 +71030,8 @@ function toTermSheetInput(row, ctx = {}) {
69641
71030
  "flags.variableBorrowDisabled"
69642
71031
  ),
69643
71032
  config,
69644
- closeFactor: num14(pick2(row, "closeFactor")),
69645
- targetHealthFactor: num14(pick2(row, "targetHealthFactor")),
71033
+ closeFactor: num15(pick2(row, "closeFactor")),
71034
+ targetHealthFactor: num15(pick2(row, "targetHealthFactor")),
69646
71035
  fixedTerm: pick2(row, "fixedTerm") ?? ctx.fixedTerm,
69647
71036
  terms: pick2(row, "terms"),
69648
71037
  market: resolveMarketDescriptors(row, ctx.market)
@@ -71014,6 +72403,107 @@ var curvanceAdapter = {
71014
72403
  function numOrUndef(v) {
71015
72404
  return typeof v === "number" && Number.isFinite(v) ? v : void 0;
71016
72405
  }
72406
+ var num16 = (v) => typeof v === "number" && Number.isFinite(v) ? v : void 0;
72407
+ var pct2 = (v) => `${(v * 100).toFixed(2)} %`;
72408
+ var twyneAdapter = {
72409
+ id: "twyne",
72410
+ matches: isTwyne,
72411
+ profileId: () => "twyne.credit-delegation@v1",
72412
+ build: (input) => {
72413
+ const tw = input.market?.twyne ?? {};
72414
+ const floorLtv = num16(tw.floorLtv);
72415
+ const maxLtv = num16(tw.maxLtv);
72416
+ const externalLiqLtv = num16(tw.externalLiqLtv);
72417
+ const creditApr = num16(tw.creditApr);
72418
+ const maturity = num16(tw.collateralMaturity);
72419
+ const matured = tw.collateralMatured === true;
72420
+ const creditAvailable = num16(tw.creditAvailable);
72421
+ const vaultType = typeof tw.vaultType === "string" ? tw.vaultType : void 0;
72422
+ const externalName = vaultType === "AAVE_V3" ? "Aave V3" : vaultType === "EULER_V2" ? "Euler V2" : "the external market";
72423
+ const creditExhausted = creditAvailable != null && creditAvailable <= 0;
72424
+ 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;
72425
+ return {
72426
+ constraints: {
72427
+ // The position is a CONTRACT the borrower deploys, and they may own
72428
+ // several per market — each with its own collateral, debt and LTV.
72429
+ positionModel: "sub-account",
72430
+ positionIdMeaning: "the address of the collateral vault you deployed \u2014 one contract per position, and you can own several in the same market",
72431
+ crossMargin: false
72432
+ },
72433
+ supply: {
72434
+ info: {
72435
+ 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."
72436
+ },
72437
+ // Credit-LPs are FIRST-LOSS for the fallback-liquidation gap. Neither
72438
+ // of these is left to default: `overcollateralized` would read as a
72439
+ // guarantee that does not exist here, and `protected: true` would say
72440
+ // the principal cannot be impaired, which is exactly what the delegation
72441
+ // risk is.
72442
+ counterparty: { solvency: "tranched-junior" },
72443
+ principal: { protected: false, risks: ["first-loss", "bad-debt"] },
72444
+ exit: {
72445
+ partialAllowed: true
72446
+ }
72447
+ },
72448
+ borrow: {
72449
+ debtShape: "accruing",
72450
+ info: {
72451
+ description: [
72452
+ `Your collateral stays in ${externalName}; Twyne only reserves other lenders\u2019 unused borrowing power so the same collateral supports a larger loan.`,
72453
+ bandNote,
72454
+ 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
72455
+ ].filter(Boolean).join(" ")
72456
+ },
72457
+ availability: {
72458
+ // A matured PT still services existing positions but must not take
72459
+ // new ones, and an exhausted credit vault cannot grant extra LTV.
72460
+ ...matured || creditExhausted ? { canOpen: false } : {},
72461
+ canClose: true
72462
+ },
72463
+ exit: {
72464
+ partialAllowed: true
72465
+ },
72466
+ liquidation: {
72467
+ // Neither 'pool' nor an auction: the liquidator inherits the position.
72468
+ model: "inheritance",
72469
+ trigger: "price",
72470
+ penalties: [
72471
+ {
72472
+ id: "twyne-inheritance",
72473
+ label: "Twyne liquidation (by inheritance)",
72474
+ value: 0,
72475
+ 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."
72476
+ },
72477
+ {
72478
+ id: "external-fallback",
72479
+ label: `${externalName} fallback liquidation`,
72480
+ value: 0,
72481
+ 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.`
72482
+ }
72483
+ ],
72484
+ ...externalLiqLtv != null ? {
72485
+ 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.`
72486
+ } : {}
72487
+ },
72488
+ // The collateral has a maturity even though the loan does not — a PT
72489
+ // stops accreting at expiry and the external threshold ramps out from
72490
+ // under it, so this is a date the borrower has to act on.
72491
+ ...maturity ? {
72492
+ maturity: {
72493
+ kind: "fixed-date",
72494
+ maturity,
72495
+ maturityIso: new Date(maturity * 1e3).toISOString(),
72496
+ ...matured ? {
72497
+ 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."
72498
+ } : {
72499
+ 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."
72500
+ }
72501
+ }
72502
+ } : {}
72503
+ }
72504
+ };
72505
+ }
72506
+ };
71017
72507
  var fraxlendAdapter = {
71018
72508
  id: "fraxlend",
71019
72509
  matches: isFraxlend,
@@ -71099,6 +72589,7 @@ var TERM_ADAPTERS = [
71099
72589
  frankencoinAdapter,
71100
72590
  resupplyAdapter,
71101
72591
  curvanceAdapter,
72592
+ twyneAdapter,
71102
72593
  fraxlendAdapter,
71103
72594
  morphoBlueAdapter
71104
72595
  ];
@@ -71298,8 +72789,8 @@ function enrichTermSheet(sheet, index) {
71298
72789
  if (!exp) continue;
71299
72790
  for (const item of exp.items) {
71300
72791
  const chain = item.asset.chainId;
71301
- const addr3 = item.asset.address;
71302
- const q = quality?.[chain]?.[addr3];
72792
+ const addr4 = item.asset.address;
72793
+ const q = quality?.[chain]?.[addr4];
71303
72794
  if (q) {
71304
72795
  item.quality = {
71305
72796
  riskScore: q.riskScore,
@@ -71541,8 +73032,6 @@ function validateTermSheet(sheet) {
71541
73032
  function validateTermSheets(sheets) {
71542
73033
  return sheets.flatMap((s) => validateTermSheet(s));
71543
73034
  }
71544
-
71545
- // src/earn/fromPool.ts
71546
73035
  var FIXED_TERM_PREFIXES = [
71547
73036
  "EXACTLY",
71548
73037
  "TELLER",
@@ -71581,10 +73070,40 @@ function venueGroupKey(chainId, venue) {
71581
73070
  return `${chainId}::${venue}`;
71582
73071
  }
71583
73072
  function resolveBasket(row) {
73073
+ const provider = listaCollateralProvider(
73074
+ row.chainId ?? "",
73075
+ str6(row.params?.market?.collateralProvider)
73076
+ );
73077
+ if (provider?.kind === "smart-lp" && provider.coins) {
73078
+ const rowAsset = addr3(row.underlying) ?? addr3(row.asset?.address);
73079
+ if (rowAsset && rowAsset === provider.collateralToken.toLowerCase()) {
73080
+ return {
73081
+ // The row's asset IS the receipt — one row for the whole position,
73082
+ // the opposite of Fluid's per-leg rows.
73083
+ rowAsset: "positionUnit",
73084
+ // `dex.coins(i)` order, NOT the collateral symbol's order:
73085
+ // "USDT & USDe-SmartLP" is [USDe, USDT].
73086
+ legs: provider.coins.map((c) => ({
73087
+ address: c.address.toLowerCase(),
73088
+ symbol: c.symbol,
73089
+ decimals: c.decimals
73090
+ })),
73091
+ autoBalanced: true,
73092
+ ...provider.dexLp ? {
73093
+ positionUnit: {
73094
+ kind: "lpToken",
73095
+ address: provider.dexLp.toLowerCase(),
73096
+ decimals: provider.collateralDecimals
73097
+ }
73098
+ } : {},
73099
+ pool: "lista-smartlp"
73100
+ };
73101
+ }
73102
+ }
71584
73103
  if (row.autoBalanced !== true) return void 0;
71585
73104
  const f = row.fluid;
71586
73105
  if (f && f.isSmartCol !== true) return void 0;
71587
- const legs = (f?.collateralPair ?? []).map((a) => addr2(a)).filter((a) => !!a).map((address) => ({ address }));
73106
+ const legs = (f?.collateralPair ?? []).map((a) => addr3(a)).filter((a) => !!a).map((address) => ({ address }));
71588
73107
  return {
71589
73108
  // Fluid emits one row PER LEG of the pool, so this row is a leg and a
71590
73109
  // consumer that sums the listing without deduping counts the position
@@ -71609,19 +73128,19 @@ function earnMarketFromPool(row, fallbackChainId, venueCollaterals) {
71609
73128
  if (!chainId || !venue) return void 0;
71610
73129
  const flags = row.flags ?? {};
71611
73130
  const assetInfo = row.underlyingInfo?.asset ?? row.asset ?? {};
71612
- const underlying = addr2(assetInfo.address) ?? addr2(row.underlying) ?? addr2(row.poolId);
73131
+ const underlying = addr3(assetInfo.address) ?? addr3(row.underlying) ?? addr3(row.poolId);
71613
73132
  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);
73133
+ const decimals = num13(assetInfo.decimals) ?? num13(row.decimals) ?? 18;
73134
+ const priceUsd = num13(row.underlyingInfo?.prices?.priceUsd) ?? num13(row.price);
73135
+ const base = num13(row.depositRate);
73136
+ const intrinsic = num13(row.intrinsicYield);
71618
73137
  const rewards = sumRewardAprs(row.rewards);
71619
73138
  const marketOwn = sum2(base, rewards);
71620
73139
  const rate = {
71621
73140
  // Prefer our own sum over the origin's `apr`, because `apr` is documented
71622
73141
  // as `depositRate + intrinsicYield` and therefore EXCLUDES incentives —
71623
73142
  // using it as the headline would under-report every incentivized market.
71624
- total: sum2(base, intrinsic, rewards) ?? num12(row.apr) ?? 0,
73143
+ total: sum2(base, intrinsic, rewards) ?? num13(row.apr) ?? 0,
71625
73144
  base,
71626
73145
  rewards,
71627
73146
  intrinsic,
@@ -71689,7 +73208,7 @@ function earnMarketFromPool(row, fallbackChainId, venueCollaterals) {
71689
73208
  row.totalLiquidityUSD ?? row.totalLiquidityUsd
71690
73209
  ),
71691
73210
  depositCapacity: void 0,
71692
- utilization: num12(row.utilization),
73211
+ utilization: num13(row.utilization),
71693
73212
  // Lending withdrawals are same-block, bounded by available liquidity —
71694
73213
  // which is exactly `instant-capped`, not `instant`. A pool at 100 %
71695
73214
  // utilization cannot be exited, and calling that `instant` is the kind of
@@ -71697,12 +73216,12 @@ function earnMarketFromPool(row, fallbackChainId, venueCollaterals) {
71697
73216
  exit: { mode: "instant-capped", settlement: "sync" },
71698
73217
  availability,
71699
73218
  risk: {
71700
- score: num12(row.risk?.score),
73219
+ score: num13(row.risk?.score),
71701
73220
  label: str6(row.risk?.label),
71702
73221
  illiquid: isIlliquid({
71703
73222
  exitMode: "instant-capped",
71704
- tvlUsd: num12(row.totalDepositsUSD ?? row.totalDepositsUsd),
71705
- liquidityUsd: num12(row.totalLiquidityUSD ?? row.totalLiquidityUsd)
73223
+ tvlUsd: num13(row.totalDepositsUSD ?? row.totalDepositsUsd),
73224
+ liquidityUsd: num13(row.totalLiquidityUSD ?? row.totalLiquidityUsd)
71706
73225
  })
71707
73226
  },
71708
73227
  ...basket ? { basket } : {},
@@ -71713,7 +73232,7 @@ function earnMarketFromPool(row, fallbackChainId, venueCollaterals) {
71713
73232
  // reads them — two markets on the same pair at the same LLTV differ by
71714
73233
  // nothing else, and one may price its collateral off a feed that ignores
71715
73234
  // a depeg in it.
71716
- oracle: addr2(row.oracleInfo?.feeds?.find((f) => f?.oracle)?.oracle),
73235
+ oracle: addr3(row.oracleInfo?.feeds?.find((f) => f?.oracle)?.oracle),
71717
73236
  oracleDescription: str6(
71718
73237
  row.oracleInfo?.feeds?.find((f) => f?.priceDescription)?.priceDescription
71719
73238
  ),
@@ -71766,9 +73285,9 @@ function resolveAvailability2(row, flags, totalRate) {
71766
73285
  };
71767
73286
  }
71768
73287
  function isSupplyCapFull(row) {
71769
- const cap = num12(row.caps?.supplyCap) ?? num12(row.supplyCap);
73288
+ const cap = num13(row.caps?.supplyCap) ?? num13(row.supplyCap);
71770
73289
  if (cap === void 0 || cap <= 0) return false;
71771
- const deposits = num12(row.totalDeposits);
73290
+ const deposits = num13(row.totalDeposits);
71772
73291
  if (deposits === void 0) return false;
71773
73292
  return deposits >= cap;
71774
73293
  }
@@ -71777,7 +73296,7 @@ function sumRewardAprs(rewards) {
71777
73296
  let total = 0;
71778
73297
  let seen = false;
71779
73298
  for (const r of rewards) {
71780
- const apr = num12(r?.depositRate);
73299
+ const apr = num13(r?.depositRate);
71781
73300
  if (apr === void 0) continue;
71782
73301
  total += apr;
71783
73302
  seen = true;
@@ -71785,7 +73304,7 @@ function sumRewardAprs(rewards) {
71785
73304
  return seen ? total : void 0;
71786
73305
  }
71787
73306
  function amount2(formatted, usd) {
71788
- return { formatted: num12(formatted), usd: num12(usd) };
73307
+ return { formatted: num13(formatted), usd: num13(usd) };
71789
73308
  }
71790
73309
  function sum2(...parts) {
71791
73310
  const present = parts.filter((p) => p !== void 0);
@@ -71818,7 +73337,7 @@ function lendingCapabilities(row) {
71818
73337
  }
71819
73338
  return caps;
71820
73339
  }
71821
- var SWAP_ROUTED_PROVIDERS = /* @__PURE__ */ new Set(["pendle"]);
73340
+ var SWAP_ROUTED_PROVIDERS = /* @__PURE__ */ new Set(["pendle", "spectra"]);
71822
73341
  function swapRoutedCapabilities(row) {
71823
73342
  const caps = [];
71824
73343
  if (row.availability.canDeposit) {
@@ -71868,7 +73387,7 @@ function vaultCapabilities(row) {
71868
73387
  caps.push({
71869
73388
  action: "withdraw",
71870
73389
  requires: withdrawRequires(provider),
71871
- feeBps: num12(meta.withdrawFeeBps) ?? row.exit.feeBps
73390
+ feeBps: num13(meta.withdrawFeeBps) ?? row.exit.feeBps
71872
73391
  });
71873
73392
  }
71874
73393
  caps.push({
@@ -71977,7 +73496,7 @@ function legEarnUid(marketUid) {
71977
73496
  if (isVaultVenue(parts[0])) return void 0;
71978
73497
  return marketUid;
71979
73498
  }
71980
- function num15(v) {
73499
+ function num17(v) {
71981
73500
  const n = typeof v === "number" ? v : Number(v);
71982
73501
  return Number.isFinite(n) ? n : 0;
71983
73502
  }
@@ -71999,10 +73518,10 @@ function legAsset(pos) {
71999
73518
  };
72000
73519
  }
72001
73520
  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;
73521
+ const depositsUsd = num17(pos.depositsUSD);
73522
+ const debtUsd = num17(pos.debtUSD) + num17(pos.debtStableUSD);
73523
+ const hasSupply = depositsUsd !== 0 || num17(pos.deposits) !== 0;
73524
+ const hasDebt = debtUsd !== 0 || num17(pos.debt) !== 0 || num17(pos.debtStable) !== 0;
72006
73525
  return {
72007
73526
  earnUid: legEarnUid(pos.marketUid),
72008
73527
  marketUid: pos.marketUid,
@@ -72042,12 +73561,12 @@ function earnPositionFromLenderEntry(entry) {
72042
73561
  (s) => s.legs.some((l) => l.side !== "none") || s.netUsd !== 0
72043
73562
  );
72044
73563
  const crossMargin = active.length <= 1;
72045
- const suppliedUsd = num15(entry.balanceData?.deposits);
72046
- const borrowedUsd = num15(entry.balanceData?.debt);
73564
+ const suppliedUsd = num17(entry.balanceData?.deposits);
73565
+ const borrowedUsd = num17(entry.balanceData?.debt);
72047
73566
  const aprBreakdown = {
72048
- market: num15(entry.aprData?.apr),
72049
- rewards: num15(entry.aprData?.rewardApr),
72050
- intrinsic: num15(entry.aprData?.intrinsicApr)
73567
+ market: num17(entry.aprData?.apr),
73568
+ rewards: num17(entry.aprData?.rewardApr),
73569
+ intrinsic: num17(entry.aprData?.intrinsicApr)
72051
73570
  };
72052
73571
  return {
72053
73572
  positionUid: buildLendingPositionUid(entry.lender, entry.chainId),
@@ -72061,15 +73580,15 @@ function earnPositionFromLenderEntry(entry) {
72061
73580
  ...entry.lenderInfo?.logoUri ? { logoURI: entry.lenderInfo.logoUri } : {},
72062
73581
  suppliedUsd,
72063
73582
  borrowedUsd,
72064
- netUsd: num15(entry.balanceData?.nav),
73583
+ netUsd: num17(entry.balanceData?.nav),
72065
73584
  apr: aprBreakdown.market + aprBreakdown.rewards + aprBreakdown.intrinsic,
72066
73585
  aprBreakdown,
72067
- depositApr: num15(entry.aprData?.depositApr),
72068
- borrowApr: num15(entry.aprData?.borrowApr),
73586
+ depositApr: num17(entry.aprData?.depositApr),
73587
+ borrowApr: num17(entry.aprData?.borrowApr),
72069
73588
  // Only a cross-margin account HAS one health factor. Publishing the first
72070
73589
  // sub-account's as the row's would be a number about a different position.
72071
73590
  health: crossMargin ? active[0]?.health ?? null : null,
72072
- leverage: num15(entry.leverage),
73591
+ leverage: num17(entry.leverage),
72073
73592
  crossMargin,
72074
73593
  legs: subAccounts.flatMap((s) => s.legs),
72075
73594
  subAccounts: active,
@@ -72151,6 +73670,6 @@ function earnPositionTotals(items) {
72151
73670
  };
72152
73671
  }
72153
73672
 
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 };
73673
+ 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
73674
  //# sourceMappingURL=index.js.map
72156
73675
  //# sourceMappingURL=index.js.map