@1delta/margin-fetcher 0.0.410 → 0.0.412

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,12 +1,12 @@
1
- import { parseAbi, keccak256, encodeAbiParameters, formatEther, BaseError, stringToHex, erc20Abi, pad, encodeFunctionData, formatUnits, isAddress, getAddress, decodeFunctionResult, decodeAbiParameters, concat, AbiEncodingLengthMismatchError, concatHex, toBytes, slice, hexToString, InvalidAddressError, boolToHex, integerRegex, numberToHex, bytesRegex, BytesSizeMismatchError, arrayRegex, UnsupportedPackedAbiType } from './chunk-YILYOOYB.js';
1
+ import { parseAbi, keccak256, encodeAbiParameters, formatEther, BaseError, erc20Abi, stringToHex, pad, encodeFunctionData, formatUnits, isAddress, 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, LIQUITY_FAMILY_LENDERS, isAaveType, isCompoundV3, isMultiMarket, isSiloV2Type, isSiloV3Type, isDolomite, isMidnight, isTerm, isExactly, isLiquityFamily, isRiver, isTeller, isInverse, isTermMax, isUsdd, isEulerType, isAaveV4Type, isInit, isMorphoType, isCompoundV2Type, isVenusType, isSumerType, AAVE_V3_LENDERS, AAVE_V2_LENDERS, isAaveV2Type, isAaveV32Type, isAaveV3Type, isFluid, isGearboxV3, isYLDR, isCompoundV3Type, isLista, isTectonicType, isKineticType, isBenqiType } from '@1delta/lender-registry';
4
+ import { Lender, LIQUITY_FAMILY_LENDERS, isAaveType, isCompoundV3, isMultiMarket, isSiloV2Type, isSiloV3Type, isDolomite, isMidnight, isTerm, isExactly, isLiquityFamily, isRiver, isTeller, isInverse, isTermMax, isResupply, isUsdd, isFrankencoin, isLlamaLend, isEulerType, isAaveV4Type, isInit, isMorphoType, isCompoundV2Type, isVenusType, isSumerType, AAVE_V3_LENDERS, AAVE_V2_LENDERS, isAaveV2Type, isAaveV32Type, isAaveV3Type, isFluid, isGearboxV3, isYLDR, isCompoundV3Type, isLista, isTectonicType, isKineticType, isBenqiType } from '@1delta/lender-registry';
5
5
  export { isAaveType, isAaveV2Type, isAaveV32Type, isAaveV3Type, isCompoundV3, isCompoundV3Type, isInit, isMorphoType, isMultiMarket, isYLDR } from '@1delta/lender-registry';
6
- import { fetchTokenLists, fetchTokenList, aavePools, compoundV3Pools, initConfig, morphoPools, compoundV2Pools, eulerVaults, siloMarkets, siloV2LenderKey, siloMarketsV3, siloV3LenderKey, aaveV4Spokes, aaveV4SpokeLenderKey, fluidResolvers, gearboxResolvers, dolomiteConfigs, midnightConfig, termConfig, termMarketsByChain, exactlyConfig, liquityLendersByChain, riverLendersByChain, inverseLendersByChain, usddLendersByChain, tellerConfigByChain, tellerPoolsByChain, termMaxConfigByChain, aaveReserves, compoundV3Reserves, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, termMaxApiBaseUrl, termMaxLenderKey, inverseConfigFor, inverseChainData, usddConfigFor, usddChainData, aaveOracles, morphoTypeMarkets, resolveMidnightApiBase, resolveTermApiBase, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, aaveTokens, morphoTypeVaults, eulerConfigs, gearboxMarketCompressor, gearboxMarketConfigurators, gearboxV3LenderKey, midnightMarketsByChain, parseAaveV4SpokeLenderKey, gearboxAccountCompressor, compoundV2Tokens, exactlyMarketsByChain, aaveOraclesConfig, compoundV2Oracles, compoundV2TokenArray, compoundV2OraclesConfig, compoundV3OraclesData, compoundV3BaseData, compoundV2Reserves, aaveV4Oracles } from '@1delta/data-sdk';
6
+ import { fetchTokenLists, fetchTokenList, aavePools, compoundV3Pools, initConfig, morphoPools, compoundV2Pools, eulerVaults, siloMarkets, siloV2LenderKey, siloMarketsV3, siloV3LenderKey, aaveV4Spokes, aaveV4SpokeLenderKey, fluidResolvers, gearboxResolvers, dolomiteConfigs, midnightConfig, termConfig, termMarketsByChain, exactlyConfig, liquityLendersByChain, riverLendersByChain, inverseLendersByChain, llamaLendLendersByChain, usddLendersByChain, frankencoinLendersByChain, resupplyLendersByChain, tellerConfigByChain, tellerPoolsByChain, termMaxConfigByChain, aaveReserves, compoundV3Reserves, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, termMaxApiBaseUrl, termMaxLenderKey, inverseConfigFor, inverseChainData, llamaLendConfigFor, llamaLendChainData, llamaLendApiBaseUrl, resupplyConfigFor, usddConfigFor, usddChainData, frankencoinConfigFor, frankencoinChainData, aaveOracles, morphoTypeMarkets, resolveMidnightApiBase, resolveTermApiBase, llamaLendMarketByVault, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, aaveTokens, morphoTypeVaults, eulerConfigs, gearboxMarketCompressor, gearboxMarketConfigurators, gearboxV3LenderKey, midnightMarketsByChain, parseAaveV4SpokeLenderKey, gearboxAccountCompressor, compoundV2Tokens, exactlyMarketsByChain, aaveOraclesConfig, compoundV2Oracles, compoundV2TokenArray, compoundV2OraclesConfig, compoundV3OraclesData, compoundV3BaseData, compoundV2Reserves, aaveV4Oracles } from '@1delta/data-sdk';
7
7
  import lodash from 'lodash';
8
8
  import { multicallRetryUniversal, getEvmClient, getEvmChain, getEvmClientUniversal } from '@1delta/providers';
9
- import { LiquityTroveManagerAbi, LiquityActivePoolAbi, LiquityStabilityPoolAbi, LiquityPriceFeedAbi, LiquitySortedTrovesAbi, RiverTroveManagerAbi, RiverStabilityPoolAbi, TellerMarketRegistryAbi, TellerV2Abi, InverseMarketAbi, InverseOracleAbi, InverseDbrAbi, Erc20Abi, MetaMorphoAbi, ExactlyPreviewerAbi, ExactlyAuditorAbi, LenderCommitmentGroupAbi, UsddVatAbi, UsddJugAbi, UsddSpotAbi, FluidLendingResolverAbi, FluidVaultResolverAbi, FluidLiquidityResolverAbi, MoolahVaultAbi, MorphoLensAbi, AaveV4SpokeAbi, AaveV4OracleAbi, AaveV4HubAbi, DolomiteMarginAbi, GearboxMarketCompressorV310Abi, MorphoBlueAbi, MidnightAbi, TermRepoTokenAbi, TermRepoServicerAbi, TermRepoCollateralManagerAbi, LiquityTroveNFTAbi, LiquityCollSurplusPoolAbi, TellerCollateralManagerAbi, InverseEscrowAbi, GearboxCreditAccountCompressorV310Abi, UsddCdpManagerAbi, UsddProxyRegistryAbi, TermPriceConsumerAbi, TermMaxOracleAggregatorV2Abi } from '@1delta/abis';
9
+ import { LiquityTroveManagerAbi, LiquityActivePoolAbi, LiquityStabilityPoolAbi, LiquityPriceFeedAbi, LiquitySortedTrovesAbi, RiverTroveManagerAbi, RiverStabilityPoolAbi, TellerMarketRegistryAbi, TellerV2Abi, InverseMarketAbi, InverseOracleAbi, InverseDbrAbi, Erc20Abi, LlamaLendControllerAbi, LlamaLendControllerV1Abi, LlamaLendControllerV2Abi, LlamaLendVaultAbi, LlamaLendAmmAbi, MetaMorphoAbi, ExactlyPreviewerAbi, ExactlyAuditorAbi, LenderCommitmentGroupAbi, ResupplyRegistryAbi, ResupplyPairAbi, UsddVatAbi, UsddJugAbi, UsddSpotAbi, FrankencoinPositionAbi, FluidLendingResolverAbi, FluidVaultResolverAbi, FluidLiquidityResolverAbi, MoolahVaultAbi, ResupplyUtilitiesAbi, MorphoLensAbi, AaveV4SpokeAbi, AaveV4OracleAbi, AaveV4HubAbi, DolomiteMarginAbi, GearboxMarketCompressorV310Abi, MorphoBlueAbi, MidnightAbi, TermRepoTokenAbi, TermRepoServicerAbi, TermRepoCollateralManagerAbi, LiquityTroveNFTAbi, LiquityCollSurplusPoolAbi, TellerCollateralManagerAbi, TermMaxViewerAbi, InverseEscrowAbi, GearboxCreditAccountCompressorV310Abi, UsddCdpManagerAbi, UsddProxyRegistryAbi, TermPriceConsumerAbi, TermMaxOracleAggregatorV2Abi } from '@1delta/abis';
10
10
  export { MorphoLensAbi } from '@1delta/abis';
11
11
  import { prepareDebitDataMulticall, prepareLenderDebitMulticall, parseDebitDataResult, parseLenderDebitResult, getPermit2ContractAddress, getCompoundV3CometAddress as getCompoundV3CometAddress$1, getMorphoAddress, getAaveCollateralTokenAddress, getSiloHalfForUnderlying, InitMarginAddresses, getLstAcceptedInputs } from '@1delta/calldata-sdk';
12
12
  import { proxyNativeFetch } from '@1delta/proxy-fetch';
@@ -7519,9 +7519,18 @@ var getLendersForChain = (c) => {
7519
7519
  for (const l of inverseLendersByChain(c)) {
7520
7520
  lenders.push(l);
7521
7521
  }
7522
+ for (const l of llamaLendLendersByChain(c)) {
7523
+ lenders.push(l);
7524
+ }
7522
7525
  for (const l of usddLendersByChain(c)) {
7523
7526
  lenders.push(l);
7524
7527
  }
7528
+ for (const l of frankencoinLendersByChain(c)) {
7529
+ lenders.push(l);
7530
+ }
7531
+ for (const l of resupplyLendersByChain(c)) {
7532
+ lenders.push(l);
7533
+ }
7525
7534
  if (tellerConfigByChain(c)?.tellerV2 && tellerPoolsByChain(c).length > 0) {
7526
7535
  lenders.push(Lender.TELLER);
7527
7536
  }
@@ -7543,7 +7552,7 @@ var filterLendersByProtocol = (allLenders, protocolList) => {
7543
7552
  (b) => protocolList.includes(b)
7544
7553
  );
7545
7554
  return allLenders.filter(
7546
- (lender) => protocolList.includes(lender) || hasMorpho && lender?.startsWith("MORPHO_BLUE") || hasMoolah && lender?.startsWith("LISTA_DAO") || hasFluid && lender?.startsWith("FLUID") || hasGearboxV3 && lender?.startsWith("GEARBOX_V3") || hasDolomite && lender?.startsWith("DOLOMITE") || liquityBases.some((b) => lender?.startsWith(b)) || protocolList.includes(Lender.RIVER) && lender?.startsWith("RIVER") || protocolList.includes(Lender.TELLER) && lender?.startsWith("TELLER") || protocolList.includes(Lender.USDD) && lender?.startsWith("USDD")
7555
+ (lender) => protocolList.includes(lender) || hasMorpho && lender?.startsWith("MORPHO_BLUE") || hasMoolah && lender?.startsWith("LISTA_DAO") || hasFluid && lender?.startsWith("FLUID") || hasGearboxV3 && lender?.startsWith("GEARBOX_V3") || hasDolomite && lender?.startsWith("DOLOMITE") || liquityBases.some((b) => lender?.startsWith(b)) || protocolList.includes(Lender.RIVER) && lender?.startsWith("RIVER") || protocolList.includes(Lender.TELLER) && lender?.startsWith("TELLER") || protocolList.includes(Lender.USDD) && lender?.startsWith("USDD") || protocolList.includes(Lender.FRANKENCOIN) && lender?.startsWith("FRANKENCOIN")
7547
7556
  );
7548
7557
  };
