@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.d.ts +475 -2
- package/dist/index.js +2266 -169
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { parseAbi, keccak256, encodeAbiParameters, formatEther, BaseError,
|
|
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
|
|
11212
|
-
BROKER_USER_CACHE[
|
|
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
|
|
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
|
|
22899
|
-
const b =
|
|
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:
|
|
22907
|
-
committed:
|
|
22908
|
-
minRateBps:
|
|
22909
|
-
collateralPerPrincipal:
|
|
22910
|
-
maxLoanDuration:
|
|
22911
|
-
marketId:
|
|
22912
|
-
totalAssets:
|
|
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 =
|
|
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
|
|
23882
|
+
const num10 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
23874
23883
|
return {
|
|
23875
23884
|
market,
|
|
23876
|
-
totalDebt:
|
|
23877
|
-
dolaLiquidity:
|
|
23878
|
-
leftToBorrow:
|
|
23879
|
-
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:
|
|
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
|
|
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) =>
|
|
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:
|
|
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
|
|
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:
|
|
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:
|
|
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 =
|
|
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
|
|
27916
|
+
var discoveryCache3 = /* @__PURE__ */ new Map();
|
|
26488
27917
|
var cacheKey2 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
|
|
26489
27918
|
var getCachedUsddCdps = (chainId, account) => {
|
|
26490
|
-
const hit =
|
|
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
|
|
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) =>
|
|
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:
|
|
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:
|
|
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 =
|
|
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
|
|
26604
|
-
var
|
|
28103
|
+
var discoveryCache5 = /* @__PURE__ */ new Map();
|
|
28104
|
+
var cacheKey4 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
|
|
26605
28105
|
var getCachedTellerBids = (chainId, account) => {
|
|
26606
|
-
const hit =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
26701
|
-
var
|
|
28200
|
+
var discoveryCache6 = /* @__PURE__ */ new Map();
|
|
28201
|
+
var cacheKey5 = (chainId, account) => `${chainId}:${account.toLowerCase()}`;
|
|
26702
28202
|
var getCachedTermMaxDiscovery = (chainId, account) => {
|
|
26703
|
-
const hit =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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) =>
|
|
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 =
|
|
29663
|
-
const spYield =
|
|
29664
|
-
const spCollGain =
|
|
29665
|
-
const spStashed =
|
|
29666
|
-
const collSurplus = branch.collSurplusPool ?
|
|
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
|
|
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) =>
|
|
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 =
|
|
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(
|
|
29771
|
-
const surplus =
|
|
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
|
|
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 =
|
|
29899
|
-
const dbrDeficit =
|
|
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 :
|
|
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 :
|
|
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 =
|
|
31435
|
+
const debt = big5(debtRaw);
|
|
29909
31436
|
if (escrowBal === 0n && debt === 0n) return;
|
|
29910
|
-
const creditLimit = isFailedCall(data[base + 2]) ? 0n :
|
|
29911
|
-
const withdrawalLimit = isFailedCall(data[base + 3]) ? 0n :
|
|
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
|
|
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) =>
|
|
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
|
|
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 =
|
|
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 =
|
|
30163
|
-
const owedInterest =
|
|
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
|
-
|
|
32096
|
+
big10(field10(loanDetails, "acceptedTimestamp", 4))
|
|
30170
32097
|
);
|
|
30171
|
-
const loanDuration = Number(
|
|
30172
|
-
const aprBps = Number(
|
|
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
|
|
37632
|
+
function cacheKey6(chainId, account) {
|
|
35685
37633
|
return `${chainId}:${account.toLowerCase()}`;
|
|
35686
37634
|
}
|
|
35687
37635
|
async function dedupedFetch(chainId, account, loader) {
|
|
35688
|
-
const key =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
52112
|
+
if (v == null || v === "") return ZERO2;
|
|
50055
52113
|
try {
|
|
50056
52114
|
return BigInt(v);
|
|
50057
52115
|
} catch {
|
|
50058
|
-
return
|
|
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 ===
|
|
50065
|
-
let weightedRay =
|
|
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 ===
|
|
52130
|
+
if (allocated === ZERO2) continue;
|
|
50073
52131
|
weightedRay += allocated * apyRay;
|
|
50074
52132
|
}
|
|
50075
|
-
if (weightedRay ===
|
|
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 ===
|
|
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 =
|
|
50091
|
-
let withdrawable =
|
|
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 ===
|
|
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 :
|
|
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
|
|
52462
|
+
var num3 = (v) => {
|
|
50405
52463
|
const n = Number(v);
|
|
50406
52464
|
return Number.isFinite(n) ? n : 0;
|
|
50407
52465
|
};
|
|
50408
|
-
var
|
|
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 =
|
|
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 =
|
|
50445
|
-
const totalSupply =
|
|
52502
|
+
const totalAssets = big11(r.totalAssets);
|
|
52503
|
+
const totalSupply = big11(r.totalSupplyAmt);
|
|
50446
52504
|
const totalAssetsFormatted = Number(totalAssets) / scale;
|
|
50447
|
-
const supplyRate =
|
|
50448
|
-
const rewardsRate =
|
|
50449
|
-
const rawLiquidity = BigInt(
|
|
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 =
|
|
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:
|
|
50471
|
-
timelock:
|
|
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 ?
|
|
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
|
|
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
|
|
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 =
|
|
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:
|
|
52669
|
+
decimals: num4(at("decimals")) ?? 18,
|
|
50612
52670
|
asset,
|
|
50613
52671
|
totalAssets,
|
|
50614
|
-
totalSupply:
|
|
50615
|
-
annualizedInterest:
|
|
50616
|
-
accretingPrincipal:
|
|
50617
|
-
performanceFeeRate:
|
|
50618
|
-
aprRaw: at("apr") != null ?
|
|
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:
|
|
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 =
|
|
50639
|
-
const idle =
|
|
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
|
|
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:
|
|
56493
|
-
monthly:
|
|
56494
|
-
yearly:
|
|
56495
|
-
inception:
|
|
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 =
|
|
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:
|
|
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
|
|
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 ?
|
|
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 =
|
|
58872
|
+
const supplyRate = num6(v.vaultApr?.formatted);
|
|
56776
58873
|
const rewardsRate = 0;
|
|
56777
58874
|
const depositRate = supplyRate + rewardsRate;
|
|
56778
|
-
const fee =
|
|
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
|
|
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 =
|
|
56843
|
-
const campaign =
|
|
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 =
|
|
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:
|
|
58969
|
+
base: num7(v.apy?.apy),
|
|
56873
58970
|
campaign,
|
|
56874
|
-
points:
|
|
56875
|
-
underlying:
|
|
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
|
|
59081
|
+
var num8 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
56985
59082
|
var toPct = (v) => {
|
|
56986
|
-
const n =
|
|
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 =
|
|
57019
|
-
const forward =
|
|
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 =
|
|
59122
|
+
const apiPrice = num8(v.tvl?.price) ?? 0;
|
|
57026
59123
|
const priceUsd = prices[oracleKey] ?? prices[assetAddr] ?? apiPrice;
|
|
57027
|
-
const apiTvlUsd =
|
|
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
|
|
60112
|
+
const big13 = (j) => typeof dsRes[base + j] === "bigint" ? dsRes[base + j] : 0n;
|
|
58016
60113
|
const cap = computeDepositCapacityUsd(
|
|
58017
|
-
[info?.longTokenAmount, longMax,
|
|
58018
|
-
[info?.shortTokenAmount, shortMax,
|
|
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 = (
|
|
58024
|
-
const reservedUsdShort = (
|
|
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
|
-
|
|
58031
|
-
|
|
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
|
|
58231
|
-
const base =
|
|
58232
|
-
const mult =
|
|
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 =
|
|
60334
|
+
const glvExtra = big13(6) * GLV_NOMINAL_MARKET_COUNT;
|
|
58238
60335
|
return {
|
|
58239
60336
|
chainId,
|
|
58240
60337
|
gasPriceWei: gasPriceWei.toString(),
|
|
58241
|
-
deposit: fee(
|
|
58242
|
-
withdrawal: fee(
|
|
58243
|
-
glvDeposit: fee(
|
|
58244
|
-
glvWithdrawal: fee(
|
|
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
|
|
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:
|
|
58285
|
-
baseApy:
|
|
58286
|
-
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
|