@1delta/margin-fetcher 5.0.61 → 5.0.63
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 +19 -2
- package/dist/index.js +307 -110
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { parseAbi, keccak256, encodeAbiParameters, formatEther, BaseError, erc20Abi, stringToHex, isAddress, pad, encodeFunctionData, formatUnits, getAddress, decodeFunctionResult, decodeAbiParameters, concat, parseAbiParameters, AbiEncodingLengthMismatchError, concatHex, toBytes, slice, hexToString, InvalidAddressError, boolToHex, integerRegex, numberToHex, bytesRegex, BytesSizeMismatchError, arrayRegex, UnsupportedPackedAbiType } from './chunk-JUYF2XLF.js';
|
|
2
2
|
import './chunk-BYTNVMX7.js';
|
|
3
3
|
import './chunk-PR4QN5HX.js';
|
|
4
|
-
import { Lender, isExactly, isMidnight, isTerm, isTermMax, isTeller, isListaDao, isLiquityFamily, isRiver, isInverse, isCooler, isDssType, isCompoundV3Type, isFluid, isGearboxV3, isLlamaLend, isFrankencoin, isResupply, isCurvance, isTwyne, isFraxlend, LIQUITY_FAMILY_LENDERS, isAaveType, isCompoundV3, isMultiMarket, isSiloV2Type, isSiloV3Type, isDolomite, isMorphoType, isUsdd, isSky, hasCrossMarginRisk, isEulerType,
|
|
4
|
+
import { Lender, isExactly, isMidnight, isTerm, isTermMax, isTeller, isListaDao, isLiquityFamily, isRiver, isInverse, isCooler, isDssType, isCompoundV3Type, isFluid, isGearboxV3, isLlamaLend, isFrankencoin, isResupply, isCurvance, isTwyne, isFraxlend, isAaveV4Type, LIQUITY_FAMILY_LENDERS, isAaveType, isCompoundV3, isCompoundV2Type, isMultiMarket, isSiloV2Type, isSiloV3Type, isDolomite, isMorphoType, isUsdd, isSky, hasCrossMarginRisk, isEulerType, isInit, isVenusType, isSumerType, AAVE_V3_LENDERS, AAVE_V2_LENDERS, isMorphoBlue, isAaveV2Type, isAaveV32Type, isAaveV3Type, isYLDR, isLista, hasSubAccounts, isTectonicType, isKineticType, isBenqiType } from '@1delta/lender-registry';
|
|
5
5
|
export { hasCrossMarginRisk, isAaveType, isAaveV2Type, isAaveV32Type, isAaveV3Type, isCompoundV3, isCompoundV3Type, isInit, isMorphoType, isMultiMarket, isYLDR } from '@1delta/lender-registry';
|
|
6
|
-
import { fetchTokenLists, fetchTokenList, aavePools, compoundV3Pools, initConfig, morphoPools, compoundV2Pools, eulerVaults, siloMarkets, siloV2LenderKey, siloMarketsV3, siloV3LenderKey, aaveV4Spokes, aaveV4SpokeLenderKey, fluidResolvers, gearboxResolvers, dolomiteConfigs, midnightConfig, termConfig, termMarketsByChain, exactlyConfig, liquityLendersByChain, riverLendersByChain, inverseLendersByChain, coolerLendersByChain, llamaLendLendersByChain, usddLendersByChain, skyLendersByChain, frankencoinLendersByChain, resupplyLendersByChain, curvanceLendersByChain, fraxlendLendersByChain, twyneLendersByChain, tellerConfigByChain, tellerPoolsByChain, termMaxConfigByChain, aaveReserves, compoundV3Reserves, resolveTermApiBase, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, termMaxApiBaseUrl, termMaxLenderKey, inverseConfigFor, inverseChainData, coolerConfigFor, llamaLendConfigFor, llamaLendChainData, llamaLendApiBaseUrl, resupplyConfigFor, fraxlendConfigFor, dssConfigFor, dssChainData, dssDebtToken, dssDebtJoin, frankencoinConfigFor, frankencoinChainData, aaveOracles, morphoTypeMarkets, resolveMidnightApiBase, llamaLendMarketByVault, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, curvanceConfigFor, aaveTokens, morphoTypeVaults, listaCollateralProvider, eulerConfigs, gearboxMarketCompressor, gearboxMarketConfigurators, gearboxV3LenderKey, midnightMarketsByChain, twyneConfigFor, twyneChainData, parseAaveV4SpokeLenderKey, fraxlendPairsFor, gearboxAccountCompressor, compoundV2Tokens, exactlyMarketsByChain, aaveOraclesConfig, compoundV2Oracles,
|
|
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, coolerLendersByChain, llamaLendLendersByChain, usddLendersByChain, skyLendersByChain, frankencoinLendersByChain, resupplyLendersByChain, curvanceLendersByChain, fraxlendLendersByChain, twyneLendersByChain, tellerConfigByChain, tellerPoolsByChain, termMaxConfigByChain, aaveReserves, compoundV3Reserves, resolveTermApiBase, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, termMaxApiBaseUrl, termMaxLenderKey, inverseConfigFor, inverseChainData, coolerConfigFor, llamaLendConfigFor, llamaLendChainData, llamaLendApiBaseUrl, resupplyConfigFor, fraxlendConfigFor, dssConfigFor, dssChainData, dssDebtToken, dssDebtJoin, frankencoinConfigFor, frankencoinChainData, aaveOracles, morphoTypeMarkets, resolveMidnightApiBase, llamaLendMarketByVault, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, curvanceConfigFor, aaveTokens, morphoTypeVaults, listaCollateralProvider, eulerConfigs, gearboxMarketCompressor, gearboxMarketConfigurators, compoundV2TokenArray, gearboxV3LenderKey, midnightMarketsByChain, twyneConfigFor, twyneChainData, parseAaveV4SpokeLenderKey, fraxlendPairsFor, gearboxAccountCompressor, compoundV2Tokens, exactlyMarketsByChain, aaveOraclesConfig, compoundV2Oracles, compoundV2OraclesConfig, compoundV3OraclesData, compoundV3BaseData, compoundV2Reserves, aaveV4Oracles, morphoTypeOracles } from '@1delta/data-sdk';
|
|
7
7
|
import lodash from 'lodash';
|
|
8
8
|
import { Chain } from '@1delta/chain-registry';
|
|
9
9
|
import { multicallRetryUniversal, getEvmClient, getEvmChain, getEvmClientUniversal } from '@1delta/providers';
|
|
@@ -7103,18 +7103,15 @@ var formatAaveYieldToNumber = (n) => {
|
|
|
7103
7103
|
if (!n) return 0;
|
|
7104
7104
|
return Number(formatEther(BigInt(n) / BigInt(1e7)));
|
|
7105
7105
|
};
|
|
7106
|
-
var calculateRateForCompoundType2 = (n) => {
|
|
7106
|
+
var calculateRateForCompoundType2 = (n, unitSeconds) => {
|
|
7107
7107
|
const rate = Number(formatEther(BigInt(n)));
|
|
7108
|
-
|
|
7108
|
+
const perUnit = unitSeconds && unitSeconds > 0 ? unitSeconds : 12;
|
|
7109
|
+
return (Math.pow(rate * 60 * 60 * 24 / perUnit + 1, 365) - 1) * 100;
|
|
7109
7110
|
};
|
|
7110
|
-
var calculateRateForCompoundType = (n, chainId, scale3 = 1 /* SECOND
|
|
7111
|
+
var calculateRateForCompoundType = (n, chainId, scale3 = 1 /* SECOND */, unitSeconds) => {
|
|
7111
7112
|
const rate = Number(formatEther(BigInt(n)));
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
rate * 60 * 60 * 24 / (BLOCK_TIMES[chainId] ?? "1") + 1,
|
|
7115
|
-
365
|
|
7116
|
-
) - 1) * 100;
|
|
7117
|
-
return (Math.pow(rate * 60 * 60 * 24 + 1, 365) - 1) * 100;
|
|
7113
|
+
const perUnit = unitSeconds && unitSeconds > 0 ? unitSeconds : scale3 === 0 /* BLOCK */ ? Number(BLOCK_TIMES[chainId] ?? 1) : 1;
|
|
7114
|
+
return (Math.pow(rate * 60 * 60 * 24 / perUnit + 1, 365) - 1) * 100;
|
|
7118
7115
|
};
|
|
7119
7116
|
var formatAaveRawApyToApr = (raw) => {
|
|
7120
7117
|
const apy = formatAaveYieldToNumber(raw);
|
|
@@ -15305,9 +15302,102 @@ function getCall(lender, chainId) {
|
|
|
15305
15302
|
params: [tk]
|
|
15306
15303
|
});
|
|
15307
15304
|
}
|
|
15305
|
+
var L1_BLOCK_SECONDS = 12;
|
|
15306
|
+
var L1_MERGE_BLOCK = 15537394;
|
|
15307
|
+
var L1_MERGE_TIMESTAMP = 1663224162;
|
|
15308
|
+
var estimateL1Height = (nowSeconds) => L1_MERGE_BLOCK + (nowSeconds - L1_MERGE_TIMESTAMP) / L1_BLOCK_SECONDS;
|
|
15309
|
+
var CADENCE_SPAN = 20000n;
|
|
15310
|
+
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
15311
|
+
var clockCache = /* @__PURE__ */ new Map();
|
|
15312
|
+
var cadenceCache = /* @__PURE__ */ new Map();
|
|
15313
|
+
var fresh = (e) => !!e && Date.now() - e.at < TTL_MS;
|
|
15314
|
+
function classifyRateClock(accrualBlockNumber, headBlockNumber, headTimestamp) {
|
|
15315
|
+
const v = Number(accrualBlockNumber);
|
|
15316
|
+
if (!Number.isFinite(v) || v <= 0) return void 0;
|
|
15317
|
+
const candidates = [
|
|
15318
|
+
["timestamp", Number(headTimestamp)],
|
|
15319
|
+
["block", Number(headBlockNumber)],
|
|
15320
|
+
// The L1 height is not readable from this chain; derive it from the L2
|
|
15321
|
+
// head's timestamp, which is the same wall clock Ethereum runs on.
|
|
15322
|
+
["l1-block", estimateL1Height(Number(headTimestamp))]
|
|
15323
|
+
];
|
|
15324
|
+
let best;
|
|
15325
|
+
let bestRatio = Infinity;
|
|
15326
|
+
for (const [kind, expected] of candidates) {
|
|
15327
|
+
if (!Number.isFinite(expected) || expected <= 0) continue;
|
|
15328
|
+
const ratio = v > expected ? v / expected : expected / v;
|
|
15329
|
+
if (ratio < bestRatio) {
|
|
15330
|
+
bestRatio = ratio;
|
|
15331
|
+
best = kind;
|
|
15332
|
+
}
|
|
15333
|
+
}
|
|
15334
|
+
return bestRatio <= 2 ? best : void 0;
|
|
15335
|
+
}
|
|
15336
|
+
async function chainBlockSeconds(chainId) {
|
|
15337
|
+
const hit = cadenceCache.get(chainId);
|
|
15338
|
+
if (fresh(hit)) return hit.value;
|
|
15339
|
+
let value;
|
|
15340
|
+
try {
|
|
15341
|
+
const client = await getEvmClient(chainId);
|
|
15342
|
+
const head = await client.getBlockNumber();
|
|
15343
|
+
const span = head > CADENCE_SPAN ? CADENCE_SPAN : head / 2n;
|
|
15344
|
+
const [b1, b0] = await Promise.all([
|
|
15345
|
+
client.getBlock({ blockNumber: head }),
|
|
15346
|
+
client.getBlock({ blockNumber: head - span })
|
|
15347
|
+
]);
|
|
15348
|
+
const secs = Number(b1.timestamp - b0.timestamp) / Number(span);
|
|
15349
|
+
if (secs >= 0.05 && secs <= 60) value = secs;
|
|
15350
|
+
} catch {
|
|
15351
|
+
value = void 0;
|
|
15352
|
+
}
|
|
15353
|
+
cadenceCache.set(chainId, { at: Date.now(), value });
|
|
15354
|
+
return value;
|
|
15355
|
+
}
|
|
15356
|
+
async function resolveRateUnitSeconds(chainId, lender) {
|
|
15357
|
+
const key3 = `${chainId}:${lender}`;
|
|
15358
|
+
let clock = clockCache.get(key3);
|
|
15359
|
+
if (!fresh(clock)) {
|
|
15360
|
+
let value;
|
|
15361
|
+
try {
|
|
15362
|
+
const sample = getCompoundV2Tokens(chainId, lender)[0]?.cToken;
|
|
15363
|
+
if (sample) {
|
|
15364
|
+
const client = await getEvmClient(chainId);
|
|
15365
|
+
const head = await client.getBlock();
|
|
15366
|
+
const accrual = await client.readContract({
|
|
15367
|
+
address: sample,
|
|
15368
|
+
abi: [
|
|
15369
|
+
{
|
|
15370
|
+
inputs: [],
|
|
15371
|
+
name: "accrualBlockNumber",
|
|
15372
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
15373
|
+
stateMutability: "view",
|
|
15374
|
+
type: "function"
|
|
15375
|
+
}
|
|
15376
|
+
],
|
|
15377
|
+
functionName: "accrualBlockNumber"
|
|
15378
|
+
});
|
|
15379
|
+
value = classifyRateClock(accrual, head.number, head.timestamp);
|
|
15380
|
+
}
|
|
15381
|
+
} catch {
|
|
15382
|
+
value = void 0;
|
|
15383
|
+
}
|
|
15384
|
+
clock = { at: Date.now(), value };
|
|
15385
|
+
clockCache.set(key3, clock);
|
|
15386
|
+
}
|
|
15387
|
+
switch (clock.value) {
|
|
15388
|
+
case "timestamp":
|
|
15389
|
+
return 1;
|
|
15390
|
+
case "l1-block":
|
|
15391
|
+
return L1_BLOCK_SECONDS;
|
|
15392
|
+
case "block":
|
|
15393
|
+
return await chainBlockSeconds(chainId);
|
|
15394
|
+
default:
|
|
15395
|
+
return void 0;
|
|
15396
|
+
}
|
|
15397
|
+
}
|
|
15308
15398
|
|
|
15309
15399
|
// src/lending/public-data/compound-v2/getters/venus.ts
|
|
15310
|
-
function readVTokenMetadata(meta, token) {
|
|
15400
|
+
function readVTokenMetadata(meta, token, unitSeconds) {
|
|
15311
15401
|
const pick3 = (...values) => values.find((v) => v !== void 0);
|
|
15312
15402
|
return {
|
|
15313
15403
|
vToken: meta.vToken ?? "",
|
|
@@ -15343,7 +15433,8 @@ function readVTokenMetadata(meta, token) {
|
|
|
15343
15433
|
meta.supplyRatePerBlockOrTimestamp
|
|
15344
15434
|
)?.toString() ?? "0",
|
|
15345
15435
|
token.chainId,
|
|
15346
|
-
0 /* BLOCK
|
|
15436
|
+
0 /* BLOCK */,
|
|
15437
|
+
unitSeconds
|
|
15347
15438
|
) / 100
|
|
15348
15439
|
) * 100,
|
|
15349
15440
|
variableBorrowRate: apyToApr(
|
|
@@ -15353,7 +15444,8 @@ function readVTokenMetadata(meta, token) {
|
|
|
15353
15444
|
meta.borrowRatePerBlockOrTimestamp
|
|
15354
15445
|
)?.toString() ?? "0",
|
|
15355
15446
|
token.chainId,
|
|
15356
|
-
0 /* BLOCK
|
|
15447
|
+
0 /* BLOCK */,
|
|
15448
|
+
unitSeconds
|
|
15357
15449
|
) / 100
|
|
15358
15450
|
) * 100,
|
|
15359
15451
|
supplyCap: 0,
|
|
@@ -15572,20 +15664,24 @@ function parseTectonicMarketData(input) {
|
|
|
15572
15664
|
isBoosted: toBool3(field3(input, "isBoosted", 22)),
|
|
15573
15665
|
baseRatePerBlock: toBigInt3(field3(input, "baseRatePerBlock", 23)),
|
|
15574
15666
|
multiplierPerBlock: toBigInt3(field3(input, "multiplierPerBlock", 24)),
|
|
15575
|
-
jumpMultiplierPerBlock: toBigInt3(
|
|
15667
|
+
jumpMultiplierPerBlock: toBigInt3(
|
|
15668
|
+
field3(input, "jumpMultiplierPerBlock", 25)
|
|
15669
|
+
),
|
|
15576
15670
|
kink: toBigInt3(field3(input, "kink", 26))
|
|
15577
15671
|
};
|
|
15578
15672
|
}
|
|
15579
|
-
function getTectonicRates(info, chainId) {
|
|
15673
|
+
function getTectonicRates(info, chainId, unitSeconds) {
|
|
15580
15674
|
const supplyApy = calculateRateForCompoundType(
|
|
15581
15675
|
info.supplyRatePerBlock.toString(),
|
|
15582
15676
|
chainId,
|
|
15583
|
-
0 /* BLOCK
|
|
15677
|
+
0 /* BLOCK */,
|
|
15678
|
+
unitSeconds
|
|
15584
15679
|
);
|
|
15585
15680
|
const borrowApy = calculateRateForCompoundType(
|
|
15586
15681
|
info.borrowRatePerBlock.toString(),
|
|
15587
15682
|
chainId,
|
|
15588
|
-
0 /* BLOCK
|
|
15683
|
+
0 /* BLOCK */,
|
|
15684
|
+
unitSeconds
|
|
15589
15685
|
);
|
|
15590
15686
|
return {
|
|
15591
15687
|
depositRate: apyToApr(supplyApy / 100) * 100,
|
|
@@ -15631,7 +15727,9 @@ function parseKineticMarketMetadata(input) {
|
|
|
15631
15727
|
totalBorrows: toBigInt4(field4(input, "totalBorrows", 9)),
|
|
15632
15728
|
collateralFactor: toBigInt4(field4(input, "collateralFactor", 10)),
|
|
15633
15729
|
underlyingToken: String(field4(input, "underlyingToken", 11)),
|
|
15634
|
-
underlyingTokenDecimals: Number(
|
|
15730
|
+
underlyingTokenDecimals: Number(
|
|
15731
|
+
field4(input, "underlyingTokenDecimals", 12)
|
|
15732
|
+
),
|
|
15635
15733
|
cTokenDecimals: Number(field4(input, "cTokenDecimals", 13)),
|
|
15636
15734
|
totalReserves: toBigInt4(field4(input, "totalReserves", 16)),
|
|
15637
15735
|
cash: toBigInt4(field4(input, "cash", 17)),
|
|
@@ -16116,9 +16214,7 @@ function parseBenqiEcoMarketMetadata(input) {
|
|
|
16116
16214
|
borrowCap: toBigInt5(field5(input, "borrowCap", 6)),
|
|
16117
16215
|
supplyCap: toBigInt5(field5(input, "supplyCap", 7)),
|
|
16118
16216
|
totalSupply: toBigInt5(field5(input, "totalSupply", 8)),
|
|
16119
|
-
totalUnderlyingSupply: toBigInt5(
|
|
16120
|
-
field5(input, "totalUnderlyingSupply", 9)
|
|
16121
|
-
),
|
|
16217
|
+
totalUnderlyingSupply: toBigInt5(field5(input, "totalUnderlyingSupply", 9)),
|
|
16122
16218
|
totalBorrows: toBigInt5(field5(input, "totalBorrows", 10)),
|
|
16123
16219
|
collateralFactor: toBigInt5(field5(input, "collateralFactor", 11)),
|
|
16124
16220
|
underlying: parseToken(field5(input, "underlying", 12)),
|
|
@@ -16129,16 +16225,18 @@ function parseBenqiEcoMarketMetadata(input) {
|
|
|
16129
16225
|
borrowPaused: toBool5(field5(input, "borrowPaused", 17))
|
|
16130
16226
|
};
|
|
16131
16227
|
}
|
|
16132
|
-
function getBenqiRates(info, chainId) {
|
|
16228
|
+
function getBenqiRates(info, chainId, unitSeconds) {
|
|
16133
16229
|
const supplyApy = calculateRateForCompoundType(
|
|
16134
16230
|
info.supplyRate.toString(),
|
|
16135
16231
|
chainId,
|
|
16136
|
-
0 /* BLOCK
|
|
16232
|
+
0 /* BLOCK */,
|
|
16233
|
+
unitSeconds
|
|
16137
16234
|
);
|
|
16138
16235
|
const borrowApy = calculateRateForCompoundType(
|
|
16139
16236
|
info.borrowRate.toString(),
|
|
16140
16237
|
chainId,
|
|
16141
|
-
0 /* BLOCK
|
|
16238
|
+
0 /* BLOCK */,
|
|
16239
|
+
unitSeconds
|
|
16142
16240
|
);
|
|
16143
16241
|
return {
|
|
16144
16242
|
depositRate: apyToApr(supplyApy / 100) * 100,
|
|
@@ -16339,27 +16437,29 @@ function parseBaseFields(meta) {
|
|
|
16339
16437
|
pausedActions: DEFAULT_PAUSED_ACTIONS
|
|
16340
16438
|
};
|
|
16341
16439
|
}
|
|
16342
|
-
function readLodestarCTokenMetadata(meta, token) {
|
|
16440
|
+
function readLodestarCTokenMetadata(meta, token, unitSeconds) {
|
|
16343
16441
|
const base = parseBaseFields(meta);
|
|
16344
16442
|
return {
|
|
16345
16443
|
...base,
|
|
16346
16444
|
depositRate: capRate(
|
|
16347
16445
|
apyToApr(
|
|
16348
16446
|
calculateRateForCompoundType2(
|
|
16349
|
-
base.supplyRatePerBlock?.toString() ?? "0"
|
|
16447
|
+
base.supplyRatePerBlock?.toString() ?? "0",
|
|
16448
|
+
unitSeconds
|
|
16350
16449
|
) / 100
|
|
16351
16450
|
) * 100
|
|
16352
16451
|
),
|
|
16353
16452
|
variableBorrowRate: capRate(
|
|
16354
16453
|
apyToApr(
|
|
16355
16454
|
calculateRateForCompoundType2(
|
|
16356
|
-
base.borrowRatePerBlock?.toString() ?? "0"
|
|
16455
|
+
base.borrowRatePerBlock?.toString() ?? "0",
|
|
16456
|
+
unitSeconds
|
|
16357
16457
|
) / 100
|
|
16358
16458
|
) * 100
|
|
16359
16459
|
)
|
|
16360
16460
|
};
|
|
16361
16461
|
}
|
|
16362
|
-
function readCompoundV2CTokenMetadata(meta, token) {
|
|
16462
|
+
function readCompoundV2CTokenMetadata(meta, token, unitSeconds) {
|
|
16363
16463
|
const base = parseBaseFields(meta);
|
|
16364
16464
|
return {
|
|
16365
16465
|
...base,
|
|
@@ -16368,7 +16468,8 @@ function readCompoundV2CTokenMetadata(meta, token) {
|
|
|
16368
16468
|
calculateRateForCompoundType(
|
|
16369
16469
|
base.supplyRatePerBlock?.toString() ?? "0",
|
|
16370
16470
|
token.chainId,
|
|
16371
|
-
0 /* BLOCK
|
|
16471
|
+
0 /* BLOCK */,
|
|
16472
|
+
unitSeconds
|
|
16372
16473
|
) / 100
|
|
16373
16474
|
) * 100
|
|
16374
16475
|
),
|
|
@@ -16377,7 +16478,8 @@ function readCompoundV2CTokenMetadata(meta, token) {
|
|
|
16377
16478
|
calculateRateForCompoundType(
|
|
16378
16479
|
base.borrowRatePerBlock?.toString() ?? "0",
|
|
16379
16480
|
token.chainId,
|
|
16380
|
-
0 /* BLOCK
|
|
16481
|
+
0 /* BLOCK */,
|
|
16482
|
+
unitSeconds
|
|
16381
16483
|
) / 100
|
|
16382
16484
|
) * 100
|
|
16383
16485
|
)
|
|
@@ -16406,7 +16508,7 @@ function parseCreamV2BaseFields(meta) {
|
|
|
16406
16508
|
pausedActions: DEFAULT_PAUSED_ACTIONS
|
|
16407
16509
|
};
|
|
16408
16510
|
}
|
|
16409
|
-
function readCreamV2CTokenMetadata(meta, token) {
|
|
16511
|
+
function readCreamV2CTokenMetadata(meta, token, unitSeconds) {
|
|
16410
16512
|
const base = parseCreamV2BaseFields(meta);
|
|
16411
16513
|
return {
|
|
16412
16514
|
...base,
|
|
@@ -16415,7 +16517,8 @@ function readCreamV2CTokenMetadata(meta, token) {
|
|
|
16415
16517
|
calculateRateForCompoundType(
|
|
16416
16518
|
base.supplyRatePerBlock?.toString() ?? "0",
|
|
16417
16519
|
token.chainId,
|
|
16418
|
-
0 /* BLOCK
|
|
16520
|
+
0 /* BLOCK */,
|
|
16521
|
+
unitSeconds
|
|
16419
16522
|
) / 100
|
|
16420
16523
|
) * 100
|
|
16421
16524
|
),
|
|
@@ -16424,7 +16527,8 @@ function readCreamV2CTokenMetadata(meta, token) {
|
|
|
16424
16527
|
calculateRateForCompoundType(
|
|
16425
16528
|
base.borrowRatePerBlock?.toString() ?? "0",
|
|
16426
16529
|
token.chainId,
|
|
16427
|
-
0 /* BLOCK
|
|
16530
|
+
0 /* BLOCK */,
|
|
16531
|
+
unitSeconds
|
|
16428
16532
|
) / 100
|
|
16429
16533
|
) * 100
|
|
16430
16534
|
)
|
|
@@ -16557,13 +16661,13 @@ var REPAIR_BACKOFF_JITTER_MS = 60;
|
|
|
16557
16661
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));
|
|
16558
16662
|
var backoffForRound = (round) => REPAIR_BACKOFF_BASE_MS * 2 ** round + Math.random() * REPAIR_BACKOFF_JITTER_MS;
|
|
16559
16663
|
var endpointUrl = (client, rpcId) => client?.transport?.url ?? `rpc#${rpcId}`;
|
|
16560
|
-
var resolveEndpoint = (chainId,
|
|
16664
|
+
var resolveEndpoint = (chainId, getEvmClient18, startRpcId, tried, maxProbe = 12, timeoutMs) => {
|
|
16561
16665
|
let fallback = null;
|
|
16562
16666
|
for (let probe = 0; probe < maxProbe; probe++) {
|
|
16563
16667
|
const rpcId = startRpcId + probe;
|
|
16564
16668
|
let client;
|
|
16565
16669
|
try {
|
|
16566
|
-
client =
|
|
16670
|
+
client = getEvmClient18(chainId, rpcId, { timeoutMs });
|
|
16567
16671
|
} catch {
|
|
16568
16672
|
break;
|
|
16569
16673
|
}
|
|
@@ -16592,7 +16696,7 @@ var recordPermanentFailures = (slots, offset, collector) => {
|
|
|
16592
16696
|
if (slots[i].permanent) collector.add(offset + i);
|
|
16593
16697
|
}
|
|
16594
16698
|
};
|
|
16595
|
-
var repairFailedSlots = async (chainId, contracts, slots,
|
|
16699
|
+
var repairFailedSlots = async (chainId, contracts, slots, getEvmClient18, nextRpcId, batchSize, logs, rounds = MULTICALL_REPAIR_ROUNDS, options) => {
|
|
16596
16700
|
let searchFrom = nextRpcId;
|
|
16597
16701
|
for (let round = 0; round < rounds; round++) {
|
|
16598
16702
|
const failedIdx = [];
|
|
@@ -16602,7 +16706,7 @@ var repairFailedSlots = async (chainId, contracts, slots, getEvmClient17, nextRp
|
|
|
16602
16706
|
if (failedIdx.length === 0) return slots;
|
|
16603
16707
|
const endpoint = resolveEndpoint(
|
|
16604
16708
|
chainId,
|
|
16605
|
-
|
|
16709
|
+
getEvmClient18,
|
|
16606
16710
|
searchFrom,
|
|
16607
16711
|
options?.tried
|
|
16608
16712
|
);
|
|
@@ -16654,7 +16758,7 @@ var repairFailedSlots = async (chainId, contracts, slots, getEvmClient17, nextRp
|
|
|
16654
16758
|
}
|
|
16655
16759
|
return slots;
|
|
16656
16760
|
};
|
|
16657
|
-
var multicallShardedAbiArray = async (chainId, abi, calls,
|
|
16761
|
+
var multicallShardedAbiArray = async (chainId, abi, calls, getEvmClient18, poolSize, retries = maxRetries, allowFailure = true, batchSize = MULTICALL_DEFAULT_BATCH_SIZE, logs = false, retryFailed = false, permanentFailures, options) => {
|
|
16658
16762
|
const abiIsArray = isArray(abi[0]);
|
|
16659
16763
|
const contracts = calls.map(({ address, name, params }, i) => ({
|
|
16660
16764
|
abi: abiIsArray ? abi?.[i] : abi,
|
|
@@ -16728,7 +16832,7 @@ var multicallShardedAbiArray = async (chainId, abi, calls, getEvmClient17, poolS
|
|
|
16728
16832
|
const attemptHedged = async (items, startRpcId, tried) => {
|
|
16729
16833
|
const primary = resolveEndpoint(
|
|
16730
16834
|
chainId,
|
|
16731
|
-
|
|
16835
|
+
getEvmClient18,
|
|
16732
16836
|
startRpcId,
|
|
16733
16837
|
tried,
|
|
16734
16838
|
12,
|
|
@@ -16752,7 +16856,7 @@ var multicallShardedAbiArray = async (chainId, abi, calls, getEvmClient17, poolS
|
|
|
16752
16856
|
clearTimeout(timer);
|
|
16753
16857
|
const alt = resolveEndpoint(
|
|
16754
16858
|
chainId,
|
|
16755
|
-
|
|
16859
|
+
getEvmClient18,
|
|
16756
16860
|
primary.rpcId + 1,
|
|
16757
16861
|
tried,
|
|
16758
16862
|
12,
|
|
@@ -16804,7 +16908,7 @@ var multicallShardedAbiArray = async (chainId, abi, calls, getEvmClient17, poolS
|
|
|
16804
16908
|
chainId,
|
|
16805
16909
|
batch.items,
|
|
16806
16910
|
slots,
|
|
16807
|
-
|
|
16911
|
+
getEvmClient18,
|
|
16808
16912
|
won.rpcId + 1,
|
|
16809
16913
|
requestBytes,
|
|
16810
16914
|
logs,
|
|
@@ -16826,7 +16930,7 @@ var multicallShardedAbiArray = async (chainId, abi, calls, getEvmClient17, poolS
|
|
|
16826
16930
|
const tried = /* @__PURE__ */ new Set();
|
|
16827
16931
|
const start = resolveEndpoint(
|
|
16828
16932
|
chainId,
|
|
16829
|
-
|
|
16933
|
+
getEvmClient18,
|
|
16830
16934
|
workerId,
|
|
16831
16935
|
void 0,
|
|
16832
16936
|
12,
|
|
@@ -16873,7 +16977,7 @@ var parseMantissaWad = (raw) => {
|
|
|
16873
16977
|
return void 0;
|
|
16874
16978
|
}
|
|
16875
16979
|
};
|
|
16876
|
-
var getCompoundV2DataConverter = (lender, chainId, prices, additionalYields, tokenList = {}) => {
|
|
16980
|
+
var getCompoundV2DataConverter = (lender, chainId, prices, additionalYields, tokenList = {}, unitSeconds) => {
|
|
16877
16981
|
if (lender === Lender.TAKARA) {
|
|
16878
16982
|
return [
|
|
16879
16983
|
(data) => {
|
|
@@ -16995,7 +17099,7 @@ var getCompoundV2DataConverter = (lender, chainId, prices, additionalYields, tok
|
|
|
16995
17099
|
const pauseReads = Boolean(stdComptroller) && usesComptrollerPauseReads(lender);
|
|
16996
17100
|
const pauseCalls = pauseReads ? tokenCount * 2 : 0;
|
|
16997
17101
|
const expectedNumberOfCalls = isSumer ? tokenCount + SUMER_GROUP_COUNT : tokenCount + stdComptrollerCalls + pauseCalls;
|
|
16998
|
-
const reader = getReader(lender, chainId);
|
|
17102
|
+
const reader = getReader(lender, chainId, unitSeconds);
|
|
16999
17103
|
return [
|
|
17000
17104
|
(data) => {
|
|
17001
17105
|
if (data.length !== expectedNumberOfCalls) return void 0;
|
|
@@ -17065,9 +17169,9 @@ var getCompoundV2DataConverter = (lender, chainId, prices, additionalYields, tok
|
|
|
17065
17169
|
expectedNumberOfCalls
|
|
17066
17170
|
];
|
|
17067
17171
|
};
|
|
17068
|
-
function getReader(lender, chainId) {
|
|
17172
|
+
function getReader(lender, chainId, unitSeconds) {
|
|
17069
17173
|
if (isVenusType(lender)) {
|
|
17070
|
-
return (x, t) => readVTokenMetadata(x, t);
|
|
17174
|
+
return (x, t) => readVTokenMetadata(x, t, unitSeconds);
|
|
17071
17175
|
}
|
|
17072
17176
|
if (lender === Lender.MOONWELL) {
|
|
17073
17177
|
return (x, t) => parseMoonwellMarket(x, t);
|
|
@@ -17076,10 +17180,10 @@ function getReader(lender, chainId) {
|
|
|
17076
17180
|
return (x, t) => readSumerCTokenMetadata(x, t);
|
|
17077
17181
|
}
|
|
17078
17182
|
if (lender === Lender.LODESTAR || lender === Lender.TENDER) {
|
|
17079
|
-
return (x, t) => readLodestarCTokenMetadata(x);
|
|
17183
|
+
return (x, t) => readLodestarCTokenMetadata(x, t, unitSeconds);
|
|
17080
17184
|
}
|
|
17081
17185
|
if (lender === Lender.CREAM_FINANCE && (chainId === Chain.POLYGON_MAINNET || chainId === Chain.ARBITRUM_ONE)) {
|
|
17082
|
-
return (x, t) => readCreamV2CTokenMetadata(x, t);
|
|
17186
|
+
return (x, t) => readCreamV2CTokenMetadata(x, t, unitSeconds);
|
|
17083
17187
|
}
|
|
17084
17188
|
if (lender === Lender.COMPOUND_V2 || lender === Lender.FLUX_FINANCE || lender === Lender.WE_PIGGY || lender === Lender.CREAM_FINANCE || lender === Lender.CAPY_FI || lender === Lender.GAMMA || // long-tail forks read through a shared 14-field lens — MUST mirror the
|
|
17085
17189
|
// `CreamLensAbi` branch in publicCallBuild.ts `getCall`. A lender in that
|
|
@@ -17087,7 +17191,7 @@ function getReader(lender, chainId) {
|
|
|
17087
17191
|
// `reader is not a function`, which is not a length mismatch and so is not
|
|
17088
17192
|
// caught by the parser's own guard.
|
|
17089
17193
|
lender === Lender.DEMETER || lender === Lender.LANDER || lender === Lender.FILDA || lender === Lender.SOLIDLIZARD || lender === Lender.IRON_BANK || lender === Lender.MENDI || lender === Lender.PAXO || lender === Lender.SONNE || lender === Lender.ASO_FINANCE || lender === Lender.BLUME || lender === Lender.KAWA || lender === Lender.XPERT || lender === Lender.KEOM || lender === Lender.REACTOR_FUSION) {
|
|
17090
|
-
return (x, t) => readCompoundV2CTokenMetadata(x, t);
|
|
17194
|
+
return (x, t) => readCompoundV2CTokenMetadata(x, t, unitSeconds);
|
|
17091
17195
|
}
|
|
17092
17196
|
}
|
|
17093
17197
|
|
|
@@ -18802,7 +18906,9 @@ function normalizeAaveV4(spokeDataList, chainId, spokeLenderKeyArg, prices, addi
|
|
|
18802
18906
|
// >= PERCENTAGE_FACTOR (README: "bonus ≥ 100% (= ≥ 0% bonus)"). Same
|
|
18803
18907
|
// semantics as V3's `liquidationBonus`, so penalty = bps/BPS - 1.
|
|
18804
18908
|
liquidationPenalty: Number.isFinite(dynCfg.maxLiquidationBonus) && dynCfg.maxLiquidationBonus > 0 ? dynCfg.maxLiquidationBonus / BPS - 1 : 0,
|
|
18805
|
-
|
|
18909
|
+
// No close factor in V4 — the ceiling is the whole debt. See the
|
|
18910
|
+
// field docstring on `AaveV4TokenEntry.closeFactor`.
|
|
18911
|
+
closeFactor: 1,
|
|
18806
18912
|
targetHealthFactor,
|
|
18807
18913
|
// _validateSetUsingAsCollateral: !paused && !frozen (frozen blocks enabling)
|
|
18808
18914
|
collateralDisabled: dynCfg.collateralFactor === 0 || reserve.config.paused || reserve.config.frozen,
|
|
@@ -18818,7 +18924,9 @@ function normalizeAaveV4(spokeDataList, chainId, spokeLenderKeyArg, prices, addi
|
|
|
18818
18924
|
collateralFactor: 0,
|
|
18819
18925
|
borrowFactor: 1,
|
|
18820
18926
|
liquidationPenalty: 0,
|
|
18821
|
-
|
|
18927
|
+
// No close factor in V4 — the ceiling is the whole debt. See the
|
|
18928
|
+
// field docstring on `AaveV4TokenEntry.closeFactor`.
|
|
18929
|
+
closeFactor: 1,
|
|
18822
18930
|
targetHealthFactor,
|
|
18823
18931
|
collateralDisabled: true,
|
|
18824
18932
|
debtDisabled: !reserve.config.borrowable || reserve.config.paused || reserve.config.frozen
|
|
@@ -18887,7 +18995,8 @@ function normalizeAaveV4(spokeDataList, chainId, spokeLenderKeyArg, prices, addi
|
|
|
18887
18995
|
borrowCap,
|
|
18888
18996
|
supplyCap,
|
|
18889
18997
|
debtCeiling: 0,
|
|
18890
|
-
|
|
18998
|
+
// No close factor in V4 — the ceiling is the whole debt.
|
|
18999
|
+
closeFactor: 1,
|
|
18891
19000
|
targetHealthFactor,
|
|
18892
19001
|
spokeActive,
|
|
18893
19002
|
spokeHalted,
|
|
@@ -18906,13 +19015,20 @@ function normalizeAaveV4(spokeDataList, chainId, spokeLenderKeyArg, prices, addi
|
|
|
18906
19015
|
};
|
|
18907
19016
|
}
|
|
18908
19017
|
if (Object.keys(data).length === 0) return void 0;
|
|
19018
|
+
const liqCfg = spokeData.liquidationConfig;
|
|
19019
|
+
const wad = (v) => v != null && v > 0n ? Number(v) / 1e18 : void 0;
|
|
18909
19020
|
return {
|
|
18910
19021
|
data,
|
|
18911
19022
|
chainId,
|
|
18912
19023
|
params: {
|
|
18913
19024
|
spoke: spokeAddr,
|
|
18914
19025
|
oracle: spokeData.oracle.toLowerCase(),
|
|
18915
|
-
label: spokeData.label
|
|
19026
|
+
label: spokeData.label,
|
|
19027
|
+
liquidation: {
|
|
19028
|
+
targetHealthFactor: wad(liqCfg?.targetHealthFactor),
|
|
19029
|
+
healthFactorForMaxBonus: wad(liqCfg?.healthFactorForMaxBonus),
|
|
19030
|
+
liquidationBonusFactorBps: liqCfg?.liquidationBonusFactor || void 0
|
|
19031
|
+
}
|
|
18916
19032
|
}
|
|
18917
19033
|
};
|
|
18918
19034
|
}
|
|
@@ -19676,7 +19792,7 @@ var buildFluidCall = (chainId, _lender) => {
|
|
|
19676
19792
|
// src/lending/public-data/fluid/apiData.ts
|
|
19677
19793
|
var FLUID_API_BASE = "https://api.fluid.instadapp.io/v2";
|
|
19678
19794
|
var SUPPORTED_CHAINS = /* @__PURE__ */ new Set(["1", "56", "137", "8453", "9745", "42161"]);
|
|
19679
|
-
var
|
|
19795
|
+
var TTL_MS2 = 6e4;
|
|
19680
19796
|
var ZERO_ADDRESS4 = "0x0000000000000000000000000000000000000000";
|
|
19681
19797
|
var cache = {};
|
|
19682
19798
|
var inflight = /* @__PURE__ */ new Map();
|
|
@@ -19724,7 +19840,7 @@ var parseChainPayload = (raw) => {
|
|
|
19724
19840
|
var fetchFluidApiData = async (chainId) => {
|
|
19725
19841
|
if (!SUPPORTED_CHAINS.has(chainId)) return void 0;
|
|
19726
19842
|
const hit = cache[chainId];
|
|
19727
|
-
if (hit && Date.now() - hit.at <
|
|
19843
|
+
if (hit && Date.now() - hit.at < TTL_MS2) return hit.data;
|
|
19728
19844
|
const pending = inflight.get(chainId);
|
|
19729
19845
|
if (pending) return pending;
|
|
19730
19846
|
const run = (async () => {
|
|
@@ -19758,14 +19874,14 @@ var DEX_RESOLVER_FALLBACK = {
|
|
|
19758
19874
|
};
|
|
19759
19875
|
var dexResolverFor = (chainId) => fluidResolvers()?.[chainId]?.dexResolver ?? DEX_RESOLVER_FALLBACK[chainId];
|
|
19760
19876
|
var ZERO_ADDRESS5 = "0x0000000000000000000000000000000000000000";
|
|
19761
|
-
var
|
|
19877
|
+
var TTL_MS3 = 6e4;
|
|
19762
19878
|
var cache2 = {};
|
|
19763
19879
|
var inflight2 = /* @__PURE__ */ new Map();
|
|
19764
19880
|
var fetchFluidDexState = async (chainId, multicallRetry, extraDexAddresses = []) => {
|
|
19765
19881
|
const resolver = dexResolverFor(chainId);
|
|
19766
19882
|
if (!resolver) return void 0;
|
|
19767
19883
|
const hit = cache2[chainId];
|
|
19768
|
-
if (hit && Date.now() - hit.at <
|
|
19884
|
+
if (hit && Date.now() - hit.at < TTL_MS3) return hit.data;
|
|
19769
19885
|
const pending = inflight2.get(chainId);
|
|
19770
19886
|
if (pending) return pending;
|
|
19771
19887
|
const run = (async () => {
|
|
@@ -20768,7 +20884,7 @@ function buildLenderCall(chainId, lender) {
|
|
|
20768
20884
|
if (isGearboxV3(lender)) return buildGearboxCall(chainId);
|
|
20769
20885
|
return [];
|
|
20770
20886
|
}
|
|
20771
|
-
function getLenderDataConverter(lender, chainId, prices, additionalYields, tokenList = {}) {
|
|
20887
|
+
function getLenderDataConverter(lender, chainId, prices, additionalYields, tokenList = {}, unitSeconds) {
|
|
20772
20888
|
if (isAaveV2Type(lender))
|
|
20773
20889
|
return getAaveV2ReservesDataConverter(
|
|
20774
20890
|
lender,
|
|
@@ -20816,7 +20932,8 @@ function getLenderDataConverter(lender, chainId, prices, additionalYields, token
|
|
|
20816
20932
|
chainId,
|
|
20817
20933
|
prices,
|
|
20818
20934
|
additionalYields,
|
|
20819
|
-
tokenList
|
|
20935
|
+
tokenList,
|
|
20936
|
+
unitSeconds
|
|
20820
20937
|
);
|
|
20821
20938
|
if (isEulerType(lender))
|
|
20822
20939
|
return getEulerV2ReservesDataConverter(
|
|
@@ -20957,6 +21074,16 @@ var getLenderPublicData = async (chainId, lenders, prices, additionalYields, mul
|
|
|
20957
21074
|
}
|
|
20958
21075
|
const invalidLenders = [];
|
|
20959
21076
|
let lenderData = {};
|
|
21077
|
+
const rateUnitSeconds = /* @__PURE__ */ new Map();
|
|
21078
|
+
await Promise.all(
|
|
21079
|
+
validLenders.filter((l) => isCompoundV2Type(l)).map(async (l) => {
|
|
21080
|
+
try {
|
|
21081
|
+
rateUnitSeconds.set(l, await resolveRateUnitSeconds(chainId, l));
|
|
21082
|
+
} catch {
|
|
21083
|
+
rateUnitSeconds.set(l, void 0);
|
|
21084
|
+
}
|
|
21085
|
+
})
|
|
21086
|
+
);
|
|
20960
21087
|
let currentSlice = 0;
|
|
20961
21088
|
for (const lender of validLenders) {
|
|
20962
21089
|
const [converter, sliceLength] = getLenderDataConverter(
|
|
@@ -20964,7 +21091,8 @@ var getLenderPublicData = async (chainId, lenders, prices, additionalYields, mul
|
|
|
20964
21091
|
chainId,
|
|
20965
21092
|
prices,
|
|
20966
21093
|
additionalYields,
|
|
20967
|
-
list
|
|
21094
|
+
list,
|
|
21095
|
+
rateUnitSeconds.get(lender)
|
|
20968
21096
|
);
|
|
20969
21097
|
if (sliceLength > 0) {
|
|
20970
21098
|
try {
|
|
@@ -21173,16 +21301,16 @@ var LKG_TTL_SEC = 30 * 60;
|
|
|
21173
21301
|
var lastGood = /* @__PURE__ */ new Map();
|
|
21174
21302
|
async function fetchTopAndBookWithFallback(source, chainId, marketId, nowSec9) {
|
|
21175
21303
|
const key3 = `${chainId}:${marketId}`;
|
|
21176
|
-
let
|
|
21304
|
+
let fresh2 = null;
|
|
21177
21305
|
if (source.getTopAndBook) {
|
|
21178
|
-
|
|
21306
|
+
fresh2 = await source.getTopAndBook(marketId, MIDNIGHT_BOOK_LEVELS).catch(() => null);
|
|
21179
21307
|
} else {
|
|
21180
21308
|
const top = await source.getBookTop(marketId).catch(() => null);
|
|
21181
|
-
if (top)
|
|
21309
|
+
if (top) fresh2 = { top, book: { bids: [], asks: [] } };
|
|
21182
21310
|
}
|
|
21183
|
-
if (
|
|
21184
|
-
lastGood.set(key3, { top:
|
|
21185
|
-
return { top:
|
|
21311
|
+
if (fresh2) {
|
|
21312
|
+
lastGood.set(key3, { top: fresh2.top, book: fresh2.book, at: nowSec9 });
|
|
21313
|
+
return { top: fresh2.top, book: fresh2.book };
|
|
21186
21314
|
}
|
|
21187
21315
|
const cached = lastGood.get(key3);
|
|
21188
21316
|
if (cached && nowSec9 - cached.at <= LKG_TTL_SEC) {
|
|
@@ -21954,21 +22082,21 @@ var LKG_TTL_SEC2 = 30 * 60;
|
|
|
21954
22082
|
var lastGood2 = /* @__PURE__ */ new Map();
|
|
21955
22083
|
async function fetchTopAndBookWithFallback2(source, chainId, config, nowSec9) {
|
|
21956
22084
|
const key3 = `${chainId}:${config.termRepoId}`;
|
|
21957
|
-
let
|
|
22085
|
+
let fresh2 = null;
|
|
21958
22086
|
if (source.getTopAndBook) {
|
|
21959
|
-
|
|
22087
|
+
fresh2 = await source.getTopAndBook(config, TERM_BOOK_LEVELS).catch(() => null);
|
|
21960
22088
|
} else {
|
|
21961
22089
|
const top = await source.getBookTop(config).catch(() => null);
|
|
21962
|
-
if (top)
|
|
22090
|
+
if (top) fresh2 = { top, book: { bids: [], asks: [] }, auction: null };
|
|
21963
22091
|
}
|
|
21964
|
-
if (
|
|
22092
|
+
if (fresh2) {
|
|
21965
22093
|
lastGood2.set(key3, {
|
|
21966
|
-
top:
|
|
21967
|
-
book:
|
|
21968
|
-
auction:
|
|
22094
|
+
top: fresh2.top,
|
|
22095
|
+
book: fresh2.book,
|
|
22096
|
+
auction: fresh2.auction ?? null,
|
|
21969
22097
|
at: nowSec9
|
|
21970
22098
|
});
|
|
21971
|
-
return { top:
|
|
22099
|
+
return { top: fresh2.top, book: fresh2.book, auction: fresh2.auction ?? null };
|
|
21972
22100
|
}
|
|
21973
22101
|
const cached = lastGood2.get(key3);
|
|
21974
22102
|
if (cached && nowSec9 - cached.at <= LKG_TTL_SEC2) {
|
|
@@ -23156,7 +23284,7 @@ async function fetchTellerMarkets(chainId) {
|
|
|
23156
23284
|
}
|
|
23157
23285
|
return null;
|
|
23158
23286
|
};
|
|
23159
|
-
const
|
|
23287
|
+
const num19 = (i) => {
|
|
23160
23288
|
const b = big22(i);
|
|
23161
23289
|
return b === null ? null : Number(b);
|
|
23162
23290
|
};
|
|
@@ -23166,9 +23294,9 @@ async function fetchTellerMarkets(chainId) {
|
|
|
23166
23294
|
config,
|
|
23167
23295
|
available: big22(base),
|
|
23168
23296
|
committed: big22(base + 1),
|
|
23169
|
-
minRateBps:
|
|
23297
|
+
minRateBps: num19(base + 2),
|
|
23170
23298
|
collateralPerPrincipal: big22(base + 3),
|
|
23171
|
-
maxLoanDuration:
|
|
23299
|
+
maxLoanDuration: num19(base + 4),
|
|
23172
23300
|
marketId: big22(base + 5),
|
|
23173
23301
|
totalAssets: big22(base + 6)
|
|
23174
23302
|
};
|
|
@@ -23578,10 +23706,10 @@ function refreshLiveMarkets(chainId, source) {
|
|
|
23578
23706
|
const running = refreshInFlight.get(chainId);
|
|
23579
23707
|
if (running) return running;
|
|
23580
23708
|
lastRefreshAttempt.set(chainId, Date.now());
|
|
23581
|
-
const p = source.getChainMarkets(chainId).then((
|
|
23582
|
-
if (!
|
|
23709
|
+
const p = source.getChainMarkets(chainId).then((fresh2) => {
|
|
23710
|
+
if (!fresh2) return;
|
|
23583
23711
|
const nowSec9 = Math.floor(Date.now() / 1e3);
|
|
23584
|
-
const live =
|
|
23712
|
+
const live = fresh2.filter((m) => m.config.maturity > nowSec9);
|
|
23585
23713
|
lastGood3.set(chainId, { markets: live, at: nowSec9 });
|
|
23586
23714
|
rememberMarkets(chainId, live);
|
|
23587
23715
|
}).catch(() => void 0).finally(() => refreshInFlight.delete(chainId));
|
|
@@ -24301,20 +24429,20 @@ async function fetchInverseMarkets(lender, chainId) {
|
|
|
24301
24429
|
if (Object.keys(byAddr).length > 0) {
|
|
24302
24430
|
const rows = markets.map((market) => {
|
|
24303
24431
|
const m = byAddr[market.address.toLowerCase()];
|
|
24304
|
-
const
|
|
24432
|
+
const num19 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
24305
24433
|
return {
|
|
24306
24434
|
market,
|
|
24307
|
-
totalDebt:
|
|
24308
|
-
dolaLiquidity:
|
|
24309
|
-
leftToBorrow:
|
|
24310
|
-
price:
|
|
24435
|
+
totalDebt: num19(m?.totalDebt),
|
|
24436
|
+
dolaLiquidity: num19(m?.dolaLiquidity),
|
|
24437
|
+
leftToBorrow: num19(m?.leftToBorrow),
|
|
24438
|
+
price: num19(m?.price),
|
|
24311
24439
|
borrowPaused: typeof m?.borrowPaused === "boolean" ? m.borrowPaused : null,
|
|
24312
|
-
dailyBorrows:
|
|
24440
|
+
dailyBorrows: num19(m?.dailyBorrows),
|
|
24313
24441
|
// The API serves it as a DECIMAL (`replenishmentIncentive: 0.1`),
|
|
24314
24442
|
// unlike the on-chain bps — normalize here, and fall back to the
|
|
24315
24443
|
// curated metadata value when the field is missing.
|
|
24316
24444
|
replenishmentIncentiveBps: (() => {
|
|
24317
|
-
const dec2 =
|
|
24445
|
+
const dec2 = num19(m?.replenishmentIncentive);
|
|
24318
24446
|
if (dec2 !== null) return Math.round(dec2 * 1e4);
|
|
24319
24447
|
const meta = Number(market.replenishmentIncentiveBps);
|
|
24320
24448
|
return Number.isFinite(meta) ? meta : null;
|
|
@@ -41769,7 +41897,7 @@ function unflattenLenderData(pools) {
|
|
|
41769
41897
|
}
|
|
41770
41898
|
return result;
|
|
41771
41899
|
}
|
|
41772
|
-
var getLenderUserDataResult = async (chainId, queriesRaw,
|
|
41900
|
+
var getLenderUserDataResult = async (chainId, queriesRaw, getEvmClient18, allowFailure = true, batchSize = MULTICALL_DEFAULT_BATCH_SIZE, retries = 3, logs = false, concurrency = 1, permanentFailures, onEndpointFailure) => {
|
|
41773
41901
|
const queries = organizeUserQueries(queriesRaw);
|
|
41774
41902
|
const builtCalls = await Promise.all(
|
|
41775
41903
|
queries.map(async (query3) => {
|
|
@@ -41779,7 +41907,7 @@ var getLenderUserDataResult = async (chainId, queriesRaw, getEvmClient17, allowF
|
|
|
41779
41907
|
query3.lender,
|
|
41780
41908
|
query3.account,
|
|
41781
41909
|
query3.params,
|
|
41782
|
-
|
|
41910
|
+
getEvmClient18
|
|
41783
41911
|
);
|
|
41784
41912
|
return callData.map((call) => ({ call, abi: call.abi ?? abi }));
|
|
41785
41913
|
})
|
|
@@ -41789,7 +41917,7 @@ var getLenderUserDataResult = async (chainId, queriesRaw, getEvmClient17, allowF
|
|
|
41789
41917
|
chainId,
|
|
41790
41918
|
calls.map((call) => call.abi),
|
|
41791
41919
|
calls.map((call) => call.call),
|
|
41792
|
-
|
|
41920
|
+
getEvmClient18,
|
|
41793
41921
|
concurrency,
|
|
41794
41922
|
retries,
|
|
41795
41923
|
allowFailure,
|
|
@@ -59478,7 +59606,7 @@ var fetchSiloVaults = async (chainId, prices = {}, tokenList = {}, options) => {
|
|
|
59478
59606
|
|
|
59479
59607
|
// src/vaults/euler-earn/entityLabels.ts
|
|
59480
59608
|
var LABELS_BASE = "https://raw.githubusercontent.com/euler-xyz/euler-labels/master";
|
|
59481
|
-
var
|
|
59609
|
+
var TTL_MS4 = 30 * 60 * 1e3;
|
|
59482
59610
|
var cache3 = /* @__PURE__ */ new Map();
|
|
59483
59611
|
var inflight4 = /* @__PURE__ */ new Map();
|
|
59484
59612
|
async function fetchChainEntities(chainId) {
|
|
@@ -59504,7 +59632,7 @@ async function fetchChainEntities(chainId) {
|
|
|
59504
59632
|
}
|
|
59505
59633
|
async function fetchEulerEntityNames(chainId) {
|
|
59506
59634
|
const hit = cache3.get(chainId);
|
|
59507
|
-
if (hit && Date.now() - hit.at <=
|
|
59635
|
+
if (hit && Date.now() - hit.at <= TTL_MS4) return hit.map;
|
|
59508
59636
|
const running = inflight4.get(chainId);
|
|
59509
59637
|
if (running) return running;
|
|
59510
59638
|
const p = fetchChainEntities(chainId).then((map) => {
|
|
@@ -69815,6 +69943,12 @@ function borrowDescription(b) {
|
|
|
69815
69943
|
parts.push(
|
|
69816
69944
|
"Liquidation is a public auction rather than a loan-to-value threshold" + (win ? `, open for ${duration(win)} once started` : "") + (pen != null ? `, and the liquidator is paid ${pct(pen * 100)}` : "") + "."
|
|
69817
69945
|
);
|
|
69946
|
+
} else if (b.liquidation.model === "repay-to-target-hf") {
|
|
69947
|
+
const l = b.liquidation;
|
|
69948
|
+
const start = l.liquidationLtv != null && l.liquidationLtv > 0 ? `Liquidation starts at ${pct(l.liquidationLtv * 100)} LTV and` : "A liquidation";
|
|
69949
|
+
const sized = l.targetHealthFactor != null ? ` repays as much of your debt as it takes to restore a health factor of ${l.targetHealthFactor.toFixed(2)}` : " repays as much of your debt as it takes to restore the spoke\u2019s target health factor";
|
|
69950
|
+
const bonus = l.penalty != null && l.penalty > 0 ? ` \u2014 the liquidator\u2019s bonus scales up to ${pct(l.penalty * 100)}` + (l.healthFactorForMaxBonus != null ? ` at a health factor of ${l.healthFactorForMaxBonus.toFixed(2)}` : "") + "." : ".";
|
|
69951
|
+
parts.push(`${start}${sized} rather than a fixed share of it${bonus}`);
|
|
69818
69952
|
} else if (b.liquidation.liquidationLtv != null && b.liquidation.liquidationLtv > 0) {
|
|
69819
69953
|
const pen = b.liquidation.penalty;
|
|
69820
69954
|
parts.push(
|
|
@@ -69848,6 +69982,27 @@ var TERM_PROFILES = [
|
|
|
69848
69982
|
]
|
|
69849
69983
|
}
|
|
69850
69984
|
}),
|
|
69985
|
+
P({
|
|
69986
|
+
id: "aave-v4.spoke@v1",
|
|
69987
|
+
name: "Aave V4 spoke (liquidated to a target health factor)",
|
|
69988
|
+
family: "pool",
|
|
69989
|
+
supply: {
|
|
69990
|
+
description: "A shared liquidity pool on an Aave V4 spoke. Deposits earn interest paid by borrowers of the hub asset, at a rate that moves with utilization. Withdrawals are instant up to the cash left in the pool.",
|
|
69991
|
+
implications: [
|
|
69992
|
+
"Your yield is not fixed \u2014 it rises and falls with borrowing demand.",
|
|
69993
|
+
"If utilization reaches 100 %, withdrawals are blocked until borrowers repay or new deposits arrive.",
|
|
69994
|
+
"Each spoke is its own market: the same asset on another spoke is a separate position with its own risk parameters."
|
|
69995
|
+
]
|
|
69996
|
+
},
|
|
69997
|
+
borrow: {
|
|
69998
|
+
description: "Borrow against collateral at a rate that moves with utilization. Liquidation here is sized to a target health factor rather than capped at a fixed share of your debt: a liquidator repays whatever it takes to bring the position back up to the target, and their bonus grows the further under water it is.",
|
|
69999
|
+
implications: [
|
|
70000
|
+
"There is no 50 % close-factor protection \u2014 how much of your debt is taken depends on how far the position fell, and a deep enough drop takes all of it.",
|
|
70001
|
+
"The published liquidation penalty is the MAXIMUM bonus, charged only once the position is far enough under water; a shallow liquidation costs less.",
|
|
70002
|
+
"V4 uses ONE loan-to-value per asset for both borrowing and liquidation \u2014 there is no buffer between the LTV you can borrow to and the one that gets you liquidated."
|
|
70003
|
+
]
|
|
70004
|
+
}
|
|
70005
|
+
}),
|
|
69851
70006
|
// ── Fixed-term families ──────────────────────────────────────────────────
|
|
69852
70007
|
P({
|
|
69853
70008
|
id: "exactly.fixed@v1",
|
|
@@ -73624,8 +73779,18 @@ function toTermSheetInput(row, ctx = {}) {
|
|
|
73624
73779
|
"flags.variableBorrowDisabled"
|
|
73625
73780
|
),
|
|
73626
73781
|
config,
|
|
73627
|
-
|
|
73628
|
-
|
|
73782
|
+
// `caps.` is NOT optional here. `/pools/latest` serializes both of these as
|
|
73783
|
+
// TOP-LEVEL row fields, while `/lending/latest` — the endpoint the lending
|
|
73784
|
+
// term sheets are actually stamped on — nests them under `caps` alongside
|
|
73785
|
+
// the supply/borrow caps (yield-tracer `utils/lending.ts`). Reading only
|
|
73786
|
+
// the flat key made every sheet on that endpoint fall through to the
|
|
73787
|
+
// builder's `?? 1`, so Aave and Compound V2 published "the whole debt can
|
|
73788
|
+
// be repaid in one liquidation" against a real close factor of 0.5, and
|
|
73789
|
+
// Aave V4's `targetHealthFactor` vanished entirely.
|
|
73790
|
+
closeFactor: num15(pick2(row, "closeFactor", "caps.closeFactor")),
|
|
73791
|
+
targetHealthFactor: num15(
|
|
73792
|
+
pick2(row, "targetHealthFactor", "caps.targetHealthFactor")
|
|
73793
|
+
),
|
|
73629
73794
|
fixedTerm: pick2(row, "fixedTerm") ?? ctx.fixedTerm,
|
|
73630
73795
|
terms: pick2(row, "terms"),
|
|
73631
73796
|
market: resolveMarketDescriptors(row, ctx.market)
|
|
@@ -73657,6 +73822,11 @@ var ROW_DESCRIPTOR_KEYS = [
|
|
|
73657
73822
|
// Fluid: distinguishes a SMART (T2/T3/T4) vault, whose collateral and/or
|
|
73658
73823
|
// debt is a two-token DEX LP position, from an ordinary T1 pool row.
|
|
73659
73824
|
"fluid",
|
|
73825
|
+
// Aave V4: the liquidation BONUS CURVE (`healthFactorForMaxBonus`,
|
|
73826
|
+
// `liquidationBonusFactor`). The sizing knob `targetHealthFactor` is a
|
|
73827
|
+
// market-level column and arrives without this; the curve is what turns the
|
|
73828
|
+
// published max bonus from a flat penalty into a bound.
|
|
73829
|
+
"aaveV4",
|
|
73660
73830
|
"broker",
|
|
73661
73831
|
"collateralProvider",
|
|
73662
73832
|
"loanProvider",
|
|
@@ -75231,6 +75401,32 @@ var morphoBlueAdapter = {
|
|
|
75231
75401
|
};
|
|
75232
75402
|
}
|
|
75233
75403
|
};
|
|
75404
|
+
var aaveV4Adapter = {
|
|
75405
|
+
id: "aave-v4",
|
|
75406
|
+
matches: isAaveV4Type,
|
|
75407
|
+
profileId: () => "aave-v4.spoke@v1",
|
|
75408
|
+
build: (input) => {
|
|
75409
|
+
const target = input.targetHealthFactor;
|
|
75410
|
+
const desc = input.market?.aaveV4 ?? {};
|
|
75411
|
+
const maxBonusHf = num17(desc.healthFactorForMaxBonus);
|
|
75412
|
+
return {
|
|
75413
|
+
borrow: {
|
|
75414
|
+
liquidation: {
|
|
75415
|
+
model: "repay-to-target-hf",
|
|
75416
|
+
// NOT a close factor — the ceiling. See the header.
|
|
75417
|
+
closeFactor: 1,
|
|
75418
|
+
targetHealthFactor: target,
|
|
75419
|
+
healthFactorForMaxBonus: maxBonusHf
|
|
75420
|
+
}
|
|
75421
|
+
}
|
|
75422
|
+
};
|
|
75423
|
+
}
|
|
75424
|
+
};
|
|
75425
|
+
function num17(v) {
|
|
75426
|
+
if (v == null) return void 0;
|
|
75427
|
+
const n = typeof v === "string" ? Number(v) : v;
|
|
75428
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
75429
|
+
}
|
|
75234
75430
|
|
|
75235
75431
|
// src/terms/adapters/index.ts
|
|
75236
75432
|
var TERM_ADAPTERS = [
|
|
@@ -75254,7 +75450,8 @@ var TERM_ADAPTERS = [
|
|
|
75254
75450
|
curvanceAdapter,
|
|
75255
75451
|
twyneAdapter,
|
|
75256
75452
|
fraxlendAdapter,
|
|
75257
|
-
morphoBlueAdapter
|
|
75453
|
+
morphoBlueAdapter,
|
|
75454
|
+
aaveV4Adapter
|
|
75258
75455
|
];
|
|
75259
75456
|
function resolveAdapter(lender) {
|
|
75260
75457
|
return TERM_ADAPTERS.find((a) => a.matches(lender));
|
|
@@ -76220,7 +76417,7 @@ function legEarnUid(marketUid) {
|
|
|
76220
76417
|
if (isVaultVenue(parts[0])) return void 0;
|
|
76221
76418
|
return marketUid;
|
|
76222
76419
|
}
|
|
76223
|
-
function
|
|
76420
|
+
function num18(v) {
|
|
76224
76421
|
const n = typeof v === "number" ? v : Number(v);
|
|
76225
76422
|
return Number.isFinite(n) ? n : 0;
|
|
76226
76423
|
}
|
|
@@ -76242,10 +76439,10 @@ function legAsset(pos) {
|
|
|
76242
76439
|
};
|
|
76243
76440
|
}
|
|
76244
76441
|
function toLeg(pos) {
|
|
76245
|
-
const depositsUsd =
|
|
76246
|
-
const debtUsd =
|
|
76247
|
-
const hasSupply = depositsUsd !== 0 ||
|
|
76248
|
-
const hasDebt = debtUsd !== 0 ||
|
|
76442
|
+
const depositsUsd = num18(pos.depositsUSD);
|
|
76443
|
+
const debtUsd = num18(pos.debtUSD) + num18(pos.debtStableUSD);
|
|
76444
|
+
const hasSupply = depositsUsd !== 0 || num18(pos.deposits) !== 0;
|
|
76445
|
+
const hasDebt = debtUsd !== 0 || num18(pos.debt) !== 0 || num18(pos.debtStable) !== 0;
|
|
76249
76446
|
return {
|
|
76250
76447
|
earnUid: legEarnUid(pos.marketUid),
|
|
76251
76448
|
marketUid: pos.marketUid,
|
|
@@ -76285,12 +76482,12 @@ function earnPositionFromLenderEntry(entry) {
|
|
|
76285
76482
|
(s) => s.legs.some((l) => l.side !== "none") || s.netUsd !== 0
|
|
76286
76483
|
);
|
|
76287
76484
|
const crossMargin = active.length <= 1;
|
|
76288
|
-
const suppliedUsd =
|
|
76289
|
-
const borrowedUsd =
|
|
76485
|
+
const suppliedUsd = num18(entry.balanceData?.deposits);
|
|
76486
|
+
const borrowedUsd = num18(entry.balanceData?.debt);
|
|
76290
76487
|
const aprBreakdown = {
|
|
76291
|
-
market:
|
|
76292
|
-
rewards:
|
|
76293
|
-
intrinsic:
|
|
76488
|
+
market: num18(entry.aprData?.apr),
|
|
76489
|
+
rewards: num18(entry.aprData?.rewardApr),
|
|
76490
|
+
intrinsic: num18(entry.aprData?.intrinsicApr)
|
|
76294
76491
|
};
|
|
76295
76492
|
return {
|
|
76296
76493
|
positionUid: buildLendingPositionUid(entry.lender, entry.chainId),
|
|
@@ -76304,15 +76501,15 @@ function earnPositionFromLenderEntry(entry) {
|
|
|
76304
76501
|
...entry.lenderInfo?.logoUri ? { logoURI: entry.lenderInfo.logoUri } : {},
|
|
76305
76502
|
suppliedUsd,
|
|
76306
76503
|
borrowedUsd,
|
|
76307
|
-
netUsd:
|
|
76504
|
+
netUsd: num18(entry.balanceData?.nav),
|
|
76308
76505
|
apr: aprBreakdown.market + aprBreakdown.rewards + aprBreakdown.intrinsic,
|
|
76309
76506
|
aprBreakdown,
|
|
76310
|
-
depositApr:
|
|
76311
|
-
borrowApr:
|
|
76507
|
+
depositApr: num18(entry.aprData?.depositApr),
|
|
76508
|
+
borrowApr: num18(entry.aprData?.borrowApr),
|
|
76312
76509
|
// Only a cross-margin account HAS one health factor. Publishing the first
|
|
76313
76510
|
// sub-account's as the row's would be a number about a different position.
|
|
76314
76511
|
health: crossMargin ? active[0]?.health ?? null : null,
|
|
76315
|
-
leverage:
|
|
76512
|
+
leverage: num18(entry.leverage),
|
|
76316
76513
|
crossMargin,
|
|
76317
76514
|
legs: subAccounts.flatMap((s) => s.legs),
|
|
76318
76515
|
subAccounts: active,
|