7549
7558
  var getAavesForChain = () => {
@@ -11208,8 +11217,8 @@ async function fetchListaBrokerUserData(chainId, account, marketKeys, nowSecs =
11208
11217
  const brokers = await resolveListaBrokers(chainId, marketKeys, getClient);
11209
11218
  const ids = Object.keys(brokers);
11210
11219
  const out = {};
11211
- const cacheKey6 = `${chainId}:${account.toLowerCase()}`;
11212
- BROKER_USER_CACHE[cacheKey6] = out;
11220
+ const cacheKey7 = `${chainId}:${account.toLowerCase()}`;
11221
+ BROKER_USER_CACHE[cacheKey7] = out;
11213
11222
  if (ids.length === 0) return out;
11214
11223
  try {
11215
11224
  const client = getClient(chainId);
@@ -22127,15 +22136,7 @@ function exactlyPairLtv(collateralAdjustFactor, borrowAdjustFactor) {
22127
22136
 
22128
22137
  // src/lending/public-data/exactly/convertPublic.ts
22129
22138
  var nowSec3 = () => Math.floor(Date.now() / 1e3);
22130
- function exactlyLenderKey(market) {
22131
- const body = market.startsWith("0x") ? market.slice(2) : market;
22132
- return "EXACTLY_" + body.toUpperCase();
22133
- }
22134
- function exactlyMarketFromLenderKey(lender) {
22135
- if (!lender.startsWith("EXACTLY_")) return void 0;
22136
- const body = lender.slice("EXACTLY_".length);
22137
- return body.length === 40 ? "0x" + body.toLowerCase() : void 0;
22138
- }
22139
+ var EXACTLY_LENDER_KEY = "EXACTLY";
22139
22140
  function toHuman(raw, decimals) {
22140
22141
  return Number(raw) / 10 ** decimals;
22141
22142
  }
@@ -22151,9 +22152,12 @@ function convertExactlyMarketsToResponse(raw, chainId, prices = {}, _additionalY
22151
22152
  const out = {};
22152
22153
  const now = nowSec3();
22153
22154
  const markets = raw?.markets ?? [];
22155
+ if (markets.length === 0) return out;
22154
22156
  const liqBonus = raw?.liquidationIncentive ? Number(raw.liquidationIncentive.liquidator) / 1e18 : 0;
22157
+ const lenderKey = EXACTLY_LENDER_KEY;
22158
+ const entry = { data: {} };
22159
+ const penaltyAprs = [];
22155
22160
  for (const m of markets) {
22156
- const lenderKey = exactlyLenderKey(m.market);
22157
22161
  const assetAddr = m.asset.toLowerCase();
22158
22162
  const decimals = m.decimals;
22159
22163
  const asset = tokens[assetAddr];
@@ -22185,9 +22189,10 @@ function convertExactlyMarketsToResponse(raw, chainId, prices = {}, _additionalY
22185
22189
  const totalDebt = toHuman(m.totalFloatingBorrowAssets, decimals) + fixedBorrowed;
22186
22190
  const borrowLiquidity = toHuman(m.floatingAvailableAssets, decimals);
22187
22191
  const utilization = totalDeposits > 0 ? totalDebt / totalDeposits : 0;
22188
- const selfLtv = exactlyPairLtv(m.adjustFactor, m.adjustFactor);
22192
+ const adjustFactor = Number(m.adjustFactor) / 1e18;
22193
+ const borrowFactor = adjustFactor > 0 ? 1 / adjustFactor : 1;
22189
22194
  const penaltyApr = exactlyPenaltyRateToAprPercent(m.penaltyRate);
22190
- const entry = { data: {} };
22195
+ penaltyAprs.push(penaltyApr);
22191
22196
  const loanUid = createMarketUid(chainId, lenderKey, assetAddr);
22192
22197
  entry.data[loanUid] = {
22193
22198
  marketUid: loanUid,
@@ -22215,17 +22220,28 @@ function convertExactlyMarketsToResponse(raw, chainId, prices = {}, _additionalY
22215
22220
  variableBorrowRate: exactlyWadRateToPercent(m.floatingBorrowRate),
22216
22221
  rateModel: "fixedTerm",
22217
22222
  // Fixed-rate lender convention (Term/Lista): best fixed borrow APR on the
22218
- // stable slot; the full per-maturity menu is params.market.terms.
22223
+ // stable slot; the full per-maturity menu is this entry's `terms`.
22219
22224
  stableBorrowRate: bestFixedBorrowApr,
22225
+ // PER-ASSET fixed-term menu + descriptor. Cross-margin means one lender
22226
+ // key spans every asset, and each asset has its OWN fixed pools — so
22227
+ // these cannot live on `params.market` (which assumes one borrowable
22228
+ // asset per key, true for every isolated fixed-term lender but not here).
22229
+ terms: terms.length > 0 ? terms : void 0,
22230
+ fixedTerm: {
22231
+ model: "exactly",
22232
+ fees: { latePenaltyApr: penaltyApr },
22233
+ earlyRepay: { kind: "discount" },
22234
+ provider: { kind: "pool", address: m.market.toLowerCase() }
22235
+ },
22220
22236
  intrinsicYield: 0,
22221
22237
  rewards: void 0,
22222
22238
  decimals,
22223
22239
  config: {
22224
22240
  0: {
22225
22241
  category: 0,
22226
- borrowCollateralFactor: selfLtv,
22227
- collateralFactor: selfLtv,
22228
- borrowFactor: 1,
22242
+ borrowCollateralFactor: adjustFactor,
22243
+ collateralFactor: adjustFactor,
22244
+ borrowFactor,
22229
22245
  liquidationPenalty: liqBonus,
22230
22246
  closeFactor: 1,
22231
22247
  collateralDisabled: false,
@@ -22240,93 +22256,50 @@ function convertExactlyMarketsToResponse(raw, chainId, prices = {}, _additionalY
22240
22256
  // Exactly DOES have a variable (floating) borrow side.
22241
22257
  variableBorrowDisabled: false,
22242
22258
  isActive: true,
22243
- isFrozen: false
22244
- };
22245
- for (const c of markets) {
22246
- if (c.market.toLowerCase() === m.market.toLowerCase()) continue;
22247
- const collAddr = c.asset.toLowerCase();
22248
- const ltv = exactlyPairLtv(c.adjustFactor, m.adjustFactor);
22249
- const collUid = createMarketUid(chainId, lenderKey, collAddr);
22250
- entry.data[collUid] = {
22251
- marketUid: collUid,
22252
- name: "Collateral " + c.assetSymbol,
22253
- poolId: c.market.toLowerCase(),
22254
- underlying: collAddr,
22255
- asset: currencyFor3(collAddr, c.decimals, c.assetSymbol, tokens),
22256
- totalDeposits: 0,
22257
- totalDebtStable: 0,
22258
- totalDebt: 0,
22259
- totalLiquidity: 0,
22260
- borrowLiquidity: 0,
22261
- totalLiquidityUSD: 0,
22262
- borrowLiquidityUSD: 0,
22263
- totalDepositsUSD: 0,
22264
- totalDebtStableUSD: 0,
22265
- totalDebtUSD: 0,
22266
- utilization: 0,
22267
- depositRate: 0,
22268
- variableBorrowRate: 0,
22269
- stableBorrowRate: 0,
22270
- intrinsicYield: 0,
22271
- rewards: void 0,
22272
- decimals: c.decimals,
22273
- config: {
22274
- 0: {
22275
- category: 0,
22276
- borrowCollateralFactor: ltv,
22277
- collateralFactor: ltv,
22278
- borrowFactor: 1,
22279
- liquidationPenalty: liqBonus,
22280
- closeFactor: 1,
22281
- collateralDisabled: false,
22282
- debtDisabled: true
22283
- }
22284
- },
22285
- closeFactor: 1,
22286
- collateralActive: true,
22287
- borrowingEnabled: false,
22288
- depositsEnabled: true,
22289
- hasStable: false,
22290
- isActive: true,
22291
- isFrozen: false
22292
- };
22293
- }
22294
- entry.params = {
22295
- market: {
22296
- lender: lenderKey,
22297
- name: "Exactly " + m.assetSymbol,
22298
- loanDecimals: decimals,
22299
- collateralDecimals: decimals,
22300
- // Market address doubles as the market id (it IS the lender-key body).
22301
- id: m.market.toLowerCase(),
22302
- // Self-pair adjust factor (WAD string); pairwise LTVs live on the
22303
- // per-collateral entries above.
22304
- lltv: m.adjustFactor.toString(),
22305
- oracle: zeroAddress,
22306
- irm: zeroAddress,
22307
- collateralAddress: assetAddr,
22308
- loanAddress: assetAddr,
22309
- terms: terms.length > 0 ? terms : void 0,
22310
- // Canonical cross-protocol fixed-term descriptor. Exactly: MENU of
22311
- // calendar maturities (terms[], termId = maturity), pool-fronted
22312
- // utilization-curve rates, early repay = DISCOUNT (unassigned-earnings
22313
- // rebate via previewRepayAtMaturity), late repay = per-second penalty.
22314
- fixedTerm: {
22315
- model: "exactly",
22316
- fees: { latePenaltyApr: penaltyApr },
22317
- earlyRepay: { kind: "discount" },
22318
- provider: { kind: "pool", address: m.market.toLowerCase() }
22319
- },
22320
- // Exactly-specific extras (consumed by calldata / worker-api resolvers)
22259
+ isFrozen: false,
22260
+ // Per-asset Exactly extras. `poolId` above already carries the Market
22261
+ // address (the write target resolve it from the ASSET now, via
22262
+ // `exactlyMarketByAsset`, never from the lender key).
22263
+ exactly: {
22264
+ market: m.market.toLowerCase(),
22321
22265
  penaltyRate: m.penaltyRate.toString(),
22322
22266
  adjustFactor: m.adjustFactor.toString(),
22323
22267
  maxFuturePools: m.maxFuturePools,
22324
22268
  usdPrice: m.usdPrice.toString()
22325
22269
  }
22326
22270
  };
22327
- entry.chainId = chainId;
22328
- out[lenderKey] = entry;
22329
22271
  }
22272
+ const uniformPenaltyApr = penaltyAprs.length > 0 && penaltyAprs.every((p) => p === penaltyAprs[0]) ? penaltyAprs[0] : void 0;
22273
+ entry.params = {
22274
+ market: {
22275
+ lender: lenderKey,
22276
+ name: "Exactly",
22277
+ // The per-chain Auditor — the shared cross-margin risk module every
22278
+ // Market reports to (Compound V2's Comptroller seam).
22279
+ id: (exactlyConfig()?.[chainId]?.auditor ?? zeroAddress).toLowerCase(),
22280
+ // No market-level LLTV: risk is per-asset (collateralFactor/borrowFactor
22281
+ // on each entry) and effective pair LTV is their product.
22282
+ lltv: "0",
22283
+ oracle: zeroAddress,
22284
+ irm: zeroAddress,
22285
+ collateralAddress: zeroAddress,
22286
+ loanAddress: zeroAddress,
22287
+ // `terms` is deliberately ABSENT at market level — each asset has its own
22288
+ // fixed pools, so the menu is on `data[*].terms`. A market-level
22289
+ // descriptor is still emitted so consumers that only probe
22290
+ // `params.market.fixedTerm` still recognise Exactly as fixed-term; its
22291
+ // `provider.address` is omitted (no single Market) and the late-penalty
22292
+ // rate is carried only when every asset agrees (it does today).
22293
+ fixedTerm: {
22294
+ model: "exactly",
22295
+ fees: uniformPenaltyApr !== void 0 ? { latePenaltyApr: uniformPenaltyApr } : {},
22296
+ earlyRepay: { kind: "discount" },
22297
+ provider: { kind: "pool" }
22298
+ }
22299
+ }
22300
+ };
22301
+ entry.chainId = chainId;
22302
+ out[lenderKey] = entry;
22330
22303
  return out;
22331
22304
  }
22332
22305
  var READS_PER_BRANCH = 8;
@@ -22918,7 +22891,7 @@ async function fetchTellerMarkets(chainId) {
22918
22891
  } catch {
22919
22892
  return { chainId, pools: [] };
22920
22893
  }
22921
- const big9 = (i) => {
22894
+ const big13 = (i) => {
22922
22895
  const r = results[i];
22923
22896
  if (typeof r === "bigint") return r;
22924
22897
  if (typeof r === "number") return BigInt(r);
@@ -22931,21 +22904,21 @@ async function fetchTellerMarkets(chainId) {
22931
22904
  }
22932
22905
  return null;
22933
22906
  };
22934
- const num9 = (i) => {
22935
- const b = big9(i);
22907
+ const num10 = (i) => {
22908
+ const b = big13(i);
22936
22909
  return b === null ? null : Number(b);
22937
22910
  };
22938
22911
  const pool0 = pools.map((config, i) => {
22939
22912
  const base = i * READS_PER_POOL;
22940
22913
  return {
22941
22914
  config,
22942
- available: big9(base),
22943
- committed: big9(base + 1),
22944
- minRateBps: num9(base + 2),
22945
- collateralPerPrincipal: big9(base + 3),
22946
- maxLoanDuration: num9(base + 4),
22947
- marketId: big9(base + 5),
22948
- totalAssets: big9(base + 6)
22915
+ available: big13(base),
22916
+ committed: big13(base + 1),
22917
+ minRateBps: num10(base + 2),
22918
+ collateralPerPrincipal: big13(base + 3),
22919
+ maxLoanDuration: num10(base + 4),
22920
+ marketId: big13(base + 5),
22921
+ totalAssets: big13(base + 6)
22949
22922
  };
22950
22923
  });
22951
22924
  const attByMarket = /* @__PURE__ */ new Map();
@@ -23863,7 +23836,7 @@ var INVERSE_PUBLIC_READ_ABI = [
23863
23836
  ...InverseDbrAbi,
23864
23837
  ...Erc20Abi
23865
23838
  ];
23866
- var READS_PER_MARKET2 = 4;
23839
+ var READS_PER_MARKET2 = 5;
23867
23840
  var fetchJson = async (url, timeoutMs = 6e3) => {
23868
23841
  const res = await fetch(url, {
23869
23842
  headers: { accept: "application/json" },
@@ -23906,15 +23879,24 @@ async function fetchInverseMarkets(lender, chainId) {
23906
23879
  if (Object.keys(byAddr).length > 0) {
23907
23880
  const rows = markets.map((market) => {
23908
23881
  const m = byAddr[market.address.toLowerCase()];
23909
- const num9 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
23882
+ const num10 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
23910
23883
  return {
23911
23884
  market,
23912
- totalDebt: num9(m?.totalDebt),
23913
- dolaLiquidity: num9(m?.dolaLiquidity),
23914
- leftToBorrow: num9(m?.leftToBorrow),
23915
- price: num9(m?.price),
23885
+ totalDebt: num10(m?.totalDebt),
23886
+ dolaLiquidity: num10(m?.dolaLiquidity),
23887
+ leftToBorrow: num10(m?.leftToBorrow),
23888
+ price: num10(m?.price),
23916
23889
  borrowPaused: typeof m?.borrowPaused === "boolean" ? m.borrowPaused : null,
23917
- dailyBorrows: num9(m?.dailyBorrows)
23890
+ dailyBorrows: num10(m?.dailyBorrows),
23891
+ // The API serves it as a DECIMAL (`replenishmentIncentive: 0.1`),
23892
+ // unlike the on-chain bps — normalize here, and fall back to the
23893
+ // curated metadata value when the field is missing.
23894
+ replenishmentIncentiveBps: (() => {
23895
+ const dec = num10(m?.replenishmentIncentive);
23896
+ if (dec !== null) return Math.round(dec * 1e4);
23897
+ const meta = Number(market.replenishmentIncentiveBps);
23898
+ return Number.isFinite(meta) ? meta : null;
23899
+ })()
23918
23900
  };
23919
23901
  });
23920
23902
  return {
@@ -23939,7 +23921,8 @@ async function fetchInverseMarkets(lender, chainId) {
23939
23921
  address: config.oracle,
23940
23922
  name: "viewPrice",
23941
23923
  params: [m.collToken, BigInt(m.collateralFactorBps)]
23942
- }
23924
+ },
23925
+ { address: m.address, name: "replenishmentIncentiveBps", params: [] }
23943
23926
  ])
23944
23927
  ];
23945
23928
  try {
@@ -23962,6 +23945,7 @@ async function fetchInverseMarkets(lender, chainId) {
23962
23945
  const paused = results[base + 1];
23963
23946
  const liq = bigAt(base + 2);
23964
23947
  const price2 = bigAt(base + 3);
23948
+ const replenishIncentive = bigAt(base + 4);
23965
23949
  return {
23966
23950
  market,
23967
23951
  totalDebt: totalDebt !== null ? Number(totalDebt) / 10 ** debtDecimals : null,
@@ -23973,7 +23957,11 @@ async function fetchInverseMarkets(lender, chainId) {
23973
23957
  // 10^(36 − collDecimals) per unit — normalize to USD per token.
23974
23958
  price: price2 !== null ? Number(price2) / 10 ** (36 - market.collDecimals) : null,
23975
23959
  borrowPaused: typeof paused === "boolean" ? paused : null,
23976
- dailyBorrows: null
23960
+ dailyBorrows: null,
23961
+ replenishmentIncentiveBps: replenishIncentive !== null ? Number(replenishIncentive) : (() => {
23962
+ const meta = Number(market.replenishmentIncentiveBps);
23963
+ return Number.isFinite(meta) ? meta : null;
23964
+ })()
23977
23965
  };
23978
23966
  });
23979
23967
  return {
@@ -23993,6 +23981,454 @@ function num(api, key) {
23993
23981
  const v = api?.[key];
23994
23982
  return typeof v === "number" && Number.isFinite(v) ? v : null;
23995
23983
  }
23984
+ var BANDS_ENDPOINTS = [4, 10, 20, 50];
23985
+ var DEFAULT_BANDS = 10;
23986
+ var LLAMALEND_READ_ABI = [
23987
+ ...LlamaLendControllerAbi,
23988
+ ...LlamaLendControllerV1Abi,
23989
+ ...LlamaLendControllerV2Abi,
23990
+ ...LlamaLendVaultAbi,
23991
+ ...LlamaLendAmmAbi,
23992
+ ...Erc20Abi
23993
+ ];
23994
+ var ZERO = "0x0000000000000000000000000000000000000000";
23995
+ var fetchJson2 = async (url, timeoutMs = 8e3) => {
23996
+ const res = await fetch(url, {
23997
+ headers: { accept: "application/json" },
23998
+ signal: AbortSignal.timeout(timeoutMs)
23999
+ });
24000
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
24001
+ return res.json();
24002
+ };
24003
+ var num2 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
24004
+ var toBig5 = (v) => {
24005
+ if (typeof v === "bigint") return v;
24006
+ if (typeof v === "number" && Number.isFinite(v)) return BigInt(Math.trunc(v));
24007
+ return null;
24008
+ };
24009
+ var human = (v, decimals) => v === null ? null : Number(v) / 10 ** decimals;
24010
+ var bandsFor = (m) => m.defaultBands && m.defaultBands >= 4 && m.defaultBands <= 50 ? m.defaultBands : DEFAULT_BANDS;
24011
+ var bandGrid = (m) => {
24012
+ const set = /* @__PURE__ */ new Set([...BANDS_ENDPOINTS, bandsFor(m)]);
24013
+ return [...set].sort((a, b) => a - b);
24014
+ };
24015
+ var maxBorrowableCall = (m, oneUnit, n) => m.version === 1 ? {
24016
+ address: m.controller,
24017
+ name: "max_borrowable",
24018
+ params: [oneUnit, BigInt(n), 0n, ZERO]
24019
+ } : {
24020
+ address: m.controller,
24021
+ name: "max_borrowable",
24022
+ params: [oneUnit, BigInt(n), ZERO]
24023
+ };
24024
+ var buildBandLtv = (perBand, borrowedDecimals, collateralPrice) => {
24025
+ if (!collateralPrice || collateralPrice <= 0) return null;
24026
+ const out = {};
24027
+ for (const { n, maxBorrowable } of perBand) {
24028
+ const borrowable = human(maxBorrowable, borrowedDecimals);
24029
+ if (borrowable === null || borrowable <= 0) continue;
24030
+ const ltv = borrowable / collateralPrice;
24031
+ if (ltv > 0 && ltv <= 1) out[String(n)] = ltv;
24032
+ }
24033
+ return Object.keys(out).length > 0 ? out : null;
24034
+ };
24035
+ async function fetchChainExtras(chainId, markets) {
24036
+ const perMarketCalls = markets.map((m) => {
24037
+ const grid = bandGrid(m);
24038
+ const oneUnit = 10n ** BigInt(m.collateralDecimals);
24039
+ const calls = [
24040
+ { address: m.amm, name: "price_oracle", params: [] },
24041
+ { address: m.amm, name: "active_band", params: [] },
24042
+ { address: m.controller, name: "n_loans", params: [] },
24043
+ { address: m.vault, name: "maxDeposit", params: [ZERO] },
24044
+ // v1 controllers have no `borrow_cap`; allowFailure turns that into a
24045
+ // null rather than sinking the whole batch.
24046
+ { address: m.controller, name: "borrow_cap", params: [] },
24047
+ ...grid.map((n) => maxBorrowableCall(m, oneUnit, n))
24048
+ ];
24049
+ return { market: m, grid, calls };
24050
+ });
24051
+ const flat = perMarketCalls.flatMap((x) => x.calls);
24052
+ if (flat.length === 0) return {};
24053
+ let results;
24054
+ try {
24055
+ results = await multicallRetryUniversal({
24056
+ chain: chainId,
24057
+ calls: flat,
24058
+ abi: LLAMALEND_READ_ABI,
24059
+ allowFailure: true
24060
+ });
24061
+ } catch {
24062
+ return {};
24063
+ }
24064
+ const out = {};
24065
+ let cursor = 0;
24066
+ for (const { market, grid } of perMarketCalls) {
24067
+ const priceRaw = toBig5(results[cursor]);
24068
+ const activeBandRaw = toBig5(results[cursor + 1]);
24069
+ const nLoansRaw = toBig5(results[cursor + 2]);
24070
+ const maxDepositRaw = toBig5(results[cursor + 3]);
24071
+ const borrowCapRaw = toBig5(results[cursor + 4]);
24072
+ const perBand = grid.map((n, i) => ({
24073
+ n,
24074
+ maxBorrowable: toBig5(results[cursor + 5 + i])
24075
+ }));
24076
+ cursor += 5 + grid.length;
24077
+ const collateralPrice = priceRaw === null ? null : Number(priceRaw) / 1e18;
24078
+ const bandLtv = buildBandLtv(
24079
+ perBand,
24080
+ market.borrowedDecimals,
24081
+ collateralPrice
24082
+ );
24083
+ const defaultN = String(bandsFor(market));
24084
+ out[market.controller.toLowerCase()] = {
24085
+ collateralPrice,
24086
+ bandLtv,
24087
+ collateralFactor: bandLtv?.[defaultN] ?? null,
24088
+ borrowCap: human(borrowCapRaw, market.borrowedDecimals),
24089
+ maxDeposit: human(maxDepositRaw, market.borrowedDecimals),
24090
+ nLoans: nLoansRaw === null ? null : Number(nLoansRaw),
24091
+ activeBand: activeBandRaw === null ? null : Number(activeBandRaw)
24092
+ };
24093
+ }
24094
+ return out;
24095
+ }
24096
+ var isBorrowingEnabled = (version, availableToBorrow, borrowCap, totalDebt) => {
24097
+ const liquid = (availableToBorrow ?? 0) > 0;
24098
+ if (version === 1) return liquid;
24099
+ if (borrowCap === null) return liquid;
24100
+ if (borrowCap <= 0) return false;
24101
+ return liquid && (totalDebt ?? 0) < borrowCap;
24102
+ };
24103
+ async function fetchLlamaLendMarkets(lender, chainId) {
24104
+ const config = llamaLendConfigFor(lender, chainId);
24105
+ const chainData = llamaLendChainData(lender, chainId);
24106
+ const markets = chainData?.markets ?? [];
24107
+ const empty = {
24108
+ lender,
24109
+ config,
24110
+ chainData,
24111
+ markets: [],
24112
+ source: "none"
24113
+ };
24114
+ if (!config || markets.length === 0) return empty;
24115
+ const extrasPromise = fetchChainExtras(chainId, markets);
24116
+ try {
24117
+ const base = llamaLendApiBaseUrl(lender, chainId);
24118
+ const api = await fetchJson2(`${base}/v1/getLendingVaults/all`);
24119
+ const byController = {};
24120
+ for (const row of api?.data?.lendingVaultData ?? []) {
24121
+ const c = row?.controllerAddress;
24122
+ if (c) byController[String(c).toLowerCase()] = row;
24123
+ }
24124
+ if (Object.keys(byController).length > 0) {
24125
+ const extras = await extrasPromise;
24126
+ const rows = markets.map((market) => {
24127
+ const r = byController[market.controller.toLowerCase()];
24128
+ const ex = extras[market.controller.toLowerCase()];
24129
+ const totalDebt = num2(r?.borrowed?.total);
24130
+ const availableToBorrow = num2(r?.availableToBorrow?.total);
24131
+ return {
24132
+ market,
24133
+ totalDebt,
24134
+ totalSupplied: num2(r?.totalSupplied?.total),
24135
+ availableToBorrow,
24136
+ // `borrowApr`/`lendApr` are the NOMINAL rates and match
24137
+ // `Vault.borrow_apr()`/`lend_apr()`. The sibling `borrowApy` /
24138
+ // `lendApy` fields are compounded — mixing them in would make this
24139
+ // lender look systematically more expensive than its peers.
24140
+ borrowApr: num2(r?.rates?.borrowApr),
24141
+ lendApr: num2(r?.rates?.lendApr),
24142
+ collateralPrice: ex?.collateralPrice ?? null,
24143
+ collateralPriceUsd: num2(r?.assets?.collateral?.usdPrice),
24144
+ borrowedPriceUsd: num2(r?.assets?.borrowed?.usdPrice),
24145
+ collateralFactor: ex?.collateralFactor ?? null,
24146
+ bandLtv: ex?.bandLtv ?? null,
24147
+ borrowCap: ex?.borrowCap ?? null,
24148
+ borrowingEnabled: isBorrowingEnabled(
24149
+ market.version,
24150
+ availableToBorrow,
24151
+ ex?.borrowCap ?? null,
24152
+ totalDebt
24153
+ ),
24154
+ maxDeposit: ex?.maxDeposit ?? null,
24155
+ nLoans: ex?.nLoans ?? null,
24156
+ activeBand: ex?.activeBand ?? null
24157
+ };
24158
+ });
24159
+ return { lender, config, chainData, markets: rows, source: "api" };
24160
+ }
24161
+ } catch {
24162
+ }
24163
+ const READS_PER_MARKET4 = 5;
24164
+ const calls = markets.flatMap((m) => [
24165
+ { address: m.controller, name: "total_debt", params: [] },
24166
+ { address: m.vault, name: "totalAssets", params: [] },
24167
+ { address: m.vault, name: "borrow_apr", params: [] },
24168
+ { address: m.vault, name: "lend_apr", params: [] },
24169
+ // v2 tracks its own lent-out accounting; v1 has no such getter, so the
24170
+ // controller's token balance IS the borrowable liquidity there.
24171
+ m.version === 2 ? { address: m.controller, name: "available_balance", params: [] } : { address: m.borrowedToken, name: "balanceOf", params: [m.controller] }
24172
+ ]);
24173
+ try {
24174
+ const results = await multicallRetryUniversal({
24175
+ chain: chainId,
24176
+ calls,
24177
+ abi: LLAMALEND_READ_ABI,
24178
+ allowFailure: true
24179
+ });
24180
+ const extras = await extrasPromise;
24181
+ const rows = markets.map((market, i) => {
24182
+ const b = i * READS_PER_MARKET4;
24183
+ const ex = extras[market.controller.toLowerCase()];
24184
+ const totalDebt = human(toBig5(results[b]), market.borrowedDecimals);
24185
+ const availableToBorrow = human(
24186
+ toBig5(results[b + 4]),
24187
+ market.borrowedDecimals
24188
+ );
24189
+ const borrowAprRaw = toBig5(results[b + 2]);
24190
+ const lendAprRaw = toBig5(results[b + 3]);
24191
+ const collateralPrice = ex?.collateralPrice ?? null;
24192
+ return {
24193
+ market,
24194
+ totalDebt,
24195
+ totalSupplied: human(toBig5(results[b + 1]), market.borrowedDecimals),
24196
+ availableToBorrow,
24197
+ // Both getters are already annualised nominal rates, WAD-scaled.
24198
+ borrowApr: borrowAprRaw === null ? null : Number(borrowAprRaw) / 1e18,
24199
+ lendApr: lendAprRaw === null ? null : Number(lendAprRaw) / 1e18,
24200
+ collateralPrice,
24201
+ // No USD leg on-chain — the oracle prices collateral in the borrowed
24202
+ // token only. The converter falls back to the global price oracle.
24203
+ collateralPriceUsd: null,
24204
+ borrowedPriceUsd: null,
24205
+ collateralFactor: ex?.collateralFactor ?? null,
24206
+ bandLtv: ex?.bandLtv ?? null,
24207
+ borrowCap: ex?.borrowCap ?? null,
24208
+ borrowingEnabled: isBorrowingEnabled(
24209
+ market.version,
24210
+ availableToBorrow,
24211
+ ex?.borrowCap ?? null,
24212
+ totalDebt
24213
+ ),
24214
+ maxDeposit: ex?.maxDeposit ?? null,
24215
+ nLoans: ex?.nLoans ?? null,
24216
+ activeBand: ex?.activeBand ?? null
24217
+ };
24218
+ });
24219
+ return { lender, config, chainData, markets: rows, source: "chain" };
24220
+ } catch {
24221
+ return empty;
24222
+ }
24223
+ }
24224
+ var VAULT_PRICE_ABI = [
24225
+ {
24226
+ name: "convertToAssets",
24227
+ type: "function",
24228
+ stateMutability: "view",
24229
+ inputs: [{ name: "shares", type: "uint256" }],
24230
+ outputs: [{ type: "uint256" }]
24231
+ }
24232
+ ];
24233
+ var IDENTITY_READS = 3;
24234
+ var STATE_READS = 12;
24235
+ var ONE = 10n ** 18n;
24236
+ var identityCache = /* @__PURE__ */ new Map();
24237
+ var identityKey = (chainId, pair) => `${chainId}:${pair.toLowerCase()}`;
24238
+ var big = (v) => {
24239
+ if (typeof v === "bigint") return v;
24240
+ if (typeof v === "number") return BigInt(v);
24241
+ return null;
24242
+ };
24243
+ async function fetchResupplyMarkets(lender, chainId) {
24244
+ const config = resupplyConfigFor(lender, chainId);
24245
+ if (!config?.registry) return { lender, config, pairs: [] };
24246
+ let discovered = [];
24247
+ try {
24248
+ const [addresses] = await multicallRetryUniversal({
24249
+ chain: chainId,
24250
+ calls: [
24251
+ { address: config.registry, name: "getAllPairAddresses", params: [] }
24252
+ ],
24253
+ abi: ResupplyRegistryAbi,
24254
+ allowFailure: true
24255
+ });
24256
+ if (Array.isArray(addresses)) {
24257
+ discovered = addresses.filter(
24258
+ (a) => typeof a === "string" && a.startsWith("0x")
24259
+ );
24260
+ }
24261
+ } catch {
24262
+ return { lender, config, pairs: [] };
24263
+ }
24264
+ if (discovered.length === 0) return { lender, config, pairs: [] };
24265
+ if (config.pairAllowlist && config.pairAllowlist.length > 0) {
24266
+ const allow = new Set(config.pairAllowlist.map((p) => p.toLowerCase()));
24267
+ discovered = discovered.filter((p) => allow.has(p.toLowerCase()));
24268
+ if (discovered.length === 0) return { lender, config, pairs: [] };
24269
+ }
24270
+ const unknown = discovered.filter(
24271
+ (p) => !identityCache.has(identityKey(chainId, p))
24272
+ );
24273
+ if (unknown.length > 0) {
24274
+ const calls2 = unknown.flatMap((pair) => [
24275
+ { address: pair, name: "name", params: [] },
24276
+ { address: pair, name: "collateral", params: [] },
24277
+ { address: pair, name: "underlying", params: [] }
24278
+ ]);
24279
+ let res = [];
24280
+ try {
24281
+ res = await multicallRetryUniversal({
24282
+ chain: chainId,
24283
+ calls: calls2,
24284
+ abi: unknown.flatMap(() => [
24285
+ ResupplyPairAbi,
24286
+ ResupplyPairAbi,
24287
+ ResupplyPairAbi
24288
+ ]),
24289
+ allowFailure: true
24290
+ });
24291
+ } catch {
24292
+ return { lender, config, pairs: [] };
24293
+ }
24294
+ const pending = [];
24295
+ unknown.forEach((pair, i) => {
24296
+ const base = i * IDENTITY_READS;
24297
+ const name = res[base];
24298
+ const collateral = res[base + 1];
24299
+ const underlying = res[base + 2];
24300
+ if (typeof collateral !== "string" || !collateral.startsWith("0x") || typeof underlying !== "string" || !underlying.startsWith("0x")) {
24301
+ return;
24302
+ }
24303
+ pending.push({
24304
+ pair,
24305
+ name: typeof name === "string" ? name : pair,
24306
+ collateral,
24307
+ underlying
24308
+ });
24309
+ });
24310
+ if (pending.length > 0) {
24311
+ let dec = [];
24312
+ try {
24313
+ dec = await multicallRetryUniversal({
24314
+ chain: chainId,
24315
+ calls: pending.flatMap((p) => [
24316
+ { address: p.collateral, name: "decimals", params: [] },
24317
+ { address: p.underlying, name: "decimals", params: [] }
24318
+ ]),
24319
+ abi: pending.flatMap(() => [erc20Abi, erc20Abi]),
24320
+ allowFailure: true
24321
+ });
24322
+ } catch {
24323
+ dec = [];
24324
+ }
24325
+ pending.forEach((p, i) => {
24326
+ const cd = Number(dec[i * 2]);
24327
+ const ud = Number(dec[i * 2 + 1]);
24328
+ identityCache.set(identityKey(chainId, p.pair), {
24329
+ pair: p.pair,
24330
+ name: p.name,
24331
+ collateral: p.collateral,
24332
+ underlying: p.underlying,
24333
+ collateralDecimals: Number.isFinite(cd) && cd > 0 ? cd : 18,
24334
+ underlyingDecimals: Number.isFinite(ud) && ud > 0 ? ud : 18
24335
+ });
24336
+ });
24337
+ }
24338
+ }
24339
+ const identities = discovered.map((p) => identityCache.get(identityKey(chainId, p))).filter((x) => !!x);
24340
+ if (identities.length === 0) return { lender, config, pairs: [] };
24341
+ const utilities = config.utilities;
24342
+ const calls = [];
24343
+ const abis = [];
24344
+ for (const id of identities) {
24345
+ calls.push(
24346
+ { address: id.pair, name: "maxLTV", params: [] },
24347
+ { address: id.pair, name: "borrowLimit", params: [] },
24348
+ { address: id.pair, name: "liquidationFee", params: [] },
24349
+ { address: id.pair, name: "mintFee", params: [] },
24350
+ { address: id.pair, name: "minimumBorrowAmount", params: [] },
24351
+ { address: id.pair, name: "getPairAccounting", params: [] },
24352
+ { address: id.pair, name: "currentRateInfo", params: [] },
24353
+ { address: id.pair, name: "exchangeRateInfo", params: [] },
24354
+ // The collateral vault's own share price — the exact input Resupply's
24355
+ // `BasicVaultOracle` uses. Read LIVE rather than inverting the pair's
24356
+ // cached `exchangeRate`, which only moves when someone writes.
24357
+ { address: id.collateral, name: "convertToAssets", params: [ONE] }
24358
+ );
24359
+ abis.push(
24360
+ ResupplyPairAbi,
24361
+ ResupplyPairAbi,
24362
+ ResupplyPairAbi,
24363
+ ResupplyPairAbi,
24364
+ ResupplyPairAbi,
24365
+ ResupplyPairAbi,
24366
+ ResupplyPairAbi,
24367
+ ResupplyPairAbi,
24368
+ VAULT_PRICE_ABI
24369
+ );
24370
+ if (utilities) {
24371
+ calls.push(
24372
+ { address: utilities, name: "getPairInterestRate", params: [id.pair] },
24373
+ {
24374
+ address: utilities,
24375
+ name: "getUnderlyingSupplyRate",
24376
+ params: [id.pair]
24377
+ },
24378
+ { address: id.pair, name: "totalDebtAvailable", params: [] }
24379
+ );
24380
+ abis.push(ResupplyUtilitiesAbi, ResupplyUtilitiesAbi, ResupplyPairAbi);
24381
+ } else {
24382
+ calls.push(
24383
+ { address: id.pair, name: "totalDebtAvailable", params: [] },
24384
+ { address: id.pair, name: "totalDebtAvailable", params: [] },
24385
+ { address: id.pair, name: "totalDebtAvailable", params: [] }
24386
+ );
24387
+ abis.push(ResupplyPairAbi, ResupplyPairAbi, ResupplyPairAbi);
24388
+ }
24389
+ }
24390
+ const PAIRS_PER_BATCH = 6;
24391
+ const results = [];
24392
+ for (let i = 0; i < identities.length; i += PAIRS_PER_BATCH) {
24393
+ const from = i * STATE_READS;
24394
+ const to = Math.min(i + PAIRS_PER_BATCH, identities.length) * STATE_READS;
24395
+ try {
24396
+ const chunk7 = await multicallRetryUniversal({
24397
+ chain: chainId,
24398
+ calls: calls.slice(from, to),
24399
+ abi: abis.slice(from, to),
24400
+ allowFailure: true
24401
+ });
24402
+ results.push(...chunk7);
24403
+ } catch {
24404
+ results.push(...new Array(to - from).fill("0x"));
24405
+ }
24406
+ }
24407
+ const pairs = identities.map((identity, i) => {
24408
+ const base = i * STATE_READS;
24409
+ const accounting = results[base + 5];
24410
+ const rateInfo = results[base + 6];
24411
+ const exchangeInfo = results[base + 7];
24412
+ const tuple = (v, idx) => Array.isArray(v) ? big(v[idx]) : null;
24413
+ return {
24414
+ identity,
24415
+ maxLTV: big(results[base]),
24416
+ borrowLimit: big(results[base + 1]),
24417
+ liquidationFee: big(results[base + 2]),
24418
+ mintFee: big(results[base + 3]),
24419
+ minimumBorrowAmount: big(results[base + 4]),
24420
+ totalBorrowAmount: tuple(accounting, 1),
24421
+ totalBorrowShares: tuple(accounting, 2),
24422
+ totalCollateral: tuple(accounting, 3),
24423
+ ratePerSec: tuple(rateInfo, 1),
24424
+ exchangeRate: tuple(exchangeInfo, 2),
24425
+ collateralPrice: big(results[base + 8]),
24426
+ liveRatePerSec: utilities ? big(results[base + 9]) : null,
24427
+ underlyingSupplyRatePerSec: utilities ? big(results[base + 10]) : null
24428
+ };
24429
+ });
24430
+ return { lender, config, pairs };
24431
+ }
23996
24432
 
23997
24433
  // src/lending/public-data/inverse/convertPublic.ts
23998
24434
  function inverseLenderKey(lender, market) {
@@ -24160,8 +24596,13 @@ function convertInverseMarketsToResponse(raw, chainId, prices = {}, _additionalY
24160
24596
  liquidationFactorBps: market.liquidationFactorBps,
24161
24597
  /** Fixed borrow APR as a DECIMAL (DBR price in DOLA). */
24162
24598
  dbrPriceDola: raw.dbrPriceDola !== null ? String(raw.dbrPriceDola) : void 0,
24163
- /** Force-replenish penalty (5475 = 54.75% APR on missed DBR). */
24599
+ /** Force-replenish penalty (5475 = 54.75% APR on missed DBR):
24600
+ * the DOLA debt added per 1 DBR minted back to the borrower. */
24164
24601
  replenishmentPriceBps: raw.replenishmentPriceBps !== null ? String(raw.replenishmentPriceBps) : void 0,
24602
+ /** Replenisher bot's cut (1000 = 10%) — carved OUT of the cost
24603
+ * above and paid from market liquidity, NOT charged on top of
24604
+ * the borrower's debt. Bot-side economics (liquidation dashboard). */
24605
+ replenishmentIncentiveBps: m.replenishmentIncentiveBps !== null ? String(m.replenishmentIncentiveBps) : void 0,
24165
24606
  borrowPaused: paused,
24166
24607
  addresses: {
24167
24608
  market: market.address,
@@ -24178,6 +24619,500 @@ function convertInverseMarketsToResponse(raw, chainId, prices = {}, _additionalY
24178
24619
  }
24179
24620
  return out;
24180
24621
  }
24622
+
24623
+ // src/lending/public-data/llamalend/convertPublic.ts
24624
+ function llamaLendLenderKey(lender, controller) {
24625
+ return `${lender}_${controller.replace(/^0x/i, "").toUpperCase()}`;
24626
+ }
24627
+ function llamaLendKeyParts(key) {
24628
+ if (!key.startsWith("LLAMALEND_")) return void 0;
24629
+ const suffix = key.slice("LLAMALEND_".length);
24630
+ if (!/^[0-9A-F]{40}$/.test(suffix)) return void 0;
24631
+ return { lender: "LLAMALEND", controller: "0x" + suffix.toLowerCase() };
24632
+ }
24633
+ function currencyFor9(address, decimals, symbol, tokens) {
24634
+ const lower3 = address.toLowerCase();
24635
+ return tokens[lower3] ?? { address: lower3, symbol, name: symbol, decimals };
24636
+ }
24637
+ function convertLlamaLendMarketsToResponse(raw, chainId, prices = {}, additionalYields = {
24638
+ intrinsicYields: {},
24639
+ lenderRewards: {},
24640
+ loaded: true
24641
+ }, tokens = {}) {
24642
+ const out = {};
24643
+ const cfg = raw?.config;
24644
+ if (!cfg) return out;
24645
+ for (const m of raw.markets ?? []) {
24646
+ const market = m.market;
24647
+ const lenderKey = llamaLendLenderKey(raw.lender, market.controller);
24648
+ const collAddr = market.collateralToken.toLowerCase();
24649
+ const loanAddr = market.borrowedToken.toLowerCase();
24650
+ const collDecimals = market.collateralDecimals;
24651
+ const loanDecimals = market.borrowedDecimals;
24652
+ const collToken = tokens[collAddr];
24653
+ const loanToken = tokens[loanAddr];
24654
+ const collSymbol = collToken?.symbol ?? market.collateralSymbol ?? "COLL";
24655
+ const loanSymbol = loanToken?.symbol ?? market.borrowedSymbol ?? "LOAN";
24656
+ const marketName = market.name ?? `${loanSymbol} / ${collSymbol}`;
24657
+ const collPriceKey = toOracleKey(collToken?.assetGroup) || toGenericPriceKey(collAddr, chainId);
24658
+ const loanPriceKey = toOracleKey(loanToken?.assetGroup) || toGenericPriceKey(loanAddr, chainId);
24659
+ prices[collPriceKey] || m.collateralPriceUsd || 0;
24660
+ const loanPrice = prices[loanPriceKey] || m.borrowedPriceUsd || 0;
24661
+ const totalDebt = m.totalDebt ?? 0;
24662
+ const totalDeposits = m.totalSupplied ?? 0;
24663
+ const borrowLiquidity = m.borrowingEnabled ? m.availableToBorrow ?? 0 : 0;
24664
+ const withdrawLiquidity = m.availableToBorrow ?? 0;
24665
+ const reserves = totalDebt + (m.availableToBorrow ?? 0);
24666
+ const utilization = reserves > 0 ? totalDebt / reserves : 0;
24667
+ const borrowRatePct = (m.borrowApr ?? 0) * 100;
24668
+ const depositRatePct = (m.lendApr ?? 0) * 100;
24669
+ const ltv = m.collateralFactor ?? 0;
24670
+ const liqPenalty = Number(market.liquidationDiscount) / 1e18 || 0;
24671
+ const closeFactor = 1;
24672
+ const depositsEnabled = (m.maxDeposit ?? 0) > 0;
24673
+ const entry = { data: {} };
24674
+ const collUid = createMarketUid(chainId, lenderKey, collAddr);
24675
+ entry.data[collUid] = {
24676
+ marketUid: collUid,
24677
+ name: "Collateral " + collSymbol,
24678
+ poolId: market.controller.toLowerCase(),
24679
+ underlying: collAddr,
24680
+ asset: currencyFor9(collAddr, collDecimals, collSymbol, tokens),
24681
+ // Collateral lives inside the LLAMMA spread over bands; there is no
24682
+ // single market-level balance worth reporting, and the number the UI
24683
+ // needs is the borrowed side anyway.
24684
+ totalDeposits: 0,
24685
+ totalDebtStable: 0,
24686
+ totalDebt: 0,
24687
+ totalLiquidity: 0,
24688
+ borrowLiquidity: 0,
24689
+ totalLiquidityUSD: 0,
24690
+ borrowLiquidityUSD: 0,
24691
+ totalDepositsUSD: 0,
24692
+ totalDebtStableUSD: 0,
24693
+ totalDebtUSD: 0,
24694
+ utilization: 0,
24695
+ depositRate: 0,
24696
+ variableBorrowRate: 0,
24697
+ stableBorrowRate: 0,
24698
+ intrinsicYield: additionalYields?.intrinsicYields?.[collToken?.assetGroup] ?? 0,
24699
+ rewards: void 0,
24700
+ decimals: collDecimals,
24701
+ config: {
24702
+ 0: {
24703
+ category: 0,
24704
+ borrowCollateralFactor: ltv,
24705
+ collateralFactor: ltv,
24706
+ borrowFactor: 1,
24707
+ liquidationPenalty: liqPenalty,
24708
+ closeFactor,
24709
+ collateralDisabled: false,
24710
+ debtDisabled: true
24711
+ }
24712
+ },
24713
+ closeFactor,
24714
+ collateralActive: true,
24715
+ borrowingEnabled: false,
24716
+ depositsEnabled: m.borrowingEnabled,
24717
+ hasStable: false,
24718
+ isActive: true,
24719
+ isFrozen: false
24720
+ };
24721
+ const loanUid = createMarketUid(chainId, lenderKey, loanAddr);
24722
+ entry.data[loanUid] = {
24723
+ marketUid: loanUid,
24724
+ name: loanSymbol,
24725
+ poolId: market.controller.toLowerCase(),
24726
+ underlying: loanAddr,
24727
+ asset: currencyFor9(loanAddr, loanDecimals, loanSymbol, tokens),
24728
+ totalDeposits,
24729
+ totalDebtStable: 0,
24730
+ totalDebt,
24731
+ totalLiquidity: withdrawLiquidity,
24732
+ borrowLiquidity,
24733
+ totalLiquidityUSD: withdrawLiquidity * loanPrice,
24734
+ borrowLiquidityUSD: borrowLiquidity * loanPrice,
24735
+ totalDepositsUSD: totalDeposits * loanPrice,
24736
+ totalDebtStableUSD: 0,
24737
+ totalDebtUSD: totalDebt * loanPrice,
24738
+ utilization,
24739
+ depositRate: depositRatePct,
24740
+ variableBorrowRate: borrowRatePct,
24741
+ stableBorrowRate: 0,
24742
+ // Which curve the depth layer should use. Both are closed-form and both
24743
+ // policies also expose an exact on-chain `future_rate`, so rate-at-depth
24744
+ // never has to be modelled here.
24745
+ rateModel: market.rateModel ?? (market.version === 1 ? "semilog" : "hyperbolic"),
24746
+ intrinsicYield: additionalYields?.intrinsicYields?.[loanToken?.assetGroup] ?? 0,
24747
+ rewards: additionalYields?.lenderRewards?.[lenderKey] ?? void 0,
24748
+ decimals: loanDecimals,
24749
+ config: {
24750
+ 0: {
24751
+ category: 0,
24752
+ borrowCollateralFactor: 0,
24753
+ collateralFactor: 0,
24754
+ borrowFactor: 1,
24755
+ liquidationPenalty: liqPenalty,
24756
+ closeFactor,
24757
+ collateralDisabled: true,
24758
+ debtDisabled: !m.borrowingEnabled
24759
+ }
24760
+ },
24761
+ closeFactor,
24762
+ collateralActive: false,
24763
+ borrowingEnabled: m.borrowingEnabled,
24764
+ depositsEnabled,
24765
+ hasStable: false,
24766
+ variableBorrowDisabled: !m.borrowingEnabled,
24767
+ isActive: true,
24768
+ isFrozen: false
24769
+ };
24770
+ entry.params = {
24771
+ market: {
24772
+ lender: lenderKey,
24773
+ name: marketName,
24774
+ loanDecimals,
24775
+ collateralDecimals: collDecimals,
24776
+ // The Controller doubles as the market id.
24777
+ id: market.controller.toLowerCase(),
24778
+ lltv: String(ltv),
24779
+ oracle: market.priceOracle ?? market.amm,
24780
+ irm: market.monetaryPolicy ?? zeroAddress,
24781
+ collateralAddress: collAddr,
24782
+ loanAddress: loanAddr,
24783
+ // --- LlamaLend descriptor (consumed by the calldata builders,
24784
+ // the leverage sizer and worker-api resolvers) ---
24785
+ llamalend: {
24786
+ /** 1 = `oneway` (v1), 2 = `oneway-v2`. Branch every encoder on this. */
24787
+ version: market.version,
24788
+ /** FAIL CLOSED — an unknown market is not delegatable. */
24789
+ supportsDelegation: market.supportsDelegation === true,
24790
+ /**
24791
+ * The market's index in its factory — also the `controller_id` that
24792
+ * Curve's leverage zap requires in `callback_args`. Without it no
24793
+ * leveraged transaction can be encoded.
24794
+ */
24795
+ factoryIndex: market.factoryIndex,
24796
+ /**
24797
+ * Whether Curve's deployed v1 zap accepts this market. A WIDER gate
24798
+ * than `supportsDelegation` — leverage is EOA-direct and needs no
24799
+ * grant — so never conflate the two.
24800
+ */
24801
+ supportsLeverage: market.supportsLeverage === true,
24802
+ /**
24803
+ * Band count the reported `collateralFactor` was computed at. A
24804
+ * consumer quoting a different `N` MUST re-read `bandLtv`.
24805
+ */
24806
+ defaultBands: market.defaultBands ?? 10,
24807
+ /** `{ [N]: ltv }` — the collateral-factor curve across band counts. */
24808
+ bandLtv: m.bandLtv ?? void 0,
24809
+ /** AMM band-geometry parameter. */
24810
+ ammA: market.ammA,
24811
+ loanDiscount: market.loanDiscount,
24812
+ /** HARD-liquidation bonus only; soft liquidation carries no penalty. */
24813
+ liquidationDiscount: market.liquidationDiscount,
24814
+ /**
24815
+ * Positions soft-liquidate over a band RANGE rather than at a single
24816
+ * price. `activeBand` says whether the market is currently
24817
+ * converting anyone; the per-user range comes from `user_prices`.
24818
+ */
24819
+ activeBand: m.activeBand ?? void 0,
24820
+ nLoans: m.nLoans ?? void 0,
24821
+ /** Collateral price in BORROWED-token terms (the AMM's EMA oracle). */
24822
+ collateralPrice: m.collateralPrice !== null ? String(m.collateralPrice) : void 0,
24823
+ /** v2 only; `0` means borrowing is switched off. */
24824
+ borrowCap: m.borrowCap !== null ? String(m.borrowCap) : void 0,
24825
+ addresses: {
24826
+ controller: market.controller,
24827
+ vault: market.vault,
24828
+ /**
24829
+ * MUST be excluded from any leverage swap route — the Controller
24830
+ * asserts this AMM's band state is unchanged across a callback,
24831
+ * so a route through it reverts with no usable reason string.
24832
+ */
24833
+ amm: market.amm,
24834
+ monetaryPolicy: market.monetaryPolicy,
24835
+ priceOracle: market.priceOracle,
24836
+ /**
24837
+ * Curve's deployed v1 leverage zaps and the aggregator routers
24838
+ * they are hard-wired to. We route leverage through these rather
24839
+ * than deploying a callbacker: their router is an immutable with
24840
+ * no allowlist, so arbitrary aggregator calldata is permitted.
24841
+ *
24842
+ * A quote MUST be checked against the matching `*Router` before
24843
+ * encoding — the zap forwards mismatched calldata to its own
24844
+ * router rather than rejecting it.
24845
+ */
24846
+ leverageZapOdos: cfg.leverageZapOdos,
24847
+ leverageZapOdosRouter: cfg.leverageZapOdosRouter,
24848
+ leverageZap1inch: cfg.leverageZap1inch,
24849
+ leverageZap1inchRouter: cfg.leverageZap1inchRouter,
24850
+ oneWayFactory: cfg.oneWayFactory,
24851
+ lendFactory: cfg.lendFactory
24852
+ }
24853
+ }
24854
+ }
24855
+ };
24856
+ entry.chainId = chainId;
24857
+ out[lenderKey] = entry;
24858
+ }
24859
+ return out;
24860
+ }
24861
+ var llamaLendKey = (controller) => `LLAMALEND_${controller.replace(/^0x/i, "").toUpperCase()}`;
24862
+ function resolveWrappedMarket(chainId, collateralVault, pairName) {
24863
+ const market = llamaLendMarketByVault("LLAMALEND", chainId, collateralVault);
24864
+ if (market) {
24865
+ return {
24866
+ provider: "llamalend",
24867
+ vault: collateralVault,
24868
+ lender: llamaLendKey(market.controller),
24869
+ controller: market.controller,
24870
+ amm: market.amm,
24871
+ version: market.version,
24872
+ collateralSymbol: market.collateralSymbol
24873
+ };
24874
+ }
24875
+ const isFraxlend = /fraxlend/i.test(pairName);
24876
+ return {
24877
+ provider: isFraxlend ? "fraxlend" : "unknown",
24878
+ vault: collateralVault
24879
+ };
24880
+ }
24881
+ function resupplyLenderKey(lender, chainId, pair) {
24882
+ return `${lender}_${chainId}_${pair.replace(/^0x/i, "").toUpperCase()}`;
24883
+ }
24884
+ function resupplyKeyParts(key) {
24885
+ if (!key.startsWith("RESUPPLY_")) return void 0;
24886
+ const suffix = key.slice("RESUPPLY_".length);
24887
+ const m = suffix.match(/^(\d+)_([0-9A-Fa-f]{40})$/);
24888
+ if (!m) return void 0;
24889
+ return {
24890
+ lender: "RESUPPLY",
24891
+ chainId: m[1],
24892
+ pair: `0x${m[2].toLowerCase()}`
24893
+ };
24894
+ }
24895
+ var SECONDS_PER_YEAR9 = 31536e3;
24896
+ var LTV_PRECISION = 1e5;
24897
+ var ONE2 = 10n ** 18n;
24898
+ function currencyFor10(address, decimals, symbol, tokens) {
24899
+ const lower3 = address.toLowerCase();
24900
+ return tokens[lower3] ?? { address: lower3, symbol, name: symbol, decimals };
24901
+ }
24902
+ function ratePerSecToApr(rate) {
24903
+ if (rate === null) return 0;
24904
+ return Number(rate) / 1e18 * SECONDS_PER_YEAR9 * 100;
24905
+ }
24906
+ function convertResupplyMarketsToResponse(raw, chainId, prices = {}, _additionalYields = {
24907
+ intrinsicYields: {},
24908
+ lenderRewards: {},
24909
+ loaded: true
24910
+ }, tokens = {}) {
24911
+ const out = {};
24912
+ const cfg = raw?.config;
24913
+ if (!cfg) return out;
24914
+ const debtAddr = cfg.reusd.toLowerCase();
24915
+ const debtDecimals = cfg.debtDecimals ?? 18;
24916
+ const debtToken = tokens[debtAddr];
24917
+ const debtSymbol = debtToken?.symbol ?? "reUSD";
24918
+ const debtPriceKey = toOracleKey(debtToken?.assetGroup) || toGenericPriceKey(debtAddr, chainId);
24919
+ const debtPrice = prices[debtPriceKey] || 1;
24920
+ for (const p of raw.pairs ?? []) {
24921
+ const id = p.identity;
24922
+ if (p.maxLTV === null || p.borrowLimit === null) continue;
24923
+ if (p.totalBorrowAmount === null || p.totalCollateral === null) continue;
24924
+ if (p.collateralPrice === null || p.collateralPrice === 0n) continue;
24925
+ const lenderKey = resupplyLenderKey(raw.lender, chainId, id.pair);
24926
+ const collAddr = id.underlying.toLowerCase();
24927
+ const collDecimals = id.underlyingDecimals;
24928
+ const collToken = tokens[collAddr];
24929
+ const collSymbol = collToken?.symbol ?? "COLL";
24930
+ const collPriceKey = toOracleKey(collToken?.assetGroup) || toGenericPriceKey(collAddr, chainId);
24931
+ const collPrice = prices[collPriceKey] || 1;
24932
+ const shares = p.totalCollateral ?? 0n;
24933
+ const sharePrice = p.collateralPrice ?? 0n;
24934
+ const collUnderlyingRaw = sharePrice > 0n ? shares * sharePrice / ONE2 : 0n;
24935
+ const totalColl = Number(collUnderlyingRaw) / 10 ** collDecimals;
24936
+ const totalDebt = p.totalBorrowAmount !== null ? Number(p.totalBorrowAmount) / 10 ** debtDecimals : 0;
24937
+ const borrowLimit = p.borrowLimit !== null ? Number(p.borrowLimit) / 10 ** debtDecimals : 0;
24938
+ const borrowLiquidity = Math.max(borrowLimit - totalDebt, 0);
24939
+ const halted = (p.borrowLimit ?? 0n) === 0n;
24940
+ const wrappedMarket = resolveWrappedMarket(chainId, id.collateral, id.name);
24941
+ const maxLtv = p.maxLTV !== null ? Number(p.maxLTV) / LTV_PRECISION : 0;
24942
+ const liquidationPenalty = p.liquidationFee !== null ? Number(p.liquidationFee) / LTV_PRECISION : 0;
24943
+ const mintFeePct = p.mintFee !== null ? Number(p.mintFee) / LTV_PRECISION * 100 : 0;
24944
+ const borrowApr = ratePerSecToApr(p.liveRatePerSec ?? p.ratePerSec);
24945
+ const collateralIntrinsicApr = ratePerSecToApr(p.underlyingSupplyRatePerSec);
24946
+ const entry = { data: {} };
24947
+ const collUid = createMarketUid(chainId, lenderKey, collAddr);
24948
+ entry.data[collUid] = {
24949
+ marketUid: collUid,
24950
+ name: "Collateral " + collSymbol,
24951
+ poolId: id.pair.toLowerCase(),
24952
+ underlying: collAddr,
24953
+ asset: currencyFor10(collAddr, collDecimals, collSymbol, tokens),
24954
+ totalDeposits: totalColl,
24955
+ totalDebtStable: 0,
24956
+ totalDebt: 0,
24957
+ totalLiquidity: totalColl,
24958
+ borrowLiquidity: 0,
24959
+ totalLiquidityUSD: totalColl * collPrice,
24960
+ borrowLiquidityUSD: 0,
24961
+ totalDepositsUSD: totalColl * collPrice,
24962
+ totalDebtStableUSD: 0,
24963
+ totalDebtUSD: 0,
24964
+ utilization: 0,
24965
+ depositRate: 0,
24966
+ variableBorrowRate: 0,
24967
+ stableBorrowRate: 0,
24968
+ // The wrapped Curve Lend / Fraxlend supply rate — this collateral is a
24969
+ // lending position and earns while it sits here.
24970
+ intrinsicYield: collateralIntrinsicApr,
24971
+ rewards: void 0,
24972
+ decimals: collDecimals,
24973
+ config: {
24974
+ 0: {
24975
+ category: 0,
24976
+ borrowCollateralFactor: maxLtv,
24977
+ collateralFactor: maxLtv,
24978
+ borrowFactor: 1,
24979
+ liquidationPenalty,
24980
+ // Liquidation takes the WHOLE position (`liquidate(borrower)` repays
24981
+ // all of it) — there is no partial close.
24982
+ closeFactor: 1,
24983
+ collateralDisabled: false,
24984
+ debtDisabled: true
24985
+ }
24986
+ },
24987
+ closeFactor: 1,
24988
+ collateralActive: true,
24989
+ borrowingEnabled: false,
24990
+ // Deposits stay open on a paused pair so positions can be topped up to
24991
+ // avoid liquidation; only borrowing is stopped.
24992
+ depositsEnabled: true,
24993
+ hasStable: false,
24994
+ isActive: !halted,
24995
+ isFrozen: halted
24996
+ };
24997
+ const loanUid = createMarketUid(chainId, lenderKey, debtAddr);
24998
+ entry.data[loanUid] = {
24999
+ marketUid: loanUid,
25000
+ name: debtSymbol,
25001
+ poolId: id.pair.toLowerCase(),
25002
+ underlying: debtAddr,
25003
+ asset: currencyFor10(debtAddr, debtDecimals, debtSymbol, tokens),
25004
+ totalDeposits: 0,
25005
+ totalDebtStable: 0,
25006
+ totalDebt,
25007
+ totalLiquidity: borrowLiquidity,
25008
+ borrowLiquidity,
25009
+ totalLiquidityUSD: borrowLiquidity * debtPrice,
25010
+ borrowLiquidityUSD: borrowLiquidity * debtPrice,
25011
+ totalDepositsUSD: 0,
25012
+ totalDebtStableUSD: 0,
25013
+ totalDebtUSD: totalDebt * debtPrice,
25014
+ // Against the governance-set debt ceiling, not a deposit base — there is
25015
+ // no supply side to be utilized.
25016
+ utilization: borrowLimit > 0 ? Math.min(totalDebt / borrowLimit, 1) : 0,
25017
+ depositRate: 0,
25018
+ variableBorrowRate: borrowApr,
25019
+ stableBorrowRate: 0,
25020
+ // Pinned to ~half the greater of {wrapped supply rate, sfrxUSD risk-free
25021
+ // rate, floor}, then scaled by the reUSD off-peg weight. No utilization
25022
+ // curve anywhere in the protocol.
25023
+ rateModel: "protocolSet",
25024
+ // `mintFee` is added to the debt at borrow time. Zero on every live pair,
25025
+ // but it is governance-settable.
25026
+ originationFee: mintFeePct,
25027
+ intrinsicYield: 0,
25028
+ rewards: void 0,
25029
+ decimals: debtDecimals,
25030
+ config: {
25031
+ 0: {
25032
+ category: 0,
25033
+ borrowCollateralFactor: 0,
25034
+ collateralFactor: 0,
25035
+ borrowFactor: 1,
25036
+ liquidationPenalty,
25037
+ closeFactor: 1,
25038
+ collateralDisabled: true,
25039
+ debtDisabled: halted
25040
+ }
25041
+ },
25042
+ closeFactor: 1,
25043
+ collateralActive: false,
25044
+ borrowingEnabled: !halted,
25045
+ depositsEnabled: false,
25046
+ hasStable: false,
25047
+ variableBorrowDisabled: halted,
25048
+ isActive: !halted,
25049
+ isFrozen: halted
25050
+ };
25051
+ entry.params = {
25052
+ market: {
25053
+ lender: lenderKey,
25054
+ name: id.name,
25055
+ loanDecimals: debtDecimals,
25056
+ collateralDecimals: collDecimals,
25057
+ id: id.pair.toLowerCase(),
25058
+ lltv: p.maxLTV !== null ? p.maxLTV.toString() : "0",
25059
+ // The oracle is the collateral vault's own `convertToAssets`; there is
25060
+ // no external price feed contract to name.
25061
+ oracle: zeroAddress,
25062
+ irm: zeroAddress,
25063
+ collateralAddress: collAddr,
25064
+ loanAddress: debtAddr,
25065
+ // --- Resupply descriptor (consumed by the calldata builders, the
25066
+ // worker-api resolvers and the loop quoter) ---
25067
+ resupply: {
25068
+ pair: id.pair,
25069
+ /** The ERC-4626 share the pair actually books as collateral. */
25070
+ collateralVault: id.collateral,
25071
+ collateralVaultDecimals: id.collateralDecimals,
25072
+ /** What the user deposits/withdraws (crvUSD or frxUSD). */
25073
+ underlying: id.underlying,
25074
+ /**
25075
+ * The EXTERNAL lending market this pair wraps. A Resupply position
25076
+ * inherits that market's risk (bad debt there is bad debt here), so
25077
+ * the link is first-class rather than a footnote. Resolved against
25078
+ * our own LlamaLend roster by vault address where possible.
25079
+ */
25080
+ wrappedMarket,
25081
+ /** `convertToAssets(1e18)` — UNDERLYING per 1e18 shares. ~1e15 for
25082
+ * Curve Lend vaults. Required to size any share-denominated arg. */
25083
+ collateralPrice: (p.collateralPrice ?? 0n).toString(),
25084
+ /** The pair's cached `1e36 / collateralPrice` (stale between writes). */
25085
+ exchangeRate: (p.exchangeRate ?? 0n).toString(),
25086
+ maxLTV: (p.maxLTV ?? 0n).toString(),
25087
+ borrowLimit: (p.borrowLimit ?? 0n).toString(),
25088
+ /** Hard floor per position — a smaller borrow, or a repay leaving
25089
+ * less than this, reverts. */
25090
+ minimumBorrowAmount: (p.minimumBorrowAmount ?? 0n).toString(),
25091
+ liquidationFee: (p.liquidationFee ?? 0n).toString(),
25092
+ mintFee: (p.mintFee ?? 0n).toString(),
25093
+ totalBorrowShares: (p.totalBorrowShares ?? 0n).toString(),
25094
+ totalBorrowAmount: (p.totalBorrowAmount ?? 0n).toString(),
25095
+ totalCollateralShares: (p.totalCollateral ?? 0n).toString(),
25096
+ borrowRatePerSecond: (p.liveRatePerSec ?? p.ratePerSec ?? 0n).toString(),
25097
+ underlyingSupplyRatePerSecond: (p.underlyingSupplyRatePerSec ?? 0n).toString(),
25098
+ /** Zero borrow limit = paused by governance (no `isPaused` exists). */
25099
+ paused: halted,
25100
+ addresses: {
25101
+ registry: cfg.registry,
25102
+ reusd: cfg.reusd,
25103
+ utilities: cfg.utilities ?? void 0,
25104
+ curveSwapper: cfg.curveSwapper ?? void 0,
25105
+ ensoSwapper: cfg.ensoSwapper ?? void 0,
25106
+ lifiSwapper: cfg.lifiSwapper ?? void 0
25107
+ }
25108
+ }
25109
+ }
25110
+ };
25111
+ entry.chainId = chainId;
25112
+ out[lenderKey] = entry;
25113
+ }
25114
+ return out;
25115
+ }
24181
25116
  var READS_PER_ILK = 4;
24182
25117
  var USDD_ABI_PER_READ = [UsddVatAbi, UsddJugAbi, UsddSpotAbi, erc20Abi];
24183
25118
  var usddIlkBytes32 = (ilk) => stringToHex(ilk, { size: 32 });
@@ -24208,12 +25143,12 @@ async function fetchUsddMarkets(lender, chainId) {
24208
25143
  } catch {
24209
25144
  return { lender, config, chainData, markets: [] };
24210
25145
  }
24211
- const big9 = (v) => {
25146
+ const big13 = (v) => {
24212
25147
  if (typeof v === "bigint") return v;
24213
25148
  if (typeof v === "number") return BigInt(v);
24214
25149
  return null;
24215
25150
  };
24216
- const field12 = (res, name, idx) => big9(res?.[name] ?? res?.[idx]);
25151
+ const field12 = (res, name, idx) => big13(res?.[name] ?? res?.[idx]);
24217
25152
  const out = markets.map((market, i) => {
24218
25153
  const base = i * READS_PER_ILK;
24219
25154
  const vatIlk = results[base];
@@ -24228,7 +25163,7 @@ async function fetchUsddMarkets(lender, chainId) {
24228
25163
  dust: field12(vatIlk, "dust", 4),
24229
25164
  duty: field12(jugIlk, "duty", 0),
24230
25165
  mat: field12(spotIlk, "mat", 1),
24231
- joinBalance: big9(results[base + 3])
25166
+ joinBalance: big13(results[base + 3])
24232
25167
  };
24233
25168
  });
24234
25169
  return { lender, config, chainData, markets: out };
@@ -24252,7 +25187,7 @@ var YEAR_SECONDS2 = 31536e3;
24252
25187
  function toHuman4(raw, decimals) {
24253
25188
  return Number(raw) / 10 ** decimals;
24254
25189
  }
24255
- function currencyFor9(address, decimals, symbol, tokens) {
25190
+ function currencyFor11(address, decimals, symbol, tokens) {
24256
25191
  const lower3 = address.toLowerCase();
24257
25192
  return tokens[lower3] ?? { address: lower3, symbol, name: symbol, decimals };
24258
25193
  }
@@ -24300,7 +25235,7 @@ function convertUsddMarketsToResponse(raw, chainId, prices = {}, _additionalYiel
24300
25235
  name: "Collateral " + collSymbol,
24301
25236
  poolId: market.gemJoin.toLowerCase(),
24302
25237
  underlying: collAddr,
24303
- asset: currencyFor9(collAddr, collDecimals, collSymbol, tokens),
25238
+ asset: currencyFor11(collAddr, collDecimals, collSymbol, tokens),
24304
25239
  totalDeposits: totalColl,
24305
25240
  totalDebtStable: 0,
24306
25241
  totalDebt: 0,
@@ -24344,7 +25279,7 @@ function convertUsddMarketsToResponse(raw, chainId, prices = {}, _additionalYiel
24344
25279
  name: debtSymbol,
24345
25280
  poolId: cfg.vat.toLowerCase(),
24346
25281
  underlying: debtAddr,
24347
- asset: currencyFor9(debtAddr, debtDecimals, debtSymbol, tokens),
25282
+ asset: currencyFor11(debtAddr, debtDecimals, debtSymbol, tokens),
24348
25283
  totalDeposits: 0,
24349
25284
  totalDebtStable: 0,
24350
25285
  totalDebt,
@@ -24436,6 +25371,304 @@ function convertUsddMarketsToResponse(raw, chainId, prices = {}, _additionalYiel
24436
25371
  }
24437
25372
  return out;
24438
25373
  }
25374
+ var READS_PER_MARKET3 = 10;
25375
+ var FRANKENCOIN_ABI_PER_READ = [
25376
+ FrankencoinPositionAbi,
25377
+ FrankencoinPositionAbi,
25378
+ FrankencoinPositionAbi,
25379
+ FrankencoinPositionAbi,
25380
+ FrankencoinPositionAbi,
25381
+ FrankencoinPositionAbi,
25382
+ FrankencoinPositionAbi,
25383
+ FrankencoinPositionAbi,
25384
+ FrankencoinPositionAbi,
25385
+ erc20Abi
25386
+ ];
25387
+ async function fetchFrankencoinMarkets(lender, chainId) {
25388
+ const config = frankencoinConfigFor(lender, chainId);
25389
+ const chainData = frankencoinChainData(lender, chainId);
25390
+ const markets = chainData?.markets ?? [];
25391
+ if (!config || markets.length === 0) {
25392
+ return { lender, config, chainData, markets: [] };
25393
+ }
25394
+ const calls = markets.flatMap((m) => [
25395
+ { address: m.position, name: "price", params: [] },
25396
+ { address: m.position, name: "minted", params: [] },
25397
+ { address: m.position, name: "availableForClones", params: [] },
25398
+ { address: m.position, name: "annualInterestPPM", params: [] },
25399
+ { address: m.position, name: "calculateCurrentFee", params: [] },
25400
+ { address: m.position, name: "reserveContribution", params: [] },
25401
+ { address: m.position, name: "challengedAmount", params: [] },
25402
+ { address: m.position, name: "expiration", params: [] },
25403
+ // Read LIVE rather than trusting the generator's snapshot: a position
25404
+ // can close between metadata runs (and dropping below
25405
+ // `minimumCollateral` closes one permanently), and publishing a dead
25406
+ // market as borrowable is the worst failure mode here.
25407
+ { address: m.position, name: "isClosed", params: [] },
25408
+ { address: m.collToken, name: "balanceOf", params: [m.position] }
25409
+ ]);
25410
+ let results = [];
25411
+ try {
25412
+ results = await multicallRetryUniversal({
25413
+ chain: chainId,
25414
+ calls,
25415
+ abi: markets.flatMap(() => FRANKENCOIN_ABI_PER_READ),
25416
+ allowFailure: true
25417
+ });
25418
+ } catch {
25419
+ return { lender, config, chainData, markets: [] };
25420
+ }
25421
+ const big13 = (v) => {
25422
+ if (typeof v === "bigint") return v;
25423
+ if (typeof v === "number") return BigInt(v);
25424
+ return null;
25425
+ };
25426
+ const out = markets.map((market, i) => {
25427
+ const base = i * READS_PER_MARKET3;
25428
+ const expiration = big13(results[base + 7]);
25429
+ return {
25430
+ market,
25431
+ price: big13(results[base]),
25432
+ minted: big13(results[base + 1]),
25433
+ availableForClones: big13(results[base + 2]),
25434
+ annualInterestPPM: big13(results[base + 3]),
25435
+ currentFeePPM: big13(results[base + 4]),
25436
+ reserveContribution: big13(results[base + 5]),
25437
+ challengedAmount: big13(results[base + 6]),
25438
+ expiration,
25439
+ isClosed: typeof results[base + 8] === "boolean" ? results[base + 8] : null,
25440
+ collateralBalance: big13(results[base + 9])
25441
+ };
25442
+ });
25443
+ return { lender, config, chainData, markets: out };
25444
+ }
25445
+
25446
+ // src/lending/public-data/frankencoin/convertPublic.ts
25447
+ function frankencoinLenderKey(lender, chainId, position) {
25448
+ return `${lender}_${chainId}_${position.replace(/^0x/i, "").toUpperCase()}`;
25449
+ }
25450
+ function frankencoinKeyParts(key) {
25451
+ if (!key.startsWith("FRANKENCOIN_")) return void 0;
25452
+ const suffix = key.slice("FRANKENCOIN_".length);
25453
+ const m = suffix.match(/^(\d+)_([0-9A-Fa-f]{40})$/);
25454
+ if (!m) return void 0;
25455
+ return {
25456
+ lender: "FRANKENCOIN",
25457
+ chainId: m[1],
25458
+ position: `0x${m[2].toLowerCase()}`
25459
+ };
25460
+ }
25461
+ var PPM = 1e6;
25462
+ function currencyFor12(address, decimals, symbol, tokens) {
25463
+ const lower3 = address.toLowerCase();
25464
+ return tokens[lower3] ?? { address: lower3, symbol, name: symbol, decimals };
25465
+ }
25466
+ function convertFrankencoinMarketsToResponse(raw, chainId, prices = {}, _additionalYields = {
25467
+ intrinsicYields: {},
25468
+ lenderRewards: {},
25469
+ loaded: true
25470
+ }, tokens = {}) {
25471
+ const out = {};
25472
+ const cfg = raw?.config;
25473
+ const chainData = raw?.chainData;
25474
+ if (!cfg || !chainData) return out;
25475
+ const debtAddr = cfg.zchf.toLowerCase();
25476
+ const debtDecimals = cfg.debtDecimals ?? 18;
25477
+ const debtToken = tokens[debtAddr];
25478
+ const debtSymbol = debtToken?.symbol ?? "ZCHF";
25479
+ const debtPriceKey = toOracleKey(debtToken?.assetGroup) || toGenericPriceKey(debtAddr, chainId);
25480
+ const debtPrice = prices[debtPriceKey] ?? 0;
25481
+ const nowSec9 = Math.floor(Date.now() / 1e3);
25482
+ for (const m of raw.markets ?? []) {
25483
+ const market = m.market;
25484
+ const lenderKey = frankencoinLenderKey(raw.lender, chainId, market.position);
25485
+ const collAddr = market.collToken.toLowerCase();
25486
+ const collDecimals = market.collDecimals;
25487
+ const collToken = tokens[collAddr];
25488
+ const collSymbol = collToken?.symbol ?? market.collSymbol ?? "COLL";
25489
+ const marketName = market.name ?? `${debtSymbol} / ${collSymbol}`;
25490
+ const collPriceKey = toOracleKey(collToken?.assetGroup) || toGenericPriceKey(collAddr, chainId);
25491
+ const collPrice = prices[collPriceKey] ?? 0;
25492
+ const declaredPrice = m.price !== null ? Number(m.price) / 10 ** (36 - collDecimals) : Number(market.price) / 10 ** (36 - collDecimals);
25493
+ const totalColl = m.collateralBalance !== null ? Number(m.collateralBalance) / 10 ** collDecimals : 0;
25494
+ const totalDebt = m.minted !== null ? Number(m.minted) / 10 ** debtDecimals : 0;
25495
+ const borrowLiquidity = m.availableForClones !== null ? Number(m.availableForClones) / 10 ** debtDecimals : 0;
25496
+ const expiration = m.expiration !== null ? Number(m.expiration) : Number(market.expiration);
25497
+ const expired = expiration > 0 && expiration <= nowSec9;
25498
+ const challenged = (m.challengedAmount ?? 0n) > 0n;
25499
+ const closed = m.isClosed === true;
25500
+ const halted = expired || closed;
25501
+ const borrowApr = m.annualInterestPPM !== null ? Number(m.annualInterestPPM) / PPM * 100 : 0;
25502
+ const upfrontFeePct = m.currentFeePPM !== null ? Number(m.currentFeePPM) / PPM * 100 : 0;
25503
+ const reserveContributionPpm = m.reserveContribution !== null ? Number(m.reserveContribution) : Number(market.reserveContribution);
25504
+ const ltvVsMarket = collPrice > 0 ? Math.min(declaredPrice / collPrice, 1) : 0;
25505
+ const declaredVsMarket = collPrice > 0 ? declaredPrice / collPrice : void 0;
25506
+ const entry = { data: {} };
25507
+ const collUid = createMarketUid(chainId, lenderKey, collAddr);
25508
+ entry.data[collUid] = {
25509
+ marketUid: collUid,
25510
+ name: "Collateral " + collSymbol,
25511
+ poolId: market.position.toLowerCase(),
25512
+ underlying: collAddr,
25513
+ asset: currencyFor12(collAddr, collDecimals, collSymbol, tokens),
25514
+ totalDeposits: totalColl,
25515
+ totalDebtStable: 0,
25516
+ totalDebt: 0,
25517
+ totalLiquidity: totalColl,
25518
+ borrowLiquidity: 0,
25519
+ totalLiquidityUSD: totalColl * collPrice,
25520
+ borrowLiquidityUSD: 0,
25521
+ totalDepositsUSD: totalColl * collPrice,
25522
+ totalDebtStableUSD: 0,
25523
+ totalDebtUSD: 0,
25524
+ utilization: 0,
25525
+ depositRate: 0,
25526
+ variableBorrowRate: 0,
25527
+ stableBorrowRate: 0,
25528
+ intrinsicYield: 0,
25529
+ rewards: void 0,
25530
+ decimals: collDecimals,
25531
+ config: {
25532
+ 0: {
25533
+ category: 0,
25534
+ borrowCollateralFactor: ltvVsMarket,
25535
+ collateralFactor: ltvVsMarket,
25536
+ borrowFactor: 1,
25537
+ // Liquidation is a Dutch auction against the declared price, not a
25538
+ // fixed penalty; the challenger reward (2 %) is the closest
25539
+ // bounded cost and is carried in the descriptor.
25540
+ liquidationPenalty: 0,
25541
+ closeFactor: 1,
25542
+ collateralDisabled: false,
25543
+ debtDisabled: true
25544
+ }
25545
+ },
25546
+ closeFactor: 1,
25547
+ collateralActive: true,
25548
+ borrowingEnabled: false,
25549
+ depositsEnabled: !halted,
25550
+ hasStable: false,
25551
+ isActive: !halted,
25552
+ isFrozen: halted
25553
+ };
25554
+ const loanUid = createMarketUid(chainId, lenderKey, debtAddr);
25555
+ entry.data[loanUid] = {
25556
+ marketUid: loanUid,
25557
+ name: debtSymbol,
25558
+ poolId: cfg.mintingHub.toLowerCase(),
25559
+ underlying: debtAddr,
25560
+ asset: currencyFor12(debtAddr, debtDecimals, debtSymbol, tokens),
25561
+ totalDeposits: 0,
25562
+ totalDebtStable: 0,
25563
+ totalDebt,
25564
+ totalLiquidity: borrowLiquidity,
25565
+ borrowLiquidity,
25566
+ totalLiquidityUSD: borrowLiquidity * debtPrice,
25567
+ borrowLiquidityUSD: borrowLiquidity * debtPrice,
25568
+ totalDepositsUSD: 0,
25569
+ totalDebtStableUSD: 0,
25570
+ totalDebtUSD: totalDebt * debtPrice,
25571
+ utilization: 0,
25572
+ // The earn side is the savings module (savings provider), not a
25573
+ // lending deposit.
25574
+ depositRate: 0,
25575
+ variableBorrowRate: borrowApr,
25576
+ stableBorrowRate: 0,
25577
+ // Per-position fixed rate (hub lead rate + risk premium) — no
25578
+ // utilization curve anywhere in the protocol.
25579
+ rateModel: "protocolSet",
25580
+ // One-off, pro-rata to expiry, charged at mint out of the proceeds.
25581
+ originationFee: upfrontFeePct,
25582
+ intrinsicYield: 0,
25583
+ rewards: void 0,
25584
+ decimals: debtDecimals,
25585
+ config: {
25586
+ 0: {
25587
+ category: 0,
25588
+ borrowCollateralFactor: 0,
25589
+ collateralFactor: 0,
25590
+ borrowFactor: 1,
25591
+ liquidationPenalty: 0,
25592
+ closeFactor: 1,
25593
+ collateralDisabled: true,
25594
+ debtDisabled: halted
25595
+ }
25596
+ },
25597
+ closeFactor: 1,
25598
+ collateralActive: false,
25599
+ borrowingEnabled: !halted && !challenged,
25600
+ depositsEnabled: false,
25601
+ hasStable: false,
25602
+ variableBorrowDisabled: halted || challenged,
25603
+ isActive: !halted,
25604
+ isFrozen: halted
25605
+ };
25606
+ entry.params = {
25607
+ market: {
25608
+ lender: lenderKey,
25609
+ name: marketName,
25610
+ loanDecimals: debtDecimals,
25611
+ collateralDecimals: collDecimals,
25612
+ // The original position doubles as the market id.
25613
+ id: market.position.toLowerCase(),
25614
+ lltv: m.price !== null ? m.price.toString() : market.price,
25615
+ // There is no oracle contract — deliberately zero, with the
25616
+ // declared price carried below.
25617
+ oracle: zeroAddress,
25618
+ irm: zeroAddress,
25619
+ collateralAddress: collAddr,
25620
+ loanAddress: debtAddr,
25621
+ // --- Frankencoin descriptor (consumed by the calldata builders,
25622
+ // worker-api resolvers and any quote layer) ---
25623
+ frankencoin: {
25624
+ position: market.position,
25625
+ /** Owner-DECLARED liquidation price (raw, 36-dec scaled). */
25626
+ declaredPrice: m.price !== null ? m.price.toString() : market.price,
25627
+ /** Same, as ZCHF per whole collateral unit. */
25628
+ declaredPriceHuman: declaredPrice,
25629
+ /** `declaredPrice / marketPrice`, UNCLAMPED — the liquidation
25630
+ * signal. `>= 1` means the collateral can no longer be sold at
25631
+ * the declared price, so a challenge would succeed. `undefined`
25632
+ * when we have no market price for the collateral. This is NOT
25633
+ * the health factor: our HF is `mintingCapacity / minted` (the
25634
+ * protocol's own `minted <= coll * price` invariant), which
25635
+ * answers "can I borrow more", not "am I liquidatable". */
25636
+ declaredVsMarket,
25637
+ /** True when the declared price has been reached or passed and a
25638
+ * challenge would therefore clear. Undefined without a market
25639
+ * price. */
25640
+ challengeable: declaredVsMarket === void 0 ? void 0 : declaredVsMarket >= 1,
25641
+ /** ppm withheld into the FPS equity reserve at mint. */
25642
+ reserveContributionPPM: String(reserveContributionPpm),
25643
+ /** ppm one-off upfront interest for minting now. */
25644
+ upfrontFeePPM: m.currentFeePPM !== null ? m.currentFeePPM.toString() : void 0,
25645
+ annualInterestPPM: m.annualInterestPPM !== null ? m.annualInterestPPM.toString() : void 0,
25646
+ riskPremiumPPM: market.riskPremiumPPM,
25647
+ minimumCollateral: market.minimumCollateral,
25648
+ expiration: String(expiration),
25649
+ expired,
25650
+ closed,
25651
+ challengePeriod: market.challengePeriod,
25652
+ challengedAmount: m.challengedAmount !== null ? m.challengedAmount.toString() : void 0,
25653
+ isChallenged: challenged,
25654
+ /** ppm reward paid to a successful challenger (hub constant). */
25655
+ challengerRewardPPM: "20000",
25656
+ version: market.version ?? 2,
25657
+ addresses: {
25658
+ mintingHub: cfg.mintingHub,
25659
+ zchf: cfg.zchf,
25660
+ equity: cfg.equity,
25661
+ roller: cfg.roller,
25662
+ chfUsdFeed: cfg.chfUsdFeed
25663
+ }
25664
+ }
25665
+ }
25666
+ };
25667
+ entry.chainId = chainId;
25668
+ out[lenderKey] = entry;
25669
+ }
25670
+ return out;
25671
+ }
24439
25672
 
24440
25673
  // src/lending/public-data/silo-v2/fetchPublic.ts
24441
25674
  var BASE_URL2 = "https://api-v3.silo.finance";
@@ -25045,8 +26278,12 @@ async function getLenderDataFromApi(lender, chainId, prices, additionalYields, i
25045
26278
  if (isRiver(lender)) return await fetchRiverMarkets(lender, chainId);
25046
26279
  if (isTeller(lender)) return await fetchTellerMarkets(chainId);
25047
26280
  if (isInverse(lender)) return await fetchInverseMarkets(lender, chainId);
26281
+ if (isLlamaLend(lender)) return await fetchLlamaLendMarkets(lender, chainId);
26282
+ if (isResupply(lender)) return await fetchResupplyMarkets(lender, chainId);
25048
26283
  if (isTermMax(lender)) return await fetchTermMaxMarkets(chainId);
25049
26284
  if (isUsdd(lender)) return await fetchUsddMarkets(lender, chainId);
26285
+ if (isFrankencoin(lender))
26286
+ return await fetchFrankencoinMarkets(lender, chainId);
25050
26287
  return {};
25051
26288
  }
25052
26289
  function convertLenderDataFromApi(lender, chainId, data, prices, additionalYields, list = {}) {
@@ -25108,6 +26345,30 @@ function convertLenderDataFromApi(lender, chainId, data, prices, additionalYield
25108
26345
  additionalYields,
25109
26346
  list
25110
26347
  );
26348
+ if (isLlamaLend(lender))
26349
+ return convertLlamaLendMarketsToResponse(
26350
+ data,
26351
+ chainId,
26352
+ prices,
26353
+ additionalYields,
26354
+ list
26355
+ );
26356
+ if (isResupply(lender))
26357
+ return convertResupplyMarketsToResponse(
26358
+ data,
26359
+ chainId,
26360
+ prices,
26361
+ additionalYields,
26362
+ list
26363
+ );
26364
+ if (isFrankencoin(lender))
26365
+ return convertFrankencoinMarketsToResponse(
26366
+ data,
26367
+ chainId,
26368
+ prices,
26369
+ additionalYields,
26370
+ list
26371
+ );
25111
26372
  if (isUsdd(lender))
25112
26373
  return convertUsddMarketsToResponse(
25113
26374
  data,
@@ -25325,7 +26586,10 @@ function lenderApiOnly(lender, chainId) {
25325
26586
  if (isTeller(lender)) return true;
25326
26587
  if (isInverse(lender)) return true;
25327
26588
  if (isTermMax(lender)) return true;
26589
+ if (isResupply(lender)) return true;
25328
26590
  if (isUsdd(lender)) return true;
26591
+ if (isFrankencoin(lender)) return true;
26592
+ if (isLlamaLend(lender)) return true;
25329
26593
  return false;
25330
26594
  }
25331
26595
  function lenderApiWithOnChainFallback(lender, chainId) {
@@ -26477,8 +27741,22 @@ var buildRiverUserCall = (chainId, lender, account) => {
26477
27741
  });
26478
27742
  return calls;
26479
27743
  };
27744
+ var LLAMALEND_CALLS_PER_MARKET = 5;
27745
+ var buildLlamaLendUserCall = (chainId, lender, account, spender) => {
27746
+ const cfg = llamaLendConfigFor(lender, chainId);
27747
+ const markets = llamaLendChainData(lender, chainId)?.markets ?? [];
27748
+ if (!cfg || markets.length === 0) return [];
27749
+ const delegate = account;
27750
+ return markets.flatMap((m) => [
27751
+ { address: m.controller, name: "user_state", params: [account] },
27752
+ { address: m.controller, name: "health", params: [account, true] },
27753
+ { address: m.controller, name: "user_prices", params: [account] },
27754
+ { address: m.amm, name: "read_user_tick_numbers", params: [account] },
27755
+ { address: m.controller, name: "approval", params: [account, delegate] }
27756
+ ]);
27757
+ };
26480
27758
  var INVERSE_CALLS_PER_MARKET = 4;
26481
- var INVERSE_TAIL_CALLS = 3;
27759
+ var INVERSE_TAIL_CALLS = 4;
26482
27760
  var proxyInitCode = (impl) => concat([
26483
27761
  "0x3d602d80600a3d3981f3363d3d373d3d3d363d73",
26484
27762
  impl,
@@ -26513,21 +27791,136 @@ var buildInverseUserCall = (chainId, lender, account) => {
26513
27791
  calls.push(
26514
27792
  { address: cfg.dbr, name: "balanceOf", params: [account] },
26515
27793
  { address: cfg.dbr, name: "deficitOf", params: [account] },
26516
- { address: cfg.dbr, name: "signedBalanceOf", params: [account] }
27794
+ { address: cfg.dbr, name: "signedBalanceOf", params: [account] },
27795
+ { address: cfg.dbr, name: "debts", params: [account] }
26517
27796
  );
26518
27797
  return calls;
26519
27798
  };
27799
+ var RESUPPLY_CALLS_PER_PAIR = 2;
27800
+ var ONE3 = 10n ** 18n;
27801
+ var ROSTER_TTL_MS = 5 * 6e4;
27802
+ var DISCOVERY_TTL_MS = 6e4;
27803
+ var SNAPSHOT_CHUNK = 12;
27804
+ var rosterCache = /* @__PURE__ */ new Map();
27805
+ var discoveryCache2 = /* @__PURE__ */ new Map();
27806
+ var rosterKey = (chainId, lender) => `${chainId}:${lender}`;
27807
+ var discoveryKey = (chainId, lender, account) => `${chainId}:${lender}:${account.toLowerCase()}`;
27808
+ var getCachedResupplyDiscovery = (chainId, lender, account) => discoveryCache2.get(discoveryKey(chainId, lender, account));
27809
+ var fetchRoster = async (chainId, lender, registry, allowlist) => {
27810
+ const cached = rosterCache.get(rosterKey(chainId, lender));
27811
+ if (cached && Date.now() - cached.at < ROSTER_TTL_MS) return cached;
27812
+ let addresses = [];
27813
+ const [raw] = await multicallRetryUniversal({
27814
+ chain: chainId,
27815
+ calls: [{ address: registry, name: "getAllPairAddresses", params: [] }],
27816
+ abi: ResupplyRegistryAbi,
27817
+ allowFailure: true
27818
+ });
27819
+ if (Array.isArray(raw)) {
27820
+ addresses = raw.filter(
27821
+ (a) => typeof a === "string" && a.startsWith("0x")
27822
+ );
27823
+ }
27824
+ if (allowlist && allowlist.length > 0) {
27825
+ const allow = new Set(allowlist.map((p) => p.toLowerCase()));
27826
+ addresses = addresses.filter((p) => allow.has(p.toLowerCase()));
27827
+ }
27828
+ if (addresses.length === 0) {
27829
+ const empty = { pairs: [], at: Date.now() };
27830
+ rosterCache.set(rosterKey(chainId, lender), empty);
27831
+ return empty;
27832
+ }
27833
+ const cols = await multicallRetryUniversal({
27834
+ chain: chainId,
27835
+ calls: addresses.map((pair) => ({
27836
+ address: pair,
27837
+ name: "collateral",
27838
+ params: []
27839
+ })),
27840
+ abi: addresses.map(() => ResupplyPairAbi),
27841
+ allowFailure: true
27842
+ });
27843
+ const pairs = addresses.map((pair, i) => ({ pair, collateral: cols[i] })).filter(
27844
+ (p) => typeof p.collateral === "string" && p.collateral.startsWith("0x")
27845
+ );
27846
+ const roster = { pairs, at: Date.now() };
27847
+ rosterCache.set(rosterKey(chainId, lender), roster);
27848
+ return roster;
27849
+ };
27850
+ var discoverPositions = async (chainId, pairs, account) => {
27851
+ const active = [];
27852
+ for (let i = 0; i < pairs.length; i += SNAPSHOT_CHUNK) {
27853
+ const slice2 = pairs.slice(i, i + SNAPSHOT_CHUNK);
27854
+ let res = [];
27855
+ try {
27856
+ res = await multicallRetryUniversal({
27857
+ chain: chainId,
27858
+ calls: slice2.map((p) => ({
27859
+ address: p.pair,
27860
+ name: "getUserSnapshot",
27861
+ params: [account]
27862
+ })),
27863
+ abi: slice2.map(() => ResupplyPairAbi),
27864
+ allowFailure: true
27865
+ });
27866
+ } catch {
27867
+ continue;
27868
+ }
27869
+ slice2.forEach((p, j) => {
27870
+ const snap = res[j];
27871
+ if (!Array.isArray(snap)) return;
27872
+ const borrowShares = typeof snap[0] === "bigint" ? snap[0] : 0n;
27873
+ const collateralShares = typeof snap[1] === "bigint" ? snap[1] : 0n;
27874
+ if (borrowShares === 0n && collateralShares === 0n) return;
27875
+ active.push({ ...p, borrowShares, collateralShares });
27876
+ });
27877
+ }
27878
+ return active;
27879
+ };
27880
+ var buildResupplyUserCall = async (chainId, lender, account) => {
27881
+ const cfg = resupplyConfigFor(lender, chainId);
27882
+ const key = discoveryKey(chainId, lender, account);
27883
+ const stash = (positions2) => discoveryCache2.set(key, { positions: positions2, at: Date.now() });
27884
+ if (!cfg?.registry) {
27885
+ stash([]);
27886
+ return [];
27887
+ }
27888
+ let roster;
27889
+ try {
27890
+ roster = await fetchRoster(chainId, lender, cfg.registry, cfg.pairAllowlist);
27891
+ } catch {
27892
+ return [];
27893
+ }
27894
+ if (roster.pairs.length === 0) {
27895
+ stash([]);
27896
+ return [];
27897
+ }
27898
+ const cachedDiscovery = discoveryCache2.get(key);
27899
+ const positions = cachedDiscovery && Date.now() - cachedDiscovery.at < DISCOVERY_TTL_MS ? cachedDiscovery.positions : await discoverPositions(chainId, roster.pairs, account);
27900
+ stash(positions);
27901
+ if (positions.length === 0) return [];
27902
+ return positions.flatMap(({ pair, collateral }) => [
27903
+ // Totals with interest previewed — the denominator for the share→amount
27904
+ // conversion the parser does locally.
27905
+ { address: pair, name: "getPairAccounting", params: [] },
27906
+ { address: collateral, name: "convertToAssets", params: [ONE3] }
27907
+ ]);
27908
+ };
27909
+ function __resetResupplyUserCaches() {
27910
+ rosterCache.clear();
27911
+ discoveryCache2.clear();
27912
+ }
26520
27913
  var USDD_CALLS_PER_CDP = 1;
26521
27914
  var MAX_CDP_WALK = 64;
26522
27915
  var CACHE_TTL_MS2 = 5 * 6e4;
26523
- var discoveryCache2 = /* @__PURE__ */ new Map();
27916
+ var discoveryCache3 = /* @__PURE__ */ new Map();
26524
27917
  var cacheKey2 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
26525
27918
  var getCachedUsddCdps = (chainId, account) => {
26526
- const hit = discoveryCache2.get(cacheKey2(chainId, account));
27919
+ const hit = discoveryCache3.get(cacheKey2(chainId, account));
26527
27920
  if (!hit || Date.now() - hit.at > CACHE_TTL_MS2) return void 0;
26528
27921
  return hit;
26529
27922
  };
26530
- var big = (v) => {
27923
+ var big2 = (v) => {
26531
27924
  try {
26532
27925
  if (typeof v === "bigint") return v;
26533
27926
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -26539,7 +27932,7 @@ var field6 = (res, name, idx) => res?.[name] ?? res?.[idx];
26539
27932
  var buildUsddUserCall = async (chainId, lender, account) => {
26540
27933
  const cfg = usddConfigFor(lender, chainId);
26541
27934
  const markets = usddChainData(lender, chainId)?.markets ?? [];
26542
- const stash = (d) => discoveryCache2.set(cacheKey2(chainId, account), d);
27935
+ const stash = (d) => discoveryCache3.set(cacheKey2(chainId, account), d);
26543
27936
  if (!cfg || markets.length === 0) {
26544
27937
  stash({ cdps: [], ilks: [], at: Date.now() });
26545
27938
  return [];
@@ -26558,7 +27951,7 @@ var buildUsddUserCall = async (chainId, lender, account) => {
26558
27951
  ],
26559
27952
  allowFailure: false
26560
27953
  });
26561
- owners.push({ owner: account, count: big(rawCount), cursor: big(rawFirst) });
27954
+ owners.push({ owner: account, count: big2(rawCount), cursor: big2(rawFirst) });
26562
27955
  const proxy = String(rawProxy ?? zero);
26563
27956
  if (proxy.toLowerCase() !== zero) {
26564
27957
  const [pCount, pFirst] = await multicallRetryUniversal({
@@ -26570,7 +27963,7 @@ var buildUsddUserCall = async (chainId, lender, account) => {
26570
27963
  ],
26571
27964
  allowFailure: false
26572
27965
  });
26573
- owners.push({ owner: proxy, count: big(pCount), cursor: big(pFirst) });
27966
+ owners.push({ owner: proxy, count: big2(pCount), cursor: big2(pFirst) });
26574
27967
  }
26575
27968
  } catch {
26576
27969
  return [];
@@ -26611,7 +28004,7 @@ var buildUsddUserCall = async (chainId, lender, account) => {
26611
28004
  if (curated.has(ilk)) {
26612
28005
  cdps.push({ cdpId: cursor.toString(), urn: String(urn), ilk });
26613
28006
  }
26614
- cursor = big(field6(link, "next", 1));
28007
+ cursor = big2(field6(link, "next", 1));
26615
28008
  }
26616
28009
  }
26617
28010
  } catch {
@@ -26634,12 +28027,83 @@ var buildUsddUserCall = async (chainId, lender, account) => {
26634
28027
  }
26635
28028
  return calls;
26636
28029
  };
28030
+ var FRANKENCOIN_CALLS_PER_POSITION = 6;
28031
+ var BOOK_TTL_MS = 5 * 6e4;
28032
+ var DISCOVERY_TTL_MS2 = 5 * 6e4;
28033
+ var API_BASE = "https://api.frankencoin.com";
28034
+ var bookCache;
28035
+ var fetchBook = async () => {
28036
+ if (bookCache && Date.now() - bookCache.at < BOOK_TTL_MS) {
28037
+ return bookCache.entries;
28038
+ }
28039
+ const res = await fetch(`${API_BASE}/positions/open`, {
28040
+ headers: { Accept: "application/json" }
28041
+ });
28042
+ if (!res.ok) throw new Error(`frankencoin book: ${res.status}`);
28043
+ const data = await res.json();
28044
+ const entries = Object.values(data?.map ?? {}).map((p) => ({
28045
+ position: String(p.position).toLowerCase(),
28046
+ owner: String(p.owner).toLowerCase(),
28047
+ // An original is its own parent.
28048
+ original: String(p.original ?? p.position).toLowerCase(),
28049
+ version: Number(p.version),
28050
+ closed: !!p.closed,
28051
+ denied: !!p.denied
28052
+ }));
28053
+ bookCache = { at: Date.now(), entries };
28054
+ return entries;
28055
+ };
28056
+ var discoveryCache4 = /* @__PURE__ */ new Map();
28057
+ var cacheKey3 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
28058
+ var getCachedFrankencoinPositions = (chainId, account) => {
28059
+ const hit = discoveryCache4.get(cacheKey3(chainId, account));
28060
+ if (!hit || Date.now() - hit.at > DISCOVERY_TTL_MS2) return void 0;
28061
+ return hit;
28062
+ };
28063
+ var buildFrankencoinUserCall = async (chainId, lender, account) => {
28064
+ const cfg = frankencoinConfigFor(lender, chainId);
28065
+ const markets = frankencoinChainData(lender, chainId)?.markets ?? [];
28066
+ const stash = (d) => discoveryCache4.set(cacheKey3(chainId, account), d);
28067
+ if (!cfg || markets.length === 0) {
28068
+ stash({ positions: [], at: Date.now() });
28069
+ return [];
28070
+ }
28071
+ const curated = new Set(markets.map((m) => m.position.toLowerCase()));
28072
+ const lower3 = account.toLowerCase();
28073
+ let book = [];
28074
+ try {
28075
+ book = await fetchBook();
28076
+ } catch {
28077
+ return [];
28078
+ }
28079
+ const positions = book.filter(
28080
+ (e) => e.owner === lower3 && e.version === 2 && !e.closed && !e.denied && curated.has(e.original)
28081
+ ).map((e) => ({ position: e.position, original: e.original }));
28082
+ stash({ positions, at: Date.now() });
28083
+ if (positions.length === 0) return [];
28084
+ const collByOriginal = new Map(
28085
+ markets.map((m) => [m.position.toLowerCase(), m.collToken])
28086
+ );
28087
+ const calls = [];
28088
+ for (const p of positions) {
28089
+ const coll = collByOriginal.get(p.original);
28090
+ calls.push(
28091
+ { address: p.position, name: "owner", params: [] },
28092
+ { address: p.position, name: "minted", params: [] },
28093
+ { address: p.position, name: "price", params: [] },
28094
+ { address: p.position, name: "expiration", params: [] },
28095
+ { address: p.position, name: "challengedAmount", params: [] },
28096
+ { address: coll, name: "balanceOf", params: [p.position] }
28097
+ );
28098
+ }
28099
+ return calls;
28100
+ };
26637
28101
  var TELLER_CALLS_PER_BID = 4;
26638
28102
  var CACHE_TTL_MS3 = 5 * 6e4;
26639
- var discoveryCache3 = /* @__PURE__ */ new Map();
26640
- var cacheKey3 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
28103
+ var discoveryCache5 = /* @__PURE__ */ new Map();
28104
+ var cacheKey4 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
26641
28105
  var getCachedTellerBids = (chainId, account) => {
26642
- const hit = discoveryCache3.get(cacheKey3(chainId, account));
28106
+ const hit = discoveryCache5.get(cacheKey4(chainId, account));
26643
28107
  if (!hit || Date.now() - hit.at > CACHE_TTL_MS3) return void 0;
26644
28108
  return hit;
26645
28109
  };
@@ -26680,7 +28144,7 @@ var buildTellerUserCall = async (chainId, _lender, account) => {
26680
28144
  return [];
26681
28145
  }
26682
28146
  if (ids.length === 0) {
26683
- discoveryCache3.set(cacheKey3(chainId, account), { bids: [], at: Date.now() });
28147
+ discoveryCache5.set(cacheKey4(chainId, account), { bids: [], at: Date.now() });
26684
28148
  return [];
26685
28149
  }
26686
28150
  const poolByAddr = /* @__PURE__ */ new Map();
@@ -26707,7 +28171,7 @@ var buildTellerUserCall = async (chainId, _lender, account) => {
26707
28171
  const pool = poolByAddr.get(lenderAddr);
26708
28172
  if (pool) kept.push({ bidId: id, pool });
26709
28173
  });
26710
- discoveryCache3.set(cacheKey3(chainId, account), { bids: kept, at: Date.now() });
28174
+ discoveryCache5.set(cacheKey4(chainId, account), { bids: kept, at: Date.now() });
26711
28175
  if (kept.length === 0) return [];
26712
28176
  const ts = nowSec5();
26713
28177
  const calls = [];
@@ -26733,10 +28197,10 @@ var buildTellerUserCall = async (chainId, _lender, account) => {
26733
28197
  };
26734
28198
  var TERMMAX_CALLS_PER_ACCOUNT = 1;
26735
28199
  var CACHE_TTL_MS4 = 5 * 6e4;
26736
- var discoveryCache4 = /* @__PURE__ */ new Map();
26737
- var cacheKey4 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
28200
+ var discoveryCache6 = /* @__PURE__ */ new Map();
28201
+ var cacheKey5 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
26738
28202
  var getCachedTermMaxDiscovery = (chainId, account) => {
26739
- const hit = discoveryCache4.get(cacheKey4(chainId, account));
28203
+ const hit = discoveryCache6.get(cacheKey5(chainId, account));
26740
28204
  if (!hit || Date.now() - hit.at > CACHE_TTL_MS4) return void 0;
26741
28205
  return hit;
26742
28206
  };
@@ -26752,11 +28216,11 @@ var buildTermMaxUserCall = async (chainId, _lender, account) => {
26752
28216
  }
26753
28217
  }
26754
28218
  if (markets.length === 0) {
26755
- discoveryCache4.set(cacheKey4(chainId, account), { markets: [], at: Date.now() });
28219
+ discoveryCache6.set(cacheKey5(chainId, account), { markets: [], at: Date.now() });
26756
28220
  return [];
26757
28221
  }
26758
28222
  markets = [...markets].sort((a, b) => a.market.localeCompare(b.market));
26759
- discoveryCache4.set(cacheKey4(chainId, account), { markets, at: Date.now() });
28223
+ discoveryCache6.set(cacheKey5(chainId, account), { markets, at: Date.now() });
26760
28224
  return [
26761
28225
  {
26762
28226
  address: proto.viewer,
@@ -26789,7 +28253,12 @@ async function buildUserCall(chainId, lender, account, params, getClient) {
26789
28253
  if (isTeller(lender)) return buildTellerUserCall(chainId, lender, account);
26790
28254
  if (isTermMax(lender)) return buildTermMaxUserCall(chainId, lender, account);
26791
28255
  if (isInverse(lender)) return buildInverseUserCall(chainId, lender, account);
28256
+ if (isLlamaLend(lender))
28257
+ return buildLlamaLendUserCall(chainId, lender, account);
28258
+ if (isResupply(lender)) return buildResupplyUserCall(chainId, lender, account);
26792
28259
  if (isUsdd(lender)) return buildUsddUserCall(chainId, lender, account);
28260
+ if (isFrankencoin(lender))
28261
+ return buildFrankencoinUserCall(chainId, lender, account);
26793
28262
  if (isCompoundV3Type(lender))
26794
28263
  return buildCompoundV3UserCall(chainId, lender, account);
26795
28264
  if (isEulerType(lender))
@@ -26826,10 +28295,12 @@ function organizeUserQueries(queries) {
26826
28295
  const teller = queries.filter((q) => isTeller(q.lender));
26827
28296
  const termMax = queries.filter((q) => isTermMax(q.lender));
26828
28297
  const usdd = queries.filter((q) => isUsdd(q.lender));
26829
- if (morphos.length === 0 && gearbox.length === 0 && midnight.length === 0 && term.length === 0 && exactly.length === 0 && liquity.length === 0 && river.length === 0 && teller.length === 0 && termMax.length === 0 && usdd.length === 0)
28298
+ const llamaLend = queries.filter((q) => isLlamaLend(q.lender));
28299
+ const frankencoin = queries.filter((q) => isFrankencoin(q.lender));
28300
+ if (morphos.length === 0 && gearbox.length === 0 && midnight.length === 0 && term.length === 0 && exactly.length === 0 && liquity.length === 0 && river.length === 0 && teller.length === 0 && termMax.length === 0 && usdd.length === 0 && frankencoin.length === 0 && llamaLend.length === 0)
26830
28301
  return queries;
26831
28302
  const others = queries.filter(
26832
- (q) => !isMorphoType(q.lender) && !isGearboxV3(q.lender) && !isMidnight(q.lender) && !isTerm(q.lender) && !isExactly(q.lender) && !isLiquityFamily(q.lender) && !isRiver(q.lender) && !isTeller(q.lender) && !isTermMax(q.lender) && !isUsdd(q.lender)
28303
+ (q) => !isMorphoType(q.lender) && !isGearboxV3(q.lender) && !isMidnight(q.lender) && !isTerm(q.lender) && !isExactly(q.lender) && !isLiquityFamily(q.lender) && !isRiver(q.lender) && !isTeller(q.lender) && !isTermMax(q.lender) && !isUsdd(q.lender) && !isFrankencoin(q.lender) && !isLlamaLend(q.lender)
26833
28304
  );
26834
28305
  const morphoBlue = morphos.filter((q) => q.lender.startsWith("MORPHO_BLUE"));
26835
28306
  const moolah = morphos.filter((q) => q.lender.startsWith("LISTA_DAO"));
@@ -26890,6 +28361,14 @@ function organizeUserQueries(queries) {
26890
28361
  assets: void 0
26891
28362
  });
26892
28363
  }
28364
+ if (frankencoin.length > 0) {
28365
+ result.push({
28366
+ lender: Lender.FRANKENCOIN,
28367
+ account: frankencoin[0].account,
28368
+ params: frankencoin.map((p) => p.lender),
28369
+ assets: void 0
28370
+ });
28371
+ }
26893
28372
  if (usdd.length > 0) {
26894
28373
  result.push({
26895
28374
  lender: Lender.USDD,
@@ -26898,6 +28377,14 @@ function organizeUserQueries(queries) {
26898
28377
  assets: void 0
26899
28378
  });
26900
28379
  }
28380
+ if (llamaLend.length > 0) {
28381
+ result.push({
28382
+ lender: Lender.LLAMALEND,
28383
+ account: llamaLend[0].account,
28384
+ params: llamaLend.map((p) => p.lender),
28385
+ assets: void 0
28386
+ });
28387
+ }
26901
28388
  if (teller.length > 0) {
26902
28389
  result.push({
26903
28390
  lender: Lender.TELLER,
@@ -29417,7 +30904,7 @@ function toDetail(positions, kind, now, penaltyRate, penaltyApr) {
29417
30904
  };
29418
30905
  });
29419
30906
  }
29420
- var getExactlyUserDataConverter = (_lender, chainId, account, meta, requestedLenders) => {
30907
+ var getExactlyUserDataConverter = (_lender, chainId, account, meta) => {
29421
30908
  const expected = exactlyConfig()?.[chainId]?.previewer ? 1 : 0;
29422
30909
  return [
29423
30910
  (data) => {
@@ -29426,69 +30913,32 @@ var getExactlyUserDataConverter = (_lender, chainId, account, meta, requestedLen
29426
30913
  if (!res || res === "0x" || !Array.isArray(res)) return void 0;
29427
30914
  const markets = res;
29428
30915
  const now = nowSec6();
29429
- const enteredCollateral = markets.filter(
29430
- (c) => c.isCollateral && c.floatingDepositAssets + sumPreview(c.fixedDepositPositions) > 0n
29431
- );
29432
- const collateralRow = (c, lenderKey, metaMap) => {
29433
- const cDeposit = c.floatingDepositAssets + sumPreview(c.fixedDepositPositions);
29434
- const collAddr = c.asset.toLowerCase();
29435
- const collUid = createMarketUid(chainId, lenderKey, collAddr);
29436
- const collMeta = metaMap[collUid];
29437
- const collDec = collMeta?.asset?.decimals ?? c.decimals;
29438
- const collDisplayPrice = collMeta ? getDisplayPrice(collMeta) : 0;
29439
- const collOraclePrice = collMeta ? getOraclePrice(collMeta) : 0;
29440
- const collPriceHist = collMeta?.price?.priceUsd24h ?? collDisplayPrice;
29441
- const collStr = parseRawAmount(cDeposit.toString(), collDec);
29442
- const collNum = Number(collStr);
29443
- return {
29444
- uid: collUid,
29445
- usd24h: collNum * collPriceHist,
29446
- row: {
29447
- marketUid: collUid,
29448
- underlying: collAddr,
29449
- deposits: collStr,
29450
- debt: "0",
29451
- debtStable: "0",
29452
- depositsUSD: collNum * collDisplayPrice,
29453
- debtUSD: 0,
29454
- debtStableUSD: 0,
29455
- depositsUSDOracle: collNum * collOraclePrice,
29456
- debtUSDOracle: 0,
29457
- debtStableUSDOracle: 0,
29458
- stableBorrowRate: "0",
29459
- collateralEnabled: true,
29460
- claimableRewards: 0,
29461
- // The SAME deposit reports as the own-asset row under its own
29462
- // market key — cross-key aggregation must skip flagged rows.
29463
- crossCollateral: true
29464
- }
29465
- };
29466
- };
29467
- const out = {};
30916
+ const lenderKey = EXACTLY_LENDER_KEY;
30917
+ const metaMap = meta?.[lenderKey];
30918
+ if (!metaMap) return void 0;
30919
+ const posData = {};
30920
+ let depositsUSD24h = 0;
30921
+ let debtUSD24h = 0;
29468
30922
  for (const m of markets) {
29469
- const lenderKey = exactlyLenderKey(m.market);
29470
- const metaMap = meta?.[lenderKey];
29471
- if (!metaMap) continue;
29472
30923
  const assetAddr = m.asset.toLowerCase();
29473
30924
  const loanUid = createMarketUid(chainId, lenderKey, assetAddr);
29474
30925
  const loanMeta = metaMap[loanUid];
29475
30926
  const decimals = loanMeta?.asset?.decimals ?? m.decimals;
29476
- const loanDisplayPrice = loanMeta ? getDisplayPrice(loanMeta) : 0;
29477
- const loanOraclePrice = loanMeta ? getOraclePrice(loanMeta) : 0;
29478
- const loanPriceHist = loanMeta?.price?.priceUsd24h ?? loanDisplayPrice;
30927
+ const displayPrice = loanMeta ? getDisplayPrice(loanMeta) : 0;
30928
+ const oraclePrice = loanMeta ? getOraclePrice(loanMeta) : 0;
30929
+ const priceHist = loanMeta?.price?.priceUsd24h ?? displayPrice;
29479
30930
  const fixedDebtUnits = sumPreview(m.fixedBorrowPositions);
29480
30931
  const depositUnits = m.floatingDepositAssets + sumPreview(m.fixedDepositPositions);
29481
30932
  const debtUnits = m.floatingBorrowAssets + fixedDebtUnits;
29482
30933
  if (depositUnits === 0n && debtUnits === 0n) continue;
29483
30934
  const depositsStr = parseRawAmount(depositUnits.toString(), decimals);
29484
30935
  const depositsNum = Number(depositsStr);
29485
- const debtStr = parseRawAmount(debtUnits.toString(), decimals);
29486
- const debtNum = Number(debtStr);
29487
30936
  const floatingDebtStr = parseRawAmount(
29488
30937
  m.floatingBorrowAssets.toString(),
29489
30938
  decimals
29490
30939
  );
29491
30940
  const fixedDebtStr = parseRawAmount(fixedDebtUnits.toString(), decimals);
30941
+ const debtNum = Number(floatingDebtStr) + Number(fixedDebtStr);
29492
30942
  const penaltyApr = exactlyPenaltyRateToAprPercent(m.penaltyRate);
29493
30943
  const fixedPositions = [
29494
30944
  ...toDetail(
@@ -29506,21 +30956,23 @@ var getExactlyUserDataConverter = (_lender, chainId, account, meta, requestedLen
29506
30956
  penaltyApr
29507
30957
  )
29508
30958
  ];
29509
- const posData = {};
29510
- let depositsUSD24h = depositsNum * loanPriceHist;
30959
+ depositsUSD24h += depositsNum * priceHist;
30960
+ debtUSD24h += debtNum * priceHist;
29511
30961
  posData[loanUid] = {
29512
30962
  marketUid: loanUid,
29513
30963
  underlying: assetAddr,
29514
30964
  deposits: depositsStr,
29515
30965
  debt: floatingDebtStr,
29516
30966
  debtStable: fixedDebtStr,
29517
- depositsUSD: depositsNum * loanDisplayPrice,
29518
- debtUSD: Number(floatingDebtStr) * loanDisplayPrice,
29519
- debtStableUSD: Number(fixedDebtStr) * loanDisplayPrice,
29520
- depositsUSDOracle: depositsNum * loanOraclePrice,
29521
- debtUSDOracle: Number(floatingDebtStr) * loanOraclePrice,
29522
- debtStableUSDOracle: Number(fixedDebtStr) * loanOraclePrice,
30967
+ depositsUSD: depositsNum * displayPrice,
30968
+ debtUSD: Number(floatingDebtStr) * displayPrice,
30969
+ debtStableUSD: Number(fixedDebtStr) * displayPrice,
30970
+ depositsUSDOracle: depositsNum * oraclePrice,
30971
+ debtUSDOracle: Number(floatingDebtStr) * oraclePrice,
30972
+ debtStableUSDOracle: Number(fixedDebtStr) * oraclePrice,
29523
30973
  stableBorrowRate: "0",
30974
+ // The Auditor's per-asset `enterMarket` flag: only entered deposits
30975
+ // back debt. A deposit with this false is inert collateral-wise.
29524
30976
  collateralEnabled: m.isCollateral,
29525
30977
  claimableRewards: 0,
29526
30978
  // Per-maturity fixed-position detail (survives to the output — the
@@ -29544,10 +30996,10 @@ var getExactlyUserDataConverter = (_lender, chainId, account, meta, requestedLen
29544
30996
  debtStable: trancheStr,
29545
30997
  depositsUSD: 0,
29546
30998
  debtUSD: 0,
29547
- debtStableUSD: Number(trancheStr) * loanDisplayPrice,
30999
+ debtStableUSD: Number(trancheStr) * displayPrice,
29548
31000
  depositsUSDOracle: 0,
29549
31001
  debtUSDOracle: 0,
29550
- debtStableUSDOracle: Number(trancheStr) * loanOraclePrice,
31002
+ debtStableUSDOracle: Number(trancheStr) * oraclePrice,
29551
31003
  collateralEnabled: false,
29552
31004
  claimableRewards: 0,
29553
31005
  term: {
@@ -29578,64 +31030,30 @@ var getExactlyUserDataConverter = (_lender, chainId, account, meta, requestedLen
29578
31030
  }
29579
31031
  };
29580
31032
  }
29581
- for (const c of enteredCollateral) {
29582
- if (c.market.toLowerCase() === m.market.toLowerCase()) continue;
29583
- const { uid, usd24h, row } = collateralRow(c, lenderKey, metaMap);
29584
- posData[uid] = row;
29585
- depositsUSD24h += usd24h;
29586
- }
29587
- const userData = createMultiAccountTypeUserState(
29588
- {
29589
- chainId,
29590
- account,
29591
- lendingPositions: { "0": posData },
29592
- modes: { "0": 0 }
29593
- },
29594
- metaMap,
29595
- {
29596
- "0": {
29597
- totalDeposits24h: depositsUSD24h,
29598
- totalDebt24h: debtNum * loanPriceHist
29599
- }
29600
- }
29601
- );
29602
- if (userData && userData.data.length > 0) out[lenderKey] = userData;
29603
31033
  }
29604
- if (enteredCollateral.length > 0 && requestedLenders?.length) {
29605
- for (const req of new Set(
29606
- requestedLenders.map((l) => l?.toUpperCase())
29607
- )) {
29608
- if (!req?.startsWith("EXACTLY_") || out[req]) continue;
29609
- const metaMap = meta?.[req];
29610
- if (!metaMap) continue;
29611
- const posData = {};
29612
- let depositsUSD24h = 0;
29613
- for (const c of enteredCollateral) {
29614
- if (exactlyLenderKey(c.market) === req) continue;
29615
- const { uid, usd24h, row } = collateralRow(c, req, metaMap);
29616
- posData[uid] = row;
29617
- depositsUSD24h += usd24h;
31034
+ if (Object.keys(posData).length === 0) return void 0;
31035
+ const userData = createMultiAccountTypeUserState(
31036
+ {
31037
+ chainId,
31038
+ account,
31039
+ lendingPositions: { "0": posData },
31040
+ modes: { "0": 0 }
31041
+ },
31042
+ metaMap,
31043
+ {
31044
+ "0": {
31045
+ totalDeposits24h: depositsUSD24h,
31046
+ totalDebt24h: debtUSD24h
29618
31047
  }
29619
- if (Object.keys(posData).length === 0) continue;
29620
- const userData = createMultiAccountTypeUserState(
29621
- {
29622
- chainId,
29623
- account,
29624
- lendingPositions: { "0": posData },
29625
- modes: { "0": 0 }
29626
- },
29627
- metaMap,
29628
- { "0": { totalDeposits24h: depositsUSD24h, totalDebt24h: 0 } }
29629
- );
29630
- if (userData && userData.data.length > 0) out[req] = userData;
29631
31048
  }
29632
- }
29633
- return Object.keys(out).length > 0 ? out : void 0;
31049
+ );
31050
+ if (!userData || userData.data.length === 0) return void 0;
31051
+ return { [lenderKey]: userData };
29634
31052
  },
29635
31053
  expected
29636
31054
  ];
29637
31055
  };
29638
- var big2 = (v) => {
31056
+ var big3 = (v) => {
29639
31057
  try {
29640
31058
  if (typeof v === "bigint") return v;
29641
31059
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -29643,7 +31061,7 @@ var big2 = (v) => {
29643
31061
  }
29644
31062
  return 0n;
29645
31063
  };
29646
- var field7 = (res, name, idx) => big2(res?.[name] ?? res?.[idx]);
31064
+ var field7 = (res, name, idx) => big3(res?.[name] ?? res?.[idx]);
29647
31065
  var getLiquityUserDataConverter = (lender, chainId, account, meta) => {
29648
31066
  const cfg = liquityConfigFor(lender, chainId);
29649
31067
  const branches = liquityBranchesByChain(lender, chainId);
@@ -29764,11 +31182,11 @@ var getLiquityUserDataConverter = (lender, chainId, account, meta) => {
29764
31182
  };
29765
31183
  });
29766
31184
  const spBase = troves.length * 2;
29767
- const spDeposit = big2(slice2[spBase]);
29768
- const spYield = big2(slice2[spBase + 1]);
29769
- const spCollGain = big2(slice2[spBase + 2]);
29770
- const spStashed = big2(slice2[spBase + 3]);
29771
- const collSurplus = branch.collSurplusPool ? big2(slice2[spBase + 4]) : 0n;
31185
+ const spDeposit = big3(slice2[spBase]);
31186
+ const spYield = big3(slice2[spBase + 1]);
31187
+ const spCollGain = big3(slice2[spBase + 2]);
31188
+ const spStashed = big3(slice2[spBase + 3]);
31189
+ const collSurplus = branch.collSurplusPool ? big3(slice2[spBase + 4]) : 0n;
29772
31190
  const spStable = spDeposit + spYield;
29773
31191
  const spColl = spCollGain + spStashed + collSurplus;
29774
31192
  if (spStable > 0n || spColl > 0n) {
@@ -29847,7 +31265,7 @@ var getLiquityUserDataConverter = (lender, chainId, account, meta) => {
29847
31265
  expected
29848
31266
  ];
29849
31267
  };
29850
- var big3 = (v) => {
31268
+ var big4 = (v) => {
29851
31269
  try {
29852
31270
  if (typeof v === "bigint") return v;
29853
31271
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -29855,7 +31273,7 @@ var big3 = (v) => {
29855
31273
  }
29856
31274
  return 0n;
29857
31275
  };
29858
- var field8 = (res, name, idx) => big3(res?.[name] ?? res?.[idx]);
31276
+ var field8 = (res, name, idx) => big4(res?.[name] ?? res?.[idx]);
29859
31277
  var getRiverUserDataConverter = (lender, chainId, account, meta) => {
29860
31278
  const cfg = riverConfigFor(lender, chainId);
29861
31279
  const markets = riverChainData(lender, chainId)?.markets ?? [];
@@ -29867,13 +31285,13 @@ var getRiverUserDataConverter = (lender, chainId, account, meta) => {
29867
31285
  const debtAddr = cfg.debtToken.toLowerCase();
29868
31286
  const debtDecimals = cfg.debtDecimals ?? 18;
29869
31287
  const out = {};
29870
- const spDeposit = big3(data[markets.length * RIVER_CALLS_PER_MARKET]);
31288
+ const spDeposit = big4(data[markets.length * RIVER_CALLS_PER_MARKET]);
29871
31289
  markets.forEach((market, i) => {
29872
31290
  const base = i * RIVER_CALLS_PER_MARKET;
29873
31291
  const entire = data[base];
29874
31292
  if (isFailedCall(entire) || isFailedCall(data[base + 1])) return;
29875
- const status = Number(big3(data[base + 1]));
29876
- const surplus = big3(data[base + 2]);
31293
+ const status = Number(big4(data[base + 1]));
31294
+ const surplus = big4(data[base + 2]);
29877
31295
  const lenderKey = riverLenderKey(lender, chainId, market.index);
29878
31296
  const metaMap = meta?.[lenderKey];
29879
31297
  if (!metaMap) return;
@@ -29981,7 +31399,7 @@ var getRiverUserDataConverter = (lender, chainId, account, meta) => {
29981
31399
  expected
29982
31400
  ];
29983
31401
  };
29984
- var big4 = (v) => {
31402
+ var big5 = (v) => {
29985
31403
  try {
29986
31404
  if (typeof v === "bigint") return v;
29987
31405
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -30000,20 +31418,24 @@ var getInverseUserDataConverter = (lender, chainId, account, meta) => {
30000
31418
  const dolaAddr = cfg.dola.toLowerCase();
30001
31419
  const debtDecimals = cfg.debtDecimals ?? 18;
30002
31420
  const tailBase = markets.length * INVERSE_CALLS_PER_MARKET;
30003
- const dbrBalance = big4(data[tailBase]);
30004
- const dbrDeficit = big4(data[tailBase + 1]);
31421
+ const dbrBalance = big5(data[tailBase]);
31422
+ const dbrDeficit = big5(data[tailBase + 1]);
30005
31423
  const dbrSignedRaw = data[tailBase + 2];
30006
- const dbrSigned = isFailedCall(dbrSignedRaw) ? 0n : big4(dbrSignedRaw);
31424
+ const dbrSigned = isFailedCall(dbrSignedRaw) ? 0n : big5(dbrSignedRaw);
31425
+ const dbrTotalDebtRaw = data[tailBase + 3];
31426
+ const dbrTotalDebt = isFailedCall(dbrTotalDebtRaw) ? 0n : big5(dbrTotalDebtRaw);
31427
+ const dbrRunway = dbrTotalDebt > 0n ? dbrBalance * 31536000n / dbrTotalDebt : 0n;
31428
+ const nowSec9 = BigInt(Math.floor(Date.now() / 1e3));
30007
31429
  const out = {};
30008
31430
  markets.forEach((market, i) => {
30009
31431
  const base = i * INVERSE_CALLS_PER_MARKET;
30010
- const escrowBal = isFailedCall(data[base]) ? 0n : big4(data[base]);
31432
+ const escrowBal = isFailedCall(data[base]) ? 0n : big5(data[base]);
30011
31433
  const debtRaw = data[base + 1];
30012
31434
  if (isFailedCall(debtRaw)) return;
30013
- const debt = big4(debtRaw);
31435
+ const debt = big5(debtRaw);
30014
31436
  if (escrowBal === 0n && debt === 0n) return;
30015
- const creditLimit = isFailedCall(data[base + 2]) ? 0n : big4(data[base + 2]);
30016
- const withdrawalLimit = isFailedCall(data[base + 3]) ? 0n : big4(data[base + 3]);
31437
+ const creditLimit = isFailedCall(data[base + 2]) ? 0n : big5(data[base + 2]);
31438
+ const withdrawalLimit = isFailedCall(data[base + 3]) ? 0n : big5(data[base + 3]);
30017
31439
  const lenderKey = inverseLenderKey(lender, market.address);
30018
31440
  const metaMap = meta?.[lenderKey];
30019
31441
  if (!metaMap) return;
@@ -30034,7 +31456,10 @@ var getInverseUserDataConverter = (lender, chainId, account, meta) => {
30034
31456
  withdrawalLimit: withdrawalLimit.toString(),
30035
31457
  dbrBalance: dbrBalance.toString(),
30036
31458
  dbrDeficit: dbrDeficit.toString(),
30037
- dbrSignedBalance: dbrSigned.toString()
31459
+ dbrSignedBalance: dbrSigned.toString(),
31460
+ dbrTotalDebt: dbrTotalDebt.toString(),
31461
+ dbrRunwaySeconds: dbrRunway.toString(),
31462
+ dbrDepletionTimestamp: dbrTotalDebt > 0n ? String(nowSec9 + dbrRunway) : void 0
30038
31463
  };
30039
31464
  const collStr = parseRawAmount(escrowBal.toString(), collDecimals);
30040
31465
  const collNum = Number(collStr);
@@ -30096,8 +31521,273 @@ var getInverseUserDataConverter = (lender, chainId, account, meta) => {
30096
31521
  expected
30097
31522
  ];
30098
31523
  };
31524
+ var big6 = (v) => {
31525
+ try {
31526
+ if (typeof v === "bigint") return v;
31527
+ if (typeof v === "number" || typeof v === "string") return BigInt(v);
31528
+ } catch {
31529
+ }
31530
+ return 0n;
31531
+ };
31532
+ var arrAt = (v, i) => {
31533
+ if (isFailedCall(v) || !Array.isArray(v)) return 0n;
31534
+ return big6(v[i]);
31535
+ };
31536
+ var getLlamaLendUserDataConverter = (lender, chainId, account, meta) => {
31537
+ const cfg = llamaLendConfigFor(lender, chainId);
31538
+ const markets = llamaLendChainData(lender, chainId)?.markets ?? [];
31539
+ const expected = cfg && markets.length > 0 ? markets.length * LLAMALEND_CALLS_PER_MARKET : 0;
31540
+ return [
31541
+ (data) => {
31542
+ if (!cfg || expected === 0) return void 0;
31543
+ if (!data || data.length < expected) return void 0;
31544
+ const out = {};
31545
+ markets.forEach((market, i) => {
31546
+ const base = i * LLAMALEND_CALLS_PER_MARKET;
31547
+ const stateRaw = data[base];
31548
+ if (isFailedCall(stateRaw) || !Array.isArray(stateRaw)) return;
31549
+ const collateral = big6(stateRaw[0]);
31550
+ const bandBorrowed = big6(stateRaw[1]);
31551
+ const debt = big6(stateRaw[2]);
31552
+ const bandCount = Number(big6(stateRaw[3]));
31553
+ if (collateral === 0n && debt === 0n && bandBorrowed === 0n) return;
31554
+ const healthRaw = data[base + 1];
31555
+ const health = isFailedCall(healthRaw) ? 0n : big6(healthRaw);
31556
+ const pricesRaw = data[base + 2];
31557
+ const priceUpper = arrAt(pricesRaw, 0);
31558
+ const priceLower = arrAt(pricesRaw, 1);
31559
+ const ticksRaw = data[base + 3];
31560
+ const bands = isFailedCall(ticksRaw) || !Array.isArray(ticksRaw) ? void 0 : [Number(big6(ticksRaw[0])), Number(big6(ticksRaw[1]))];
31561
+ const approvalRaw = data[base + 4];
31562
+ const delegated = isFailedCall(approvalRaw) ? false : approvalRaw === true;
31563
+ const lenderKey = llamaLendLenderKey(lender, market.controller);
31564
+ const metaMap = meta?.[lenderKey];
31565
+ if (!metaMap) return;
31566
+ const collAddr = market.collateralToken.toLowerCase();
31567
+ const loanAddr = market.borrowedToken.toLowerCase();
31568
+ const collUid = createMarketUid(chainId, lenderKey, collAddr);
31569
+ const loanUid = createMarketUid(chainId, lenderKey, loanAddr);
31570
+ const collMeta = metaMap[collUid];
31571
+ const loanMeta = metaMap[loanUid];
31572
+ const collDecimals = collMeta?.asset?.decimals ?? market.collateralDecimals;
31573
+ const loanDecimals = loanMeta?.asset?.decimals ?? market.borrowedDecimals;
31574
+ const collDisplay = collMeta ? getDisplayPrice(collMeta) : 0;
31575
+ const collOracle = collMeta ? getOraclePrice(collMeta) : 0;
31576
+ const collHist = collMeta?.price?.priceUsd24h ?? collDisplay;
31577
+ const loanDisplay = loanMeta ? getDisplayPrice(loanMeta) : 0;
31578
+ const loanOracle = loanMeta ? getOraclePrice(loanMeta) : 0;
31579
+ const loanHist = loanMeta?.price?.priceUsd24h ?? loanDisplay;
31580
+ const llamalendInfo = {
31581
+ health: health.toString(),
31582
+ priceUpper: priceUpper.toString(),
31583
+ priceLower: priceLower.toString(),
31584
+ bands,
31585
+ bandCount,
31586
+ bandCollateralInBorrowed: bandBorrowed.toString(),
31587
+ softLiquidating: bandBorrowed > 0n,
31588
+ delegated,
31589
+ supportsDelegation: market.supportsDelegation === true,
31590
+ version: market.version
31591
+ };
31592
+ const collStr = parseRawAmount(collateral.toString(), collDecimals);
31593
+ const collNum = Number(collStr);
31594
+ const debtStr = parseRawAmount(debt.toString(), loanDecimals);
31595
+ const debtNum = Number(debtStr);
31596
+ const bandBorrowedStr = parseRawAmount(
31597
+ bandBorrowed.toString(),
31598
+ loanDecimals
31599
+ );
31600
+ const bandBorrowedNum = Number(bandBorrowedStr);
31601
+ const lendingPositions = {
31602
+ "0": {
31603
+ [collUid]: {
31604
+ marketUid: collUid,
31605
+ underlying: collAddr,
31606
+ deposits: collStr,
31607
+ debt: "0",
31608
+ debtStable: "0",
31609
+ depositsUSD: collNum * collDisplay,
31610
+ debtUSD: 0,
31611
+ debtStableUSD: 0,
31612
+ depositsUSDOracle: collNum * collOracle,
31613
+ debtUSDOracle: 0,
31614
+ debtStableUSDOracle: 0,
31615
+ stableBorrowRate: "0",
31616
+ collateralEnabled: true,
31617
+ claimableRewards: 0
31618
+ },
31619
+ [loanUid]: {
31620
+ marketUid: loanUid,
31621
+ underlying: loanAddr,
31622
+ deposits: bandBorrowedStr,
31623
+ debt: debtStr,
31624
+ debtStable: "0",
31625
+ depositsUSD: bandBorrowedNum * loanDisplay,
31626
+ debtUSD: debtNum * loanDisplay,
31627
+ debtStableUSD: 0,
31628
+ depositsUSDOracle: bandBorrowedNum * loanOracle,
31629
+ debtUSDOracle: debtNum * loanOracle,
31630
+ debtStableUSDOracle: 0,
31631
+ stableBorrowRate: "0",
31632
+ collateralEnabled: false,
31633
+ claimableRewards: 0,
31634
+ llamalendInfo
31635
+ }
31636
+ }
31637
+ };
31638
+ const modes = { "0": 0 };
31639
+ const hist = {
31640
+ "0": {
31641
+ totalDeposits24h: collNum * collHist + bandBorrowedNum * loanHist,
31642
+ totalDebt24h: debtNum * loanHist
31643
+ }
31644
+ };
31645
+ const userData = createMultiAccountTypeUserState(
31646
+ { chainId, account, lendingPositions, modes },
31647
+ metaMap,
31648
+ hist
31649
+ );
31650
+ if (userData && userData.data.length > 0) out[lenderKey] = userData;
31651
+ });
31652
+ return Object.keys(out).length > 0 ? out : void 0;
31653
+ },
31654
+ expected
31655
+ ];
31656
+ };
31657
+ var big7 = (v) => {
31658
+ try {
31659
+ if (typeof v === "bigint") return v;
31660
+ if (typeof v === "number" || typeof v === "string") return BigInt(v);
31661
+ } catch {
31662
+ }
31663
+ return 0n;
31664
+ };
31665
+ var tupleAt = (v, i) => Array.isArray(v) ? big7(v[i]) : 0n;
31666
+ var ONE4 = 10n ** 18n;
31667
+ function sharesToAmount(shares, totalAmount, totalShares) {
31668
+ if (totalShares === 0n || shares === 0n) return 0n;
31669
+ const q = shares * totalAmount / totalShares;
31670
+ return q * totalShares < shares * totalAmount ? q + 1n : q;
31671
+ }
31672
+ var getResupplyUserDataConverter = (lender, chainId, account, meta) => {
31673
+ const cfg = resupplyConfigFor(lender, chainId);
31674
+ const discovery = getCachedResupplyDiscovery(chainId, lender, account);
31675
+ const positions = discovery?.positions ?? [];
31676
+ const expected = cfg && positions.length > 0 ? positions.length * RESUPPLY_CALLS_PER_PAIR : 0;
31677
+ return [
31678
+ (data) => {
31679
+ if (!cfg || expected === 0) return void 0;
31680
+ if (!data || data.length < expected) return void 0;
31681
+ const debtAddr = cfg.reusd.toLowerCase();
31682
+ const debtDecimals = cfg.debtDecimals ?? 18;
31683
+ const out = {};
31684
+ positions.forEach(
31685
+ ({ pair, collateral, borrowShares, collateralShares }, i) => {
31686
+ const base = i * RESUPPLY_CALLS_PER_PAIR;
31687
+ const accounting = data[base];
31688
+ if (isFailedCall(accounting) || !Array.isArray(accounting)) return;
31689
+ const totalBorrowAmount = tupleAt(accounting, 1);
31690
+ const totalBorrowShares = tupleAt(accounting, 2);
31691
+ const sharePrice = isFailedCall(data[base + 1]) ? 0n : big7(data[base + 1]);
31692
+ const lenderKey = resupplyLenderKey(lender, chainId, pair);
31693
+ const metaMap = meta?.[lenderKey];
31694
+ if (!metaMap) return;
31695
+ const debt = sharesToAmount(
31696
+ borrowShares,
31697
+ totalBorrowAmount,
31698
+ totalBorrowShares
31699
+ );
31700
+ const collUnderlying = sharePrice > 0n ? collateralShares * sharePrice / ONE4 : 0n;
31701
+ const collAddrEntry = Object.values(metaMap).find(
31702
+ (m) => m?.underlying && m.underlying.toLowerCase() !== debtAddr
31703
+ );
31704
+ const collAddr = collAddrEntry?.underlying?.toLowerCase();
31705
+ if (!collAddr) return;
31706
+ const collUid = createMarketUid(chainId, lenderKey, collAddr);
31707
+ const loanUid = createMarketUid(chainId, lenderKey, debtAddr);
31708
+ const collMeta = metaMap[collUid];
31709
+ const loanMeta = metaMap[loanUid];
31710
+ const collDecimals = collMeta?.asset?.decimals ?? 18;
31711
+ const collDisplay = collMeta ? getDisplayPrice(collMeta) : 0;
31712
+ const collOracle = collMeta ? getOraclePrice(collMeta) : 0;
31713
+ const collHist = collMeta?.price?.priceUsd24h ?? collDisplay;
31714
+ const loanDisplay = loanMeta ? getDisplayPrice(loanMeta) : 0;
31715
+ const loanOracle = loanMeta ? getOraclePrice(loanMeta) : 0;
31716
+ const loanHist = loanMeta?.price?.priceUsd24h ?? loanDisplay;
31717
+ const resupplyInfo = {
31718
+ borrowShares: borrowShares.toString(),
31719
+ collateralShares: collateralShares.toString(),
31720
+ collateralSharePrice: sharePrice.toString(),
31721
+ pair,
31722
+ collateralVault: collateral
31723
+ };
31724
+ const collStr = parseRawAmount(
31725
+ collUnderlying.toString(),
31726
+ collDecimals
31727
+ );
31728
+ const collNum = Number(collStr);
31729
+ const debtStr = parseRawAmount(debt.toString(), debtDecimals);
31730
+ const debtNum = Number(debtStr);
31731
+ const lendingPositions = {
31732
+ "0": {
31733
+ [collUid]: {
31734
+ marketUid: collUid,
31735
+ underlying: collAddr,
31736
+ deposits: collStr,
31737
+ debt: "0",
31738
+ debtStable: "0",
31739
+ depositsUSD: collNum * collDisplay,
31740
+ debtUSD: 0,
31741
+ debtStableUSD: 0,
31742
+ depositsUSDOracle: collNum * collOracle,
31743
+ debtUSDOracle: 0,
31744
+ debtStableUSDOracle: 0,
31745
+ stableBorrowRate: "0",
31746
+ collateralEnabled: true,
31747
+ claimableRewards: 0,
31748
+ resupplyInfo
31749
+ },
31750
+ [loanUid]: {
31751
+ marketUid: loanUid,
31752
+ underlying: debtAddr,
31753
+ deposits: "0",
31754
+ debt: debtStr,
31755
+ debtStable: "0",
31756
+ depositsUSD: 0,
31757
+ debtUSD: debtNum * loanDisplay,
31758
+ debtStableUSD: 0,
31759
+ depositsUSDOracle: 0,
31760
+ debtUSDOracle: debtNum * loanOracle,
31761
+ debtStableUSDOracle: 0,
31762
+ stableBorrowRate: "0",
31763
+ collateralEnabled: false,
31764
+ claimableRewards: 0,
31765
+ resupplyInfo
31766
+ }
31767
+ }
31768
+ };
31769
+ const modes = { "0": 0 };
31770
+ const hist = {
31771
+ "0": {
31772
+ totalDeposits24h: collNum * collHist,
31773
+ totalDebt24h: debtNum * loanHist
31774
+ }
31775
+ };
31776
+ const userData = createMultiAccountTypeUserState(
31777
+ { chainId, account, lendingPositions, modes },
31778
+ metaMap,
31779
+ hist
31780
+ );
31781
+ if (userData && userData.data.length > 0) out[lenderKey] = userData;
31782
+ }
31783
+ );
31784
+ return Object.keys(out).length > 0 ? out : void 0;
31785
+ },
31786
+ expected
31787
+ ];
31788
+ };
30099
31789
  var RAY4 = 10n ** 27n;
30100
- var big5 = (v) => {
31790
+ var big8 = (v) => {
30101
31791
  try {
30102
31792
  if (typeof v === "bigint") return v;
30103
31793
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -30105,7 +31795,7 @@ var big5 = (v) => {
30105
31795
  }
30106
31796
  return 0n;
30107
31797
  };
30108
- var field9 = (res, name, idx) => big5(res?.[name] ?? res?.[idx]);
31798
+ var field9 = (res, name, idx) => big8(res?.[name] ?? res?.[idx]);
30109
31799
  var getUsddUserDataConverter = (lender, chainId, account, meta) => {
30110
31800
  const cfg = usddConfigFor(lender, chainId);
30111
31801
  const markets = usddChainData(lender, chainId)?.markets ?? [];
@@ -30218,10 +31908,142 @@ var getUsddUserDataConverter = (lender, chainId, account, meta) => {
30218
31908
  expected
30219
31909
  ];
30220
31910
  };
31911
+ var big9 = (v) => {
31912
+ try {
31913
+ if (typeof v === "bigint") return v;
31914
+ if (typeof v === "number" || typeof v === "string") return BigInt(v);
31915
+ } catch {
31916
+ }
31917
+ return 0n;
31918
+ };
31919
+ var getFrankencoinUserDataConverter = (lender, chainId, account, meta) => {
31920
+ const cfg = frankencoinConfigFor(lender, chainId);
31921
+ const markets = frankencoinChainData(lender, chainId)?.markets ?? [];
31922
+ const discovery = getCachedFrankencoinPositions(chainId, account);
31923
+ const positions = discovery?.positions ?? [];
31924
+ const expected = cfg && markets.length > 0 && positions.length > 0 ? positions.length * FRANKENCOIN_CALLS_PER_POSITION : 0;
31925
+ return [
31926
+ (data) => {
31927
+ if (!cfg || expected === 0) return void 0;
31928
+ if (!data || data.length < expected) return void 0;
31929
+ const debtAddr = cfg.zchf.toLowerCase();
31930
+ const debtDecimals = cfg.debtDecimals ?? 18;
31931
+ const marketByOriginal = new Map(
31932
+ markets.map((m) => [m.position.toLowerCase(), m])
31933
+ );
31934
+ const lowerAccount = account.toLowerCase();
31935
+ const perMarket = /* @__PURE__ */ new Map();
31936
+ positions.forEach((p, i) => {
31937
+ const base = i * FRANKENCOIN_CALLS_PER_POSITION;
31938
+ const ownerRes = data[base];
31939
+ if (isFailedCall(ownerRes)) return;
31940
+ if (String(ownerRes).toLowerCase() !== lowerAccount) return;
31941
+ const minted = big9(data[base + 1]);
31942
+ const price2 = big9(data[base + 2]);
31943
+ const expiration = big9(data[base + 3]);
31944
+ const challenged = big9(data[base + 4]);
31945
+ const coll = big9(data[base + 5]);
31946
+ if (minted === 0n && coll === 0n) return;
31947
+ const market = marketByOriginal.get(p.original);
31948
+ if (!market) return;
31949
+ const key = frankencoinLenderKey(lender, chainId, market.position);
31950
+ if (!perMarket.has(key)) perMarket.set(key, { market, rows: [] });
31951
+ perMarket.get(key).rows.push({
31952
+ info: {
31953
+ position: p.position,
31954
+ original: p.original,
31955
+ declaredPrice: price2.toString(),
31956
+ expiration: expiration.toString(),
31957
+ challengedAmount: challenged.toString(),
31958
+ reserveContributionPPM: String(market.reserveContribution)
31959
+ },
31960
+ coll,
31961
+ debt: minted
31962
+ });
31963
+ });
31964
+ const out = {};
31965
+ for (const [lenderKey, { market, rows }] of perMarket) {
31966
+ const metaMap = meta?.[lenderKey];
31967
+ if (!metaMap) continue;
31968
+ const collAddr = market.collToken.toLowerCase();
31969
+ const collUid = createMarketUid(chainId, lenderKey, collAddr);
31970
+ const loanUid = createMarketUid(chainId, lenderKey, debtAddr);
31971
+ const collMeta = metaMap[collUid];
31972
+ const loanMeta = metaMap[loanUid];
31973
+ const collDecimals = collMeta?.asset?.decimals ?? market.collDecimals;
31974
+ const collDisplay = collMeta ? getDisplayPrice(collMeta) : 0;
31975
+ const collOracle = collMeta ? getOraclePrice(collMeta) : 0;
31976
+ const collHist = collMeta?.price?.priceUsd24h ?? collDisplay;
31977
+ const loanDisplay = loanMeta ? getDisplayPrice(loanMeta) : 0;
31978
+ const loanOracle = loanMeta ? getOraclePrice(loanMeta) : 0;
31979
+ const loanHist = loanMeta?.price?.priceUsd24h ?? loanDisplay;
31980
+ const lendingPositions = {};
31981
+ const modes = {};
31982
+ const hist = {};
31983
+ for (const row of rows) {
31984
+ const id = row.info.position;
31985
+ const collStr = parseRawAmount(row.coll.toString(), collDecimals);
31986
+ const collNum = Number(collStr);
31987
+ const debtStr = parseRawAmount(row.debt.toString(), debtDecimals);
31988
+ const debtNum = Number(debtStr);
31989
+ lendingPositions[id] = {
31990
+ [collUid]: {
31991
+ marketUid: collUid,
31992
+ underlying: collAddr,
31993
+ deposits: collStr,
31994
+ debt: "0",
31995
+ debtStable: "0",
31996
+ depositsUSD: collNum * collDisplay,
31997
+ debtUSD: 0,
31998
+ debtStableUSD: 0,
31999
+ depositsUSDOracle: collNum * collOracle,
32000
+ debtUSDOracle: 0,
32001
+ debtStableUSDOracle: 0,
32002
+ stableBorrowRate: "0",
32003
+ collateralEnabled: true,
32004
+ claimableRewards: 0
32005
+ },
32006
+ [loanUid]: {
32007
+ marketUid: loanUid,
32008
+ underlying: debtAddr,
32009
+ deposits: "0",
32010
+ debt: debtStr,
32011
+ debtStable: "0",
32012
+ depositsUSD: 0,
32013
+ debtUSD: debtNum * loanDisplay,
32014
+ debtStableUSD: 0,
32015
+ depositsUSDOracle: 0,
32016
+ debtUSDOracle: debtNum * loanOracle,
32017
+ debtStableUSDOracle: 0,
32018
+ stableBorrowRate: "0",
32019
+ collateralEnabled: false,
32020
+ claimableRewards: 0,
32021
+ frankencoinInfo: row.info
32022
+ }
32023
+ };
32024
+ modes[id] = 0;
32025
+ hist[id] = {
32026
+ totalDeposits24h: collNum * collHist,
32027
+ totalDebt24h: debtNum * loanHist
32028
+ };
32029
+ }
32030
+ if (Object.keys(lendingPositions).length === 0) continue;
32031
+ const userData = createMultiAccountTypeUserState(
32032
+ { chainId, account, lendingPositions, modes },
32033
+ metaMap,
32034
+ hist
32035
+ );
32036
+ if (userData && userData.data.length > 0) out[lenderKey] = userData;
32037
+ }
32038
+ return Object.keys(out).length > 0 ? out : void 0;
32039
+ },
32040
+ expected
32041
+ ];
32042
+ };
30221
32043
 
30222
32044
  // src/lending/user-data/teller/userCallParse.ts
30223
32045
  var nowSec7 = () => Math.floor(Date.now() / 1e3);
30224
- var big6 = (v) => {
32046
+ var big10 = (v) => {
30225
32047
  try {
30226
32048
  if (typeof v === "bigint") return v;
30227
32049
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -30243,7 +32065,7 @@ var getTellerUserDataConverter = (_lender, chainId, account, meta) => {
30243
32065
  const base = i * TELLER_CALLS_PER_BID;
30244
32066
  const bidRes = data[base];
30245
32067
  const owed = data[base + 1];
30246
- const collAmount = big6(data[base + 2]);
32068
+ const collAmount = big10(data[base + 2]);
30247
32069
  const defaulted = !!data[base + 3];
30248
32070
  if (isFailedCall(bidRes) || isFailedCall(owed) || !bidRes) return;
30249
32071
  const pool = b.pool;
@@ -30264,17 +32086,17 @@ var getTellerUserDataConverter = (_lender, chainId, account, meta) => {
30264
32086
  const collDisplay = collMeta ? getDisplayPrice(collMeta) : 0;
30265
32087
  const collOracle = collMeta ? getOraclePrice(collMeta) : 0;
30266
32088
  const collHist = collMeta?.price?.priceUsd24h ?? collDisplay;
30267
- const owedPrincipal = big6(field10(owed, "principal", 0));
30268
- const owedInterest = big6(field10(owed, "interest", 1));
32089
+ const owedPrincipal = big10(field10(owed, "principal", 0));
32090
+ const owedInterest = big10(field10(owed, "interest", 1));
30269
32091
  const owedTotal = owedPrincipal + owedInterest;
30270
32092
  if (owedTotal === 0n && collAmount === 0n) return;
30271
32093
  const loanDetails = field10(bidRes, "loanDetails", 5);
30272
32094
  const terms = field10(bidRes, "terms", 6);
30273
32095
  const acceptedTs = Number(
30274
- big6(field10(loanDetails, "acceptedTimestamp", 4))
32096
+ big10(field10(loanDetails, "acceptedTimestamp", 4))
30275
32097
  );
30276
- const loanDuration = Number(big6(field10(loanDetails, "loanDuration", 6)));
30277
- const aprBps = Number(big6(field10(terms, "APR", 2)));
32098
+ const loanDuration = Number(big10(field10(loanDetails, "loanDuration", 6)));
32099
+ const aprBps = Number(big10(field10(terms, "APR", 2)));
30278
32100
  const maturity = acceptedTs > 0 ? acceptedTs + loanDuration : void 0;
30279
32101
  const isMatured = defaulted || maturity !== void 0 && maturity < now;
30280
32102
  const collStr = parseRawAmount(collAmount.toString(), collDecimals);
@@ -30561,7 +32383,7 @@ function getUserDataConverter(lender, chainId, account, params, meta) {
30561
32383
  if (isTerm(lender))
30562
32384
  return getTermUserDataConverter(lender, chainId, account, meta);
30563
32385
  if (isExactly(lender))
30564
- return getExactlyUserDataConverter(lender, chainId, account, meta, params);
32386
+ return getExactlyUserDataConverter(lender, chainId, account, meta);
30565
32387
  if (isLiquityFamily(lender))
30566
32388
  return getLiquityUserDataConverter(lender, chainId, account, meta);
30567
32389
  if (isRiver(lender))
@@ -30572,8 +32394,14 @@ function getUserDataConverter(lender, chainId, account, params, meta) {
30572
32394
  return getTermMaxUserDataConverter(lender, chainId, account, meta);
30573
32395
  if (isInverse(lender))
30574
32396
  return getInverseUserDataConverter(lender, chainId, account, meta);
32397
+ if (isLlamaLend(lender))
32398
+ return getLlamaLendUserDataConverter(lender, chainId, account, meta);
32399
+ if (isResupply(lender))
32400
+ return getResupplyUserDataConverter(lender, chainId, account, meta);
30575
32401
  if (isUsdd(lender))
30576
32402
  return getUsddUserDataConverter(lender, chainId, account, meta);
32403
+ if (isFrankencoin(lender))
32404
+ return getFrankencoinUserDataConverter(lender, chainId, account, meta);
30577
32405
  if (isCompoundV3Type(lender))
30578
32406
  return getCompoundV3UserDataConverter(
30579
32407
  lender,
@@ -35129,6 +36957,15 @@ var accountLensAbi = [
35129
36957
  stateMutability: "view"
35130
36958
  }
35131
36959
  ];
36960
+ var VAULT_CONVERT_ABI = [
36961
+ {
36962
+ name: "convertToAssets",
36963
+ type: "function",
36964
+ stateMutability: "view",
36965
+ inputs: [{ name: "shares", type: "uint256" }],
36966
+ outputs: [{ type: "uint256" }]
36967
+ }
36968
+ ];
35132
36969
  var getAbi2 = (lender) => {
35133
36970
  if (isAaveV4Type(lender)) return [...AaveV4SpokeAbi];
35134
36971
  if (isAaveV2Type(lender))
@@ -35171,9 +37008,16 @@ var getAbi2 = (lender) => {
35171
37008
  return [...RiverTroveManagerAbi, ...RiverStabilityPoolAbi];
35172
37009
  if (isTeller(lender))
35173
37010
  return [...TellerV2Abi, ...TellerCollateralManagerAbi];
37011
+ if (isTermMax(lender)) return [...TermMaxViewerAbi];
35174
37012
  if (isInverse(lender))
35175
37013
  return [...InverseMarketAbi, ...InverseEscrowAbi, ...InverseDbrAbi];
37014
+ if (isLlamaLend(lender))
37015
+ return [...LlamaLendControllerAbi, ...LlamaLendAmmAbi];
35176
37016
  if (isUsdd(lender)) return [...UsddVatAbi];
37017
+ if (isFrankencoin(lender))
37018
+ return [...FrankencoinPositionAbi, ...erc20Abi];
37019
+ if (isResupply(lender))
37020
+ return [...ResupplyPairAbi, ...VAULT_CONVERT_ABI];
35177
37021
  if (isInit(lender)) return InitLensAbi;
35178
37022
  if (isEulerType(lender)) return accountLensAbi;
35179
37023
  if (isCompoundV2Type(lender))
@@ -35785,11 +37629,11 @@ async function fetchJsonWithProxyFallback(url, body, proxyConfig) {
35785
37629
  }
35786
37630
  var inflight = /* @__PURE__ */ new Map();
35787
37631
  var resolved = /* @__PURE__ */ new Map();
35788
- function cacheKey5(chainId, account) {
37632
+ function cacheKey6(chainId, account) {
35789
37633
  return `${chainId}:${account.toLowerCase()}`;
35790
37634
  }
35791
37635
  async function dedupedFetch(chainId, account, loader) {
35792
- const key = cacheKey5(chainId, account);
37636
+ const key = cacheKey6(chainId, account);
35793
37637
  const now = Date.now();
35794
37638
  const cached = resolved.get(key);
35795
37639
  if (cached && cached.expiresAt > now) {
@@ -40275,7 +42119,7 @@ var DOLA_STAKING_URL = "https://www.inverse.finance/api/dola-staking";
40275
42119
  var JDOLA_STAKING_URL = "https://www.inverse.finance/api/junior/jdola-staking";
40276
42120
  var SDOLA_KEY = "SDOLA";
40277
42121
  var SDOLA_GROUP_KEY = "sDOLA::SDOLA";
40278
- var fetchJson2 = async (url) => {
42122
+ var fetchJson3 = async (url) => {
40279
42123
  const res = await fetch(url, {
40280
42124
  headers: { accept: "application/json" },
40281
42125
  signal: AbortSignal.timeout(8e3)
@@ -40285,12 +42129,12 @@ var fetchJson2 = async (url) => {
40285
42129
  };
40286
42130
  var fetchSdolaApyPercent = async () => {
40287
42131
  try {
40288
- const d = await fetchJson2(DOLA_STAKING_URL);
42132
+ const d = await fetchJson3(DOLA_STAKING_URL);
40289
42133
  const apy = Number(d?.calculatedApy);
40290
42134
  if (Number.isFinite(apy) && apy > 0) return apy;
40291
42135
  throw new Error("calculatedApy missing");
40292
42136
  } catch {
40293
- const d = await fetchJson2(JDOLA_STAKING_URL);
42137
+ const d = await fetchJson3(JDOLA_STAKING_URL);
40294
42138
  const apy = Number(d?.sDolaApy);
40295
42139
  if (Number.isFinite(apy) && apy > 0) return apy;
40296
42140
  throw new Error("sDolaApy missing");
@@ -40722,6 +42566,72 @@ var usddFetcher = {
40722
42566
  return out;
40723
42567
  }
40724
42568
  };
42569
+ var FRANKENCOIN_SAVINGS_MODULE = "0x27d9ad987bde08a0d083ef7e0e4043c857a17b38";
42570
+ var SAVINGS_INFO_URL = "https://api.frankencoin.com/savings/core/info";
42571
+ var RATE_ABI2 = [
42572
+ {
42573
+ name: "currentRatePPM",
42574
+ type: "function",
42575
+ stateMutability: "view",
42576
+ inputs: [],
42577
+ outputs: [{ type: "uint24" }]
42578
+ }
42579
+ ];
42580
+ var ZCHF_SAVINGS_KEY = "ZCHF_SAVINGS";
42581
+ var aprFromRatePPM = (ppm) => Number(ppm) / 1e4;
42582
+ var fetchRateOnChain = async () => {
42583
+ const [ppm] = await multicallRetryUniversal({
42584
+ chain: Chain.ETHEREUM_MAINNET,
42585
+ abi: RATE_ABI2,
42586
+ calls: [
42587
+ {
42588
+ address: FRANKENCOIN_SAVINGS_MODULE,
42589
+ name: "currentRatePPM",
42590
+ params: []
42591
+ }
42592
+ ],
42593
+ allowFailure: false
42594
+ });
42595
+ if (ppm === void 0 || ppm === null) {
42596
+ throw new Error("Frankencoin: unreadable currentRatePPM()");
42597
+ }
42598
+ return aprFromRatePPM(ppm);
42599
+ };
42600
+ var fetchRateFromApi = async () => {
42601
+ const res = await fetch(SAVINGS_INFO_URL, {
42602
+ headers: { accept: "application/json" },
42603
+ signal: AbortSignal.timeout(8e3)
42604
+ });
42605
+ if (!res.ok) throw new Error(`Frankencoin: savings info HTTP ${res.status}`);
42606
+ const body = await res.json();
42607
+ const rate = body?.status?.[String(Chain.ETHEREUM_MAINNET)]?.[FRANKENCOIN_SAVINGS_MODULE]?.rate;
42608
+ if (typeof rate !== "number" || !Number.isFinite(rate)) {
42609
+ throw new Error("Frankencoin: savings info carried no rate for the module");
42610
+ }
42611
+ return aprFromRatePPM(rate);
42612
+ };
42613
+ var frankencoinSavingsFetcher = {
42614
+ label: "FRANKENCOIN_SAVINGS",
42615
+ fetch: async () => {
42616
+ const legs = await Promise.allSettled([
42617
+ fetchRateOnChain(),
42618
+ fetchRateFromApi()
42619
+ ]);
42620
+ const onChain = legs[0];
42621
+ if (onChain.status === "fulfilled") {
42622
+ return { [ZCHF_SAVINGS_KEY]: onChain.value };
42623
+ }
42624
+ const api = legs[1];
42625
+ if (api.status === "fulfilled") {
42626
+ return { [ZCHF_SAVINGS_KEY]: api.value };
42627
+ }
42628
+ throw new Error(
42629
+ `Frankencoin: both rate legs failed (chain: ${String(
42630
+ onChain.reason
42631
+ )}; api: ${String(api.reason)})`
42632
+ );
42633
+ }
42634
+ };
40725
42635
 
40726
42636
  // src/yields/intrinsic/fetchers/nativeCreditPool.ts
40727
42637
  var nativeCreditPoolYieldKey = (chainId, underlying) => `${chainId}:${underlying.toLowerCase()}`;
@@ -42830,6 +44740,50 @@ var SINGLE_CHAIN_ENTRIES = {
42830
44740
  withdrawalCooldownSeconds: 90 * 86400,
42831
44741
  yieldFetcher: reProtocolFetcher,
42832
44742
  yieldKey: REUSDE_KEY
44743
+ },
44744
+ {
44745
+ // Frankencoin savings module — a Swiss-franc savings account, not
44746
+ // a vault. There is NO share token: `save(amount)` books ZCHF into
44747
+ // an internal `savings(address)` account and `withdraw(target,
44748
+ // amount)` pays it back out, so the position is a balance that
44749
+ // grows in place (`isRebasing: true`, `exchangeRate` pinned at
44750
+ // par) and the module's own ZCHF balance is the whole book. Hence
44751
+ // the bespoke `frankencoin-savings` reader.
44752
+ //
44753
+ // TRAP — the published address config is stale. `@frankencoin/zchf`
44754
+ // exports `savingsV2 = 0x3BF301B0…`, which now runs at 1 % and
44755
+ // holds 17k ZCHF; the live module is the `savingsReferral`
44756
+ // deployment below, at 3.5 % holding 12.17M (verified on-chain
44757
+ // 2026-08-04, `currentRatePPM() = 35000`). Both answer
44758
+ // `currentRatePPM()`, so only the balance distinguishes them.
44759
+ //
44760
+ // `symbol: 'ZCHF'` is deliberate. `fetchPublic` composes
44761
+ // `displayName` from the *underlying's* token-list symbol
44762
+ // (→ "Frankencoin ZCHF"), so `symbol` only drives `name` and the
44763
+ // ticker a vault list renders — and the honest ticker for a
44764
+ // position denominated 1:1 in ZCHF is ZCHF. Inventing `sZCHF`
44765
+ // would name a token that does not exist, and `svZCHF` is already
44766
+ // taken by an unrelated third-party ERC-4626 wrapper
44767
+ // (0x637f00cA…, ~1 ZCHF of TVL) that would then be conflated with
44768
+ // this row.
44769
+ //
44770
+ // Exit is instant and never short (withdrawals are paid from the
44771
+ // module's own balance), but the YIELD is not instant:
44772
+ // `INTEREST_DELAY` is 3 days and a top-up re-weights the account's
44773
+ // tick counter, so exiting early can realise ~0 %.
44774
+ reader: "frankencoin-savings",
44775
+ address: "0x27d9ad987bde08a0d083ef7e0e4043c857a17b38",
44776
+ underlying: "0xb58e61c3098d85632df34eecfb899a1ed80921cb",
44777
+ // ZCHF
44778
+ symbol: "ZCHF",
44779
+ brand: "Frankencoin",
44780
+ description: "ZCHF is Frankencoin's decentralised Swiss-franc stablecoin, minted against collateral in permissionless, auction-policed positions. The savings module pays a governance-set rate funded by borrower interest: deposits are never lent on (they sit segregated inside the module) and interest is minted by the protocol into your balance, so there are no shares and no share price. Withdrawals are instant and uncapped, but interest only starts accruing after 3 days and a top-up restarts that clock pro-rata, so a short stay can earn nothing.",
44781
+ decimals: 18,
44782
+ isRebasing: true,
44783
+ isMintable: true,
44784
+ withdrawalMode: "instant",
44785
+ yieldFetcher: frankencoinSavingsFetcher,
44786
+ yieldKey: ZCHF_SAVINGS_KEY
42833
44787
  }
42834
44788
  ],
42835
44789
  "42161": [
@@ -44608,14 +46562,15 @@ function parseExactlyResults(data, _meta, context) {
44608
46562
  if (tracked.size > 0 && !tracked.has(market.toLowerCase())) continue;
44609
46563
  const priceUSD = Number(usdPrice) / 1e18;
44610
46564
  if (!(priceUSD > 0)) continue;
44611
- const lenderKey = exactlyLenderKey(market);
44612
46565
  entries.push({
44613
46566
  asset,
44614
46567
  // Direct USD price — no oracle-unit denomination, so raw == USD.
44615
46568
  price: priceUSD,
44616
46569
  priceUSD,
44617
- marketUid: createMarketUid(chainId, lenderKey, asset),
44618
- targetLender: lenderKey,
46570
+ // ONE Exactly key per chain (cross-margin); the asset segment of the
46571
+ // marketUid is what distinguishes the per-asset rows.
46572
+ marketUid: createMarketUid(chainId, EXACTLY_LENDER_KEY, asset),
46573
+ targetLender: EXACTLY_LENDER_KEY,
44619
46574
  description: "Exactly market oracle (USD)"
44620
46575
  });
44621
46576
  }
@@ -50139,7 +52094,7 @@ query EvkByAssets($assets: [Bytes!]!) {
50139
52094
  }
50140
52095
  }
50141
52096
  `;
50142
- var ZERO = 0n;
52097
+ var ZERO2 = 0n;
50143
52098
  var RAY_TO_PERCENT3 = 1e25;
50144
52099
  function readAddress2(field12) {
50145
52100
  if (!field12) return void 0;
@@ -50154,28 +52109,28 @@ function parseVaultFee(v) {
50154
52109
  return n;
50155
52110
  }
50156
52111
  function safeBigInt(v) {
50157
- if (v == null || v === "") return ZERO;
52112
+ if (v == null || v === "") return ZERO2;
50158
52113
  try {
50159
52114
  return BigInt(v);
50160
52115
  } catch {
50161
- return ZERO;
52116
+ return ZERO2;
50162
52117
  }
50163
52118
  }
50164
52119
  function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent, evkIndex) {
50165
52120
  if (!strategies?.length) return 0;
50166
52121
  const totalAssets = safeBigInt(totalAssetsRaw);
50167
- if (totalAssets === ZERO) return 0;
50168
- let weightedRay = ZERO;
52122
+ if (totalAssets === ZERO2) return 0;
52123
+ let weightedRay = ZERO2;
50169
52124
  for (const s of strategies) {
50170
52125
  const evk = s.strategy?.toLowerCase();
50171
52126
  if (!evk) continue;
50172
52127
  const apyRay = evkIndex.bySupplyApyRay.get(evk);
50173
52128
  if (apyRay == null) continue;
50174
52129
  const allocated = safeBigInt(s.allocatedAssets);
50175
- if (allocated === ZERO) continue;
52130
+ if (allocated === ZERO2) continue;
50176
52131
  weightedRay += allocated * apyRay;
50177
52132
  }
50178
- if (weightedRay === ZERO) return 0;
52133
+ if (weightedRay === ZERO2) return 0;
50179
52134
  const apyRayPerAsset = weightedRay / totalAssets;
50180
52135
  const grossPercent = apyToAprPercent(Number(apyRayPerAsset) / RAY_TO_PERCENT3);
50181
52136
  const netPercent = grossPercent * (1 - feePercent / 100);
@@ -50183,24 +52138,24 @@ function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent, evkInd
50183
52138
  }
50184
52139
  function computeRealLiquidity(strategies, totalAssetsRaw, evkIndex) {
50185
52140
  const totalAssets = safeBigInt(totalAssetsRaw);
50186
- if (totalAssets === ZERO) return ZERO;
52141
+ if (totalAssets === ZERO2) return ZERO2;
50187
52142
  if (evkIndex.byCash.size === 0 && evkIndex.bySupplyApyRay.size === 0) {
50188
52143
  return totalAssets;
50189
52144
  }
50190
52145
  if (!strategies?.length) {
50191
52146
  return totalAssets;
50192
52147
  }
50193
- let allocSum = ZERO;
50194
- let withdrawable = ZERO;
52148
+ let allocSum = ZERO2;
52149
+ let withdrawable = ZERO2;
50195
52150
  for (const s of strategies) {
50196
52151
  const alloc = safeBigInt(s.allocatedAssets);
50197
- if (alloc === ZERO) continue;
52152
+ if (alloc === ZERO2) continue;
50198
52153
  allocSum += alloc;
50199
52154
  const evk = s.strategy?.toLowerCase();
50200
52155
  const cash = evk ? evkIndex.byCash.get(evk) : void 0;
50201
52156
  withdrawable += cash == null ? alloc : alloc < cash ? alloc : cash;
50202
52157
  }
50203
- const idle = totalAssets > allocSum ? totalAssets - allocSum : ZERO;
52158
+ const idle = totalAssets > allocSum ? totalAssets - allocSum : ZERO2;
50204
52159
  const result = idle + withdrawable;
50205
52160
  return result > totalAssets ? totalAssets : result;
50206
52161
  }
@@ -50504,11 +52459,11 @@ var fetchEulerEarnVaults = async (chainId, prices = {}, tokenList = {}, multical
50504
52459
  };
50505
52460
  var warn6 = (...args) => {
50506
52461
  };
50507
- var num2 = (v) => {
52462
+ var num3 = (v) => {
50508
52463
  const n = Number(v);
50509
52464
  return Number.isFinite(n) ? n : 0;
50510
52465
  };
50511
- var big7 = (v) => {
52466
+ var big11 = (v) => {
50512
52467
  try {
50513
52468
  if (v === void 0 || v === null || v === "") return "0";
50514
52469
  const s = String(v);
@@ -50539,21 +52494,21 @@ async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, f
50539
52494
  const underlying = lower2(r?.asset?.contractAddress);
50540
52495
  if (!address || !underlying) continue;
50541
52496
  if (r.isEnabled === false) continue;
50542
- const assetDecimals = num2(r?.asset?.decimals) || 18;
52497
+ const assetDecimals = num3(r?.asset?.decimals) || 18;
50543
52498
  const scale = 10 ** assetDecimals;
50544
52499
  const assetEntry = tokenList[underlying];
50545
52500
  const priceKey = toOracleKey(assetEntry?.assetGroup) || toGenericPriceKey(underlying, chainId);
50546
52501
  const priceUsd = prices[priceKey];
50547
- const totalAssets = big7(r.totalAssets);
50548
- const totalSupply = big7(r.totalSupplyAmt);
52502
+ const totalAssets = big11(r.totalAssets);
52503
+ const totalSupply = big11(r.totalSupplyAmt);
50549
52504
  const totalAssetsFormatted = Number(totalAssets) / scale;
50550
- const supplyRate = num2(r.apr) * 100;
50551
- const rewardsRate = num2(r?.incentiveData?.TMX_APR) * 100;
50552
- const rawLiquidity = BigInt(big7(r.redeemableAmt ?? r.idleFunds ?? "0"));
52505
+ const supplyRate = num3(r.apr) * 100;
52506
+ const rewardsRate = num3(r?.incentiveData?.TMX_APR) * 100;
52507
+ const rawLiquidity = BigInt(big11(r.redeemableAmt ?? r.idleFunds ?? "0"));
50553
52508
  const totalAssetsBig = BigInt(totalAssets);
50554
52509
  const liquidity = (rawLiquidity > totalAssetsBig ? totalAssetsBig : rawLiquidity).toString();
50555
52510
  const liquidityFormatted = Number(liquidity) / scale;
50556
- const totalSupplyValue = num2(r.totalSupplyValue);
52511
+ const totalSupplyValue = num3(r.totalSupplyValue);
50557
52512
  out[address] = {
50558
52513
  address,
50559
52514
  underlying,
@@ -50570,8 +52525,8 @@ async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, f
50570
52525
  rewardsRate,
50571
52526
  depositRate: supplyRate + rewardsRate,
50572
52527
  // 1e8-scaled upstream (10000000 = 10%).
50573
- fee: num2(r.performanceFeeRate) / 1e6,
50574
- timelock: num2(r.timeLockSeconds) || void 0,
52528
+ fee: num3(r.performanceFeeRate) / 1e6,
52529
+ timelock: num3(r.timeLockSeconds) || void 0,
50575
52530
  curator: r?.curator?.curatorAddress ? lower2(r.curator.curatorAddress) : void 0,
50576
52531
  // The API is the ONLY source for this — do not derive it from `name`.
50577
52532
  curatorName: r?.curator?.name || void 0,
@@ -50585,7 +52540,7 @@ async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, f
50585
52540
  liquidityUsd: priceUsd ? liquidityFormatted * priceUsd : 0,
50586
52541
  version: r.version,
50587
52542
  isPaused: r.isPaused === true || void 0,
50588
- supplyCap: r.capacity ? big7(r.capacity) : void 0,
52543
+ supplyCap: r.capacity ? big11(r.capacity) : void 0,
50589
52544
  basePool: r.poolAddress ? lower2(r.poolAddress) : void 0
50590
52545
  };
50591
52546
  }
@@ -50641,7 +52596,7 @@ var Erc20DecimalsBalanceAbi = [
50641
52596
 
50642
52597
  // src/vaults/termmax/fetchFromChain.ts
50643
52598
  var DECIMAL_BASE2 = 100000000n;
50644
- var big8 = (v) => {
52599
+ var big12 = (v) => {
50645
52600
  if (v === void 0 || v === null || v === "0x") return 0n;
50646
52601
  try {
50647
52602
  return typeof v === "bigint" ? v : BigInt(v);
@@ -50649,7 +52604,7 @@ var big8 = (v) => {
50649
52604
  return 0n;
50650
52605
  }
50651
52606
  };
50652
- var num3 = (v) => {
52607
+ var num4 = (v) => {
50653
52608
  const n = Number(v);
50654
52609
  return Number.isFinite(n) ? n : void 0;
50655
52610
  };
@@ -50705,23 +52660,23 @@ var fetchTermMaxVaultsFromChain = async (chainId, multicallRetry, prices = {}, t
50705
52660
  vaults.forEach((address, i) => {
50706
52661
  const at = (k) => res[i * READS_PER_VAULT + VAULT_READS.indexOf(k)];
50707
52662
  const asset = addr(at("asset"));
50708
- const totalAssets = big8(at("totalAssets"));
52663
+ const totalAssets = big12(at("totalAssets"));
50709
52664
  if (!asset || totalAssets === 0n) return;
50710
52665
  rows.push({
50711
52666
  address,
50712
52667
  name: str(at("name")),
50713
52668
  symbol: str(at("symbol")),
50714
- decimals: num3(at("decimals")) ?? 18,
52669
+ decimals: num4(at("decimals")) ?? 18,
50715
52670
  asset,
50716
52671
  totalAssets,
50717
- totalSupply: big8(at("totalSupply")),
50718
- annualizedInterest: big8(at("annualizedInterest")),
50719
- accretingPrincipal: big8(at("accretingPrincipal")),
50720
- performanceFeeRate: big8(at("performanceFeeRate")),
50721
- aprRaw: at("apr") != null ? big8(at("apr")) : void 0,
52672
+ totalSupply: big12(at("totalSupply")),
52673
+ annualizedInterest: big12(at("annualizedInterest")),
52674
+ accretingPrincipal: big12(at("accretingPrincipal")),
52675
+ performanceFeeRate: big12(at("performanceFeeRate")),
52676
+ aprRaw: at("apr") != null ? big12(at("apr")) : void 0,
50722
52677
  curator: addr(at("curator")),
50723
52678
  guardian: addr(at("guardian")),
50724
- timelock: num3(at("timelock")),
52679
+ timelock: num4(at("timelock")),
50725
52680
  version: str(at("getVersion"))
50726
52681
  });
50727
52682
  });
@@ -50738,8 +52693,8 @@ var fetchTermMaxVaultsFromChain = async (chainId, multicallRetry, prices = {}, t
50738
52693
  });
50739
52694
  const out = {};
50740
52695
  rows.forEach((r, i) => {
50741
- const assetDecimals = num3(res2[i * 2]) ?? r.decimals;
50742
- const idle = big8(res2[i * 2 + 1]);
52696
+ const assetDecimals = num4(res2[i * 2]) ?? r.decimals;
52697
+ const idle = big12(res2[i * 2 + 1]);
50743
52698
  const assetEntry = tokenList[r.asset];
50744
52699
  const priceKey = toOracleKey(assetEntry?.assetGroup) || toGenericPriceKey(r.asset, chainId);
50745
52700
  const priceUsd = prices[priceKey];
@@ -56142,6 +58097,20 @@ var NativeWithdrawQueueReadAbi = [
56142
58097
  }
56143
58098
  ];
56144
58099
 
58100
+ // src/vaults/savings/abis/frankencoin.ts
58101
+ var FrankencoinSavingsReadAbi = [
58102
+ {
58103
+ /** Savings rate in parts per million — `35000` = 3.5 % nominal APR.
58104
+ * `0` means the module is disabled (`save` reverts with
58105
+ * `ModuleDisabled`); existing balances stay withdrawable. */
58106
+ name: "currentRatePPM",
58107
+ type: "function",
58108
+ stateMutability: "view",
58109
+ inputs: [],
58110
+ outputs: [{ type: "uint24" }]
58111
+ }
58112
+ ];
58113
+
56145
58114
  // src/vaults/savings/abis/yearnStrategy.ts
56146
58115
  var AvailableWithdrawLimitAbi = [
56147
58116
  {
@@ -56241,6 +58210,29 @@ var readerErc4626WithdrawLimit = (entry) => {
56241
58210
  };
56242
58211
  };
56243
58212
 
58213
+ // src/vaults/savings/readers/frankencoinSavings.ts
58214
+ var readerFrankencoinSavings = (entry) => ({
58215
+ calls: [
58216
+ { address: entry.underlying, name: "balanceOf", params: [entry.address] },
58217
+ { address: entry.address, name: "currentRatePPM", params: [] }
58218
+ ],
58219
+ abis: [BalanceOfAbi, FrankencoinSavingsReadAbi],
58220
+ parse: ([balance, ratePPM]) => {
58221
+ const deposits = toBigInt15(balance);
58222
+ if (deposits === void 0) return void 0;
58223
+ if (toBigInt15(ratePPM) === void 0) return void 0;
58224
+ return {
58225
+ totalAssets: deposits,
58226
+ // No shares exist; the "supply" IS the deposited principal, and
58227
+ // the rate is fixed at par. Both are load-bearing downstream:
58228
+ // `fetchPublic` derives `convertToAssets` / `convertToShares` from
58229
+ // `exchangeRate`, and 1e18 makes them the identity.
58230
+ totalSupply: deposits,
58231
+ exchangeRate: ONE_E1811
58232
+ };
58233
+ }
58234
+ });
58235
+
56244
58236
  // src/vaults/savings/readers/navOracle.ts
56245
58237
  var readerNavOracle = (entry) => {
56246
58238
  const shareUnit = 10n ** BigInt(entry.decimals);
@@ -56334,6 +58326,8 @@ var buildReader2 = (entry) => {
56334
58326
  return readerNativeWnlp(entry);
56335
58327
  case "nav-oracle":
56336
58328
  return readerNavOracle(entry);
58329
+ case "frankencoin-savings":
58330
+ return readerFrankencoinSavings(entry);
56337
58331
  case "erc4626-idle":
56338
58332
  return readerErc4626Idle(entry);
56339
58333
  case "erc4626-withdraw-limit":
@@ -56576,7 +58570,7 @@ var pickApr = (apr) => {
56576
58570
  if (apr.inception != null) return { rate: apr.inception, window: "inception" };
56577
58571
  return { rate: 0, window: "none" };
56578
58572
  };
56579
- var num4 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
58573
+ var num5 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
56580
58574
  function parseVault7(v, chainId, prices, tokenList) {
56581
58575
  const address = (v?.address ?? "").toLowerCase();
56582
58576
  const assetAddr = (v?.asset?.address ?? "").toLowerCase();
@@ -56592,14 +58586,14 @@ function parseVault7(v, chainId, prices, tokenList) {
56592
58586
  parseRawAmount(totalAssetsRaw, assetDecimals)
56593
58587
  );
56594
58588
  const apr = {
56595
- weekly: num4(state.weeklyApr?.twrrNetApr),
56596
- monthly: num4(state.monthlyApr?.twrrNetApr),
56597
- yearly: num4(state.yearlyApr?.twrrNetApr),
56598
- inception: num4(state.inceptionApr?.twrrNetApr)
58589
+ weekly: num5(state.weeklyApr?.twrrNetApr),
58590
+ monthly: num5(state.monthlyApr?.twrrNetApr),
58591
+ yearly: num5(state.yearlyApr?.twrrNetApr),
58592
+ inception: num5(state.inceptionApr?.twrrNetApr)
56599
58593
  };
56600
58594
  const { rate: supplyRate, window: aprWindow } = pickApr(apr);
56601
58595
  const oracleKey = toOracleKey(assetMeta?.assetGroup) ?? toGenericPriceKey(assetAddr, chainId);
56602
- const apiTotalAssetsUsd = num4(state.totalAssetsUsd) ?? 0;
58596
+ const apiTotalAssetsUsd = num5(state.totalAssetsUsd) ?? 0;
56603
58597
  const impliedPriceUsd = totalAssetsFormatted > 0 ? apiTotalAssetsUsd / totalAssetsFormatted : 0;
56604
58598
  const priceUsd = prices[oracleKey] ?? prices[assetAddr] ?? impliedPriceUsd;
56605
58599
  const totalAssetsUsd = apiTotalAssetsUsd || totalAssetsFormatted * priceUsd;
@@ -56619,7 +58613,7 @@ function parseVault7(v, chainId, prices, tokenList) {
56619
58613
  totalAssets: totalAssetsRaw,
56620
58614
  totalSupply: totalSupplyRaw,
56621
58615
  pricePerShare: state.pricePerShare?.toString() ?? "0",
56622
- pricePerShareUsd: num4(state.pricePerShareUsd) ?? void 0,
58616
+ pricePerShareUsd: num5(state.pricePerShareUsd) ?? void 0,
56623
58617
  supplyRate,
56624
58618
  rewardsRate: 0,
56625
58619
  depositRate: supplyRate,
@@ -56816,7 +58810,7 @@ var toBigInt16 = (v) => {
56816
58810
  }
56817
58811
  return void 0;
56818
58812
  };
56819
- var num5 = (v) => {
58813
+ var num6 = (v) => {
56820
58814
  const n = Number(v);
56821
58815
  return Number.isFinite(n) ? n : 0;
56822
58816
  };
@@ -56873,12 +58867,12 @@ var fetchAaveEarnVaults = async (chainId, multicallRetry, prices = {}, tokenList
56873
58867
  const totalAssets = toBigInt16(slice2[0]) ?? totalSupply * convertToAssets / shareUnit;
56874
58868
  const totalAssetsFormatted = Number(totalAssets) / 10 ** assetDecimals;
56875
58869
  const asset = tokenList[underlyingLc];
56876
- const priceUsd = prices[underlyingLc] ?? (v.balance?.usdPerToken != null ? num5(v.balance.usdPerToken) : void 0);
58870
+ const priceUsd = prices[underlyingLc] ?? (v.balance?.usdPerToken != null ? num6(v.balance.usdPerToken) : void 0);
56877
58871
  const totalAssetsUsd = priceUsd !== void 0 ? totalAssetsFormatted * priceUsd : 0;
56878
- const supplyRate = num5(v.vaultApr?.formatted);
58872
+ const supplyRate = num6(v.vaultApr?.formatted);
56879
58873
  const rewardsRate = 0;
56880
58874
  const depositRate = supplyRate + rewardsRate;
56881
- const fee = num5(v.fee?.value);
58875
+ const fee = num6(v.fee?.value);
56882
58876
  const symbol = (v.shareSymbol ?? "").trim();
56883
58877
  const shareName = (v.shareName ?? "").trim();
56884
58878
  const name = shareName || symbol;
@@ -56915,7 +58909,7 @@ var fetchAaveEarnVaults = async (chainId, multicallRetry, prices = {}, tokenList
56915
58909
  };
56916
58910
 
56917
58911
  // src/vaults/upshift/fetchPublic.ts
56918
- var num6 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
58912
+ var num7 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
56919
58913
  var isEvmAddress = (a) => /^0x[0-9a-fA-F]{40}$/.test(a);
56920
58914
  var derivePricePerShare = (totalAssetsRaw, totalSupplyRaw, shareDecimals) => {
56921
58915
  try {
@@ -56942,12 +58936,12 @@ function parseVault8(v, chainId, prices, tokenList) {
56942
58936
  const totalAssetsFormatted = Number(
56943
58937
  parseRawAmount(totalAssetsRaw, assetDecimals)
56944
58938
  );
56945
- const base = num6(v.apy?.apy) ?? 0;
56946
- const campaign = num6(v.apy?.campaignApy);
58939
+ const base = num7(v.apy?.apy) ?? 0;
58940
+ const campaign = num7(v.apy?.campaignApy);
56947
58941
  const supplyRate = apyToAprPercent(base);
56948
58942
  const rewardsRate = campaign != null ? apyToAprPercent(campaign) : 0;
56949
58943
  const oracleKey = toOracleKey(assetMeta?.assetGroup) ?? toGenericPriceKey(assetAddr, chainId);
56950
- const apiTvlUsd = num6(v.latest_reported_tvl) ?? 0;
58944
+ const apiTvlUsd = num7(v.latest_reported_tvl) ?? 0;
56951
58945
  const impliedPriceUsd = totalAssetsFormatted > 0 ? apiTvlUsd / totalAssetsFormatted : 0;
56952
58946
  const priceUsd = prices[oracleKey] ?? prices[assetAddr] ?? impliedPriceUsd;
56953
58947
  const totalAssetsUsd = apiTvlUsd || totalAssetsFormatted * priceUsd;
@@ -56972,10 +58966,10 @@ function parseVault8(v, chainId, prices, tokenList) {
56972
58966
  rewardsRate,
56973
58967
  depositRate: supplyRate + rewardsRate,
56974
58968
  apy: {
56975
- base: num6(v.apy?.apy),
58969
+ base: num7(v.apy?.apy),
56976
58970
  campaign,
56977
- points: num6(v.apy?.pointsApy),
56978
- underlying: num6(v.apy?.underlyingApy)
58971
+ points: num7(v.apy?.pointsApy),
58972
+ underlying: num7(v.apy?.underlyingApy)
56979
58973
  },
56980
58974
  isDepositPaused: v.isDepositPaused ?? false,
56981
58975
  isWithdrawalPaused: v.isWithdrawalPaused ?? false,
@@ -57084,9 +59078,9 @@ var asBig = (v) => {
57084
59078
  return null;
57085
59079
  }
57086
59080
  };
57087
- var num7 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
59081
+ var num8 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
57088
59082
  var toPct = (v) => {
57089
- const n = num7(v);
59083
+ const n = num8(v);
57090
59084
  return n == null ? 0 : n * 100;
57091
59085
  };
57092
59086
  var deriveTotalSupply = (totalAssetsRaw, pricePerShareRaw, decimals) => {
@@ -57118,16 +59112,16 @@ function parseVault9(v, chainId, prices, tokenList) {
57118
59112
  const totalAssetsFormatted = Number(
57119
59113
  parseRawAmount(totalAssetsRaw, assetDecimals)
57120
59114
  );
57121
- const realized = num7(v.apr?.netAPR);
57122
- const forward = num7(v.apr?.forwardAPR?.netAPR);
59115
+ const realized = num8(v.apr?.netAPR);
59116
+ const forward = num8(v.apr?.forwardAPR?.netAPR);
57123
59117
  const isForwardApr = realized == null && forward != null;
57124
59118
  const supplyRate = toPct(realized ?? forward);
57125
59119
  const rewardsRate = toPct(v.apr?.extra?.stakingRewardsAPR);
57126
59120
  const fee = toPct(v.apr?.fees?.performance);
57127
59121
  const oracleKey = toOracleKey(assetMeta?.assetGroup) ?? toGenericPriceKey(assetAddr, chainId);
57128
- const apiPrice = num7(v.tvl?.price) ?? 0;
59122
+ const apiPrice = num8(v.tvl?.price) ?? 0;
57129
59123
  const priceUsd = prices[oracleKey] ?? prices[assetAddr] ?? apiPrice;
57130
- const apiTvlUsd = num7(v.tvl?.tvl) ?? 0;
59124
+ const apiTvlUsd = num8(v.tvl?.tvl) ?? 0;
57131
59125
  const totalAssetsUsd = apiTvlUsd || totalAssetsFormatted * priceUsd;
57132
59126
  const name = (v.name ?? "").trim();
57133
59127
  const symbol = (v.symbol ?? "").trim();
@@ -58115,23 +60109,23 @@ var priceGmMarkets = async (chainId, multicallRetry, markets, prices) => {
58115
60109
  const indexMax = price(prices, m.indexToken)?.max;
58116
60110
  if (Array.isArray(dsRes) && longMax != null && shortMax != null) {
58117
60111
  const base = i * SLOTS;
58118
- const big9 = (j) => typeof dsRes[base + j] === "bigint" ? dsRes[base + j] : 0n;
60112
+ const big13 = (j) => typeof dsRes[base + j] === "bigint" ? dsRes[base + j] : 0n;
58119
60113
  const cap = computeDepositCapacityUsd(
58120
- [info?.longTokenAmount, longMax, big9(0), big9(2)],
58121
- [info?.shortTokenAmount, shortMax, big9(1), big9(3)]
60114
+ [info?.longTokenAmount, longMax, big13(0), big13(2)],
60115
+ [info?.shortTokenAmount, shortMax, big13(1), big13(3)]
58122
60116
  );
58123
60117
  if (cap != null) value.depositCapacityUsd = cap;
58124
60118
  if (indexMax != null) {
58125
60119
  const divisor = m.longToken.toLowerCase() === m.shortToken.toLowerCase() ? 2n : 1n;
58126
- const reservedUsdLong = (big9(4) + big9(5)) / divisor * indexMax;
58127
- const reservedUsdShort = (big9(6) + big9(7)) / divisor;
60120
+ const reservedUsdLong = (big13(4) + big13(5)) / divisor * indexMax;
60121
+ const reservedUsdShort = (big13(6) + big13(7)) / divisor;
58128
60122
  const liq = computeLiquidityUsd(
58129
60123
  info?.longTokenUsd,
58130
60124
  info?.shortTokenUsd,
58131
60125
  reservedUsdLong,
58132
60126
  reservedUsdShort,
58133
- big9(8),
58134
- big9(9)
60127
+ big13(8),
60128
+ big13(9)
58135
60129
  );
58136
60130
  if (liq != null)
58137
60131
  value.liquidityUsd = Math.max(0, Math.min(liq, value.tvlUsd));
@@ -58330,27 +60324,27 @@ var fetchGmxExecutionFees = async (chainId, multicallRetry, gasPriceWei) => {
58330
60324
  } catch {
58331
60325
  return void 0;
58332
60326
  }
58333
- const big9 = (i) => typeof res[i] === "bigint" ? res[i] : 0n;
58334
- const base = big9(0);
58335
- const mult = big9(1);
60327
+ const big13 = (i) => typeof res[i] === "bigint" ? res[i] : 0n;
60328
+ const base = big13(0);
60329
+ const mult = big13(1);
58336
60330
  if (base === 0n && mult === 0n) return void 0;
58337
60331
  const PRECISION = 10n ** 30n;
58338
60332
  const adjusted = (opGas) => base + opGas * mult / PRECISION;
58339
60333
  const fee = (opGas) => (adjusted(opGas) * gasPriceWei).toString();
58340
- const glvExtra = big9(6) * GLV_NOMINAL_MARKET_COUNT;
60334
+ const glvExtra = big13(6) * GLV_NOMINAL_MARKET_COUNT;
58341
60335
  return {
58342
60336
  chainId,
58343
60337
  gasPriceWei: gasPriceWei.toString(),
58344
- deposit: fee(big9(2)),
58345
- withdrawal: fee(big9(3)),
58346
- glvDeposit: fee(big9(4) + glvExtra),
58347
- glvWithdrawal: fee(big9(5) + glvExtra)
60338
+ deposit: fee(big13(2)),
60339
+ withdrawal: fee(big13(3)),
60340
+ glvDeposit: fee(big13(4) + glvExtra),
60341
+ glvWithdrawal: fee(big13(5) + glvExtra)
58348
60342
  };
58349
60343
  };
58350
60344
 
58351
60345
  // src/vaults/gmx/fetchPublic.ts
58352
60346
  var GMX_TOKEN_DECIMALS = 18;
58353
- var num8 = (n) => typeof n === "number" && Number.isFinite(n) ? n : 0;
60347
+ var num9 = (n) => typeof n === "number" && Number.isFinite(n) ? n : 0;
58354
60348
  var minDefined = (a, b) => a == null ? b : b == null ? a : Math.min(a, b);
58355
60349
  var glvMarketRoomUsd = (cap, priceUsd) => {
58356
60350
  const currentUsd = Number(cap.balanceAmount) / 1e18 * priceUsd;
@@ -58384,9 +60378,9 @@ var fetchGmxVaults = async (chainId, multicallRetry, options) => {
58384
60378
  indexToken: indexToken ? indexToken.toLowerCase() : void 0,
58385
60379
  longSymbol,
58386
60380
  shortSymbol,
58387
- apy: num8(entry?.apy),
58388
- baseApy: num8(entry?.baseApy),
58389
- bonusApr: num8(entry?.bonusApr),
60381
+ apy: num9(entry?.apy),
60382
+ baseApy: num9(entry?.baseApy),
60383
+ bonusApr: num9(entry?.bonusApr),
58390
60384
  yieldProfile: "volatile",
58391
60385
  denomination: denominationFor(longSymbol, shortSymbol)
58392
60386
  };
@@ -59563,6 +61557,6 @@ async function fetchTokenBalances(chainId, account, tokens, options = {}) {
59563
61557
  return parseTokenBalanceResult(rawResult, prepared.query);
59564
61558
  }
59565
61559
 
59566
- export { ApiBookSource, DEFAULT_MIDNIGHT_API, DEFAULT_OUTLIER_GUARD, DEFAULT_STALE_REJECT_SECONDS, DEFAULT_TERMMAX_API, EMPTY_BALANCE, 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, MaxParamThresholds, 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, TermMaxApiSource, TermSubgraphSource, UPSHIFT_CHAIN_IDS, UPSHIFT_VAULTS_URL, VAULT_SHARE_PRICE_PROBE, VOLATILE_VAULT_OVERRIDES, YEARN_CHAIN_IDS, YEARN_YDAEMON_BASE, accountDepositListKey, accountWithdrawalListKey, appendSnapshot, applyPositionDelta, attachPricesToFlashLiquidity, buildFluidFTokensCall, buildLiquityUserCall, buildLoopResult, buildMorphoTypeCall, buildMorphoTypeUserCallWithLens, buildPortfolioTotals, buildSumerAccumulators, buildSummaries, buildTellerUserCall, buildTermMaxUserCall, buildVaultLookup, calculateLeverage, calculateNetApr, calculateOverallNetApr, calculateWeightedAverage, classifyFreshness, classifyReliability, classifyVault, 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, convertExactlyMarketsToResponse, convertInverseMarketsToResponse, convertLenderUserDataResult, convertLiquityMarketsToResponse, convertRiverMarketsToResponse, convertTellerMarketsToResponse, convertTermMarketsToResponse, convertTermMaxMarketsToResponse, convertUsddMarketsToResponse, createMarketUid, createMidnightBookSource, createMulticallRpcCall, createRawRpcCalls, createTermBookSource, createTermMaxDataSource, decodeListaMarkets, decodeMarkets, decodePackedListaUserDataset, decodePackedMorphoUserDataset, detectInterfaceKinds, encodeBalanceFetcherCalldata, exactlyLenderKey, exactlyMarketFromLenderKey, exactlyPairLtv, exactlyPenaltyRateToAprPercent, exactlyWadRateToPercent, feedKeyOf, feedStatKey, fetchDolomiteAccountNumbers, fetchEulerEarnVaults, fetchEulerEarnVaultsFromSubgraph, fetchEulerSubAccountIndexes, fetchExactlyMarkets, fetchFlashLiquidityForChain, fetchFluidFTokens, fetchGeneralYields, fetchGeneralYieldsByMarketUid, fetchGmxExecutionFees, fetchGmxTickerPrices, fetchGmxVaults, fetchHypercoreVaults, fetchInverseMarkets, fetchLagoonApiVaults, fetchLagoonVaults, fetchLiquityMarkets, fetchListaVaultsFromChain, fetchMorphoUserBalances, fetchMorphoUserPositionMarkets, fetchMorphoVaults, fetchMorphoVaultsFromApi, fetchMorphoVaultsFromChain, fetchOraclePrices, fetchPendlePrices, fetchRiverMarkets, fetchSiloVaults, fetchTellerMarkets, fetchTermMarkets, fetchTermMaxMarkets, fetchTokenBalances, fetchTokenMetadata, fetchUpshiftApiVaults, fetchUpshiftVaults, fetchUsddMarkets, fetchYearnApiVaults, fetchYearnVaults, filterActiveLenders, filterLendersByProtocol, fuseLenderData, generateLendingPools, getAavesForChain, getAssetConfig, getBalanceForMarketUid, getBorrowCapacity, 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, getResolvedDolomiteAccountNumbers, getStCeloValidatorGroups, getSubAccountAddress, getSubAccountIndex, getVaultPublicDataAll, getVaultWithdrawalRequests, hasEulerEarnVaultSubgraph, hasLagoonVaults, hasMorphoPositionIndex, hasMorphoUserApi, hasMorphoUserSubgraph, hasUpshiftVaults, hasYearnVaults, inverseKeyParts, inverseLenderKey, isStablecoinSymbol, isYearnV3, keysFromMaps, lenderApiOnly, lenderFamily, liquityCandidateTroveIds, liquityKeyParts, liquityLenderKey, multicall3Abi2 as multicall3Abi, nanTo, needsLenderApproval, needsTokenApproval, noOpResult, normalizeToBytes, parseBalanceFetcherResult, parseMergedResult, parseMulticallRpcResponses, parseRawRpcBatchResponses, parseRawRpcResponses, parseTermMaxLtv, parseTokenBalanceResult, positivePart2 as positivePart, predictInverseEscrow, prepareLenderUserDataRpcCalls, prepareMergedMulticallParams, prepareMergedRpcCalls, prepareMulticallInputs, prepareTokenBalanceRpcCalls, priceGlvVaults, priceGmMarkets, probeAaveFeedTimestamps, pruneFeedStats, readVaultSharePrices, rejectOutliers as rejectPriceOutliers, resolveDerivation, resolveStCeloDepositGroup, riverKeyParts, riverLenderKey, selectAssetGroupPrices, stampVaultClassification, 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, unflattenLenderData, updateFeedStats, usddIlkBytes32, usddKeyParts, usddLenderKey };
61560
+ export { ApiBookSource, DEFAULT_MIDNIGHT_API, DEFAULT_OUTLIER_GUARD, DEFAULT_STALE_REJECT_SECONDS, DEFAULT_TERMMAX_API, EMPTY_BALANCE, EXACTLY_LENDER_KEY, 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, MaxParamThresholds, 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, TermMaxApiSource, TermSubgraphSource, UPSHIFT_CHAIN_IDS, UPSHIFT_VAULTS_URL, VAULT_SHARE_PRICE_PROBE, VOLATILE_VAULT_OVERRIDES, YEARN_CHAIN_IDS, YEARN_YDAEMON_BASE, __resetResupplyUserCaches, accountDepositListKey, accountWithdrawalListKey, appendSnapshot, applyPositionDelta, attachPricesToFlashLiquidity, buildFluidFTokensCall, buildLiquityUserCall, buildLoopResult, buildMorphoTypeCall, buildMorphoTypeUserCallWithLens, buildPortfolioTotals, buildSumerAccumulators, buildSummaries, buildTellerUserCall, buildTermMaxUserCall, buildVaultLookup, calculateLeverage, calculateNetApr, calculateOverallNetApr, calculateWeightedAverage, classifyFreshness, classifyReliability, classifyVault, 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, convertExactlyMarketsToResponse, convertFrankencoinMarketsToResponse, convertInverseMarketsToResponse, convertLenderUserDataResult, convertLiquityMarketsToResponse, convertLlamaLendMarketsToResponse, convertResupplyMarketsToResponse, convertRiverMarketsToResponse, convertTellerMarketsToResponse, convertTermMarketsToResponse, convertTermMaxMarketsToResponse, convertUsddMarketsToResponse, createMarketUid, createMidnightBookSource, createMulticallRpcCall, createRawRpcCalls, createTermBookSource, createTermMaxDataSource, decodeListaMarkets, decodeMarkets, decodePackedListaUserDataset, decodePackedMorphoUserDataset, detectInterfaceKinds, encodeBalanceFetcherCalldata, exactlyPairLtv, exactlyPenaltyRateToAprPercent, exactlyWadRateToPercent, feedKeyOf, feedStatKey, fetchDolomiteAccountNumbers, fetchEulerEarnVaults, fetchEulerEarnVaultsFromSubgraph, fetchEulerSubAccountIndexes, fetchExactlyMarkets, fetchFlashLiquidityForChain, fetchFluidFTokens, fetchFrankencoinMarkets, fetchGeneralYields, fetchGeneralYieldsByMarketUid, fetchGmxExecutionFees, fetchGmxTickerPrices, fetchGmxVaults, fetchHypercoreVaults, fetchInverseMarkets, fetchLagoonApiVaults, fetchLagoonVaults, fetchLiquityMarkets, fetchListaVaultsFromChain, fetchLlamaLendMarkets, fetchMorphoUserBalances, fetchMorphoUserPositionMarkets, fetchMorphoVaults, fetchMorphoVaultsFromApi, fetchMorphoVaultsFromChain, fetchOraclePrices, fetchPendlePrices, fetchResupplyMarkets, fetchRiverMarkets, fetchSiloVaults, fetchTellerMarkets, fetchTermMarkets, fetchTermMaxMarkets, fetchTokenBalances, fetchTokenMetadata, fetchUpshiftApiVaults, fetchUpshiftVaults, fetchUsddMarkets, fetchYearnApiVaults, fetchYearnVaults, filterActiveLenders, filterLendersByProtocol, frankencoinKeyParts, frankencoinLenderKey, fuseLenderData, generateLendingPools, getAavesForChain, getAssetConfig, getBalanceForMarketUid, getBorrowCapacity, 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, getResolvedDolomiteAccountNumbers, getStCeloValidatorGroups, getSubAccountAddress, getSubAccountIndex, getVaultPublicDataAll, getVaultWithdrawalRequests, hasEulerEarnVaultSubgraph, hasLagoonVaults, hasMorphoPositionIndex, hasMorphoUserApi, hasMorphoUserSubgraph, hasUpshiftVaults, hasYearnVaults, inverseKeyParts, inverseLenderKey, isStablecoinSymbol, isYearnV3, keysFromMaps, lenderApiOnly, lenderFamily, liquityCandidateTroveIds, liquityKeyParts, liquityLenderKey, llamaLendKeyParts, llamaLendLenderKey, multicall3Abi2 as multicall3Abi, nanTo, needsLenderApproval, needsTokenApproval, noOpResult, normalizeToBytes, parseBalanceFetcherResult, parseMergedResult, parseMulticallRpcResponses, parseRawRpcBatchResponses, parseRawRpcResponses, parseTermMaxLtv, parseTokenBalanceResult, positivePart2 as positivePart, predictInverseEscrow, prepareLenderUserDataRpcCalls, prepareMergedMulticallParams, prepareMergedRpcCalls, prepareMulticallInputs, prepareTokenBalanceRpcCalls, priceGlvVaults, priceGmMarkets, probeAaveFeedTimestamps, pruneFeedStats, readVaultSharePrices, rejectOutliers as rejectPriceOutliers, resolveDerivation, resolveStCeloDepositGroup, resupplyKeyParts, resupplyLenderKey, riverKeyParts, riverLenderKey, selectAssetGroupPrices, stampVaultClassification, 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, unflattenLenderData, updateFeedStats, usddIlkBytes32, usddKeyParts, usddLenderKey };
59567
61561
  //# sourceMappingURL=index.js.map
59568
61562
  //# sourceMappingURL=index.js.map