@1delta/margin-fetcher 0.0.411 → 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, TermMaxViewerAbi, 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);
@@ -22882,7 +22891,7 @@ async function fetchTellerMarkets(chainId) {
22882
22891
  } catch {
22883
22892
  return { chainId, pools: [] };
22884
22893
  }
22885
- const big9 = (i) => {
22894
+ const big13 = (i) => {
22886
22895
  const r = results[i];
22887
22896
  if (typeof r === "bigint") return r;
22888
22897
  if (typeof r === "number") return BigInt(r);
@@ -22895,21 +22904,21 @@ async function fetchTellerMarkets(chainId) {
22895
22904
  }
22896
22905
  return null;
22897
22906
  };
22898
- const num9 = (i) => {
22899
- const b = big9(i);
22907
+ const num10 = (i) => {
22908
+ const b = big13(i);
22900
22909
  return b === null ? null : Number(b);
22901
22910
  };
22902
22911
  const pool0 = pools.map((config, i) => {
22903
22912
  const base = i * READS_PER_POOL;
22904
22913
  return {
22905
22914
  config,
22906
- available: big9(base),
22907
- committed: big9(base + 1),
22908
- minRateBps: num9(base + 2),
22909
- collateralPerPrincipal: big9(base + 3),
22910
- maxLoanDuration: num9(base + 4),
22911
- marketId: big9(base + 5),
22912
- 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)
22913
22922
  };
22914
22923
  });
22915
22924
  const attByMarket = /* @__PURE__ */ new Map();
@@ -23827,7 +23836,7 @@ var INVERSE_PUBLIC_READ_ABI = [
23827
23836
  ...InverseDbrAbi,
23828
23837
  ...Erc20Abi
23829
23838
  ];
23830
- var READS_PER_MARKET2 = 4;
23839
+ var READS_PER_MARKET2 = 5;
23831
23840
  var fetchJson = async (url, timeoutMs = 6e3) => {
23832
23841
  const res = await fetch(url, {
23833
23842
  headers: { accept: "application/json" },
@@ -23870,15 +23879,24 @@ async function fetchInverseMarkets(lender, chainId) {
23870
23879
  if (Object.keys(byAddr).length > 0) {
23871
23880
  const rows = markets.map((market) => {
23872
23881
  const m = byAddr[market.address.toLowerCase()];
23873
- const num9 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
23882
+ const num10 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
23874
23883
  return {
23875
23884
  market,
23876
- totalDebt: num9(m?.totalDebt),
23877
- dolaLiquidity: num9(m?.dolaLiquidity),
23878
- leftToBorrow: num9(m?.leftToBorrow),
23879
- price: num9(m?.price),
23885
+ totalDebt: num10(m?.totalDebt),
23886
+ dolaLiquidity: num10(m?.dolaLiquidity),
23887
+ leftToBorrow: num10(m?.leftToBorrow),
23888
+ price: num10(m?.price),
23880
23889
  borrowPaused: typeof m?.borrowPaused === "boolean" ? m.borrowPaused : null,
23881
- 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
+ })()
23882
23900
  };
23883
23901
  });
23884
23902
  return {
@@ -23903,7 +23921,8 @@ async function fetchInverseMarkets(lender, chainId) {
23903
23921
  address: config.oracle,
23904
23922
  name: "viewPrice",
23905
23923
  params: [m.collToken, BigInt(m.collateralFactorBps)]
23906
- }
23924
+ },
23925
+ { address: m.address, name: "replenishmentIncentiveBps", params: [] }
23907
23926
  ])
23908
23927
  ];
23909
23928
  try {
@@ -23926,6 +23945,7 @@ async function fetchInverseMarkets(lender, chainId) {
23926
23945
  const paused = results[base + 1];
23927
23946
  const liq = bigAt(base + 2);
23928
23947
  const price2 = bigAt(base + 3);
23948
+ const replenishIncentive = bigAt(base + 4);
23929
23949
  return {
23930
23950
  market,
23931
23951
  totalDebt: totalDebt !== null ? Number(totalDebt) / 10 ** debtDecimals : null,
@@ -23937,7 +23957,11 @@ async function fetchInverseMarkets(lender, chainId) {
23937
23957
  // 10^(36 − collDecimals) per unit — normalize to USD per token.
23938
23958
  price: price2 !== null ? Number(price2) / 10 ** (36 - market.collDecimals) : null,
23939
23959
  borrowPaused: typeof paused === "boolean" ? paused : null,
23940
- 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
+ })()
23941
23965
  };
23942
23966
  });
