@1delta/margin-fetcher 5.0.60 → 5.0.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +768 -532
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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, isAaveV4Type, isInit,
|
|
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, isCompoundV2Type, isMultiMarket, isSiloV2Type, isSiloV3Type, isDolomite, isMorphoType, isUsdd, isSky, hasCrossMarginRisk, isEulerType, isAaveV4Type, 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';
|
|
@@ -6325,10 +6325,45 @@ var ENABLED_COMPOUNDS = [
|
|
|
6325
6325
|
Lender.SEGMENT,
|
|
6326
6326
|
Lender.COMPOUND_V2,
|
|
6327
6327
|
Lender.FLUX_FINANCE,
|
|
6328
|
-
Lender.CAPY_FI
|
|
6328
|
+
Lender.CAPY_FI,
|
|
6329
|
+
// Long-tail forks read through a shared CompoundLens on their chain
|
|
6330
|
+
// (addresses/compoundV2.ts). Enabled only where a lens exists AND the
|
|
6331
|
+
// markets are open; the rest of the `lender-metadata` long tail stays off
|
|
6332
|
+
// this list — see the table in
|
|
6333
|
+
// `lending/public-data/compound-v2/README.md`.
|
|
6334
|
+
Lender.DEMETER,
|
|
6335
|
+
Lender.LANDER,
|
|
6336
|
+
Lender.FILDA,
|
|
6337
|
+
Lender.SOLIDLIZARD,
|
|
6338
|
+
// Reachable since the CompoundV2MarketLens deployment on Optimism, Linea and
|
|
6339
|
+
// Base (2026-08-24). Xpert is deliberately NOT here: 4 of its 6 Base markets
|
|
6340
|
+
// revert their own `exchangeRateStored`, so the lens reads them as zero and
|
|
6341
|
+
// serving them would publish a market with no exchange rate.
|
|
6342
|
+
Lender.IRON_BANK,
|
|
6343
|
+
Lender.MENDI,
|
|
6344
|
+
Lender.PAXO,
|
|
6345
|
+
Lender.SONNE,
|
|
6346
|
+
Lender.ASO_FINANCE,
|
|
6347
|
+
Lender.BLUME,
|
|
6348
|
+
Lender.KAWA,
|
|
6349
|
+
Lender.XPERT,
|
|
6350
|
+
// Manta and zkSync Era joined the lens rollout. KEOM_STONE is deliberately
|
|
6351
|
+
// absent: 1 of its 2 markets (kSTONE) exposes no exchange-rate getter at all,
|
|
6352
|
+
// so half the pool would publish with `exchangeRate = 0`.
|
|
6353
|
+
Lender.KEOM,
|
|
6354
|
+
Lender.REACTOR_FUSION
|
|
6329
6355
|
];
|
|
6330
6356
|
var DISABLED_COMPOUNDS = {
|
|
6331
|
-
[Chain.ETHEREUM_MAINNET]: [Lender.CREAM_FINANCE]
|
|
6357
|
+
[Chain.ETHEREUM_MAINNET]: [Lender.CREAM_FINANCE],
|
|
6358
|
+
// FilDA's IoTeX deployment: no lens on that chain, and all 9 markets are
|
|
6359
|
+
// mint+borrow paused with `seizeGuardianPaused` set globally. Its BNB
|
|
6360
|
+
// deployment is open and stays enabled.
|
|
6361
|
+
[Chain.IOTEX_NETWORK_MAINNET]: [Lender.FILDA],
|
|
6362
|
+
// Xpert on Base: 4 of its 6 markets revert their OWN `exchangeRateStored`
|
|
6363
|
+
// (checked against two independent RPCs), so any lens reads them as zero and
|
|
6364
|
+
// serving them would publish markets with no exchange rate. Its Ink
|
|
6365
|
+
// deployment reads 5/5 clean and stays enabled.
|
|
6366
|
+
[Chain.BASE]: [Lender.XPERT]
|
|
6332
6367
|
};
|
|
6333
6368
|
var isExcludedLender = (lender) => {
|
|
6334
6369
|
if (lender === Lender.PLOUTOS) return true;
|
|
@@ -7068,18 +7103,15 @@ var formatAaveYieldToNumber = (n) => {
|
|
|
7068
7103
|
if (!n) return 0;
|
|
7069
7104
|
return Number(formatEther(BigInt(n) / BigInt(1e7)));
|
|
7070
7105
|
};
|
|
7071
|
-
var calculateRateForCompoundType2 = (n) => {
|
|
7106
|
+
var calculateRateForCompoundType2 = (n, unitSeconds) => {
|
|
7072
7107
|
const rate = Number(formatEther(BigInt(n)));
|
|
7073
|
-
|
|
7108
|
+
const perUnit = unitSeconds && unitSeconds > 0 ? unitSeconds : 12;
|
|
7109
|
+
return (Math.pow(rate * 60 * 60 * 24 / perUnit + 1, 365) - 1) * 100;
|
|
7074
7110
|
};
|
|
7075
|
-
var calculateRateForCompoundType = (n, chainId, scale3 = 1 /* SECOND
|
|
7111
|
+
var calculateRateForCompoundType = (n, chainId, scale3 = 1 /* SECOND */, unitSeconds) => {
|
|
7076
7112
|
const rate = Number(formatEther(BigInt(n)));
|
|
7077
|
-
|
|
7078
|
-
|
|
7079
|
-
rate * 60 * 60 * 24 / (BLOCK_TIMES[chainId] ?? "1") + 1,
|
|
7080
|
-
365
|
|
7081
|
-
) - 1) * 100;
|
|
7082
|
-
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;
|
|
7083
7115
|
};
|
|
7084
7116
|
var formatAaveRawApyToApr = (raw) => {
|
|
7085
7117
|
const apy = formatAaveYieldToNumber(raw);
|
|
@@ -12821,7 +12853,8 @@ var SUMER_LENS = {
|
|
|
12821
12853
|
};
|
|
12822
12854
|
var MOONWELL_LENS = {
|
|
12823
12855
|
[Chain.OP_MAINNET]: "0xD6C66868f937f00604d0FB860241970D6CC2CBfE",
|
|
12824
|
-
[Chain.BASE]: "0x6834770aba6c2028f448e3259ddee4bcb879d459"
|
|
12856
|
+
[Chain.BASE]: "0x6834770aba6c2028f448e3259ddee4bcb879d459",
|
|
12857
|
+
[Chain.ETHEREUM_MAINNET]: "0x2d85b9c48a8c582f0AA244e134e9C6f30Cf7786e"
|
|
12825
12858
|
};
|
|
12826
12859
|
var ENCLABS_LENS = {
|
|
12827
12860
|
[Chain.SONIC_MAINNET]: "0x3567B16050cB90236997eF47B1941502e85d65f3",
|
|
@@ -12868,15 +12901,45 @@ var SEGMENT_LENS = {
|
|
|
12868
12901
|
var ROBUST_LENS = {
|
|
12869
12902
|
[Chain.ETHEREUM_MAINNET]: "0x92ee472A52A79AB407aED9FE0deB512d230baF87"
|
|
12870
12903
|
};
|
|
12904
|
+
var COMPOUND_V2_MARKET_LENS = "0xD16EC79B110f27AA2EEEc913087823Df032121E4";
|
|
12905
|
+
var MARKET_LENS = {
|
|
12906
|
+
[Chain.OP_MAINNET]: COMPOUND_V2_MARKET_LENS,
|
|
12907
|
+
[Chain.XDC_NETWORK]: COMPOUND_V2_MARKET_LENS,
|
|
12908
|
+
[Chain.SEI_NETWORK]: COMPOUND_V2_MARKET_LENS,
|
|
12909
|
+
[Chain.MORPH]: COMPOUND_V2_MARKET_LENS,
|
|
12910
|
+
[Chain.BASE]: COMPOUND_V2_MARKET_LENS,
|
|
12911
|
+
[Chain.AVALANCHE_C_CHAIN]: COMPOUND_V2_MARKET_LENS,
|
|
12912
|
+
[Chain.INK]: COMPOUND_V2_MARKET_LENS,
|
|
12913
|
+
[Chain.LINEA]: COMPOUND_V2_MARKET_LENS,
|
|
12914
|
+
[Chain.BLAST]: COMPOUND_V2_MARKET_LENS,
|
|
12915
|
+
[Chain.MANTA_PACIFIC_MAINNET]: COMPOUND_V2_MARKET_LENS,
|
|
12916
|
+
/**
|
|
12917
|
+
* zkSync Era is the one chain where the address differs. zk-stack chains
|
|
12918
|
+
* derive contract addresses from a registered bytecode hash rather than
|
|
12919
|
+
* `keccak(0xff ‖ factory ‖ salt ‖ initCodeHash)`, so the CREATE2 factory path
|
|
12920
|
+
* is skipped there (see the deploy script) and this is the nonce-derived
|
|
12921
|
+
* address of the same runtime — byte-identical to the other nine, verified
|
|
12922
|
+
* against the compiled artifact.
|
|
12923
|
+
*/
|
|
12924
|
+
[Chain.ZKSYNC_MAINNET]: "0x6Bc6aCB905c1216B0119C87Bf9E178ce298310FA"
|
|
12925
|
+
};
|
|
12871
12926
|
var CREAM_LENS = {
|
|
12872
12927
|
[Chain.ETHEREUM_MAINNET]: "0x92ee472A52A79AB407aED9FE0deB512d230baF87",
|
|
12873
12928
|
[Chain.BNB_SMART_CHAIN_MAINNET]: "0x1A014Ffe0cd187A298a7E79BA5ab05538686ea4a",
|
|
12874
12929
|
[Chain.POLYGON_MAINNET]: "0x139Dd8Bb6355d20342e08ff013150b1aE5040a42",
|
|
12875
|
-
[Chain.ARBITRUM_ONE]: "0x139Dd8Bb6355d20342e08ff013150b1aE5040a42"
|
|
12930
|
+
[Chain.ARBITRUM_ONE]: "0x139Dd8Bb6355d20342e08ff013150b1aE5040a42",
|
|
12931
|
+
// Cream's Base deployment has no lens of its own; ours serves it.
|
|
12932
|
+
[Chain.BASE]: COMPOUND_V2_MARKET_LENS
|
|
12876
12933
|
};
|
|
12877
12934
|
var GAMMA_LENS = {
|
|
12878
12935
|
[Chain.BNB_SMART_CHAIN_MAINNET]: "0xcaf6856f6Ec1B66EE89dD296D2020dfA431D8f6B"
|
|
12879
12936
|
};
|
|
12937
|
+
var SHARED_LENS_BNB = {
|
|
12938
|
+
[Chain.BNB_SMART_CHAIN_MAINNET]: "0x560dD9b47d40E0cd0aEDA326e46BeD25249d936A"
|
|
12939
|
+
};
|
|
12940
|
+
var SHARED_LENS_ARBITRUM = {
|
|
12941
|
+
[Chain.ARBITRUM_ONE]: "0x14Ec7324753340Bd8685496da14c4B173ac05b18"
|
|
12942
|
+
};
|
|
12880
12943
|
var COMPOUND_V2_LENS = {
|
|
12881
12944
|
[Lender.VENUS]: VENUS_LENS,
|
|
12882
12945
|
[Lender.VENUS_ETH]: VENUS_LENS,
|
|
@@ -12901,7 +12964,25 @@ var COMPOUND_V2_LENS = {
|
|
|
12901
12964
|
[Lender.SEGMENT]: SEGMENT_LENS,
|
|
12902
12965
|
[Lender.CREAM_FINANCE]: CREAM_LENS,
|
|
12903
12966
|
[Lender.GAMMA]: GAMMA_LENS,
|
|
12904
|
-
[Lender.CAPY_FI]: ROBUST_LENS
|
|
12967
|
+
[Lender.CAPY_FI]: ROBUST_LENS,
|
|
12968
|
+
[Lender.DEMETER]: SHARED_LENS_BNB,
|
|
12969
|
+
[Lender.LANDER]: SHARED_LENS_BNB,
|
|
12970
|
+
// FilDA also has an IoTeX deployment; it is NOT wired here (no lens on that
|
|
12971
|
+
// chain, and all 9 of its IoTeX markets are mint+borrow paused) and is held
|
|
12972
|
+
// back by `DISABLED_COMPOUNDS` in `utils/index.ts`.
|
|
12973
|
+
[Lender.FILDA]: SHARED_LENS_BNB,
|
|
12974
|
+
[Lender.SOLIDLIZARD]: SHARED_LENS_ARBITRUM,
|
|
12975
|
+
// Served by our own CompoundV2MarketLens deployment.
|
|
12976
|
+
[Lender.IRON_BANK]: MARKET_LENS,
|
|
12977
|
+
[Lender.MENDI]: MARKET_LENS,
|
|
12978
|
+
[Lender.PAXO]: MARKET_LENS,
|
|
12979
|
+
[Lender.SONNE]: MARKET_LENS,
|
|
12980
|
+
[Lender.ASO_FINANCE]: MARKET_LENS,
|
|
12981
|
+
[Lender.BLUME]: MARKET_LENS,
|
|
12982
|
+
[Lender.KAWA]: MARKET_LENS,
|
|
12983
|
+
[Lender.XPERT]: MARKET_LENS,
|
|
12984
|
+
[Lender.KEOM]: MARKET_LENS,
|
|
12985
|
+
[Lender.REACTOR_FUSION]: MARKET_LENS
|
|
12905
12986
|
};
|
|
12906
12987
|
function getCompoundV2Comptroller(chainId, lender = Lender.VENUS) {
|
|
12907
12988
|
return compoundV2Pools()?.[lender]?.[chainId];
|
|
@@ -15028,7 +15109,24 @@ var COMPTROLLER_PAUSE_READ_LENDERS = [
|
|
|
15028
15109
|
Lender.GAMMA,
|
|
15029
15110
|
Lender.CAPY_FI,
|
|
15030
15111
|
Lender.LODESTAR,
|
|
15031
|
-
Lender.TENDER
|
|
15112
|
+
Lender.TENDER,
|
|
15113
|
+
// Long-tail forks on the shared lenses — same plain `cTokenMetadata`, same
|
|
15114
|
+
// missing pause field. Their Comptrollers DO answer both guardian getters
|
|
15115
|
+
// (verified 2026-08-24), so the live read resolves every market.
|
|
15116
|
+
Lender.DEMETER,
|
|
15117
|
+
Lender.LANDER,
|
|
15118
|
+
Lender.FILDA,
|
|
15119
|
+
Lender.SOLIDLIZARD,
|
|
15120
|
+
Lender.IRON_BANK,
|
|
15121
|
+
Lender.MENDI,
|
|
15122
|
+
Lender.PAXO,
|
|
15123
|
+
Lender.SONNE,
|
|
15124
|
+
Lender.ASO_FINANCE,
|
|
15125
|
+
Lender.BLUME,
|
|
15126
|
+
Lender.KAWA,
|
|
15127
|
+
Lender.XPERT,
|
|
15128
|
+
Lender.KEOM,
|
|
15129
|
+
Lender.REACTOR_FUSION
|
|
15032
15130
|
];
|
|
15033
15131
|
var usesComptrollerPauseReads = (lender) => COMPTROLLER_PAUSE_READ_LENDERS.includes(lender);
|
|
15034
15132
|
var parsePausedFlag = (raw) => typeof raw === "boolean" ? raw : void 0;
|
|
@@ -15041,6 +15139,7 @@ var resolveMarketPause = (token, live) => {
|
|
|
15041
15139
|
|
|
15042
15140
|
// src/lending/public-data/compound-v2/publicCallBuild.ts
|
|
15043
15141
|
var buildCompoundV2StyleLenderReserveCall = (chainId, lender) => {
|
|
15142
|
+
if (!getCompoundV2Lens(chainId, lender)) return [];
|
|
15044
15143
|
if (lender === Lender.TAKARA) {
|
|
15045
15144
|
const lens = getCompoundV2Lens(chainId, lender);
|
|
15046
15145
|
return [
|
|
@@ -15178,7 +15277,10 @@ function getCall(lender, chainId) {
|
|
|
15178
15277
|
params: [tk]
|
|
15179
15278
|
});
|
|
15180
15279
|
}
|
|
15181
|
-
if (lender === Lender.CREAM_FINANCE || lender === Lender.GAMMA || lender === Lender.TENDER || lender === Lender.COMPOUND_V2 || lender === Lender.CAPY_FI || lender === Lender.FLUX_FINANCE || lender === Lender.WE_PIGGY
|
|
15280
|
+
if (lender === Lender.CREAM_FINANCE || lender === Lender.GAMMA || lender === Lender.TENDER || lender === Lender.COMPOUND_V2 || lender === Lender.CAPY_FI || lender === Lender.FLUX_FINANCE || lender === Lender.WE_PIGGY || // long-tail forks served by a shared lens on their chain — see
|
|
15281
|
+
// SHARED_LENS_BNB / SHARED_LENS_ARBITRUM in addresses/compoundV2.ts
|
|
15282
|
+
lender === Lender.DEMETER || lender === Lender.LANDER || lender === Lender.FILDA || lender === Lender.SOLIDLIZARD || // served by our own CompoundV2MarketLens deployment (same 14-field struct)
|
|
15283
|
+
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) {
|
|
15182
15284
|
return (tk) => ({
|
|
15183
15285
|
abi: CreamLensAbi,
|
|
15184
15286
|
address: lens,
|
|
@@ -15200,9 +15302,102 @@ function getCall(lender, chainId) {
|
|
|
15200
15302
|
params: [tk]
|
|
15201
15303
|
});
|
|
15202
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
|
+
}
|
|
15203
15398
|
|
|
15204
15399
|
// src/lending/public-data/compound-v2/getters/venus.ts
|
|
15205
|
-
function readVTokenMetadata(meta, token) {
|
|
15400
|
+
function readVTokenMetadata(meta, token, unitSeconds) {
|
|
15206
15401
|
const pick3 = (...values) => values.find((v) => v !== void 0);
|
|
15207
15402
|
return {
|
|
15208
15403
|
vToken: meta.vToken ?? "",
|
|
@@ -15238,7 +15433,8 @@ function readVTokenMetadata(meta, token) {
|
|
|
15238
15433
|
meta.supplyRatePerBlockOrTimestamp
|
|
15239
15434
|
)?.toString() ?? "0",
|
|
15240
15435
|
token.chainId,
|
|
15241
|
-
0 /* BLOCK
|
|
15436
|
+
0 /* BLOCK */,
|
|
15437
|
+
unitSeconds
|
|
15242
15438
|
) / 100
|
|
15243
15439
|
) * 100,
|
|
15244
15440
|
variableBorrowRate: apyToApr(
|
|
@@ -15248,7 +15444,8 @@ function readVTokenMetadata(meta, token) {
|
|
|
15248
15444
|
meta.borrowRatePerBlockOrTimestamp
|
|
15249
15445
|
)?.toString() ?? "0",
|
|
15250
15446
|
token.chainId,
|
|
15251
|
-
0 /* BLOCK
|
|
15447
|
+
0 /* BLOCK */,
|
|
15448
|
+
unitSeconds
|
|
15252
15449
|
) / 100
|
|
15253
15450
|
) * 100,
|
|
15254
15451
|
supplyCap: 0,
|
|
@@ -15467,20 +15664,24 @@ function parseTectonicMarketData(input) {
|
|
|
15467
15664
|
isBoosted: toBool3(field3(input, "isBoosted", 22)),
|
|
15468
15665
|
baseRatePerBlock: toBigInt3(field3(input, "baseRatePerBlock", 23)),
|
|
15469
15666
|
multiplierPerBlock: toBigInt3(field3(input, "multiplierPerBlock", 24)),
|
|
15470
|
-
jumpMultiplierPerBlock: toBigInt3(
|
|
15667
|
+
jumpMultiplierPerBlock: toBigInt3(
|
|
15668
|
+
field3(input, "jumpMultiplierPerBlock", 25)
|
|
15669
|
+
),
|
|
15471
15670
|
kink: toBigInt3(field3(input, "kink", 26))
|
|
15472
15671
|
};
|
|
15473
15672
|
}
|
|
15474
|
-
function getTectonicRates(info, chainId) {
|
|
15673
|
+
function getTectonicRates(info, chainId, unitSeconds) {
|
|
15475
15674
|
const supplyApy = calculateRateForCompoundType(
|
|
15476
15675
|
info.supplyRatePerBlock.toString(),
|
|
15477
15676
|
chainId,
|
|
15478
|
-
0 /* BLOCK
|
|
15677
|
+
0 /* BLOCK */,
|
|
15678
|
+
unitSeconds
|
|
15479
15679
|
);
|
|
15480
15680
|
const borrowApy = calculateRateForCompoundType(
|
|
15481
15681
|
info.borrowRatePerBlock.toString(),
|
|
15482
15682
|
chainId,
|
|
15483
|
-
0 /* BLOCK
|
|
15683
|
+
0 /* BLOCK */,
|
|
15684
|
+
unitSeconds
|
|
15484
15685
|
);
|
|
15485
15686
|
return {
|
|
15486
15687
|
depositRate: apyToApr(supplyApy / 100) * 100,
|
|
@@ -15526,7 +15727,9 @@ function parseKineticMarketMetadata(input) {
|
|
|
15526
15727
|
totalBorrows: toBigInt4(field4(input, "totalBorrows", 9)),
|
|
15527
15728
|
collateralFactor: toBigInt4(field4(input, "collateralFactor", 10)),
|
|
15528
15729
|
underlyingToken: String(field4(input, "underlyingToken", 11)),
|
|
15529
|
-
underlyingTokenDecimals: Number(
|
|
15730
|
+
underlyingTokenDecimals: Number(
|
|
15731
|
+
field4(input, "underlyingTokenDecimals", 12)
|
|
15732
|
+
),
|
|
15530
15733
|
cTokenDecimals: Number(field4(input, "cTokenDecimals", 13)),
|
|
15531
15734
|
totalReserves: toBigInt4(field4(input, "totalReserves", 16)),
|
|
15532
15735
|
cash: toBigInt4(field4(input, "cash", 17)),
|
|
@@ -15559,9 +15762,20 @@ var RESERVE_MANTISSA_DECIMALS = 18;
|
|
|
15559
15762
|
var DEFAULT_CLOSE_FACTOR = 0.5;
|
|
15560
15763
|
var DEFAULT_LIQUIDATION_PENALTY = 0.08;
|
|
15561
15764
|
|
|
15765
|
+
// src/lending/public-data/compound-v2/convert/liquidity.ts
|
|
15766
|
+
var cashLiquidity = (raw, decimals) => raw === void 0 || raw === null ? void 0 : Number(parseRawAmount(raw.toString(), decimals));
|
|
15767
|
+
|
|
15562
15768
|
// src/lending/public-data/compound-v2/convert/standard.ts
|
|
15563
15769
|
var COMPOUND_V2_NAME_OVERRIDES = {
|
|
15564
|
-
"0xccf4429db6322d5c611ee964527d42e5d685dd6a": "Compound"
|
|
15770
|
+
"1:0xccf4429db6322d5c611ee964527d42e5d685dd6a": "Compound",
|
|
15771
|
+
// PAXO (WeFi) on XDC runs three assets twice, split by purpose. Verified
|
|
15772
|
+
// on-chain 2026-08-24 against each cToken's `name()` / `symbol()`.
|
|
15773
|
+
// vBuyFXD, against vFXD "WEFI FXD"
|
|
15774
|
+
"50:0xfc839b46019606b425f8b4c65b4479c3315de5c6": "Paxo FXD Buy",
|
|
15775
|
+
// vBuyEURS, against vEURS "EURS Vault"
|
|
15776
|
+
"50:0xb7c3b74f897adce04db33d9438d60a8fcf70cbc1": "Paxo EURS Buy",
|
|
15777
|
+
// vBorrowWXDC, against vWXDC "WEFI WXDC"
|
|
15778
|
+
"50:0xcc402f9573132b006d6b63b5d5b5a986767959a5": "Paxo WXDC Borrow"
|
|
15565
15779
|
};
|
|
15566
15780
|
function convertSingleEntry(opts) {
|
|
15567
15781
|
const {
|
|
@@ -15607,7 +15821,7 @@ function convertSingleEntry(opts) {
|
|
|
15607
15821
|
const totalDebt = Number(
|
|
15608
15822
|
parseRawAmount(currentEntry?.totalBorrows?.toString(), decs)
|
|
15609
15823
|
);
|
|
15610
|
-
const liquidity = totalSupplyUnderlying - totalDebt;
|
|
15824
|
+
const liquidity = cashLiquidity(currentEntry?.totalCash ?? currentEntry?.cash, decs) ?? totalSupplyUnderlying - totalDebt;
|
|
15611
15825
|
const price2 = prices[asset.assetGroup] ?? 0;
|
|
15612
15826
|
const pausedActions = { ...currentEntry.pausedActions };
|
|
15613
15827
|
if (opts.pause?.mintPaused !== void 0)
|
|
@@ -15619,7 +15833,7 @@ function convertSingleEntry(opts) {
|
|
|
15619
15833
|
const collateralActive = Boolean(currentEntry?.isListed);
|
|
15620
15834
|
const borrowingEnabled = Boolean(currentEntry?.isBorrowAllowed) && !pausedActions[2 /* BORROW */];
|
|
15621
15835
|
const marketUid = createMarketUid(chainId, lender, cToken);
|
|
15622
|
-
const name = COMPOUND_V2_NAME_OVERRIDES[cToken.toLowerCase()] ?? lenderShortName(lender) + " " + (asset?.symbol ?? "");
|
|
15836
|
+
const name = COMPOUND_V2_NAME_OVERRIDES[`${chainId}:${cToken.toLowerCase()}`] ?? lenderShortName(lender) + " " + (asset?.symbol ?? "");
|
|
15623
15837
|
return {
|
|
15624
15838
|
marketUid,
|
|
15625
15839
|
name,
|
|
@@ -15696,7 +15910,7 @@ function convertSumerEntry(opts) {
|
|
|
15696
15910
|
const totalDebt = Number(
|
|
15697
15911
|
parseRawAmount(currentEntry.totalBorrows?.toString(), decs)
|
|
15698
15912
|
);
|
|
15699
|
-
const liquidity = totalSupplyUnderlying - totalDebt;
|
|
15913
|
+
const liquidity = cashLiquidity(currentEntry?.totalCash, decs) ?? totalSupplyUnderlying - totalDebt;
|
|
15700
15914
|
const price2 = prices[asset.assetGroup] ?? 0;
|
|
15701
15915
|
const poolId = asset.address;
|
|
15702
15916
|
const collateralActive = Boolean(currentEntry.isListed);
|
|
@@ -15872,19 +16086,15 @@ function convertTectonicEntry(opts) {
|
|
|
15872
16086
|
parseRawAmount(info.collateralFactor.toString(), RESERVE_MANTISSA_DECIMALS)
|
|
15873
16087
|
);
|
|
15874
16088
|
const liquidationPenalty = Math.max(
|
|
15875
|
-
Number(
|
|
15876
|
-
parseRawAmount(info.liquidationPenalty.toString(), PRICE_DECIMALS)
|
|
15877
|
-
) - 1,
|
|
16089
|
+
Number(parseRawAmount(info.liquidationPenalty.toString(), PRICE_DECIMALS)) - 1,
|
|
15878
16090
|
0
|
|
15879
16091
|
);
|
|
15880
16092
|
const exchangeRateCurrent = Number(
|
|
15881
16093
|
parseRawAmount(info.exchangeRate.toString(), PRICE_DECIMALS)
|
|
15882
16094
|
);
|
|
15883
16095
|
const totalSupplyUnderlying = Number(parseRawAmount(info.totalSupply.toString(), decs)) * exchangeRateCurrent;
|
|
15884
|
-
const totalDebt = Number(
|
|
15885
|
-
|
|
15886
|
-
);
|
|
15887
|
-
const liquidity = totalSupplyUnderlying - totalDebt;
|
|
16096
|
+
const totalDebt = Number(parseRawAmount(info.totalBorrow.toString(), decs));
|
|
16097
|
+
const liquidity = cashLiquidity(info.availableLiquidity, decs) ?? totalSupplyUnderlying - totalDebt;
|
|
15888
16098
|
const poolId = asset.address;
|
|
15889
16099
|
const marketUid = createMarketUid(chainId, lender, cToken);
|
|
15890
16100
|
return {
|
|
@@ -16004,9 +16214,7 @@ function parseBenqiEcoMarketMetadata(input) {
|
|
|
16004
16214
|
borrowCap: toBigInt5(field5(input, "borrowCap", 6)),
|
|
16005
16215
|
supplyCap: toBigInt5(field5(input, "supplyCap", 7)),
|
|
16006
16216
|
totalSupply: toBigInt5(field5(input, "totalSupply", 8)),
|
|
16007
|
-
totalUnderlyingSupply: toBigInt5(
|
|
16008
|
-
field5(input, "totalUnderlyingSupply", 9)
|
|
16009
|
-
),
|
|
16217
|
+
totalUnderlyingSupply: toBigInt5(field5(input, "totalUnderlyingSupply", 9)),
|
|
16010
16218
|
totalBorrows: toBigInt5(field5(input, "totalBorrows", 10)),
|
|
16011
16219
|
collateralFactor: toBigInt5(field5(input, "collateralFactor", 11)),
|
|
16012
16220
|
underlying: parseToken(field5(input, "underlying", 12)),
|
|
@@ -16017,16 +16225,18 @@ function parseBenqiEcoMarketMetadata(input) {
|
|
|
16017
16225
|
borrowPaused: toBool5(field5(input, "borrowPaused", 17))
|
|
16018
16226
|
};
|
|
16019
16227
|
}
|
|
16020
|
-
function getBenqiRates(info, chainId) {
|
|
16228
|
+
function getBenqiRates(info, chainId, unitSeconds) {
|
|
16021
16229
|
const supplyApy = calculateRateForCompoundType(
|
|
16022
16230
|
info.supplyRate.toString(),
|
|
16023
16231
|
chainId,
|
|
16024
|
-
0 /* BLOCK
|
|
16232
|
+
0 /* BLOCK */,
|
|
16233
|
+
unitSeconds
|
|
16025
16234
|
);
|
|
16026
16235
|
const borrowApy = calculateRateForCompoundType(
|
|
16027
16236
|
info.borrowRate.toString(),
|
|
16028
16237
|
chainId,
|
|
16029
|
-
0 /* BLOCK
|
|
16238
|
+
0 /* BLOCK */,
|
|
16239
|
+
unitSeconds
|
|
16030
16240
|
);
|
|
16031
16241
|
return {
|
|
16032
16242
|
depositRate: apyToApr(supplyApy / 100) * 100,
|
|
@@ -16049,10 +16259,8 @@ function convertBenqiEntry(opts) {
|
|
|
16049
16259
|
const totalDeposits = Number(
|
|
16050
16260
|
parseRawAmount(parsed.totalUnderlyingSupply.toString(), decs)
|
|
16051
16261
|
);
|
|
16052
|
-
const totalDebt = Number(
|
|
16053
|
-
|
|
16054
|
-
);
|
|
16055
|
-
const liquidity = totalDeposits - totalDebt;
|
|
16262
|
+
const totalDebt = Number(parseRawAmount(parsed.totalBorrows.toString(), decs));
|
|
16263
|
+
const liquidity = cashLiquidity(parsed.cash, decs) ?? totalDeposits - totalDebt;
|
|
16056
16264
|
const poolId = asset.address;
|
|
16057
16265
|
const marketUid = createMarketUid(chainId, lender, cToken);
|
|
16058
16266
|
const collateralActive = !parsed.mintPaused;
|
|
@@ -16123,10 +16331,8 @@ function convertKineticEntry(opts) {
|
|
|
16123
16331
|
const totalDeposits = Number(
|
|
16124
16332
|
parseRawAmount(parsed.totalUnderlyingSupply.toString(), decs)
|
|
16125
16333
|
);
|
|
16126
|
-
const totalDebt = Number(
|
|
16127
|
-
|
|
16128
|
-
);
|
|
16129
|
-
const liquidity = totalDeposits - totalDebt;
|
|
16334
|
+
const totalDebt = Number(parseRawAmount(parsed.totalBorrows.toString(), decs));
|
|
16335
|
+
const liquidity = cashLiquidity(parsed.cash, decs) ?? totalDeposits - totalDebt;
|
|
16130
16336
|
const poolId = asset.address;
|
|
16131
16337
|
const marketUid = createMarketUid(chainId, lender, cToken);
|
|
16132
16338
|
const collateralActive = !parsed.mintPaused;
|
|
@@ -16215,7 +16421,10 @@ function parseBaseFields(meta) {
|
|
|
16215
16421
|
totalBorrows: pick(meta, "totalBorrows", 5) ?? 0n,
|
|
16216
16422
|
totalReserves: pick(meta, "totalReserves", 6) ?? 0n,
|
|
16217
16423
|
totalSupply: pick(meta, "totalSupply", 7) ?? 0n,
|
|
16218
|
-
|
|
16424
|
+
// deliberately NOT `?? 0n`: an absent cash field must stay `undefined`
|
|
16425
|
+
// so the converter falls back to the derived figure instead of
|
|
16426
|
+
// reporting a live market as empty. See `convert/liquidity.ts`.
|
|
16427
|
+
totalCash: pick(meta, "totalCash", 8),
|
|
16219
16428
|
isListed: pick(meta, "isListed", 9) ?? true,
|
|
16220
16429
|
collateralFactorMantissa: pick(meta, "collateralFactorMantissa", 10) ?? 0n,
|
|
16221
16430
|
underlyingAssetAddress: pick(meta, "underlyingAssetAddress", 11) ?? "",
|
|
@@ -16228,27 +16437,29 @@ function parseBaseFields(meta) {
|
|
|
16228
16437
|
pausedActions: DEFAULT_PAUSED_ACTIONS
|
|
16229
16438
|
};
|
|
16230
16439
|
}
|
|
16231
|
-
function readLodestarCTokenMetadata(meta, token) {
|
|
16440
|
+
function readLodestarCTokenMetadata(meta, token, unitSeconds) {
|
|
16232
16441
|
const base = parseBaseFields(meta);
|
|
16233
16442
|
return {
|
|
16234
16443
|
...base,
|
|
16235
16444
|
depositRate: capRate(
|
|
16236
16445
|
apyToApr(
|
|
16237
16446
|
calculateRateForCompoundType2(
|
|
16238
|
-
base.supplyRatePerBlock?.toString() ?? "0"
|
|
16447
|
+
base.supplyRatePerBlock?.toString() ?? "0",
|
|
16448
|
+
unitSeconds
|
|
16239
16449
|
) / 100
|
|
16240
16450
|
) * 100
|
|
16241
16451
|
),
|
|
16242
16452
|
variableBorrowRate: capRate(
|
|
16243
16453
|
apyToApr(
|
|
16244
16454
|
calculateRateForCompoundType2(
|
|
16245
|
-
base.borrowRatePerBlock?.toString() ?? "0"
|
|
16455
|
+
base.borrowRatePerBlock?.toString() ?? "0",
|
|
16456
|
+
unitSeconds
|
|
16246
16457
|
) / 100
|
|
16247
16458
|
) * 100
|
|
16248
16459
|
)
|
|
16249
16460
|
};
|
|
16250
16461
|
}
|
|
16251
|
-
function readCompoundV2CTokenMetadata(meta, token) {
|
|
16462
|
+
function readCompoundV2CTokenMetadata(meta, token, unitSeconds) {
|
|
16252
16463
|
const base = parseBaseFields(meta);
|
|
16253
16464
|
return {
|
|
16254
16465
|
...base,
|
|
@@ -16257,7 +16468,8 @@ function readCompoundV2CTokenMetadata(meta, token) {
|
|
|
16257
16468
|
calculateRateForCompoundType(
|
|
16258
16469
|
base.supplyRatePerBlock?.toString() ?? "0",
|
|
16259
16470
|
token.chainId,
|
|
16260
|
-
0 /* BLOCK
|
|
16471
|
+
0 /* BLOCK */,
|
|
16472
|
+
unitSeconds
|
|
16261
16473
|
) / 100
|
|
16262
16474
|
) * 100
|
|
16263
16475
|
),
|
|
@@ -16266,7 +16478,8 @@ function readCompoundV2CTokenMetadata(meta, token) {
|
|
|
16266
16478
|
calculateRateForCompoundType(
|
|
16267
16479
|
base.borrowRatePerBlock?.toString() ?? "0",
|
|
16268
16480
|
token.chainId,
|
|
16269
|
-
0 /* BLOCK
|
|
16481
|
+
0 /* BLOCK */,
|
|
16482
|
+
unitSeconds
|
|
16270
16483
|
) / 100
|
|
16271
16484
|
) * 100
|
|
16272
16485
|
)
|
|
@@ -16282,7 +16495,10 @@ function parseCreamV2BaseFields(meta) {
|
|
|
16282
16495
|
totalBorrows: pick(meta, "totalBorrows", 5) ?? 0n,
|
|
16283
16496
|
totalReserves: pick(meta, "totalReserves", 6) ?? 0n,
|
|
16284
16497
|
totalSupply: pick(meta, "totalSupply", 7) ?? 0n,
|
|
16285
|
-
|
|
16498
|
+
// deliberately NOT `?? 0n`: an absent cash field must stay `undefined`
|
|
16499
|
+
// so the converter falls back to the derived figure instead of
|
|
16500
|
+
// reporting a live market as empty. See `convert/liquidity.ts`.
|
|
16501
|
+
totalCash: pick(meta, "totalCash", 8),
|
|
16286
16502
|
isListed: pick(meta, "isListed", 10) ?? true,
|
|
16287
16503
|
collateralFactorMantissa: pick(meta, "collateralFactorMantissa", 11) ?? 0n,
|
|
16288
16504
|
underlyingAssetAddress: pick(meta, "underlyingAssetAddress", 12) ?? "",
|
|
@@ -16292,7 +16508,7 @@ function parseCreamV2BaseFields(meta) {
|
|
|
16292
16508
|
pausedActions: DEFAULT_PAUSED_ACTIONS
|
|
16293
16509
|
};
|
|
16294
16510
|
}
|
|
16295
|
-
function readCreamV2CTokenMetadata(meta, token) {
|
|
16511
|
+
function readCreamV2CTokenMetadata(meta, token, unitSeconds) {
|
|
16296
16512
|
const base = parseCreamV2BaseFields(meta);
|
|
16297
16513
|
return {
|
|
16298
16514
|
...base,
|
|
@@ -16301,7 +16517,8 @@ function readCreamV2CTokenMetadata(meta, token) {
|
|
|
16301
16517
|
calculateRateForCompoundType(
|
|
16302
16518
|
base.supplyRatePerBlock?.toString() ?? "0",
|
|
16303
16519
|
token.chainId,
|
|
16304
|
-
0 /* BLOCK
|
|
16520
|
+
0 /* BLOCK */,
|
|
16521
|
+
unitSeconds
|
|
16305
16522
|
) / 100
|
|
16306
16523
|
) * 100
|
|
16307
16524
|
),
|
|
@@ -16310,12 +16527,446 @@ function readCreamV2CTokenMetadata(meta, token) {
|
|
|
16310
16527
|
calculateRateForCompoundType(
|
|
16311
16528
|
base.borrowRatePerBlock?.toString() ?? "0",
|
|
16312
16529
|
token.chainId,
|
|
16313
|
-
0 /* BLOCK
|
|
16530
|
+
0 /* BLOCK */,
|
|
16531
|
+
unitSeconds
|
|
16314
16532
|
) / 100
|
|
16315
16533
|
) * 100
|
|
16316
16534
|
)
|
|
16317
16535
|
};
|
|
16318
16536
|
}
|
|
16537
|
+
var MULTICALL_DEFAULT_BATCH_SIZE = 4096;
|
|
16538
|
+
var CELO_MULTICALL_ADDRESS = "0x633987602DE5C4F337e3DbF265303A1080324204";
|
|
16539
|
+
var BNB_MULTICALL_ADDRESS = "0x963Df249eD09c358A4819E39d9Cd5736c3087184";
|
|
16540
|
+
var MANTLE_MULTICALL_ADDRESS = "0x2A51f2F647E1883F88C992244dEd171238693107";
|
|
16541
|
+
var ARBITRUM_ONE_MULTICALL_ADDRESS = "0xadF885960B47eA2CD9B55E6DAc6B42b7Cb2806dB";
|
|
16542
|
+
var LINEA_MULTICALL_ADDRESS = "0xac1cE734566f390A94b00eb9bf561c2625BF44ea";
|
|
16543
|
+
var AVALANCHE_MULTICALL_ADDRESS = "0x0139141Cd4Ee88dF3Cdb65881D411bAE271Ef0C2";
|
|
16544
|
+
var BASE_MULTICALL_ADDRESS = "0x091e99cb1C49331a94dD62755D168E941AbD0693";
|
|
16545
|
+
var BLAST_MULTICALL_ADDRESS = "0xdC7f370de7631cE9e2c2e1DCDA6B3B5744Cf4705";
|
|
16546
|
+
var TAIKO_MULTICALL_ADDRESS = "0x8E24CfC19c6C00c524353CB8816f5f1c2F33c201";
|
|
16547
|
+
var HEMI_MULTICALL_ADDRESS = "0x352A86168e6988A1aDF9A15Cb00017AAd3B67155";
|
|
16548
|
+
var GNOSIS_MULTICALL_ADDRESS = "0x4dfa9a980efE4802E969AC33968E3d6E59B8a19e";
|
|
16549
|
+
var MODE_MULTICALL_ADDRESS = "0xAB39cE30D98a59DFDa40A630b074170800bfF179";
|
|
16550
|
+
var FANTOM_MULTICALL_ADDRESS = "0xDb51CffFf3B989d0cB6b58AbF173371b6F2d0D24";
|
|
16551
|
+
var SCROLL_MULTICALL_ADDRESS = "0x3b615B1AC55bc34e51a81D3dea67467F32bcb8C2";
|
|
16552
|
+
var SHAPE_MULTICALL_ADDRESS = "0x356A450B32f5030ae7083702b86FaFbBe7490411";
|
|
16553
|
+
var SONIC_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
|
|
16554
|
+
var INK_MULTICALL_ADDRESS = "0xA0fCec583AeE6176527C07B198e5561722332014";
|
|
16555
|
+
var METIS_MULTICALL_ADDRESS = "0x7a59ddbB76521E8982Fa3A08598C9a83b14A6C07";
|
|
16556
|
+
var IOTA_MULTICALL_ADDRESS = "0x9683D433621A83aA7dd290106e1da85251317F55";
|
|
16557
|
+
var KAVA_MULTICALL_ADDRESS = "0x8B741B0D79BE80E135C880F7583d427B4D41F015";
|
|
16558
|
+
var SAGA_MULTICALL_ADDRESS = "0x743E03cceB4af2efA3CC76838f6E8B50B63F184c";
|
|
16559
|
+
var CYBER_MULTICALL_ADDRESS = "0x906d6eB9CF8f64e100e44f8f491b833a8d40B530";
|
|
16560
|
+
var METAL_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
|
|
16561
|
+
var ZERO_MULTICALL_ADDRESS = "0x9CA4dcb2505fbf536F6c54AA0a77C79f4fBC35C0";
|
|
16562
|
+
var BOB_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
|
|
16563
|
+
var WORLDCHAIN_MULTICALL_ADDRESS = "0x0a22c04215c97E3F532F4eF30e0aD9458792dAB9";
|
|
16564
|
+
var LISK_MULTICALL_ADDRESS = "0xE3dbcD53f4Ce1b06Ab200f4912BD35672e68f1FA";
|
|
16565
|
+
var REDSTONE_MULTICALL_ADDRESS = "0xd57B52452a0FDfE3ff8e0A40Bd10D00D0bfe0723";
|
|
16566
|
+
var MANTA_MULTICALL_ADDRESS = "0x52dFC0D9960F11A9Ca9FF616e791B91188446a60";
|
|
16567
|
+
var ZORA_MULTICALL_ADDRESS = "0xA51c76bEE6746cB487a7e9312E43e2b8f4A37C15";
|
|
16568
|
+
var CORE_MULTICALL_ADDRESS = "0xFe9F82D820757787895Da00B1dBD35c3B8b04894";
|
|
16569
|
+
var MORPH_MULTICALL_ADDRESS = "0xAcD82113982479B25E7c1D09858F0130921Dbbca";
|
|
16570
|
+
var TELOS_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
|
|
16571
|
+
var MULTICALL_ADDRESS = {
|
|
16572
|
+
[Chain.OP_MAINNET]: "0x1F98415757620B543A52E61c46B32eB19261F984",
|
|
16573
|
+
[Chain.POLYGON_MAINNET]: "0x1F98415757620B543A52E61c46B32eB19261F984",
|
|
16574
|
+
[Chain.ETHEREUM_MAINNET]: "0x1F98415757620B543A52E61c46B32eB19261F984",
|
|
16575
|
+
[Chain.ARBITRUM_ONE]: ARBITRUM_ONE_MULTICALL_ADDRESS,
|
|
16576
|
+
[Chain.BASE]: BASE_MULTICALL_ADDRESS,
|
|
16577
|
+
[Chain.CELO_MAINNET]: CELO_MULTICALL_ADDRESS,
|
|
16578
|
+
[Chain.BNB_SMART_CHAIN_MAINNET]: BNB_MULTICALL_ADDRESS,
|
|
16579
|
+
[Chain.MANTLE]: MANTLE_MULTICALL_ADDRESS,
|
|
16580
|
+
[Chain.BLAST]: BLAST_MULTICALL_ADDRESS,
|
|
16581
|
+
[Chain.LINEA]: LINEA_MULTICALL_ADDRESS,
|
|
16582
|
+
[Chain.AVALANCHE_C_CHAIN]: AVALANCHE_MULTICALL_ADDRESS,
|
|
16583
|
+
[Chain.TAIKO_ALETHIA]: TAIKO_MULTICALL_ADDRESS,
|
|
16584
|
+
[Chain.HEMI_NETWORK]: HEMI_MULTICALL_ADDRESS,
|
|
16585
|
+
[Chain.GNOSIS]: GNOSIS_MULTICALL_ADDRESS,
|
|
16586
|
+
[Chain.CORE_BLOCKCHAIN_MAINNET]: CORE_MULTICALL_ADDRESS,
|
|
16587
|
+
[Chain.METIS_ANDROMEDA_MAINNET]: METIS_MULTICALL_ADDRESS,
|
|
16588
|
+
[Chain.MODE]: MODE_MULTICALL_ADDRESS,
|
|
16589
|
+
[Chain.INK]: INK_MULTICALL_ADDRESS,
|
|
16590
|
+
[Chain.IOTA_EVM]: IOTA_MULTICALL_ADDRESS,
|
|
16591
|
+
[Chain.SONIC_MAINNET]: SONIC_MULTICALL_ADDRESS,
|
|
16592
|
+
[Chain.FANTOM_OPERA]: FANTOM_MULTICALL_ADDRESS,
|
|
16593
|
+
[Chain.SCROLL]: SCROLL_MULTICALL_ADDRESS,
|
|
16594
|
+
[Chain.SHAPE]: SHAPE_MULTICALL_ADDRESS,
|
|
16595
|
+
[Chain.CYBER_MAINNET]: CYBER_MULTICALL_ADDRESS,
|
|
16596
|
+
[Chain.ZORA]: ZORA_MULTICALL_ADDRESS,
|
|
16597
|
+
[Chain.MANTA_PACIFIC_MAINNET]: MANTA_MULTICALL_ADDRESS,
|
|
16598
|
+
[Chain.REDSTONE]: REDSTONE_MULTICALL_ADDRESS,
|
|
16599
|
+
[Chain.KAVA]: KAVA_MULTICALL_ADDRESS,
|
|
16600
|
+
[Chain.METAL_L2]: METAL_MULTICALL_ADDRESS,
|
|
16601
|
+
[Chain.LISK]: LISK_MULTICALL_ADDRESS,
|
|
16602
|
+
[Chain.BOB]: BOB_MULTICALL_ADDRESS,
|
|
16603
|
+
[Chain.ZERO_NETWORK]: ZERO_MULTICALL_ADDRESS,
|
|
16604
|
+
[Chain.SAGA]: SAGA_MULTICALL_ADDRESS,
|
|
16605
|
+
[Chain.MORPH]: MORPH_MULTICALL_ADDRESS,
|
|
16606
|
+
[Chain.TELOS_EVM_MAINNET]: TELOS_MULTICALL_ADDRESS,
|
|
16607
|
+
[Chain.WORLD_CHAIN]: WORLDCHAIN_MULTICALL_ADDRESS
|
|
16608
|
+
};
|
|
16609
|
+
|
|
16610
|
+
// src/utils/multicall.ts
|
|
16611
|
+
var { isArray } = lodash;
|
|
16612
|
+
var maxRetries = 3;
|
|
16613
|
+
var MULTICALL_FAILURE = "0x";
|
|
16614
|
+
var isFailedCall = (value) => value === void 0 || value === null || value === MULTICALL_FAILURE;
|
|
16615
|
+
var MULTICALL_REPAIR_ROUNDS = 3;
|
|
16616
|
+
var MAX_CALLS_PER_SHARD = 300;
|
|
16617
|
+
var ONE_REQUEST_BATCH_BYTES = 1e6;
|
|
16618
|
+
var MAX_INFLIGHT_REQUESTS = 6;
|
|
16619
|
+
var HEDGE_DELAY_MS = 1200;
|
|
16620
|
+
var SHARD_TIMEOUT_MS = 4e3;
|
|
16621
|
+
var MIN_ADAPTIVE_SHARD = 25;
|
|
16622
|
+
var ADAPTIVE_CAP_TTL_MS = 6e4;
|
|
16623
|
+
var endpointCallCap = /* @__PURE__ */ new Map();
|
|
16624
|
+
var capFor = (url, requested) => {
|
|
16625
|
+
const hit = endpointCallCap.get(url);
|
|
16626
|
+
if (!hit) return requested;
|
|
16627
|
+
if (Date.now() - hit.at > ADAPTIVE_CAP_TTL_MS) {
|
|
16628
|
+
endpointCallCap.delete(url);
|
|
16629
|
+
return requested;
|
|
16630
|
+
}
|
|
16631
|
+
return Math.min(requested, hit.calls);
|
|
16632
|
+
};
|
|
16633
|
+
var noteEndpointRefusal = (url, calls) => {
|
|
16634
|
+
if (calls <= MIN_ADAPTIVE_SHARD) return;
|
|
16635
|
+
const next = Math.max(MIN_ADAPTIVE_SHARD, Math.floor(calls / 2));
|
|
16636
|
+
const current = endpointCallCap.get(url);
|
|
16637
|
+
if (current && Date.now() - current.at <= ADAPTIVE_CAP_TTL_MS && current.calls <= next)
|
|
16638
|
+
return;
|
|
16639
|
+
endpointCallCap.set(url, { calls: next, at: Date.now() });
|
|
16640
|
+
};
|
|
16641
|
+
var DETERMINISTIC_ERROR_NAMES = /* @__PURE__ */ new Set([
|
|
16642
|
+
"ContractFunctionRevertedError",
|
|
16643
|
+
"RawContractError",
|
|
16644
|
+
"AbiDecodingZeroDataError",
|
|
16645
|
+
"AbiDecodingDataSizeTooSmallError",
|
|
16646
|
+
"AbiFunctionNotFoundError"
|
|
16647
|
+
]);
|
|
16648
|
+
var isDeterministicCallError = (error) => {
|
|
16649
|
+
let err = error;
|
|
16650
|
+
for (let depth = 0; err && depth < 8; depth++) {
|
|
16651
|
+
if (DETERMINISTIC_ERROR_NAMES.has(err.name)) return true;
|
|
16652
|
+
const message = String(err.shortMessage ?? err.message ?? "").toLowerCase();
|
|
16653
|
+
if (message.includes("execution reverted") || message.includes("returned no data"))
|
|
16654
|
+
return true;
|
|
16655
|
+
err = err.cause;
|
|
16656
|
+
}
|
|
16657
|
+
return false;
|
|
16658
|
+
};
|
|
16659
|
+
var REPAIR_BACKOFF_BASE_MS = 100;
|
|
16660
|
+
var REPAIR_BACKOFF_JITTER_MS = 60;
|
|
16661
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));
|
|
16662
|
+
var backoffForRound = (round) => REPAIR_BACKOFF_BASE_MS * 2 ** round + Math.random() * REPAIR_BACKOFF_JITTER_MS;
|
|
16663
|
+
var endpointUrl = (client, rpcId) => client?.transport?.url ?? `rpc#${rpcId}`;
|
|
16664
|
+
var resolveEndpoint = (chainId, getEvmClient18, startRpcId, tried, maxProbe = 12, timeoutMs) => {
|
|
16665
|
+
let fallback = null;
|
|
16666
|
+
for (let probe = 0; probe < maxProbe; probe++) {
|
|
16667
|
+
const rpcId = startRpcId + probe;
|
|
16668
|
+
let client;
|
|
16669
|
+
try {
|
|
16670
|
+
client = getEvmClient18(chainId, rpcId, { timeoutMs });
|
|
16671
|
+
} catch {
|
|
16672
|
+
break;
|
|
16673
|
+
}
|
|
16674
|
+
const url = endpointUrl(client, rpcId);
|
|
16675
|
+
if (!tried?.has(url)) {
|
|
16676
|
+
tried?.add(url);
|
|
16677
|
+
return { client, rpcId, url, reused: false };
|
|
16678
|
+
}
|
|
16679
|
+
fallback ??= { client, rpcId, url, reused: true };
|
|
16680
|
+
}
|
|
16681
|
+
return fallback;
|
|
16682
|
+
};
|
|
16683
|
+
var toSlots = (returnData, allowFailure) => {
|
|
16684
|
+
if (!allowFailure)
|
|
16685
|
+
return returnData.map((value) => ({ value, permanent: false }));
|
|
16686
|
+
return returnData.map(
|
|
16687
|
+
({ result, status, error }) => status === "success" ? { value: result, permanent: false } : {
|
|
16688
|
+
value: MULTICALL_FAILURE,
|
|
16689
|
+
permanent: isDeterministicCallError(error)
|
|
16690
|
+
}
|
|
16691
|
+
);
|
|
16692
|
+
};
|
|
16693
|
+
var recordPermanentFailures = (slots, offset, collector) => {
|
|
16694
|
+
if (!collector) return;
|
|
16695
|
+
for (let i = 0; i < slots.length; i++) {
|
|
16696
|
+
if (slots[i].permanent) collector.add(offset + i);
|
|
16697
|
+
}
|
|
16698
|
+
};
|
|
16699
|
+
var repairFailedSlots = async (chainId, contracts, slots, getEvmClient18, nextRpcId, batchSize, logs, rounds = MULTICALL_REPAIR_ROUNDS, options) => {
|
|
16700
|
+
let searchFrom = nextRpcId;
|
|
16701
|
+
for (let round = 0; round < rounds; round++) {
|
|
16702
|
+
const failedIdx = [];
|
|
16703
|
+
for (let i = 0; i < slots.length; i++) {
|
|
16704
|
+
if (isFailedCall(slots[i].value) && !slots[i].permanent) failedIdx.push(i);
|
|
16705
|
+
}
|
|
16706
|
+
if (failedIdx.length === 0) return slots;
|
|
16707
|
+
const endpoint = resolveEndpoint(
|
|
16708
|
+
chainId,
|
|
16709
|
+
getEvmClient18,
|
|
16710
|
+
searchFrom,
|
|
16711
|
+
options?.tried
|
|
16712
|
+
);
|
|
16713
|
+
if (!endpoint) {
|
|
16714
|
+
if (logs)
|
|
16715
|
+
console.log(
|
|
16716
|
+
`multicall repair: no usable endpoint for chain ${chainId}, giving up with ${failedIdx.length} failed slots`
|
|
16717
|
+
);
|
|
16718
|
+
return slots;
|
|
16719
|
+
}
|
|
16720
|
+
searchFrom = endpoint.rpcId + 1;
|
|
16721
|
+
await sleep(backoffForRound(round));
|
|
16722
|
+
try {
|
|
16723
|
+
const returnData = await endpoint.client.multicall({
|
|
16724
|
+
allowFailure: true,
|
|
16725
|
+
batchSize,
|
|
16726
|
+
contracts: failedIdx.map((i) => contracts[i])
|
|
16727
|
+
});
|
|
16728
|
+
let repaired = 0;
|
|
16729
|
+
returnData.forEach((entry, k) => {
|
|
16730
|
+
const idx = failedIdx[k];
|
|
16731
|
+
if (entry?.status === "success") {
|
|
16732
|
+
slots[idx] = { value: entry.result, permanent: false };
|
|
16733
|
+
repaired++;
|
|
16734
|
+
} else if (isDeterministicCallError(entry?.error)) {
|
|
16735
|
+
slots[idx].permanent = true;
|
|
16736
|
+
}
|
|
16737
|
+
});
|
|
16738
|
+
if (repaired === 0)
|
|
16739
|
+
options?.onEndpointFailure?.({
|
|
16740
|
+
chainId,
|
|
16741
|
+
url: endpoint.url,
|
|
16742
|
+
rpcId: endpoint.rpcId,
|
|
16743
|
+
kind: "slots"
|
|
16744
|
+
});
|
|
16745
|
+
} catch (error) {
|
|
16746
|
+
options?.onEndpointFailure?.({
|
|
16747
|
+
chainId,
|
|
16748
|
+
url: endpoint.url,
|
|
16749
|
+
rpcId: endpoint.rpcId,
|
|
16750
|
+
kind: "transport"
|
|
16751
|
+
});
|
|
16752
|
+
if (logs)
|
|
16753
|
+
console.log(
|
|
16754
|
+
`error in multicall failure-repair round ${round} chain ${chainId}`,
|
|
16755
|
+
error
|
|
16756
|
+
);
|
|
16757
|
+
}
|
|
16758
|
+
}
|
|
16759
|
+
return slots;
|
|
16760
|
+
};
|
|
16761
|
+
var multicallShardedAbiArray = async (chainId, abi, calls, getEvmClient18, poolSize, retries = maxRetries, allowFailure = true, batchSize = MULTICALL_DEFAULT_BATCH_SIZE, logs = false, retryFailed = false, permanentFailures, options) => {
|
|
16762
|
+
const abiIsArray = isArray(abi[0]);
|
|
16763
|
+
const contracts = calls.map(({ address, name, params }, i) => ({
|
|
16764
|
+
abi: abiIsArray ? abi?.[i] : abi,
|
|
16765
|
+
address,
|
|
16766
|
+
functionName: name,
|
|
16767
|
+
args: params
|
|
16768
|
+
}));
|
|
16769
|
+
const requestBytes = batchSize < MULTICALL_DEFAULT_BATCH_SIZE ? batchSize : ONE_REQUEST_BATCH_BYTES;
|
|
16770
|
+
const workerBudget = Math.max(1, Math.floor(MAX_INFLIGHT_REQUESTS / 2));
|
|
16771
|
+
const workers = Math.max(1, Math.min(poolSize, workerBudget));
|
|
16772
|
+
const shardSize = Math.max(
|
|
16773
|
+
1,
|
|
16774
|
+
Math.min(MAX_CALLS_PER_SHARD, Math.ceil(contracts.length / workers))
|
|
16775
|
+
);
|
|
16776
|
+
const batches = [];
|
|
16777
|
+
for (let i = 0; i < contracts.length; i += shardSize) {
|
|
16778
|
+
batches.push({ start: i, items: contracts.slice(i, i + shardSize) });
|
|
16779
|
+
}
|
|
16780
|
+
const results = new Array(contracts.length);
|
|
16781
|
+
const request = async (endpoint, items) => {
|
|
16782
|
+
try {
|
|
16783
|
+
const returnData = await endpoint.client.multicall({
|
|
16784
|
+
allowFailure,
|
|
16785
|
+
batchSize: requestBytes,
|
|
16786
|
+
contracts: items
|
|
16787
|
+
});
|
|
16788
|
+
const slots = toSlots(returnData, allowFailure);
|
|
16789
|
+
if (allowFailure && slots.length > 0 && slots.every((s) => isFailedCall(s.value) && !s.permanent)) {
|
|
16790
|
+
if (logs)
|
|
16791
|
+
console.log(
|
|
16792
|
+
`sharded multicall: rpc ${endpoint.rpcId} answered ${items.length} calls with nothing`
|
|
16793
|
+
);
|
|
16794
|
+
options?.onEndpointFailure?.({
|
|
16795
|
+
chainId,
|
|
16796
|
+
url: endpoint.url,
|
|
16797
|
+
rpcId: endpoint.rpcId,
|
|
16798
|
+
kind: "slots"
|
|
16799
|
+
});
|
|
16800
|
+
noteEndpointRefusal(endpoint.url, items.length);
|
|
16801
|
+
return null;
|
|
16802
|
+
}
|
|
16803
|
+
return slots;
|
|
16804
|
+
} catch (error) {
|
|
16805
|
+
if (logs) console.log("error in sharded multicall request", error);
|
|
16806
|
+
options?.onEndpointFailure?.({
|
|
16807
|
+
chainId,
|
|
16808
|
+
url: endpoint.url,
|
|
16809
|
+
rpcId: endpoint.rpcId,
|
|
16810
|
+
kind: "transport"
|
|
16811
|
+
});
|
|
16812
|
+
noteEndpointRefusal(endpoint.url, items.length);
|
|
16813
|
+
return null;
|
|
16814
|
+
}
|
|
16815
|
+
};
|
|
16816
|
+
const firstUsable = (attempts) => new Promise((resolve) => {
|
|
16817
|
+
let pending = attempts.length;
|
|
16818
|
+
let settled = false;
|
|
16819
|
+
const lose = () => {
|
|
16820
|
+
if (!settled && --pending === 0) resolve(null);
|
|
16821
|
+
};
|
|
16822
|
+
for (const attempt of attempts) {
|
|
16823
|
+
attempt.then((won) => {
|
|
16824
|
+
if (settled) return;
|
|
16825
|
+
if (won) {
|
|
16826
|
+
settled = true;
|
|
16827
|
+
resolve(won);
|
|
16828
|
+
} else lose();
|
|
16829
|
+
}, lose);
|
|
16830
|
+
}
|
|
16831
|
+
});
|
|
16832
|
+
const attemptHedged = async (items, startRpcId, tried) => {
|
|
16833
|
+
const primary = resolveEndpoint(
|
|
16834
|
+
chainId,
|
|
16835
|
+
getEvmClient18,
|
|
16836
|
+
startRpcId,
|
|
16837
|
+
tried,
|
|
16838
|
+
12,
|
|
16839
|
+
SHARD_TIMEOUT_MS
|
|
16840
|
+
);
|
|
16841
|
+
if (!primary) {
|
|
16842
|
+
if (logs)
|
|
16843
|
+
console.log(
|
|
16844
|
+
`sharded multicall: no untried endpoint left for chain ${chainId}`
|
|
16845
|
+
);
|
|
16846
|
+
return null;
|
|
16847
|
+
}
|
|
16848
|
+
let timer;
|
|
16849
|
+
let hedgeStarted = false;
|
|
16850
|
+
let beginHedge = () => {
|
|
16851
|
+
};
|
|
16852
|
+
const hedged = new Promise((resolve) => {
|
|
16853
|
+
beginHedge = () => {
|
|
16854
|
+
if (hedgeStarted) return;
|
|
16855
|
+
hedgeStarted = true;
|
|
16856
|
+
clearTimeout(timer);
|
|
16857
|
+
const alt = resolveEndpoint(
|
|
16858
|
+
chainId,
|
|
16859
|
+
getEvmClient18,
|
|
16860
|
+
primary.rpcId + 1,
|
|
16861
|
+
tried,
|
|
16862
|
+
12,
|
|
16863
|
+
SHARD_TIMEOUT_MS
|
|
16864
|
+
);
|
|
16865
|
+
if (!alt) return resolve(null);
|
|
16866
|
+
const altItems = items.slice(0, capFor(alt.url, items.length));
|
|
16867
|
+
if (altItems.length < items.length) return resolve(null);
|
|
16868
|
+
request(alt, items).then(
|
|
16869
|
+
(slots) => resolve(slots ? { slots, rpcId: alt.rpcId } : null)
|
|
16870
|
+
);
|
|
16871
|
+
};
|
|
16872
|
+
});
|
|
16873
|
+
timer = setTimeout(() => beginHedge(), HEDGE_DELAY_MS);
|
|
16874
|
+
const direct = request(primary, items).then((slots) => {
|
|
16875
|
+
if (slots) return { slots, rpcId: primary.rpcId };
|
|
16876
|
+
beginHedge();
|
|
16877
|
+
return null;
|
|
16878
|
+
});
|
|
16879
|
+
const won = await firstUsable([direct, hedged]);
|
|
16880
|
+
clearTimeout(timer);
|
|
16881
|
+
return won;
|
|
16882
|
+
};
|
|
16883
|
+
const runBatch = async (batch, rpcId, attemptsLeft, tried) => {
|
|
16884
|
+
if (!batch.items.length) return;
|
|
16885
|
+
const won = await attemptHedged(batch.items, rpcId, tried);
|
|
16886
|
+
if (!won) {
|
|
16887
|
+
if (attemptsLeft > 0 && batch.items.length > 1) {
|
|
16888
|
+
const half = Math.ceil(batch.items.length / 2);
|
|
16889
|
+
await sleep(backoffForRound(0));
|
|
16890
|
+
await runBatch(
|
|
16891
|
+
{ start: batch.start, items: batch.items.slice(0, half) },
|
|
16892
|
+
rpcId,
|
|
16893
|
+
attemptsLeft - 1,
|
|
16894
|
+
tried
|
|
16895
|
+
);
|
|
16896
|
+
await runBatch(
|
|
16897
|
+
{ start: batch.start + half, items: batch.items.slice(half) },
|
|
16898
|
+
rpcId + 1,
|
|
16899
|
+
attemptsLeft - 1,
|
|
16900
|
+
tried
|
|
16901
|
+
);
|
|
16902
|
+
}
|
|
16903
|
+
return;
|
|
16904
|
+
}
|
|
16905
|
+
let slots = won.slots;
|
|
16906
|
+
if (allowFailure && retryFailed) {
|
|
16907
|
+
slots = await repairFailedSlots(
|
|
16908
|
+
chainId,
|
|
16909
|
+
batch.items,
|
|
16910
|
+
slots,
|
|
16911
|
+
getEvmClient18,
|
|
16912
|
+
won.rpcId + 1,
|
|
16913
|
+
requestBytes,
|
|
16914
|
+
logs,
|
|
16915
|
+
MULTICALL_REPAIR_ROUNDS,
|
|
16916
|
+
{ tried, onEndpointFailure: options?.onEndpointFailure }
|
|
16917
|
+
);
|
|
16918
|
+
}
|
|
16919
|
+
recordPermanentFailures(slots, batch.start, permanentFailures);
|
|
16920
|
+
for (let j = 0; j < slots.length; j++) {
|
|
16921
|
+
results[batch.start + j] = slots[j].value;
|
|
16922
|
+
}
|
|
16923
|
+
};
|
|
16924
|
+
let cursor = 0;
|
|
16925
|
+
const worker = async (workerId) => {
|
|
16926
|
+
while (true) {
|
|
16927
|
+
const idx = cursor++;
|
|
16928
|
+
if (idx >= batches.length) break;
|
|
16929
|
+
const batch = batches[idx];
|
|
16930
|
+
const tried = /* @__PURE__ */ new Set();
|
|
16931
|
+
const start = resolveEndpoint(
|
|
16932
|
+
chainId,
|
|
16933
|
+
getEvmClient18,
|
|
16934
|
+
workerId,
|
|
16935
|
+
void 0,
|
|
16936
|
+
12,
|
|
16937
|
+
SHARD_TIMEOUT_MS
|
|
16938
|
+
);
|
|
16939
|
+
const cap = start ? capFor(start.url, batch.items.length) : batch.items.length;
|
|
16940
|
+
for (let off = 0; off < batch.items.length; off += cap) {
|
|
16941
|
+
await runBatch(
|
|
16942
|
+
{
|
|
16943
|
+
start: batch.start + off,
|
|
16944
|
+
items: batch.items.slice(off, off + cap)
|
|
16945
|
+
},
|
|
16946
|
+
workerId,
|
|
16947
|
+
retries,
|
|
16948
|
+
tried
|
|
16949
|
+
);
|
|
16950
|
+
}
|
|
16951
|
+
}
|
|
16952
|
+
};
|
|
16953
|
+
await Promise.all(
|
|
16954
|
+
Array.from(
|
|
16955
|
+
{ length: Math.min(workers, batches.length) },
|
|
16956
|
+
(_3, w) => worker(w)
|
|
16957
|
+
)
|
|
16958
|
+
);
|
|
16959
|
+
return results;
|
|
16960
|
+
};
|
|
16961
|
+
function prepareMulticallInputs(abi, calls) {
|
|
16962
|
+
const abiIsArray = isArray(abi[0]);
|
|
16963
|
+
return calls.map(({ address, name, params }, i) => ({
|
|
16964
|
+
address,
|
|
16965
|
+
functionName: name,
|
|
16966
|
+
params: params || [],
|
|
16967
|
+
abi: abiIsArray ? abi[i] : abi
|
|
16968
|
+
}));
|
|
16969
|
+
}
|
|
16319
16970
|
|
|
16320
16971
|
// src/lending/public-data/compound-v2/publicCallParse.ts
|
|
16321
16972
|
var parseMantissaWad = (raw) => {
|
|
@@ -16326,7 +16977,7 @@ var parseMantissaWad = (raw) => {
|
|
|
16326
16977
|
return void 0;
|
|
16327
16978
|
}
|
|
16328
16979
|
};
|
|
16329
|
-
var getCompoundV2DataConverter = (lender, chainId, prices, additionalYields, tokenList = {}) => {
|
|
16980
|
+
var getCompoundV2DataConverter = (lender, chainId, prices, additionalYields, tokenList = {}, unitSeconds) => {
|
|
16330
16981
|
if (lender === Lender.TAKARA) {
|
|
16331
16982
|
return [
|
|
16332
16983
|
(data) => {
|
|
@@ -16448,7 +17099,7 @@ var getCompoundV2DataConverter = (lender, chainId, prices, additionalYields, tok
|
|
|
16448
17099
|
const pauseReads = Boolean(stdComptroller) && usesComptrollerPauseReads(lender);
|
|
16449
17100
|
const pauseCalls = pauseReads ? tokenCount * 2 : 0;
|
|
16450
17101
|
const expectedNumberOfCalls = isSumer ? tokenCount + SUMER_GROUP_COUNT : tokenCount + stdComptrollerCalls + pauseCalls;
|
|
16451
|
-
const reader = getReader(lender, chainId);
|
|
17102
|
+
const reader = getReader(lender, chainId, unitSeconds);
|
|
16452
17103
|
return [
|
|
16453
17104
|
(data) => {
|
|
16454
17105
|
if (data.length !== expectedNumberOfCalls) return void 0;
|
|
@@ -16492,6 +17143,7 @@ var getCompoundV2DataConverter = (lender, chainId, prices, additionalYields, tok
|
|
|
16492
17143
|
const asset = tokenList[underlying];
|
|
16493
17144
|
if (!asset) continue;
|
|
16494
17145
|
const entryRaw = data[i];
|
|
17146
|
+
if (isFailedCall(entryRaw)) continue;
|
|
16495
17147
|
const entry = convertSingleEntry({
|
|
16496
17148
|
entryRaw,
|
|
16497
17149
|
reader,
|
|
@@ -16517,9 +17169,9 @@ var getCompoundV2DataConverter = (lender, chainId, prices, additionalYields, tok
|
|
|
16517
17169
|
expectedNumberOfCalls
|
|
16518
17170
|
];
|
|
16519
17171
|
};
|
|
16520
|
-
function getReader(lender, chainId) {
|
|
17172
|
+
function getReader(lender, chainId, unitSeconds) {
|
|
16521
17173
|
if (isVenusType(lender)) {
|
|
16522
|
-
return (x, t) => readVTokenMetadata(x, t);
|
|
17174
|
+
return (x, t) => readVTokenMetadata(x, t, unitSeconds);
|
|
16523
17175
|
}
|
|
16524
17176
|
if (lender === Lender.MOONWELL) {
|
|
16525
17177
|
return (x, t) => parseMoonwellMarket(x, t);
|
|
@@ -16528,13 +17180,18 @@ function getReader(lender, chainId) {
|
|
|
16528
17180
|
return (x, t) => readSumerCTokenMetadata(x, t);
|
|
16529
17181
|
}
|
|
16530
17182
|
if (lender === Lender.LODESTAR || lender === Lender.TENDER) {
|
|
16531
|
-
return (x, t) => readLodestarCTokenMetadata(x);
|
|
17183
|
+
return (x, t) => readLodestarCTokenMetadata(x, t, unitSeconds);
|
|
16532
17184
|
}
|
|
16533
17185
|
if (lender === Lender.CREAM_FINANCE && (chainId === Chain.POLYGON_MAINNET || chainId === Chain.ARBITRUM_ONE)) {
|
|
16534
|
-
return (x, t) => readCreamV2CTokenMetadata(x, t);
|
|
17186
|
+
return (x, t) => readCreamV2CTokenMetadata(x, t, unitSeconds);
|
|
16535
17187
|
}
|
|
16536
|
-
if (lender === Lender.COMPOUND_V2 || lender === Lender.FLUX_FINANCE || lender === Lender.WE_PIGGY || lender === Lender.CREAM_FINANCE || lender === Lender.CAPY_FI || lender === Lender.GAMMA
|
|
16537
|
-
|
|
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
|
|
17189
|
+
// `CreamLensAbi` branch in publicCallBuild.ts `getCall`. A lender in that
|
|
17190
|
+
// branch and missing here builds fine and then dies in the converter with
|
|
17191
|
+
// `reader is not a function`, which is not a length mismatch and so is not
|
|
17192
|
+
// caught by the parser's own guard.
|
|
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) {
|
|
17194
|
+
return (x, t) => readCompoundV2CTokenMetadata(x, t, unitSeconds);
|
|
16538
17195
|
}
|
|
16539
17196
|
}
|
|
16540
17197
|
|
|
@@ -19123,7 +19780,7 @@ var buildFluidCall = (chainId, _lender) => {
|
|
|
19123
19780
|
// src/lending/public-data/fluid/apiData.ts
|
|
19124
19781
|
var FLUID_API_BASE = "https://api.fluid.instadapp.io/v2";
|
|
19125
19782
|
var SUPPORTED_CHAINS = /* @__PURE__ */ new Set(["1", "56", "137", "8453", "9745", "42161"]);
|
|
19126
|
-
var
|
|
19783
|
+
var TTL_MS2 = 6e4;
|
|
19127
19784
|
var ZERO_ADDRESS4 = "0x0000000000000000000000000000000000000000";
|
|
19128
19785
|
var cache = {};
|
|
19129
19786
|
var inflight = /* @__PURE__ */ new Map();
|
|
@@ -19171,7 +19828,7 @@ var parseChainPayload = (raw) => {
|
|
|
19171
19828
|
var fetchFluidApiData = async (chainId) => {
|
|
19172
19829
|
if (!SUPPORTED_CHAINS.has(chainId)) return void 0;
|
|
19173
19830
|
const hit = cache[chainId];
|
|
19174
|
-
if (hit && Date.now() - hit.at <
|
|
19831
|
+
if (hit && Date.now() - hit.at < TTL_MS2) return hit.data;
|
|
19175
19832
|
const pending = inflight.get(chainId);
|
|
19176
19833
|
if (pending) return pending;
|
|
19177
19834
|
const run = (async () => {
|
|
@@ -19205,14 +19862,14 @@ var DEX_RESOLVER_FALLBACK = {
|
|
|
19205
19862
|
};
|
|
19206
19863
|
var dexResolverFor = (chainId) => fluidResolvers()?.[chainId]?.dexResolver ?? DEX_RESOLVER_FALLBACK[chainId];
|
|
19207
19864
|
var ZERO_ADDRESS5 = "0x0000000000000000000000000000000000000000";
|
|
19208
|
-
var
|
|
19865
|
+
var TTL_MS3 = 6e4;
|
|
19209
19866
|
var cache2 = {};
|
|
19210
19867
|
var inflight2 = /* @__PURE__ */ new Map();
|
|
19211
19868
|
var fetchFluidDexState = async (chainId, multicallRetry, extraDexAddresses = []) => {
|
|
19212
19869
|
const resolver = dexResolverFor(chainId);
|
|
19213
19870
|
if (!resolver) return void 0;
|
|
19214
19871
|
const hit = cache2[chainId];
|
|
19215
|
-
if (hit && Date.now() - hit.at <
|
|
19872
|
+
if (hit && Date.now() - hit.at < TTL_MS3) return hit.data;
|
|
19216
19873
|
const pending = inflight2.get(chainId);
|
|
19217
19874
|
if (pending) return pending;
|
|
19218
19875
|
const run = (async () => {
|
|
@@ -20215,7 +20872,7 @@ function buildLenderCall(chainId, lender) {
|
|
|
20215
20872
|
if (isGearboxV3(lender)) return buildGearboxCall(chainId);
|
|
20216
20873
|
return [];
|
|
20217
20874
|
}
|
|
20218
|
-
function getLenderDataConverter(lender, chainId, prices, additionalYields, tokenList = {}) {
|
|
20875
|
+
function getLenderDataConverter(lender, chainId, prices, additionalYields, tokenList = {}, unitSeconds) {
|
|
20219
20876
|
if (isAaveV2Type(lender))
|
|
20220
20877
|
return getAaveV2ReservesDataConverter(
|
|
20221
20878
|
lender,
|
|
@@ -20263,7 +20920,8 @@ function getLenderDataConverter(lender, chainId, prices, additionalYields, token
|
|
|
20263
20920
|
chainId,
|
|
20264
20921
|
prices,
|
|
20265
20922
|
additionalYields,
|
|
20266
|
-
tokenList
|
|
20923
|
+
tokenList,
|
|
20924
|
+
unitSeconds
|
|
20267
20925
|
);
|
|
20268
20926
|
if (isEulerType(lender))
|
|
20269
20927
|
return getEulerV2ReservesDataConverter(
|
|
@@ -20404,6 +21062,16 @@ var getLenderPublicData = async (chainId, lenders, prices, additionalYields, mul
|
|
|
20404
21062
|
}
|
|
20405
21063
|
const invalidLenders = [];
|
|
20406
21064
|
let lenderData = {};
|
|
21065
|
+
const rateUnitSeconds = /* @__PURE__ */ new Map();
|
|
21066
|
+
await Promise.all(
|
|
21067
|
+
validLenders.filter((l) => isCompoundV2Type(l)).map(async (l) => {
|
|
21068
|
+
try {
|
|
21069
|
+
rateUnitSeconds.set(l, await resolveRateUnitSeconds(chainId, l));
|
|
21070
|
+
} catch {
|
|
21071
|
+
rateUnitSeconds.set(l, void 0);
|
|
21072
|
+
}
|
|
21073
|
+
})
|
|
21074
|
+
);
|
|
20407
21075
|
let currentSlice = 0;
|
|
20408
21076
|
for (const lender of validLenders) {
|
|
20409
21077
|
const [converter, sliceLength] = getLenderDataConverter(
|
|
@@ -20411,7 +21079,8 @@ var getLenderPublicData = async (chainId, lenders, prices, additionalYields, mul
|
|
|
20411
21079
|
chainId,
|
|
20412
21080
|
prices,
|
|
20413
21081
|
additionalYields,
|
|
20414
|
-
list
|
|
21082
|
+
list,
|
|
21083
|
+
rateUnitSeconds.get(lender)
|
|
20415
21084
|
);
|
|
20416
21085
|
if (sliceLength > 0) {
|
|
20417
21086
|
try {
|
|
@@ -20620,16 +21289,16 @@ var LKG_TTL_SEC = 30 * 60;
|
|
|
20620
21289
|
var lastGood = /* @__PURE__ */ new Map();
|
|
20621
21290
|
async function fetchTopAndBookWithFallback(source, chainId, marketId, nowSec9) {
|
|
20622
21291
|
const key3 = `${chainId}:${marketId}`;
|
|
20623
|
-
let
|
|
21292
|
+
let fresh2 = null;
|
|
20624
21293
|
if (source.getTopAndBook) {
|
|
20625
|
-
|
|
21294
|
+
fresh2 = await source.getTopAndBook(marketId, MIDNIGHT_BOOK_LEVELS).catch(() => null);
|
|
20626
21295
|
} else {
|
|
20627
21296
|
const top = await source.getBookTop(marketId).catch(() => null);
|
|
20628
|
-
if (top)
|
|
21297
|
+
if (top) fresh2 = { top, book: { bids: [], asks: [] } };
|
|
20629
21298
|
}
|
|
20630
|
-
if (
|
|
20631
|
-
lastGood.set(key3, { top:
|
|
20632
|
-
return { top:
|
|
21299
|
+
if (fresh2) {
|
|
21300
|
+
lastGood.set(key3, { top: fresh2.top, book: fresh2.book, at: nowSec9 });
|
|
21301
|
+
return { top: fresh2.top, book: fresh2.book };
|
|
20633
21302
|
}
|
|
20634
21303
|
const cached = lastGood.get(key3);
|
|
20635
21304
|
if (cached && nowSec9 - cached.at <= LKG_TTL_SEC) {
|
|
@@ -21401,21 +22070,21 @@ var LKG_TTL_SEC2 = 30 * 60;
|
|
|
21401
22070
|
var lastGood2 = /* @__PURE__ */ new Map();
|
|
21402
22071
|
async function fetchTopAndBookWithFallback2(source, chainId, config, nowSec9) {
|
|
21403
22072
|
const key3 = `${chainId}:${config.termRepoId}`;
|
|
21404
|
-
let
|
|
22073
|
+
let fresh2 = null;
|
|
21405
22074
|
if (source.getTopAndBook) {
|
|
21406
|
-
|
|
22075
|
+
fresh2 = await source.getTopAndBook(config, TERM_BOOK_LEVELS).catch(() => null);
|
|
21407
22076
|
} else {
|
|
21408
22077
|
const top = await source.getBookTop(config).catch(() => null);
|
|
21409
|
-
if (top)
|
|
22078
|
+
if (top) fresh2 = { top, book: { bids: [], asks: [] }, auction: null };
|
|
21410
22079
|
}
|
|
21411
|
-
if (
|
|
22080
|
+
if (fresh2) {
|
|
21412
22081
|
lastGood2.set(key3, {
|
|
21413
|
-
top:
|
|
21414
|
-
book:
|
|
21415
|
-
auction:
|
|
22082
|
+
top: fresh2.top,
|
|
22083
|
+
book: fresh2.book,
|
|
22084
|
+
auction: fresh2.auction ?? null,
|
|
21416
22085
|
at: nowSec9
|
|
21417
22086
|
});
|
|
21418
|
-
return { top:
|
|
22087
|
+
return { top: fresh2.top, book: fresh2.book, auction: fresh2.auction ?? null };
|
|
21419
22088
|
}
|
|
21420
22089
|
const cached = lastGood2.get(key3);
|
|
21421
22090
|
if (cached && nowSec9 - cached.at <= LKG_TTL_SEC2) {
|
|
@@ -23025,10 +23694,10 @@ function refreshLiveMarkets(chainId, source) {
|
|
|
23025
23694
|
const running = refreshInFlight.get(chainId);
|
|
23026
23695
|
if (running) return running;
|
|
23027
23696
|
lastRefreshAttempt.set(chainId, Date.now());
|
|
23028
|
-
const p = source.getChainMarkets(chainId).then((
|
|
23029
|
-
if (!
|
|
23697
|
+
const p = source.getChainMarkets(chainId).then((fresh2) => {
|
|
23698
|
+
if (!fresh2) return;
|
|
23030
23699
|
const nowSec9 = Math.floor(Date.now() / 1e3);
|
|
23031
|
-
const live =
|
|
23700
|
+
const live = fresh2.filter((m) => m.config.maturity > nowSec9);
|
|
23032
23701
|
lastGood3.set(chainId, { markets: live, at: nowSec9 });
|
|
23033
23702
|
rememberMarkets(chainId, live);
|
|
23034
23703
|
}).catch(() => void 0).finally(() => refreshInFlight.delete(chainId));
|
|
@@ -28930,439 +29599,6 @@ var buildAaveV2UserCall = (chainId, lender, account) => {
|
|
|
28930
29599
|
}
|
|
28931
29600
|
}
|
|
28932
29601
|
};
|
|
28933
|
-
var MULTICALL_DEFAULT_BATCH_SIZE = 4096;
|
|
28934
|
-
var CELO_MULTICALL_ADDRESS = "0x633987602DE5C4F337e3DbF265303A1080324204";
|
|
28935
|
-
var BNB_MULTICALL_ADDRESS = "0x963Df249eD09c358A4819E39d9Cd5736c3087184";
|
|
28936
|
-
var MANTLE_MULTICALL_ADDRESS = "0x2A51f2F647E1883F88C992244dEd171238693107";
|
|
28937
|
-
var ARBITRUM_ONE_MULTICALL_ADDRESS = "0xadF885960B47eA2CD9B55E6DAc6B42b7Cb2806dB";
|
|
28938
|
-
var LINEA_MULTICALL_ADDRESS = "0xac1cE734566f390A94b00eb9bf561c2625BF44ea";
|
|
28939
|
-
var AVALANCHE_MULTICALL_ADDRESS = "0x0139141Cd4Ee88dF3Cdb65881D411bAE271Ef0C2";
|
|
28940
|
-
var BASE_MULTICALL_ADDRESS = "0x091e99cb1C49331a94dD62755D168E941AbD0693";
|
|
28941
|
-
var BLAST_MULTICALL_ADDRESS = "0xdC7f370de7631cE9e2c2e1DCDA6B3B5744Cf4705";
|
|
28942
|
-
var TAIKO_MULTICALL_ADDRESS = "0x8E24CfC19c6C00c524353CB8816f5f1c2F33c201";
|
|
28943
|
-
var HEMI_MULTICALL_ADDRESS = "0x352A86168e6988A1aDF9A15Cb00017AAd3B67155";
|
|
28944
|
-
var GNOSIS_MULTICALL_ADDRESS = "0x4dfa9a980efE4802E969AC33968E3d6E59B8a19e";
|
|
28945
|
-
var MODE_MULTICALL_ADDRESS = "0xAB39cE30D98a59DFDa40A630b074170800bfF179";
|
|
28946
|
-
var FANTOM_MULTICALL_ADDRESS = "0xDb51CffFf3B989d0cB6b58AbF173371b6F2d0D24";
|
|
28947
|
-
var SCROLL_MULTICALL_ADDRESS = "0x3b615B1AC55bc34e51a81D3dea67467F32bcb8C2";
|
|
28948
|
-
var SHAPE_MULTICALL_ADDRESS = "0x356A450B32f5030ae7083702b86FaFbBe7490411";
|
|
28949
|
-
var SONIC_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
|
|
28950
|
-
var INK_MULTICALL_ADDRESS = "0xA0fCec583AeE6176527C07B198e5561722332014";
|
|
28951
|
-
var METIS_MULTICALL_ADDRESS = "0x7a59ddbB76521E8982Fa3A08598C9a83b14A6C07";
|
|
28952
|
-
var IOTA_MULTICALL_ADDRESS = "0x9683D433621A83aA7dd290106e1da85251317F55";
|
|
28953
|
-
var KAVA_MULTICALL_ADDRESS = "0x8B741B0D79BE80E135C880F7583d427B4D41F015";
|
|
28954
|
-
var SAGA_MULTICALL_ADDRESS = "0x743E03cceB4af2efA3CC76838f6E8B50B63F184c";
|
|
28955
|
-
var CYBER_MULTICALL_ADDRESS = "0x906d6eB9CF8f64e100e44f8f491b833a8d40B530";
|
|
28956
|
-
var METAL_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
|
|
28957
|
-
var ZERO_MULTICALL_ADDRESS = "0x9CA4dcb2505fbf536F6c54AA0a77C79f4fBC35C0";
|
|
28958
|
-
var BOB_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
|
|
28959
|
-
var WORLDCHAIN_MULTICALL_ADDRESS = "0x0a22c04215c97E3F532F4eF30e0aD9458792dAB9";
|
|
28960
|
-
var LISK_MULTICALL_ADDRESS = "0xE3dbcD53f4Ce1b06Ab200f4912BD35672e68f1FA";
|
|
28961
|
-
var REDSTONE_MULTICALL_ADDRESS = "0xd57B52452a0FDfE3ff8e0A40Bd10D00D0bfe0723";
|
|
28962
|
-
var MANTA_MULTICALL_ADDRESS = "0x52dFC0D9960F11A9Ca9FF616e791B91188446a60";
|
|
28963
|
-
var ZORA_MULTICALL_ADDRESS = "0xA51c76bEE6746cB487a7e9312E43e2b8f4A37C15";
|
|
28964
|
-
var CORE_MULTICALL_ADDRESS = "0xFe9F82D820757787895Da00B1dBD35c3B8b04894";
|
|
28965
|
-
var MORPH_MULTICALL_ADDRESS = "0xAcD82113982479B25E7c1D09858F0130921Dbbca";
|
|
28966
|
-
var TELOS_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
|
|
28967
|
-
var MULTICALL_ADDRESS = {
|
|
28968
|
-
[Chain.OP_MAINNET]: "0x1F98415757620B543A52E61c46B32eB19261F984",
|
|
28969
|
-
[Chain.POLYGON_MAINNET]: "0x1F98415757620B543A52E61c46B32eB19261F984",
|
|
28970
|
-
[Chain.ETHEREUM_MAINNET]: "0x1F98415757620B543A52E61c46B32eB19261F984",
|
|
28971
|
-
[Chain.ARBITRUM_ONE]: ARBITRUM_ONE_MULTICALL_ADDRESS,
|
|
28972
|
-
[Chain.BASE]: BASE_MULTICALL_ADDRESS,
|
|
28973
|
-
[Chain.CELO_MAINNET]: CELO_MULTICALL_ADDRESS,
|
|
28974
|
-
[Chain.BNB_SMART_CHAIN_MAINNET]: BNB_MULTICALL_ADDRESS,
|
|
28975
|
-
[Chain.MANTLE]: MANTLE_MULTICALL_ADDRESS,
|
|
28976
|
-
[Chain.BLAST]: BLAST_MULTICALL_ADDRESS,
|
|
28977
|
-
[Chain.LINEA]: LINEA_MULTICALL_ADDRESS,
|
|
28978
|
-
[Chain.AVALANCHE_C_CHAIN]: AVALANCHE_MULTICALL_ADDRESS,
|
|
28979
|
-
[Chain.TAIKO_ALETHIA]: TAIKO_MULTICALL_ADDRESS,
|
|
28980
|
-
[Chain.HEMI_NETWORK]: HEMI_MULTICALL_ADDRESS,
|
|
28981
|
-
[Chain.GNOSIS]: GNOSIS_MULTICALL_ADDRESS,
|
|
28982
|
-
[Chain.CORE_BLOCKCHAIN_MAINNET]: CORE_MULTICALL_ADDRESS,
|
|
28983
|
-
[Chain.METIS_ANDROMEDA_MAINNET]: METIS_MULTICALL_ADDRESS,
|
|
28984
|
-
[Chain.MODE]: MODE_MULTICALL_ADDRESS,
|
|
28985
|
-
[Chain.INK]: INK_MULTICALL_ADDRESS,
|
|
28986
|
-
[Chain.IOTA_EVM]: IOTA_MULTICALL_ADDRESS,
|
|
28987
|
-
[Chain.SONIC_MAINNET]: SONIC_MULTICALL_ADDRESS,
|
|
28988
|
-
[Chain.FANTOM_OPERA]: FANTOM_MULTICALL_ADDRESS,
|
|
28989
|
-
[Chain.SCROLL]: SCROLL_MULTICALL_ADDRESS,
|
|
28990
|
-
[Chain.SHAPE]: SHAPE_MULTICALL_ADDRESS,
|
|
28991
|
-
[Chain.CYBER_MAINNET]: CYBER_MULTICALL_ADDRESS,
|
|
28992
|
-
[Chain.ZORA]: ZORA_MULTICALL_ADDRESS,
|
|
28993
|
-
[Chain.MANTA_PACIFIC_MAINNET]: MANTA_MULTICALL_ADDRESS,
|
|
28994
|
-
[Chain.REDSTONE]: REDSTONE_MULTICALL_ADDRESS,
|
|
28995
|
-
[Chain.KAVA]: KAVA_MULTICALL_ADDRESS,
|
|
28996
|
-
[Chain.METAL_L2]: METAL_MULTICALL_ADDRESS,
|
|
28997
|
-
[Chain.LISK]: LISK_MULTICALL_ADDRESS,
|
|
28998
|
-
[Chain.BOB]: BOB_MULTICALL_ADDRESS,
|
|
28999
|
-
[Chain.ZERO_NETWORK]: ZERO_MULTICALL_ADDRESS,
|
|
29000
|
-
[Chain.SAGA]: SAGA_MULTICALL_ADDRESS,
|
|
29001
|
-
[Chain.MORPH]: MORPH_MULTICALL_ADDRESS,
|
|
29002
|
-
[Chain.TELOS_EVM_MAINNET]: TELOS_MULTICALL_ADDRESS,
|
|
29003
|
-
[Chain.WORLD_CHAIN]: WORLDCHAIN_MULTICALL_ADDRESS
|
|
29004
|
-
};
|
|
29005
|
-
|
|
29006
|
-
// src/utils/multicall.ts
|
|
29007
|
-
var { isArray } = lodash;
|
|
29008
|
-
var maxRetries = 3;
|
|
29009
|
-
var MULTICALL_FAILURE = "0x";
|
|
29010
|
-
var isFailedCall = (value) => value === void 0 || value === null || value === MULTICALL_FAILURE;
|
|
29011
|
-
var MULTICALL_REPAIR_ROUNDS = 3;
|
|
29012
|
-
var MAX_CALLS_PER_SHARD = 300;
|
|
29013
|
-
var ONE_REQUEST_BATCH_BYTES = 1e6;
|
|
29014
|
-
var MAX_INFLIGHT_REQUESTS = 6;
|
|
29015
|
-
var HEDGE_DELAY_MS = 1200;
|
|
29016
|
-
var SHARD_TIMEOUT_MS = 4e3;
|
|
29017
|
-
var MIN_ADAPTIVE_SHARD = 25;
|
|
29018
|
-
var ADAPTIVE_CAP_TTL_MS = 6e4;
|
|
29019
|
-
var endpointCallCap = /* @__PURE__ */ new Map();
|
|
29020
|
-
var capFor = (url, requested) => {
|
|
29021
|
-
const hit = endpointCallCap.get(url);
|
|
29022
|
-
if (!hit) return requested;
|
|
29023
|
-
if (Date.now() - hit.at > ADAPTIVE_CAP_TTL_MS) {
|
|
29024
|
-
endpointCallCap.delete(url);
|
|
29025
|
-
return requested;
|
|
29026
|
-
}
|
|
29027
|
-
return Math.min(requested, hit.calls);
|
|
29028
|
-
};
|
|
29029
|
-
var noteEndpointRefusal = (url, calls) => {
|
|
29030
|
-
if (calls <= MIN_ADAPTIVE_SHARD) return;
|
|
29031
|
-
const next = Math.max(MIN_ADAPTIVE_SHARD, Math.floor(calls / 2));
|
|
29032
|
-
const current = endpointCallCap.get(url);
|
|
29033
|
-
if (current && Date.now() - current.at <= ADAPTIVE_CAP_TTL_MS && current.calls <= next)
|
|
29034
|
-
return;
|
|
29035
|
-
endpointCallCap.set(url, { calls: next, at: Date.now() });
|
|
29036
|
-
};
|
|
29037
|
-
var DETERMINISTIC_ERROR_NAMES = /* @__PURE__ */ new Set([
|
|
29038
|
-
"ContractFunctionRevertedError",
|
|
29039
|
-
"RawContractError",
|
|
29040
|
-
"AbiDecodingZeroDataError",
|
|
29041
|
-
"AbiDecodingDataSizeTooSmallError",
|
|
29042
|
-
"AbiFunctionNotFoundError"
|
|
29043
|
-
]);
|
|
29044
|
-
var isDeterministicCallError = (error) => {
|
|
29045
|
-
let err = error;
|
|
29046
|
-
for (let depth = 0; err && depth < 8; depth++) {
|
|
29047
|
-
if (DETERMINISTIC_ERROR_NAMES.has(err.name)) return true;
|
|
29048
|
-
const message = String(err.shortMessage ?? err.message ?? "").toLowerCase();
|
|
29049
|
-
if (message.includes("execution reverted") || message.includes("returned no data"))
|
|
29050
|
-
return true;
|
|
29051
|
-
err = err.cause;
|
|
29052
|
-
}
|
|
29053
|
-
return false;
|
|
29054
|
-
};
|
|
29055
|
-
var REPAIR_BACKOFF_BASE_MS = 100;
|
|
29056
|
-
var REPAIR_BACKOFF_JITTER_MS = 60;
|
|
29057
|
-
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));
|
|
29058
|
-
var backoffForRound = (round) => REPAIR_BACKOFF_BASE_MS * 2 ** round + Math.random() * REPAIR_BACKOFF_JITTER_MS;
|
|
29059
|
-
var endpointUrl = (client, rpcId) => client?.transport?.url ?? `rpc#${rpcId}`;
|
|
29060
|
-
var resolveEndpoint = (chainId, getEvmClient17, startRpcId, tried, maxProbe = 12, timeoutMs) => {
|
|
29061
|
-
let fallback = null;
|
|
29062
|
-
for (let probe = 0; probe < maxProbe; probe++) {
|
|
29063
|
-
const rpcId = startRpcId + probe;
|
|
29064
|
-
let client;
|
|
29065
|
-
try {
|
|
29066
|
-
client = getEvmClient17(chainId, rpcId, { timeoutMs });
|
|
29067
|
-
} catch {
|
|
29068
|
-
break;
|
|
29069
|
-
}
|
|
29070
|
-
const url = endpointUrl(client, rpcId);
|
|
29071
|
-
if (!tried?.has(url)) {
|
|
29072
|
-
tried?.add(url);
|
|
29073
|
-
return { client, rpcId, url, reused: false };
|
|
29074
|
-
}
|
|
29075
|
-
fallback ??= { client, rpcId, url, reused: true };
|
|
29076
|
-
}
|
|
29077
|
-
return fallback;
|
|
29078
|
-
};
|
|
29079
|
-
var toSlots = (returnData, allowFailure) => {
|
|
29080
|
-
if (!allowFailure)
|
|
29081
|
-
return returnData.map((value) => ({ value, permanent: false }));
|
|
29082
|
-
return returnData.map(
|
|
29083
|
-
({ result, status, error }) => status === "success" ? { value: result, permanent: false } : {
|
|
29084
|
-
value: MULTICALL_FAILURE,
|
|
29085
|
-
permanent: isDeterministicCallError(error)
|
|
29086
|
-
}
|
|
29087
|
-
);
|
|
29088
|
-
};
|
|
29089
|
-
var recordPermanentFailures = (slots, offset, collector) => {
|
|
29090
|
-
if (!collector) return;
|
|
29091
|
-
for (let i = 0; i < slots.length; i++) {
|
|
29092
|
-
if (slots[i].permanent) collector.add(offset + i);
|
|
29093
|
-
}
|
|
29094
|
-
};
|
|
29095
|
-
var repairFailedSlots = async (chainId, contracts, slots, getEvmClient17, nextRpcId, batchSize, logs, rounds = MULTICALL_REPAIR_ROUNDS, options) => {
|
|
29096
|
-
let searchFrom = nextRpcId;
|
|
29097
|
-
for (let round = 0; round < rounds; round++) {
|
|
29098
|
-
const failedIdx = [];
|
|
29099
|
-
for (let i = 0; i < slots.length; i++) {
|
|
29100
|
-
if (isFailedCall(slots[i].value) && !slots[i].permanent) failedIdx.push(i);
|
|
29101
|
-
}
|
|
29102
|
-
if (failedIdx.length === 0) return slots;
|
|
29103
|
-
const endpoint = resolveEndpoint(
|
|
29104
|
-
chainId,
|
|
29105
|
-
getEvmClient17,
|
|
29106
|
-
searchFrom,
|
|
29107
|
-
options?.tried
|
|
29108
|
-
);
|
|
29109
|
-
if (!endpoint) {
|
|
29110
|
-
if (logs)
|
|
29111
|
-
console.log(
|
|
29112
|
-
`multicall repair: no usable endpoint for chain ${chainId}, giving up with ${failedIdx.length} failed slots`
|
|
29113
|
-
);
|
|
29114
|
-
return slots;
|
|
29115
|
-
}
|
|
29116
|
-
searchFrom = endpoint.rpcId + 1;
|
|
29117
|
-
await sleep(backoffForRound(round));
|
|
29118
|
-
try {
|
|
29119
|
-
const returnData = await endpoint.client.multicall({
|
|
29120
|
-
allowFailure: true,
|
|
29121
|
-
batchSize,
|
|
29122
|
-
contracts: failedIdx.map((i) => contracts[i])
|
|
29123
|
-
});
|
|
29124
|
-
let repaired = 0;
|
|
29125
|
-
returnData.forEach((entry, k) => {
|
|
29126
|
-
const idx = failedIdx[k];
|
|
29127
|
-
if (entry?.status === "success") {
|
|
29128
|
-
slots[idx] = { value: entry.result, permanent: false };
|
|
29129
|
-
repaired++;
|
|
29130
|
-
} else if (isDeterministicCallError(entry?.error)) {
|
|
29131
|
-
slots[idx].permanent = true;
|
|
29132
|
-
}
|
|
29133
|
-
});
|
|
29134
|
-
if (repaired === 0)
|
|
29135
|
-
options?.onEndpointFailure?.({
|
|
29136
|
-
chainId,
|
|
29137
|
-
url: endpoint.url,
|
|
29138
|
-
rpcId: endpoint.rpcId,
|
|
29139
|
-
kind: "slots"
|
|
29140
|
-
});
|
|
29141
|
-
} catch (error) {
|
|
29142
|
-
options?.onEndpointFailure?.({
|
|
29143
|
-
chainId,
|
|
29144
|
-
url: endpoint.url,
|
|
29145
|
-
rpcId: endpoint.rpcId,
|
|
29146
|
-
kind: "transport"
|
|
29147
|
-
});
|
|
29148
|
-
if (logs)
|
|
29149
|
-
console.log(
|
|
29150
|
-
`error in multicall failure-repair round ${round} chain ${chainId}`,
|
|
29151
|
-
error
|
|
29152
|
-
);
|
|
29153
|
-
}
|
|
29154
|
-
}
|
|
29155
|
-
return slots;
|
|
29156
|
-
};
|
|
29157
|
-
var multicallShardedAbiArray = async (chainId, abi, calls, getEvmClient17, poolSize, retries = maxRetries, allowFailure = true, batchSize = MULTICALL_DEFAULT_BATCH_SIZE, logs = false, retryFailed = false, permanentFailures, options) => {
|
|
29158
|
-
const abiIsArray = isArray(abi[0]);
|
|
29159
|
-
const contracts = calls.map(({ address, name, params }, i) => ({
|
|
29160
|
-
abi: abiIsArray ? abi?.[i] : abi,
|
|
29161
|
-
address,
|
|
29162
|
-
functionName: name,
|
|
29163
|
-
args: params
|
|
29164
|
-
}));
|
|
29165
|
-
const requestBytes = batchSize < MULTICALL_DEFAULT_BATCH_SIZE ? batchSize : ONE_REQUEST_BATCH_BYTES;
|
|
29166
|
-
const workerBudget = Math.max(1, Math.floor(MAX_INFLIGHT_REQUESTS / 2));
|
|
29167
|
-
const workers = Math.max(1, Math.min(poolSize, workerBudget));
|
|
29168
|
-
const shardSize = Math.max(
|
|
29169
|
-
1,
|
|
29170
|
-
Math.min(MAX_CALLS_PER_SHARD, Math.ceil(contracts.length / workers))
|
|
29171
|
-
);
|
|
29172
|
-
const batches = [];
|
|
29173
|
-
for (let i = 0; i < contracts.length; i += shardSize) {
|
|
29174
|
-
batches.push({ start: i, items: contracts.slice(i, i + shardSize) });
|
|
29175
|
-
}
|
|
29176
|
-
const results = new Array(contracts.length);
|
|
29177
|
-
const request = async (endpoint, items) => {
|
|
29178
|
-
try {
|
|
29179
|
-
const returnData = await endpoint.client.multicall({
|
|
29180
|
-
allowFailure,
|
|
29181
|
-
batchSize: requestBytes,
|
|
29182
|
-
contracts: items
|
|
29183
|
-
});
|
|
29184
|
-
const slots = toSlots(returnData, allowFailure);
|
|
29185
|
-
if (allowFailure && slots.length > 0 && slots.every((s) => isFailedCall(s.value) && !s.permanent)) {
|
|
29186
|
-
if (logs)
|
|
29187
|
-
console.log(
|
|
29188
|
-
`sharded multicall: rpc ${endpoint.rpcId} answered ${items.length} calls with nothing`
|
|
29189
|
-
);
|
|
29190
|
-
options?.onEndpointFailure?.({
|
|
29191
|
-
chainId,
|
|
29192
|
-
url: endpoint.url,
|
|
29193
|
-
rpcId: endpoint.rpcId,
|
|
29194
|
-
kind: "slots"
|
|
29195
|
-
});
|
|
29196
|
-
noteEndpointRefusal(endpoint.url, items.length);
|
|
29197
|
-
return null;
|
|
29198
|
-
}
|
|
29199
|
-
return slots;
|
|
29200
|
-
} catch (error) {
|
|
29201
|
-
if (logs) console.log("error in sharded multicall request", error);
|
|
29202
|
-
options?.onEndpointFailure?.({
|
|
29203
|
-
chainId,
|
|
29204
|
-
url: endpoint.url,
|
|
29205
|
-
rpcId: endpoint.rpcId,
|
|
29206
|
-
kind: "transport"
|
|
29207
|
-
});
|
|
29208
|
-
noteEndpointRefusal(endpoint.url, items.length);
|
|
29209
|
-
return null;
|
|
29210
|
-
}
|
|
29211
|
-
};
|
|
29212
|
-
const firstUsable = (attempts) => new Promise((resolve) => {
|
|
29213
|
-
let pending = attempts.length;
|
|
29214
|
-
let settled = false;
|
|
29215
|
-
const lose = () => {
|
|
29216
|
-
if (!settled && --pending === 0) resolve(null);
|
|
29217
|
-
};
|
|
29218
|
-
for (const attempt of attempts) {
|
|
29219
|
-
attempt.then((won) => {
|
|
29220
|
-
if (settled) return;
|
|
29221
|
-
if (won) {
|
|
29222
|
-
settled = true;
|
|
29223
|
-
resolve(won);
|
|
29224
|
-
} else lose();
|
|
29225
|
-
}, lose);
|
|
29226
|
-
}
|
|
29227
|
-
});
|
|
29228
|
-
const attemptHedged = async (items, startRpcId, tried) => {
|
|
29229
|
-
const primary = resolveEndpoint(
|
|
29230
|
-
chainId,
|
|
29231
|
-
getEvmClient17,
|
|
29232
|
-
startRpcId,
|
|
29233
|
-
tried,
|
|
29234
|
-
12,
|
|
29235
|
-
SHARD_TIMEOUT_MS
|
|
29236
|
-
);
|
|
29237
|
-
if (!primary) {
|
|
29238
|
-
if (logs)
|
|
29239
|
-
console.log(
|
|
29240
|
-
`sharded multicall: no untried endpoint left for chain ${chainId}`
|
|
29241
|
-
);
|
|
29242
|
-
return null;
|
|
29243
|
-
}
|
|
29244
|
-
let timer;
|
|
29245
|
-
let hedgeStarted = false;
|
|
29246
|
-
let beginHedge = () => {
|
|
29247
|
-
};
|
|
29248
|
-
const hedged = new Promise((resolve) => {
|
|
29249
|
-
beginHedge = () => {
|
|
29250
|
-
if (hedgeStarted) return;
|
|
29251
|
-
hedgeStarted = true;
|
|
29252
|
-
clearTimeout(timer);
|
|
29253
|
-
const alt = resolveEndpoint(
|
|
29254
|
-
chainId,
|
|
29255
|
-
getEvmClient17,
|
|
29256
|
-
primary.rpcId + 1,
|
|
29257
|
-
tried,
|
|
29258
|
-
12,
|
|
29259
|
-
SHARD_TIMEOUT_MS
|
|
29260
|
-
);
|
|
29261
|
-
if (!alt) return resolve(null);
|
|
29262
|
-
const altItems = items.slice(0, capFor(alt.url, items.length));
|
|
29263
|
-
if (altItems.length < items.length) return resolve(null);
|
|
29264
|
-
request(alt, items).then(
|
|
29265
|
-
(slots) => resolve(slots ? { slots, rpcId: alt.rpcId } : null)
|
|
29266
|
-
);
|
|
29267
|
-
};
|
|
29268
|
-
});
|
|
29269
|
-
timer = setTimeout(() => beginHedge(), HEDGE_DELAY_MS);
|
|
29270
|
-
const direct = request(primary, items).then((slots) => {
|
|
29271
|
-
if (slots) return { slots, rpcId: primary.rpcId };
|
|
29272
|
-
beginHedge();
|
|
29273
|
-
return null;
|
|
29274
|
-
});
|
|
29275
|
-
const won = await firstUsable([direct, hedged]);
|
|
29276
|
-
clearTimeout(timer);
|
|
29277
|
-
return won;
|
|
29278
|
-
};
|
|
29279
|
-
const runBatch = async (batch, rpcId, attemptsLeft, tried) => {
|
|
29280
|
-
if (!batch.items.length) return;
|
|
29281
|
-
const won = await attemptHedged(batch.items, rpcId, tried);
|
|
29282
|
-
if (!won) {
|
|
29283
|
-
if (attemptsLeft > 0 && batch.items.length > 1) {
|
|
29284
|
-
const half = Math.ceil(batch.items.length / 2);
|
|
29285
|
-
await sleep(backoffForRound(0));
|
|
29286
|
-
await runBatch(
|
|
29287
|
-
{ start: batch.start, items: batch.items.slice(0, half) },
|
|
29288
|
-
rpcId,
|
|
29289
|
-
attemptsLeft - 1,
|
|
29290
|
-
tried
|
|
29291
|
-
);
|
|
29292
|
-
await runBatch(
|
|
29293
|
-
{ start: batch.start + half, items: batch.items.slice(half) },
|
|
29294
|
-
rpcId + 1,
|
|
29295
|
-
attemptsLeft - 1,
|
|
29296
|
-
tried
|
|
29297
|
-
);
|
|
29298
|
-
}
|
|
29299
|
-
return;
|
|
29300
|
-
}
|
|
29301
|
-
let slots = won.slots;
|
|
29302
|
-
if (allowFailure && retryFailed) {
|
|
29303
|
-
slots = await repairFailedSlots(
|
|
29304
|
-
chainId,
|
|
29305
|
-
batch.items,
|
|
29306
|
-
slots,
|
|
29307
|
-
getEvmClient17,
|
|
29308
|
-
won.rpcId + 1,
|
|
29309
|
-
requestBytes,
|
|
29310
|
-
logs,
|
|
29311
|
-
MULTICALL_REPAIR_ROUNDS,
|
|
29312
|
-
{ tried, onEndpointFailure: options?.onEndpointFailure }
|
|
29313
|
-
);
|
|
29314
|
-
}
|
|
29315
|
-
recordPermanentFailures(slots, batch.start, permanentFailures);
|
|
29316
|
-
for (let j = 0; j < slots.length; j++) {
|
|
29317
|
-
results[batch.start + j] = slots[j].value;
|
|
29318
|
-
}
|
|
29319
|
-
};
|
|
29320
|
-
let cursor = 0;
|
|
29321
|
-
const worker = async (workerId) => {
|
|
29322
|
-
while (true) {
|
|
29323
|
-
const idx = cursor++;
|
|
29324
|
-
if (idx >= batches.length) break;
|
|
29325
|
-
const batch = batches[idx];
|
|
29326
|
-
const tried = /* @__PURE__ */ new Set();
|
|
29327
|
-
const start = resolveEndpoint(
|
|
29328
|
-
chainId,
|
|
29329
|
-
getEvmClient17,
|
|
29330
|
-
workerId,
|
|
29331
|
-
void 0,
|
|
29332
|
-
12,
|
|
29333
|
-
SHARD_TIMEOUT_MS
|
|
29334
|
-
);
|
|
29335
|
-
const cap = start ? capFor(start.url, batch.items.length) : batch.items.length;
|
|
29336
|
-
for (let off = 0; off < batch.items.length; off += cap) {
|
|
29337
|
-
await runBatch(
|
|
29338
|
-
{
|
|
29339
|
-
start: batch.start + off,
|
|
29340
|
-
items: batch.items.slice(off, off + cap)
|
|
29341
|
-
},
|
|
29342
|
-
workerId,
|
|
29343
|
-
retries,
|
|
29344
|
-
tried
|
|
29345
|
-
);
|
|
29346
|
-
}
|
|
29347
|
-
}
|
|
29348
|
-
};
|
|
29349
|
-
await Promise.all(
|
|
29350
|
-
Array.from(
|
|
29351
|
-
{ length: Math.min(workers, batches.length) },
|
|
29352
|
-
(_3, w) => worker(w)
|
|
29353
|
-
)
|
|
29354
|
-
);
|
|
29355
|
-
return results;
|
|
29356
|
-
};
|
|
29357
|
-
function prepareMulticallInputs(abi, calls) {
|
|
29358
|
-
const abiIsArray = isArray(abi[0]);
|
|
29359
|
-
return calls.map(({ address, name, params }, i) => ({
|
|
29360
|
-
address,
|
|
29361
|
-
functionName: name,
|
|
29362
|
-
params: params || [],
|
|
29363
|
-
abi: abiIsArray ? abi[i] : abi
|
|
29364
|
-
}));
|
|
29365
|
-
}
|
|
29366
29602
|
var POSITION_LENS_V6 = "0x110ff05D2822DBBe1a5404d2a485267e2Ed962C6";
|
|
29367
29603
|
var LENS_FAMILY = {
|
|
29368
29604
|
COMPOUND_V2: 1,
|
|
@@ -41649,7 +41885,7 @@ function unflattenLenderData(pools) {
|
|
|
41649
41885
|
}
|
|
41650
41886
|
return result;
|
|
41651
41887
|
}
|
|
41652
|
-
var getLenderUserDataResult = async (chainId, queriesRaw,
|
|
41888
|
+
var getLenderUserDataResult = async (chainId, queriesRaw, getEvmClient18, allowFailure = true, batchSize = MULTICALL_DEFAULT_BATCH_SIZE, retries = 3, logs = false, concurrency = 1, permanentFailures, onEndpointFailure) => {
|
|
41653
41889
|
const queries = organizeUserQueries(queriesRaw);
|
|
41654
41890
|
const builtCalls = await Promise.all(
|
|
41655
41891
|
queries.map(async (query3) => {
|
|
@@ -41659,7 +41895,7 @@ var getLenderUserDataResult = async (chainId, queriesRaw, getEvmClient17, allowF
|
|
|
41659
41895
|
query3.lender,
|
|
41660
41896
|
query3.account,
|
|
41661
41897
|
query3.params,
|
|
41662
|
-
|
|
41898
|
+
getEvmClient18
|
|
41663
41899
|
);
|
|
41664
41900
|
return callData.map((call) => ({ call, abi: call.abi ?? abi }));
|
|
41665
41901
|
})
|
|
@@ -41669,7 +41905,7 @@ var getLenderUserDataResult = async (chainId, queriesRaw, getEvmClient17, allowF
|
|
|
41669
41905
|
chainId,
|
|
41670
41906
|
calls.map((call) => call.abi),
|
|
41671
41907
|
calls.map((call) => call.call),
|
|
41672
|
-
|
|
41908
|
+
getEvmClient18,
|
|
41673
41909
|
concurrency,
|
|
41674
41910
|
retries,
|
|
41675
41911
|
allowFailure,
|
|
@@ -59358,7 +59594,7 @@ var fetchSiloVaults = async (chainId, prices = {}, tokenList = {}, options) => {
|
|
|
59358
59594
|
|
|
59359
59595
|
// src/vaults/euler-earn/entityLabels.ts
|
|
59360
59596
|
var LABELS_BASE = "https://raw.githubusercontent.com/euler-xyz/euler-labels/master";
|
|
59361
|
-
var
|
|
59597
|
+
var TTL_MS4 = 30 * 60 * 1e3;
|
|
59362
59598
|
var cache3 = /* @__PURE__ */ new Map();
|
|
59363
59599
|
var inflight4 = /* @__PURE__ */ new Map();
|
|
59364
59600
|
async function fetchChainEntities(chainId) {
|
|
@@ -59384,7 +59620,7 @@ async function fetchChainEntities(chainId) {
|
|
|
59384
59620
|
}
|
|
59385
59621
|
async function fetchEulerEntityNames(chainId) {
|
|
59386
59622
|
const hit = cache3.get(chainId);
|
|
59387
|
-
if (hit && Date.now() - hit.at <=
|
|
59623
|
+
if (hit && Date.now() - hit.at <= TTL_MS4) return hit.map;
|
|
59388
59624
|
const running = inflight4.get(chainId);
|
|
59389
59625
|
if (running) return running;
|
|
59390
59626
|
const p = fetchChainEntities(chainId).then((map) => {
|