23943
23967
  return {
@@ -23957,6 +23981,454 @@ function num(api, key) {
23957
23981
  const v = api?.[key];
23958
23982
  return typeof v === "number" && Number.isFinite(v) ? v : null;
23959
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
+ }
23960
24432
 
23961
24433
  // src/lending/public-data/inverse/convertPublic.ts
23962
24434
  function inverseLenderKey(lender, market) {
@@ -24124,8 +24596,13 @@ function convertInverseMarketsToResponse(raw, chainId, prices = {}, _additionalY
24124
24596
  liquidationFactorBps: market.liquidationFactorBps,
24125
24597
  /** Fixed borrow APR as a DECIMAL (DBR price in DOLA). */
24126
24598
  dbrPriceDola: raw.dbrPriceDola !== null ? String(raw.dbrPriceDola) : void 0,
24127
- /** 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. */
24128
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,
24129
24606
  borrowPaused: paused,
24130
24607
  addresses: {
24131
24608
  market: market.address,
@@ -24142,6 +24619,500 @@ function convertInverseMarketsToResponse(raw, chainId, prices = {}, _additionalY
24142
24619
  }
24143
24620
  return out;
24144
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
+ }
24145
25116
  var READS_PER_ILK = 4;
24146
25117
  var USDD_ABI_PER_READ = [UsddVatAbi, UsddJugAbi, UsddSpotAbi, erc20Abi];
24147
25118
  var usddIlkBytes32 = (ilk) => stringToHex(ilk, { size: 32 });
@@ -24172,12 +25143,12 @@ async function fetchUsddMarkets(lender, chainId) {
24172
25143
  } catch {
24173
25144
  return { lender, config, chainData, markets: [] };
24174
25145
  }
24175
- const big9 = (v) => {
25146
+ const big13 = (v) => {
24176
25147
  if (typeof v === "bigint") return v;
24177
25148
  if (typeof v === "number") return BigInt(v);
24178
25149
  return null;
24179
25150
  };
24180
- const field12 = (res, name, idx) => big9(res?.[name] ?? res?.[idx]);
25151
+ const field12 = (res, name, idx) => big13(res?.[name] ?? res?.[idx]);
24181
25152
  const out = markets.map((market, i) => {
24182
25153
  const base = i * READS_PER_ILK;
24183
25154
  const vatIlk = results[base];
@@ -24192,7 +25163,7 @@ async function fetchUsddMarkets(lender, chainId) {
24192
25163
  dust: field12(vatIlk, "dust", 4),
24193
25164
  duty: field12(jugIlk, "duty", 0),
24194
25165
  mat: field12(spotIlk, "mat", 1),
24195
- joinBalance: big9(results[base + 3])
25166
+ joinBalance: big13(results[base + 3])
24196
25167
  };
24197
25168
  });
24198
25169
  return { lender, config, chainData, markets: out };
@@ -24216,7 +25187,7 @@ var YEAR_SECONDS2 = 31536e3;
24216
25187
  function toHuman4(raw, decimals) {
24217
25188
  return Number(raw) / 10 ** decimals;
24218
25189
  }
24219
- function currencyFor9(address, decimals, symbol, tokens) {
25190
+ function currencyFor11(address, decimals, symbol, tokens) {
24220
25191
  const lower3 = address.toLowerCase();
24221
25192
  return tokens[lower3] ?? { address: lower3, symbol, name: symbol, decimals };
24222
25193
  }
@@ -24264,7 +25235,7 @@ function convertUsddMarketsToResponse(raw, chainId, prices = {}, _additionalYiel
24264
25235
  name: "Collateral " + collSymbol,
24265
25236
  poolId: market.gemJoin.toLowerCase(),
24266
25237
  underlying: collAddr,
24267
- asset: currencyFor9(collAddr, collDecimals, collSymbol, tokens),
25238
+ asset: currencyFor11(collAddr, collDecimals, collSymbol, tokens),
24268
25239
  totalDeposits: totalColl,
24269
25240
  totalDebtStable: 0,
24270
25241
  totalDebt: 0,
@@ -24308,7 +25279,7 @@ function convertUsddMarketsToResponse(raw, chainId, prices = {}, _additionalYiel
24308
25279
  name: debtSymbol,
24309
25280
  poolId: cfg.vat.toLowerCase(),
24310
25281
  underlying: debtAddr,
24311
- asset: currencyFor9(debtAddr, debtDecimals, debtSymbol, tokens),
25282
+ asset: currencyFor11(debtAddr, debtDecimals, debtSymbol, tokens),
24312
25283
  totalDeposits: 0,
24313
25284
  totalDebtStable: 0,
24314
25285
  totalDebt,
@@ -24400,6 +25371,304 @@ function convertUsddMarketsToResponse(raw, chainId, prices = {}, _additionalYiel
24400
25371
  }
24401
25372
  return out;
24402
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
+ }
24403
25672
 
24404
25673
  // src/lending/public-data/silo-v2/fetchPublic.ts
24405
25674
  var BASE_URL2 = "https://api-v3.silo.finance";
@@ -25009,8 +26278,12 @@ async function getLenderDataFromApi(lender, chainId, prices, additionalYields, i
25009
26278
  if (isRiver(lender)) return await fetchRiverMarkets(lender, chainId);
25010
26279
  if (isTeller(lender)) return await fetchTellerMarkets(chainId);
25011
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);
25012
26283
  if (isTermMax(lender)) return await fetchTermMaxMarkets(chainId);
25013
26284
  if (isUsdd(lender)) return await fetchUsddMarkets(lender, chainId);
26285
+ if (isFrankencoin(lender))
26286
+ return await fetchFrankencoinMarkets(lender, chainId);
25014
26287
  return {};
25015
26288
  }
25016
26289
  function convertLenderDataFromApi(lender, chainId, data, prices, additionalYields, list = {}) {
@@ -25072,6 +26345,30 @@ function convertLenderDataFromApi(lender, chainId, data, prices, additionalYield
25072
26345
  additionalYields,
25073
26346
  list
25074
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
+ );
25075
26372
  if (isUsdd(lender))
25076
26373
  return convertUsddMarketsToResponse(
25077
26374
  data,
@@ -25289,7 +26586,10 @@ function lenderApiOnly(lender, chainId) {
25289
26586
  if (isTeller(lender)) return true;
25290
26587
  if (isInverse(lender)) return true;
25291
26588
  if (isTermMax(lender)) return true;
26589
+ if (isResupply(lender)) return true;
25292
26590
  if (isUsdd(lender)) return true;
26591
+ if (isFrankencoin(lender)) return true;
26592
+ if (isLlamaLend(lender)) return true;
25293
26593
  return false;
25294
26594
  }
25295
26595
  function lenderApiWithOnChainFallback(lender, chainId) {
@@ -26441,8 +27741,22 @@ var buildRiverUserCall = (chainId, lender, account) => {
26441
27741
  });
26442
27742
  return calls;
26443
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
+ };
26444
27758
  var INVERSE_CALLS_PER_MARKET = 4;
26445
- var INVERSE_TAIL_CALLS = 3;
27759
+ var INVERSE_TAIL_CALLS = 4;
26446
27760
  var proxyInitCode = (impl) => concat([
26447
27761
  "0x3d602d80600a3d3981f3363d3d373d3d3d363d73",
26448
27762
  impl,
@@ -26477,21 +27791,136 @@ var buildInverseUserCall = (chainId, lender, account) => {
26477
27791
  calls.push(
26478
27792
  { address: cfg.dbr, name: "balanceOf", params: [account] },
26479
27793
  { address: cfg.dbr, name: "deficitOf", params: [account] },
26480
- { address: cfg.dbr, name: "signedBalanceOf", params: [account] }
27794
+ { address: cfg.dbr, name: "signedBalanceOf", params: [account] },
27795
+ { address: cfg.dbr, name: "debts", params: [account] }
26481
27796
  );
26482
27797
  return calls;
26483
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
+ }
26484
27913
  var USDD_CALLS_PER_CDP = 1;
26485
27914
  var MAX_CDP_WALK = 64;
26486
27915
  var CACHE_TTL_MS2 = 5 * 6e4;
26487
- var discoveryCache2 = /* @__PURE__ */ new Map();
27916
+ var discoveryCache3 = /* @__PURE__ */ new Map();
26488
27917
  var cacheKey2 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
26489
27918
  var getCachedUsddCdps = (chainId, account) => {
26490
- const hit = discoveryCache2.get(cacheKey2(chainId, account));
27919
+ const hit = discoveryCache3.get(cacheKey2(chainId, account));
26491
27920
  if (!hit || Date.now() - hit.at > CACHE_TTL_MS2) return void 0;
26492
27921
  return hit;
26493
27922
  };
26494
- var big = (v) => {
27923
+ var big2 = (v) => {
26495
27924
  try {
26496
27925
  if (typeof v === "bigint") return v;
26497
27926
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -26503,7 +27932,7 @@ var field6 = (res, name, idx) => res?.[name] ?? res?.[idx];
26503
27932
  var buildUsddUserCall = async (chainId, lender, account) => {
26504
27933
  const cfg = usddConfigFor(lender, chainId);
26505
27934
  const markets = usddChainData(lender, chainId)?.markets ?? [];
26506
- const stash = (d) => discoveryCache2.set(cacheKey2(chainId, account), d);
27935
+ const stash = (d) => discoveryCache3.set(cacheKey2(chainId, account), d);
26507
27936
  if (!cfg || markets.length === 0) {
26508
27937
  stash({ cdps: [], ilks: [], at: Date.now() });
26509
27938
  return [];
@@ -26522,7 +27951,7 @@ var buildUsddUserCall = async (chainId, lender, account) => {
26522
27951
  ],
26523
27952
  allowFailure: false
26524
27953
  });
26525
- owners.push({ owner: account, count: big(rawCount), cursor: big(rawFirst) });
27954
+ owners.push({ owner: account, count: big2(rawCount), cursor: big2(rawFirst) });
26526
27955
  const proxy = String(rawProxy ?? zero);
26527
27956
  if (proxy.toLowerCase() !== zero) {
26528
27957
  const [pCount, pFirst] = await multicallRetryUniversal({
@@ -26534,7 +27963,7 @@ var buildUsddUserCall = async (chainId, lender, account) => {
26534
27963
  ],
26535
27964
  allowFailure: false
26536
27965
  });
26537
- owners.push({ owner: proxy, count: big(pCount), cursor: big(pFirst) });
27966
+ owners.push({ owner: proxy, count: big2(pCount), cursor: big2(pFirst) });
26538
27967
  }
26539
27968
  } catch {
26540
27969
  return [];
@@ -26575,7 +28004,7 @@ var buildUsddUserCall = async (chainId, lender, account) => {
26575
28004
  if (curated.has(ilk)) {
26576
28005
  cdps.push({ cdpId: cursor.toString(), urn: String(urn), ilk });
26577
28006
  }
26578
- cursor = big(field6(link, "next", 1));
28007
+ cursor = big2(field6(link, "next", 1));
26579
28008
  }
26580
28009
  }
26581
28010
  } catch {
@@ -26598,12 +28027,83 @@ var buildUsddUserCall = async (chainId, lender, account) => {
26598
28027
  }
26599
28028
  return calls;
26600
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
+ };
26601
28101
  var TELLER_CALLS_PER_BID = 4;
26602
28102
  var CACHE_TTL_MS3 = 5 * 6e4;
26603
- var discoveryCache3 = /* @__PURE__ */ new Map();
26604
- var cacheKey3 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
28103
+ var discoveryCache5 = /* @__PURE__ */ new Map();
28104
+ var cacheKey4 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
26605
28105
  var getCachedTellerBids = (chainId, account) => {
26606
- const hit = discoveryCache3.get(cacheKey3(chainId, account));
28106
+ const hit = discoveryCache5.get(cacheKey4(chainId, account));
26607
28107
  if (!hit || Date.now() - hit.at > CACHE_TTL_MS3) return void 0;
26608
28108
  return hit;
26609
28109
  };
@@ -26644,7 +28144,7 @@ var buildTellerUserCall = async (chainId, _lender, account) => {
26644
28144
  return [];
26645
28145
  }
26646
28146
  if (ids.length === 0) {
26647
- discoveryCache3.set(cacheKey3(chainId, account), { bids: [], at: Date.now() });
28147
+ discoveryCache5.set(cacheKey4(chainId, account), { bids: [], at: Date.now() });
26648
28148
  return [];
26649
28149
  }
26650
28150
  const poolByAddr = /* @__PURE__ */ new Map();
@@ -26671,7 +28171,7 @@ var buildTellerUserCall = async (chainId, _lender, account) => {
26671
28171
  const pool = poolByAddr.get(lenderAddr);
26672
28172
  if (pool) kept.push({ bidId: id, pool });
26673
28173
  });
26674
- discoveryCache3.set(cacheKey3(chainId, account), { bids: kept, at: Date.now() });
28174
+ discoveryCache5.set(cacheKey4(chainId, account), { bids: kept, at: Date.now() });
26675
28175
  if (kept.length === 0) return [];
26676
28176
  const ts = nowSec5();
26677
28177
  const calls = [];
@@ -26697,10 +28197,10 @@ var buildTellerUserCall = async (chainId, _lender, account) => {
26697
28197
  };
26698
28198
  var TERMMAX_CALLS_PER_ACCOUNT = 1;
26699
28199
  var CACHE_TTL_MS4 = 5 * 6e4;
26700
- var discoveryCache4 = /* @__PURE__ */ new Map();
26701
- var cacheKey4 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
28200
+ var discoveryCache6 = /* @__PURE__ */ new Map();
28201
+ var cacheKey5 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
26702
28202
  var getCachedTermMaxDiscovery = (chainId, account) => {
26703
- const hit = discoveryCache4.get(cacheKey4(chainId, account));
28203
+ const hit = discoveryCache6.get(cacheKey5(chainId, account));
26704
28204
  if (!hit || Date.now() - hit.at > CACHE_TTL_MS4) return void 0;
26705
28205
  return hit;
26706
28206
  };
@@ -26716,11 +28216,11 @@ var buildTermMaxUserCall = async (chainId, _lender, account) => {
26716
28216
  }
26717
28217
  }
26718
28218
  if (markets.length === 0) {
26719
- discoveryCache4.set(cacheKey4(chainId, account), { markets: [], at: Date.now() });
28219
+ discoveryCache6.set(cacheKey5(chainId, account), { markets: [], at: Date.now() });
26720
28220
  return [];
26721
28221
  }
26722
28222
  markets = [...markets].sort((a, b) => a.market.localeCompare(b.market));
26723
- discoveryCache4.set(cacheKey4(chainId, account), { markets, at: Date.now() });
28223
+ discoveryCache6.set(cacheKey5(chainId, account), { markets, at: Date.now() });
26724
28224
  return [
26725
28225
  {
26726
28226
  address: proto.viewer,
@@ -26753,7 +28253,12 @@ async function buildUserCall(chainId, lender, account, params, getClient) {
26753
28253
  if (isTeller(lender)) return buildTellerUserCall(chainId, lender, account);
26754
28254
  if (isTermMax(lender)) return buildTermMaxUserCall(chainId, lender, account);
26755
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);
26756
28259
  if (isUsdd(lender)) return buildUsddUserCall(chainId, lender, account);
28260
+ if (isFrankencoin(lender))
28261
+ return buildFrankencoinUserCall(chainId, lender, account);
26757
28262
  if (isCompoundV3Type(lender))
26758
28263
  return buildCompoundV3UserCall(chainId, lender, account);
26759
28264
  if (isEulerType(lender))
@@ -26790,10 +28295,12 @@ function organizeUserQueries(queries) {
26790
28295
  const teller = queries.filter((q) => isTeller(q.lender));
26791
28296
  const termMax = queries.filter((q) => isTermMax(q.lender));
26792
28297
  const usdd = queries.filter((q) => isUsdd(q.lender));
26793
- 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)
26794
28301
  return queries;
26795
28302
  const others = queries.filter(
26796
- (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)
26797
28304
  );
26798
28305
  const morphoBlue = morphos.filter((q) => q.lender.startsWith("MORPHO_BLUE"));
26799
28306
  const moolah = morphos.filter((q) => q.lender.startsWith("LISTA_DAO"));
@@ -26854,6 +28361,14 @@ function organizeUserQueries(queries) {
26854
28361
  assets: void 0
26855
28362
  });
26856
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
+ }
26857
28372
  if (usdd.length > 0) {
26858
28373
  result.push({
26859
28374
  lender: Lender.USDD,
@@ -26862,6 +28377,14 @@ function organizeUserQueries(queries) {
26862
28377
  assets: void 0
26863
28378
  });
26864
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
+ }
26865
28388
  if (teller.length > 0) {
26866
28389
  result.push({
26867
28390
  lender: Lender.TELLER,
@@ -29530,7 +31053,7 @@ var getExactlyUserDataConverter = (_lender, chainId, account, meta) => {
29530
31053
  expected
29531
31054
  ];
29532
31055
  };
29533
- var big2 = (v) => {
31056
+ var big3 = (v) => {
29534
31057
  try {
29535
31058
  if (typeof v === "bigint") return v;
29536
31059
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -29538,7 +31061,7 @@ var big2 = (v) => {
29538
31061
  }
29539
31062
  return 0n;
29540
31063
  };
29541
- var field7 = (res, name, idx) => big2(res?.[name] ?? res?.[idx]);
31064
+ var field7 = (res, name, idx) => big3(res?.[name] ?? res?.[idx]);
29542
31065
  var getLiquityUserDataConverter = (lender, chainId, account, meta) => {
29543
31066
  const cfg = liquityConfigFor(lender, chainId);
29544
31067
  const branches = liquityBranchesByChain(lender, chainId);
@@ -29659,11 +31182,11 @@ var getLiquityUserDataConverter = (lender, chainId, account, meta) => {
29659
31182
  };
29660
31183
  });
29661
31184
  const spBase = troves.length * 2;
29662
- const spDeposit = big2(slice2[spBase]);
29663
- const spYield = big2(slice2[spBase + 1]);
29664
- const spCollGain = big2(slice2[spBase + 2]);
29665
- const spStashed = big2(slice2[spBase + 3]);
29666
- 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;
29667
31190
  const spStable = spDeposit + spYield;
29668
31191
  const spColl = spCollGain + spStashed + collSurplus;
29669
31192
  if (spStable > 0n || spColl > 0n) {
@@ -29742,7 +31265,7 @@ var getLiquityUserDataConverter = (lender, chainId, account, meta) => {
29742
31265
  expected
29743
31266
  ];
29744
31267
  };
29745
- var big3 = (v) => {
31268
+ var big4 = (v) => {
29746
31269
  try {
29747
31270
  if (typeof v === "bigint") return v;
29748
31271
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -29750,7 +31273,7 @@ var big3 = (v) => {
29750
31273
  }
29751
31274
  return 0n;
29752
31275
  };
29753
- var field8 = (res, name, idx) => big3(res?.[name] ?? res?.[idx]);
31276
+ var field8 = (res, name, idx) => big4(res?.[name] ?? res?.[idx]);
29754
31277
  var getRiverUserDataConverter = (lender, chainId, account, meta) => {
29755
31278
  const cfg = riverConfigFor(lender, chainId);
29756
31279
  const markets = riverChainData(lender, chainId)?.markets ?? [];
@@ -29762,13 +31285,13 @@ var getRiverUserDataConverter = (lender, chainId, account, meta) => {
29762
31285
  const debtAddr = cfg.debtToken.toLowerCase();
29763
31286
  const debtDecimals = cfg.debtDecimals ?? 18;
29764
31287
  const out = {};
29765
- const spDeposit = big3(data[markets.length * RIVER_CALLS_PER_MARKET]);
31288
+ const spDeposit = big4(data[markets.length * RIVER_CALLS_PER_MARKET]);
29766
31289
  markets.forEach((market, i) => {
29767
31290
  const base = i * RIVER_CALLS_PER_MARKET;
29768
31291
  const entire = data[base];
29769
31292
  if (isFailedCall(entire) || isFailedCall(data[base + 1])) return;
29770
- const status = Number(big3(data[base + 1]));
29771
- const surplus = big3(data[base + 2]);
31293
+ const status = Number(big4(data[base + 1]));
31294
+ const surplus = big4(data[base + 2]);
29772
31295
  const lenderKey = riverLenderKey(lender, chainId, market.index);
29773
31296
  const metaMap = meta?.[lenderKey];
29774
31297
  if (!metaMap) return;
@@ -29876,7 +31399,7 @@ var getRiverUserDataConverter = (lender, chainId, account, meta) => {
29876
31399
  expected
29877
31400
  ];
29878
31401
  };
29879
- var big4 = (v) => {
31402
+ var big5 = (v) => {
29880
31403
  try {
29881
31404
  if (typeof v === "bigint") return v;
29882
31405
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -29895,20 +31418,24 @@ var getInverseUserDataConverter = (lender, chainId, account, meta) => {
29895
31418
  const dolaAddr = cfg.dola.toLowerCase();
29896
31419
  const debtDecimals = cfg.debtDecimals ?? 18;
29897
31420
  const tailBase = markets.length * INVERSE_CALLS_PER_MARKET;
29898
- const dbrBalance = big4(data[tailBase]);
29899
- const dbrDeficit = big4(data[tailBase + 1]);
31421
+ const dbrBalance = big5(data[tailBase]);
31422
+ const dbrDeficit = big5(data[tailBase + 1]);
29900
31423
  const dbrSignedRaw = data[tailBase + 2];
29901
- 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));
29902
31429
  const out = {};
29903
31430
  markets.forEach((market, i) => {
29904
31431
  const base = i * INVERSE_CALLS_PER_MARKET;
29905
- const escrowBal = isFailedCall(data[base]) ? 0n : big4(data[base]);
31432
+ const escrowBal = isFailedCall(data[base]) ? 0n : big5(data[base]);
29906
31433
  const debtRaw = data[base + 1];
29907
31434
  if (isFailedCall(debtRaw)) return;
29908
- const debt = big4(debtRaw);
31435
+ const debt = big5(debtRaw);
29909
31436
  if (escrowBal === 0n && debt === 0n) return;
29910
- const creditLimit = isFailedCall(data[base + 2]) ? 0n : big4(data[base + 2]);
29911
- 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]);
29912
31439
  const lenderKey = inverseLenderKey(lender, market.address);
29913
31440
  const metaMap = meta?.[lenderKey];
29914
31441
  if (!metaMap) return;
@@ -29929,7 +31456,10 @@ var getInverseUserDataConverter = (lender, chainId, account, meta) => {
29929
31456
  withdrawalLimit: withdrawalLimit.toString(),
29930
31457
  dbrBalance: dbrBalance.toString(),
29931
31458
  dbrDeficit: dbrDeficit.toString(),
29932
- dbrSignedBalance: dbrSigned.toString()
31459
+ dbrSignedBalance: dbrSigned.toString(),
31460
+ dbrTotalDebt: dbrTotalDebt.toString(),
31461
+ dbrRunwaySeconds: dbrRunway.toString(),
31462
+ dbrDepletionTimestamp: dbrTotalDebt > 0n ? String(nowSec9 + dbrRunway) : void 0
29933
31463
  };
29934
31464
  const collStr = parseRawAmount(escrowBal.toString(), collDecimals);
29935
31465
  const collNum = Number(collStr);
@@ -29991,8 +31521,273 @@ var getInverseUserDataConverter = (lender, chainId, account, meta) => {
29991
31521
  expected
29992
31522
  ];
29993
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
+ };
29994
31789
  var RAY4 = 10n ** 27n;
29995
- var big5 = (v) => {
31790
+ var big8 = (v) => {
29996
31791
  try {
29997
31792
  if (typeof v === "bigint") return v;
29998
31793
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -30000,7 +31795,7 @@ var big5 = (v) => {
30000
31795
  }
30001
31796
  return 0n;
30002
31797
  };
30003
- var field9 = (res, name, idx) => big5(res?.[name] ?? res?.[idx]);
31798
+ var field9 = (res, name, idx) => big8(res?.[name] ?? res?.[idx]);
30004
31799
  var getUsddUserDataConverter = (lender, chainId, account, meta) => {
30005
31800
  const cfg = usddConfigFor(lender, chainId);
30006
31801
  const markets = usddChainData(lender, chainId)?.markets ?? [];
@@ -30113,10 +31908,142 @@ var getUsddUserDataConverter = (lender, chainId, account, meta) => {
30113
31908
  expected
30114
31909
  ];
30115
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
+ };
30116
32043
 
30117
32044
  // src/lending/user-data/teller/userCallParse.ts
30118
32045
  var nowSec7 = () => Math.floor(Date.now() / 1e3);
30119
- var big6 = (v) => {
32046
+ var big10 = (v) => {
30120
32047
  try {
30121
32048
  if (typeof v === "bigint") return v;
30122
32049
  if (typeof v === "number" || typeof v === "string") return BigInt(v);
@@ -30138,7 +32065,7 @@ var getTellerUserDataConverter = (_lender, chainId, account, meta) => {
30138
32065
  const base = i * TELLER_CALLS_PER_BID;
30139
32066
  const bidRes = data[base];
30140
32067
  const owed = data[base + 1];
30141
- const collAmount = big6(data[base + 2]);
32068
+ const collAmount = big10(data[base + 2]);
30142
32069
  const defaulted = !!data[base + 3];
30143
32070
  if (isFailedCall(bidRes) || isFailedCall(owed) || !bidRes) return;
30144
32071
  const pool = b.pool;
@@ -30159,17 +32086,17 @@ var getTellerUserDataConverter = (_lender, chainId, account, meta) => {
30159
32086
  const collDisplay = collMeta ? getDisplayPrice(collMeta) : 0;
30160
32087
  const collOracle = collMeta ? getOraclePrice(collMeta) : 0;
30161
32088
  const collHist = collMeta?.price?.priceUsd24h ?? collDisplay;
30162
- const owedPrincipal = big6(field10(owed, "principal", 0));
30163
- const owedInterest = big6(field10(owed, "interest", 1));
32089
+ const owedPrincipal = big10(field10(owed, "principal", 0));
32090
+ const owedInterest = big10(field10(owed, "interest", 1));
30164
32091
  const owedTotal = owedPrincipal + owedInterest;
30165
32092
  if (owedTotal === 0n && collAmount === 0n) return;
30166
32093
  const loanDetails = field10(bidRes, "loanDetails", 5);
30167
32094
  const terms = field10(bidRes, "terms", 6);
30168
32095
  const acceptedTs = Number(
30169
- big6(field10(loanDetails, "acceptedTimestamp", 4))
32096
+ big10(field10(loanDetails, "acceptedTimestamp", 4))
30170
32097
  );
30171
- const loanDuration = Number(big6(field10(loanDetails, "loanDuration", 6)));
30172
- 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)));
30173
32100
  const maturity = acceptedTs > 0 ? acceptedTs + loanDuration : void 0;
30174
32101
  const isMatured = defaulted || maturity !== void 0 && maturity < now;
30175
32102
  const collStr = parseRawAmount(collAmount.toString(), collDecimals);
@@ -30467,8 +32394,14 @@ function getUserDataConverter(lender, chainId, account, params, meta) {
30467
32394
  return getTermMaxUserDataConverter(lender, chainId, account, meta);
30468
32395
  if (isInverse(lender))
30469
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);
30470
32401
  if (isUsdd(lender))
30471
32402
  return getUsddUserDataConverter(lender, chainId, account, meta);
32403
+ if (isFrankencoin(lender))
32404
+ return getFrankencoinUserDataConverter(lender, chainId, account, meta);
30472
32405
  if (isCompoundV3Type(lender))
30473
32406
  return getCompoundV3UserDataConverter(
30474
32407
  lender,
@@ -35024,6 +36957,15 @@ var accountLensAbi = [
35024
36957
  stateMutability: "view"
35025
36958
  }
35026
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
+ ];
35027
36969
  var getAbi2 = (lender) => {
35028
36970
  if (isAaveV4Type(lender)) return [...AaveV4SpokeAbi];
35029
36971
  if (isAaveV2Type(lender))
@@ -35069,7 +37011,13 @@ var getAbi2 = (lender) => {
35069
37011
  if (isTermMax(lender)) return [...TermMaxViewerAbi];
35070
37012
  if (isInverse(lender))
35071
37013
  return [...InverseMarketAbi, ...InverseEscrowAbi, ...InverseDbrAbi];
37014
+ if (isLlamaLend(lender))
37015
+ return [...LlamaLendControllerAbi, ...LlamaLendAmmAbi];
35072
37016
  if (isUsdd(lender)) return [...UsddVatAbi];
37017
+ if (isFrankencoin(lender))
37018
+ return [...FrankencoinPositionAbi, ...erc20Abi];
37019
+ if (isResupply(lender))
37020
+ return [...ResupplyPairAbi, ...VAULT_CONVERT_ABI];
35073
37021
  if (isInit(lender)) return InitLensAbi;
35074
37022
  if (isEulerType(lender)) return accountLensAbi;
35075
37023
  if (isCompoundV2Type(lender))
@@ -35681,11 +37629,11 @@ async function fetchJsonWithProxyFallback(url, body, proxyConfig) {
35681
37629
  }
35682
37630
  var inflight = /* @__PURE__ */ new Map();
35683
37631
  var resolved = /* @__PURE__ */ new Map();
35684
- function cacheKey5(chainId, account) {
37632
+ function cacheKey6(chainId, account) {
35685
37633
  return `${chainId}:${account.toLowerCase()}`;
35686
37634
  }
35687
37635
  async function dedupedFetch(chainId, account, loader) {
35688
- const key = cacheKey5(chainId, account);
37636
+ const key = cacheKey6(chainId, account);
35689
37637
  const now = Date.now();
35690
37638
  const cached = resolved.get(key);
35691
37639
  if (cached && cached.expiresAt > now) {
@@ -40171,7 +42119,7 @@ var DOLA_STAKING_URL = "https://www.inverse.finance/api/dola-staking";
40171
42119
  var JDOLA_STAKING_URL = "https://www.inverse.finance/api/junior/jdola-staking";
40172
42120
  var SDOLA_KEY = "SDOLA";
40173
42121
  var SDOLA_GROUP_KEY = "sDOLA::SDOLA";
40174
- var fetchJson2 = async (url) => {
42122
+ var fetchJson3 = async (url) => {
40175
42123
  const res = await fetch(url, {
40176
42124
  headers: { accept: "application/json" },
40177
42125
  signal: AbortSignal.timeout(8e3)
@@ -40181,12 +42129,12 @@ var fetchJson2 = async (url) => {
40181
42129
  };
40182
42130
  var fetchSdolaApyPercent = async () => {
40183
42131
  try {
40184
- const d = await fetchJson2(DOLA_STAKING_URL);
42132
+ const d = await fetchJson3(DOLA_STAKING_URL);
40185
42133
  const apy = Number(d?.calculatedApy);
40186
42134
  if (Number.isFinite(apy) && apy > 0) return apy;
40187
42135
  throw new Error("calculatedApy missing");
40188
42136
  } catch {
40189
- const d = await fetchJson2(JDOLA_STAKING_URL);
42137
+ const d = await fetchJson3(JDOLA_STAKING_URL);
40190
42138
  const apy = Number(d?.sDolaApy);
40191
42139
  if (Number.isFinite(apy) && apy > 0) return apy;
40192
42140
  throw new Error("sDolaApy missing");
@@ -40618,6 +42566,72 @@ var usddFetcher = {
40618
42566
  return out;
40619
42567
  }
40620
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
+ };
40621
42635
 
40622
42636
  // src/yields/intrinsic/fetchers/nativeCreditPool.ts
40623
42637
  var nativeCreditPoolYieldKey = (chainId, underlying) => `${chainId}:${underlying.toLowerCase()}`;
@@ -42726,6 +44740,50 @@ var SINGLE_CHAIN_ENTRIES = {
42726
44740
  withdrawalCooldownSeconds: 90 * 86400,
42727
44741
  yieldFetcher: reProtocolFetcher,
42728
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
42729
44787
  }
42730
44788
  ],
42731
44789
  "42161": [
@@ -50036,7 +52094,7 @@ query EvkByAssets($assets: [Bytes!]!) {
50036
52094
  }
50037
52095
  }
50038
52096
  `;
50039
- var ZERO = 0n;
52097
+ var ZERO2 = 0n;
50040
52098
  var RAY_TO_PERCENT3 = 1e25;
50041
52099
  function readAddress2(field12) {
50042
52100
  if (!field12) return void 0;
@@ -50051,28 +52109,28 @@ function parseVaultFee(v) {
50051
52109
  return n;
50052
52110
  }
50053
52111
  function safeBigInt(v) {
50054
- if (v == null || v === "") return ZERO;
52112
+ if (v == null || v === "") return ZERO2;
50055
52113
  try {
50056
52114
  return BigInt(v);
50057
52115
  } catch {
50058
- return ZERO;
52116
+ return ZERO2;
50059
52117
  }
50060
52118
  }
50061
52119
  function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent, evkIndex) {
50062
52120
  if (!strategies?.length) return 0;
50063
52121
  const totalAssets = safeBigInt(totalAssetsRaw);
50064
- if (totalAssets === ZERO) return 0;
50065
- let weightedRay = ZERO;
52122
+ if (totalAssets === ZERO2) return 0;
52123
+ let weightedRay = ZERO2;
50066
52124
  for (const s of strategies) {
50067
52125
  const evk = s.strategy?.toLowerCase();
50068
52126
  if (!evk) continue;
50069
52127
  const apyRay = evkIndex.bySupplyApyRay.get(evk);
50070
52128
  if (apyRay == null) continue;
50071
52129
  const allocated = safeBigInt(s.allocatedAssets);
50072
- if (allocated === ZERO) continue;
52130
+ if (allocated === ZERO2) continue;
50073
52131
  weightedRay += allocated * apyRay;
50074
52132
  }
50075
- if (weightedRay === ZERO) return 0;
52133
+ if (weightedRay === ZERO2) return 0;
50076
52134
  const apyRayPerAsset = weightedRay / totalAssets;
50077
52135
  const grossPercent = apyToAprPercent(Number(apyRayPerAsset) / RAY_TO_PERCENT3);
50078
52136
  const netPercent = grossPercent * (1 - feePercent / 100);
@@ -50080,24 +52138,24 @@ function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent, evkInd
50080
52138
  }
50081
52139
  function computeRealLiquidity(strategies, totalAssetsRaw, evkIndex) {
50082
52140
  const totalAssets = safeBigInt(totalAssetsRaw);
50083
- if (totalAssets === ZERO) return ZERO;
52141
+ if (totalAssets === ZERO2) return ZERO2;
50084
52142
  if (evkIndex.byCash.size === 0 && evkIndex.bySupplyApyRay.size === 0) {
50085
52143
  return totalAssets;
50086
52144
  }
50087
52145
  if (!strategies?.length) {
50088
52146
  return totalAssets;
50089
52147
  }
50090
- let allocSum = ZERO;
50091
- let withdrawable = ZERO;
52148
+ let allocSum = ZERO2;
52149
+ let withdrawable = ZERO2;
50092
52150
  for (const s of strategies) {
50093
52151
  const alloc = safeBigInt(s.allocatedAssets);
50094
- if (alloc === ZERO) continue;
52152
+ if (alloc === ZERO2) continue;
50095
52153
  allocSum += alloc;
50096
52154
  const evk = s.strategy?.toLowerCase();
50097
52155
  const cash = evk ? evkIndex.byCash.get(evk) : void 0;
50098
52156
  withdrawable += cash == null ? alloc : alloc < cash ? alloc : cash;
50099
52157
  }
50100
- const idle = totalAssets > allocSum ? totalAssets - allocSum : ZERO;
52158
+ const idle = totalAssets > allocSum ? totalAssets - allocSum : ZERO2;
50101
52159
  const result = idle + withdrawable;
50102
52160
  return result > totalAssets ? totalAssets : result;
50103
52161
  }
@@ -50401,11 +52459,11 @@ var fetchEulerEarnVaults = async (chainId, prices = {}, tokenList = {}, multical
50401
52459
  };
50402
52460
  var warn6 = (...args) => {
50403
52461
  };
50404
- var num2 = (v) => {
52462
+ var num3 = (v) => {
50405
52463
  const n = Number(v);
50406
52464
  return Number.isFinite(n) ? n : 0;
50407
52465
  };
50408
- var big7 = (v) => {
52466
+ var big11 = (v) => {
50409
52467
  try {
50410
52468
  if (v === void 0 || v === null || v === "") return "0";
50411
52469
  const s = String(v);
@@ -50436,21 +52494,21 @@ async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, f
50436
52494
  const underlying = lower2(r?.asset?.contractAddress);
50437
52495
  if (!address || !underlying) continue;
50438
52496
  if (r.isEnabled === false) continue;
50439
- const assetDecimals = num2(r?.asset?.decimals) || 18;
52497
+ const assetDecimals = num3(r?.asset?.decimals) || 18;
50440
52498
  const scale = 10 ** assetDecimals;
50441
52499
  const assetEntry = tokenList[underlying];
50442
52500
  const priceKey = toOracleKey(assetEntry?.assetGroup) || toGenericPriceKey(underlying, chainId);
50443
52501
  const priceUsd = prices[priceKey];
50444
- const totalAssets = big7(r.totalAssets);
50445
- const totalSupply = big7(r.totalSupplyAmt);
52502
+ const totalAssets = big11(r.totalAssets);
52503
+ const totalSupply = big11(r.totalSupplyAmt);
50446
52504
  const totalAssetsFormatted = Number(totalAssets) / scale;
50447
- const supplyRate = num2(r.apr) * 100;
50448
- const rewardsRate = num2(r?.incentiveData?.TMX_APR) * 100;
50449
- 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"));
50450
52508
  const totalAssetsBig = BigInt(totalAssets);
50451
52509
  const liquidity = (rawLiquidity > totalAssetsBig ? totalAssetsBig : rawLiquidity).toString();
50452
52510
  const liquidityFormatted = Number(liquidity) / scale;
50453
- const totalSupplyValue = num2(r.totalSupplyValue);
52511
+ const totalSupplyValue = num3(r.totalSupplyValue);
50454
52512
  out[address] = {
50455
52513
  address,
50456
52514
  underlying,
@@ -50467,8 +52525,8 @@ async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, f
50467
52525
  rewardsRate,
50468
52526
  depositRate: supplyRate + rewardsRate,
50469
52527
  // 1e8-scaled upstream (10000000 = 10%).
50470
- fee: num2(r.performanceFeeRate) / 1e6,
50471
- timelock: num2(r.timeLockSeconds) || void 0,
52528
+ fee: num3(r.performanceFeeRate) / 1e6,
52529
+ timelock: num3(r.timeLockSeconds) || void 0,
50472
52530
  curator: r?.curator?.curatorAddress ? lower2(r.curator.curatorAddress) : void 0,
50473
52531
  // The API is the ONLY source for this — do not derive it from `name`.
50474
52532
  curatorName: r?.curator?.name || void 0,
@@ -50482,7 +52540,7 @@ async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, f
50482
52540
  liquidityUsd: priceUsd ? liquidityFormatted * priceUsd : 0,
50483
52541
  version: r.version,
50484
52542
  isPaused: r.isPaused === true || void 0,
50485
- supplyCap: r.capacity ? big7(r.capacity) : void 0,
52543
+ supplyCap: r.capacity ? big11(r.capacity) : void 0,
50486
52544
  basePool: r.poolAddress ? lower2(r.poolAddress) : void 0
50487
52545
  };
50488
52546
  }
@@ -50538,7 +52596,7 @@ var Erc20DecimalsBalanceAbi = [
50538
52596
 
50539
52597
  // src/vaults/termmax/fetchFromChain.ts
50540
52598
  var DECIMAL_BASE2 = 100000000n;
50541
- var big8 = (v) => {
52599
+ var big12 = (v) => {
50542
52600
  if (v === void 0 || v === null || v === "0x") return 0n;
50543
52601
  try {
50544
52602
  return typeof v === "bigint" ? v : BigInt(v);
@@ -50546,7 +52604,7 @@ var big8 = (v) => {
50546
52604
  return 0n;
50547
52605
  }
50548
52606
  };
50549
- var num3 = (v) => {
52607
+ var num4 = (v) => {
50550
52608
  const n = Number(v);
50551
52609
  return Number.isFinite(n) ? n : void 0;
50552
52610
  };
@@ -50602,23 +52660,23 @@ var fetchTermMaxVaultsFromChain = async (chainId, multicallRetry, prices = {}, t
50602
52660
  vaults.forEach((address, i) => {
50603
52661
  const at = (k) => res[i * READS_PER_VAULT + VAULT_READS.indexOf(k)];
50604
52662
  const asset = addr(at("asset"));
50605
- const totalAssets = big8(at("totalAssets"));
52663
+ const totalAssets = big12(at("totalAssets"));
50606
52664
  if (!asset || totalAssets === 0n) return;
50607
52665
  rows.push({
50608
52666
  address,
50609
52667
  name: str(at("name")),
50610
52668
  symbol: str(at("symbol")),
50611
- decimals: num3(at("decimals")) ?? 18,
52669
+ decimals: num4(at("decimals")) ?? 18,
50612
52670
  asset,
50613
52671
  totalAssets,
50614
- totalSupply: big8(at("totalSupply")),
50615
- annualizedInterest: big8(at("annualizedInterest")),
50616
- accretingPrincipal: big8(at("accretingPrincipal")),
50617
- performanceFeeRate: big8(at("performanceFeeRate")),
50618
- 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,
50619
52677
  curator: addr(at("curator")),
50620
52678
  guardian: addr(at("guardian")),
50621
- timelock: num3(at("timelock")),
52679
+ timelock: num4(at("timelock")),
50622
52680
  version: str(at("getVersion"))
50623
52681
  });
50624
52682
  });
@@ -50635,8 +52693,8 @@ var fetchTermMaxVaultsFromChain = async (chainId, multicallRetry, prices = {}, t
50635
52693
  });
50636
52694
  const out = {};
50637
52695
  rows.forEach((r, i) => {
50638
- const assetDecimals = num3(res2[i * 2]) ?? r.decimals;
50639
- const idle = big8(res2[i * 2 + 1]);
52696
+ const assetDecimals = num4(res2[i * 2]) ?? r.decimals;
52697
+ const idle = big12(res2[i * 2 + 1]);
50640
52698
  const assetEntry = tokenList[r.asset];
50641
52699
  const priceKey = toOracleKey(assetEntry?.assetGroup) || toGenericPriceKey(r.asset, chainId);
50642
52700
  const priceUsd = prices[priceKey];
@@ -56039,6 +58097,20 @@ var NativeWithdrawQueueReadAbi = [
56039
58097
  }
56040
58098
  ];
56041
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
+
56042
58114
  // src/vaults/savings/abis/yearnStrategy.ts
56043
58115
  var AvailableWithdrawLimitAbi = [
56044
58116
  {
@@ -56138,6 +58210,29 @@ var readerErc4626WithdrawLimit = (entry) => {
56138
58210
  };
56139
58211
  };
56140
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
+
56141
58236
  // src/vaults/savings/readers/navOracle.ts
56142
58237
  var readerNavOracle = (entry) => {
56143
58238
  const shareUnit = 10n ** BigInt(entry.decimals);
@@ -56231,6 +58326,8 @@ var buildReader2 = (entry) => {
56231
58326
  return readerNativeWnlp(entry);
56232
58327
  case "nav-oracle":
56233
58328
  return readerNavOracle(entry);
58329
+ case "frankencoin-savings":
58330
+ return readerFrankencoinSavings(entry);
56234
58331
  case "erc4626-idle":
56235
58332
  return readerErc4626Idle(entry);
56236
58333
  case "erc4626-withdraw-limit":
@@ -56473,7 +58570,7 @@ var pickApr = (apr) => {
56473
58570
  if (apr.inception != null) return { rate: apr.inception, window: "inception" };
56474
58571
  return { rate: 0, window: "none" };
56475
58572
  };
56476
- var num4 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
58573
+ var num5 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
56477
58574
  function parseVault7(v, chainId, prices, tokenList) {
56478
58575
  const address = (v?.address ?? "").toLowerCase();
56479
58576
  const assetAddr = (v?.asset?.address ?? "").toLowerCase();
@@ -56489,14 +58586,14 @@ function parseVault7(v, chainId, prices, tokenList) {
56489
58586
  parseRawAmount(totalAssetsRaw, assetDecimals)
56490
58587
  );
56491
58588
  const apr = {
56492
- weekly: num4(state.weeklyApr?.twrrNetApr),
56493
- monthly: num4(state.monthlyApr?.twrrNetApr),
56494
- yearly: num4(state.yearlyApr?.twrrNetApr),
56495
- 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)
56496
58593
  };
56497
58594
  const { rate: supplyRate, window: aprWindow } = pickApr(apr);
56498
58595
  const oracleKey = toOracleKey(assetMeta?.assetGroup) ?? toGenericPriceKey(assetAddr, chainId);
56499
- const apiTotalAssetsUsd = num4(state.totalAssetsUsd) ?? 0;
58596
+ const apiTotalAssetsUsd = num5(state.totalAssetsUsd) ?? 0;
56500
58597
  const impliedPriceUsd = totalAssetsFormatted > 0 ? apiTotalAssetsUsd / totalAssetsFormatted : 0;
56501
58598
  const priceUsd = prices[oracleKey] ?? prices[assetAddr] ?? impliedPriceUsd;
56502
58599
  const totalAssetsUsd = apiTotalAssetsUsd || totalAssetsFormatted * priceUsd;
@@ -56516,7 +58613,7 @@ function parseVault7(v, chainId, prices, tokenList) {
56516
58613
  totalAssets: totalAssetsRaw,
56517
58614
  totalSupply: totalSupplyRaw,
56518
58615
  pricePerShare: state.pricePerShare?.toString() ?? "0",
56519
- pricePerShareUsd: num4(state.pricePerShareUsd) ?? void 0,
58616
+ pricePerShareUsd: num5(state.pricePerShareUsd) ?? void 0,
56520
58617
  supplyRate,
56521
58618
  rewardsRate: 0,
56522
58619
  depositRate: supplyRate,
@@ -56713,7 +58810,7 @@ var toBigInt16 = (v) => {
56713
58810
  }
56714
58811
  return void 0;
56715
58812
  };
56716
- var num5 = (v) => {
58813
+ var num6 = (v) => {
56717
58814
  const n = Number(v);
56718
58815
  return Number.isFinite(n) ? n : 0;
56719
58816
  };
@@ -56770,12 +58867,12 @@ var fetchAaveEarnVaults = async (chainId, multicallRetry, prices = {}, tokenList
56770
58867
  const totalAssets = toBigInt16(slice2[0]) ?? totalSupply * convertToAssets / shareUnit;
56771
58868
  const totalAssetsFormatted = Number(totalAssets) / 10 ** assetDecimals;
56772
58869
  const asset = tokenList[underlyingLc];
56773
- 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);
56774
58871
  const totalAssetsUsd = priceUsd !== void 0 ? totalAssetsFormatted * priceUsd : 0;
56775
- const supplyRate = num5(v.vaultApr?.formatted);
58872
+ const supplyRate = num6(v.vaultApr?.formatted);
56776
58873
  const rewardsRate = 0;
56777
58874
  const depositRate = supplyRate + rewardsRate;
56778
- const fee = num5(v.fee?.value);
58875
+ const fee = num6(v.fee?.value);
56779
58876
  const symbol = (v.shareSymbol ?? "").trim();
56780
58877
  const shareName = (v.shareName ?? "").trim();
56781
58878
  const name = shareName || symbol;
@@ -56812,7 +58909,7 @@ var fetchAaveEarnVaults = async (chainId, multicallRetry, prices = {}, tokenList
56812
58909
  };
56813
58910
 
56814
58911
  // src/vaults/upshift/fetchPublic.ts
56815
- var num6 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
58912
+ var num7 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
56816
58913
  var isEvmAddress = (a) => /^0x[0-9a-fA-F]{40}$/.test(a);
56817
58914
  var derivePricePerShare = (totalAssetsRaw, totalSupplyRaw, shareDecimals) => {
56818
58915
  try {
@@ -56839,12 +58936,12 @@ function parseVault8(v, chainId, prices, tokenList) {
56839
58936
  const totalAssetsFormatted = Number(
56840
58937
  parseRawAmount(totalAssetsRaw, assetDecimals)
56841
58938
  );
56842
- const base = num6(v.apy?.apy) ?? 0;
56843
- const campaign = num6(v.apy?.campaignApy);
58939
+ const base = num7(v.apy?.apy) ?? 0;
58940
+ const campaign = num7(v.apy?.campaignApy);
56844
58941
  const supplyRate = apyToAprPercent(base);
56845
58942
  const rewardsRate = campaign != null ? apyToAprPercent(campaign) : 0;
56846
58943
  const oracleKey = toOracleKey(assetMeta?.assetGroup) ?? toGenericPriceKey(assetAddr, chainId);
56847
- const apiTvlUsd = num6(v.latest_reported_tvl) ?? 0;
58944
+ const apiTvlUsd = num7(v.latest_reported_tvl) ?? 0;
56848
58945
  const impliedPriceUsd = totalAssetsFormatted > 0 ? apiTvlUsd / totalAssetsFormatted : 0;
56849
58946
  const priceUsd = prices[oracleKey] ?? prices[assetAddr] ?? impliedPriceUsd;
56850
58947
  const totalAssetsUsd = apiTvlUsd || totalAssetsFormatted * priceUsd;
@@ -56869,10 +58966,10 @@ function parseVault8(v, chainId, prices, tokenList) {
56869
58966
  rewardsRate,
56870
58967
  depositRate: supplyRate + rewardsRate,
56871
58968
  apy: {
56872
- base: num6(v.apy?.apy),
58969
+ base: num7(v.apy?.apy),
56873
58970
  campaign,
56874
- points: num6(v.apy?.pointsApy),
56875
- underlying: num6(v.apy?.underlyingApy)
58971
+ points: num7(v.apy?.pointsApy),
58972
+ underlying: num7(v.apy?.underlyingApy)
56876
58973
  },
56877
58974
  isDepositPaused: v.isDepositPaused ?? false,
56878
58975
  isWithdrawalPaused: v.isWithdrawalPaused ?? false,
@@ -56981,9 +59078,9 @@ var asBig = (v) => {
56981
59078
  return null;
56982
59079
  }
56983
59080
  };
56984
- var num7 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
59081
+ var num8 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
56985
59082
  var toPct = (v) => {
56986
- const n = num7(v);
59083
+ const n = num8(v);
56987
59084
  return n == null ? 0 : n * 100;
56988
59085
  };
56989
59086
  var deriveTotalSupply = (totalAssetsRaw, pricePerShareRaw, decimals) => {
@@ -57015,16 +59112,16 @@ function parseVault9(v, chainId, prices, tokenList) {
57015
59112
  const totalAssetsFormatted = Number(
57016
59113
  parseRawAmount(totalAssetsRaw, assetDecimals)
57017
59114
  );
57018
- const realized = num7(v.apr?.netAPR);
57019
- const forward = num7(v.apr?.forwardAPR?.netAPR);
59115
+ const realized = num8(v.apr?.netAPR);
59116
+ const forward = num8(v.apr?.forwardAPR?.netAPR);
57020
59117
  const isForwardApr = realized == null && forward != null;
57021
59118
  const supplyRate = toPct(realized ?? forward);
57022
59119
  const rewardsRate = toPct(v.apr?.extra?.stakingRewardsAPR);
57023
59120
  const fee = toPct(v.apr?.fees?.performance);
57024
59121
  const oracleKey = toOracleKey(assetMeta?.assetGroup) ?? toGenericPriceKey(assetAddr, chainId);
57025
- const apiPrice = num7(v.tvl?.price) ?? 0;
59122
+ const apiPrice = num8(v.tvl?.price) ?? 0;
57026
59123
  const priceUsd = prices[oracleKey] ?? prices[assetAddr] ?? apiPrice;
57027
- const apiTvlUsd = num7(v.tvl?.tvl) ?? 0;
59124
+ const apiTvlUsd = num8(v.tvl?.tvl) ?? 0;
57028
59125
  const totalAssetsUsd = apiTvlUsd || totalAssetsFormatted * priceUsd;
57029
59126
  const name = (v.name ?? "").trim();
57030
59127
  const symbol = (v.symbol ?? "").trim();
@@ -58012,23 +60109,23 @@ var priceGmMarkets = async (chainId, multicallRetry, markets, prices) => {
58012
60109
  const indexMax = price(prices, m.indexToken)?.max;
58013
60110
  if (Array.isArray(dsRes) && longMax != null && shortMax != null) {
58014
60111
  const base = i * SLOTS;
58015
- 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;
58016
60113
  const cap = computeDepositCapacityUsd(
58017
- [info?.longTokenAmount, longMax, big9(0), big9(2)],
58018
- [info?.shortTokenAmount, shortMax, big9(1), big9(3)]
60114
+ [info?.longTokenAmount, longMax, big13(0), big13(2)],
60115
+ [info?.shortTokenAmount, shortMax, big13(1), big13(3)]
58019
60116
  );
58020
60117
  if (cap != null) value.depositCapacityUsd = cap;
58021
60118
  if (indexMax != null) {
58022
60119
  const divisor = m.longToken.toLowerCase() === m.shortToken.toLowerCase() ? 2n : 1n;
58023
- const reservedUsdLong = (big9(4) + big9(5)) / divisor * indexMax;
58024
- const reservedUsdShort = (big9(6) + big9(7)) / divisor;
60120
+ const reservedUsdLong = (big13(4) + big13(5)) / divisor * indexMax;
60121
+ const reservedUsdShort = (big13(6) + big13(7)) / divisor;
58025
60122
  const liq = computeLiquidityUsd(
58026
60123
  info?.longTokenUsd,
58027
60124
  info?.shortTokenUsd,
58028
60125
  reservedUsdLong,
58029
60126
  reservedUsdShort,
58030
- big9(8),
58031
- big9(9)
60127
+ big13(8),
60128
+ big13(9)
58032
60129
  );
58033
60130
  if (liq != null)
58034
60131
  value.liquidityUsd = Math.max(0, Math.min(liq, value.tvlUsd));
@@ -58227,27 +60324,27 @@ var fetchGmxExecutionFees = async (chainId, multicallRetry, gasPriceWei) => {
58227
60324
  } catch {
58228
60325
  return void 0;
58229
60326
  }
58230
- const big9 = (i) => typeof res[i] === "bigint" ? res[i] : 0n;
58231
- const base = big9(0);
58232
- 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);
58233
60330
  if (base === 0n && mult === 0n) return void 0;
58234
60331
  const PRECISION = 10n ** 30n;
58235
60332
  const adjusted = (opGas) => base + opGas * mult / PRECISION;
58236
60333
  const fee = (opGas) => (adjusted(opGas) * gasPriceWei).toString();
58237
- const glvExtra = big9(6) * GLV_NOMINAL_MARKET_COUNT;
60334
+ const glvExtra = big13(6) * GLV_NOMINAL_MARKET_COUNT;
58238
60335
  return {
58239
60336
  chainId,
58240
60337
  gasPriceWei: gasPriceWei.toString(),
58241
- deposit: fee(big9(2)),
58242
- withdrawal: fee(big9(3)),
58243
- glvDeposit: fee(big9(4) + glvExtra),
58244
- 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)
58245
60342
  };
58246
60343
  };
58247
60344
 
58248
60345
  // src/vaults/gmx/fetchPublic.ts
58249
60346
  var GMX_TOKEN_DECIMALS = 18;
58250
- var num8 = (n) => typeof n === "number" && Number.isFinite(n) ? n : 0;
60347
+ var num9 = (n) => typeof n === "number" && Number.isFinite(n) ? n : 0;
58251
60348
  var minDefined = (a, b) => a == null ? b : b == null ? a : Math.min(a, b);
58252
60349
  var glvMarketRoomUsd = (cap, priceUsd) => {
58253
60350
  const currentUsd = Number(cap.balanceAmount) / 1e18 * priceUsd;
@@ -58281,9 +60378,9 @@ var fetchGmxVaults = async (chainId, multicallRetry, options) => {
58281
60378
  indexToken: indexToken ? indexToken.toLowerCase() : void 0,
58282
60379
  longSymbol,
58283
60380
  shortSymbol,
58284
- apy: num8(entry?.apy),
58285
- baseApy: num8(entry?.baseApy),
58286
- bonusApr: num8(entry?.bonusApr),
60381
+ apy: num9(entry?.apy),
60382
+ baseApy: num9(entry?.baseApy),
60383
+ bonusApr: num9(entry?.bonusApr),
58287
60384
  yieldProfile: "volatile",
58288
60385
  denomination: denominationFor(longSymbol, shortSymbol)
58289
60386
  };
@@ -59460,6 +61557,6 @@ async function fetchTokenBalances(chainId, account, tokens, options = {}) {
59460
61557
  return parseTokenBalanceResult(rawResult, prepared.query);
59461
61558
  }
59462
61559
 
59463
- 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, 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, 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 };
59464
61561
  //# sourceMappingURL=index.js.map
59465
61562
  //# sourceMappingURL=index.js.map