@1delta/margin-fetcher 0.0.196 → 0.0.197

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import './chunk-PR4QN5HX.js';
4
4
  import { Lender, isAaveType, isCompoundV3, isMultiMarket, isInit, isMorphoType, isCompoundV2Type, isVenusType, isSumerType, AAVE_V3_LENDERS, AAVE_V2_LENDERS, isAaveV2Type, isAaveV32Type, isAaveV3Type, isEulerType, isYLDR, isCompoundV3Type, isTectonicType, isBenqiType, isLista } from '@1delta/lender-registry';
5
5
  export { isAaveType, isAaveV2Type, isAaveV32Type, isAaveV3Type, isCompoundV3, isCompoundV3Type, isInit, isMorphoType, isMultiMarket, isYLDR } from '@1delta/lender-registry';
6
6
  import lodash from 'lodash';
7
- import { getEvmChain, multicallRetry, getEvmClient, getEvmClientUniversal } from '@1delta/providers';
7
+ import { getEvmChain, multicallRetryUniversal, getEvmClient, getEvmClientUniversal } from '@1delta/providers';
8
8
  import { MorphoLensAbi, MorphoBlueAbi } from '@1delta/abis';
9
9
  export { MorphoLensAbi } from '@1delta/abis';
10
10
  import { prepareDebitDataMulticall, prepareLenderDebitMulticall, parseDebitDataResult, parseLenderDebitResult, getPermit2ContractAddress, InitMarginAddresses } from '@1delta/calldata-sdk';
@@ -17998,7 +17998,7 @@ var getAbi = (lender) => {
17998
17998
  if (isCompoundV2Type(lender)) return VenusLensAbi;
17999
17999
  return [];
18000
18000
  };
18001
- var getLenderPublicData = async (chainId, lenders, prices, additionalYields, multicallRetry3, tokenList = async () => {
18001
+ var getLenderPublicData = async (chainId, lenders, prices, additionalYields, multicallRetry, tokenList = async () => {
18002
18002
  return {};
18003
18003
  }) => {
18004
18004
  let calls = [];
@@ -18009,16 +18009,12 @@ var getLenderPublicData = async (chainId, lenders, prices, additionalYields, mul
18009
18009
  calls = [...calls, ...mappedCalls];
18010
18010
  }
18011
18011
  const [rawResults, list] = await Promise.all([
18012
- multicallRetry3(
18013
- chainId,
18014
- calls.map((call) => call.call),
18015
- calls.map((call) => call.abi),
18016
- chainId === Chain.ETHEREUM_MAINNET ? 500 : void 0
18017
- // default size
18018
- // retries = 3
18019
- // provider = 0
18020
- // allowFailure = false
18021
- ),
18012
+ multicallRetry({
18013
+ chain: chainId,
18014
+ calls: calls.map((call) => call.call),
18015
+ abi: calls.map((call) => call.abi),
18016
+ batchSize: chainId === Chain.ETHEREUM_MAINNET ? 500 : void 0
18017
+ }),
18022
18018
  await tokenList()
18023
18019
  ]);
18024
18020
  const invalidLenders = [];
@@ -18126,7 +18122,7 @@ function lenderCanUseApi(lender, chainId) {
18126
18122
  }
18127
18123
  return false;
18128
18124
  }
18129
- var getLenderPublicDataAll = async (chainId, lenders, prices, additionalYields, multicallRetry3, tokenList, includeUnlistedMorphoMarkets = false) => {
18125
+ var getLenderPublicDataAll = async (chainId, lenders, prices, additionalYields, multicallRetry, tokenList, includeUnlistedMorphoMarkets = false) => {
18130
18126
  const lendersApi = lenders.filter((l) => lenderCanUseApi(l, chainId));
18131
18127
  const lendersOnChain = lenders.filter((l) => !lenderCanUseApi(l, chainId));
18132
18128
  const onChain = getLenderPublicData(
@@ -18134,7 +18130,7 @@ var getLenderPublicDataAll = async (chainId, lenders, prices, additionalYields,
18134
18130
  lendersOnChain,
18135
18131
  prices,
18136
18132
  additionalYields,
18137
- multicallRetry3,
18133
+ multicallRetry,
18138
18134
  tokenList
18139
18135
  );
18140
18136
  const api = getLenderPublicDataViaApi(
@@ -24732,20 +24728,20 @@ function parseMergedResult(chainId, rawResults, prepared, lenderState) {
24732
24728
  }
24733
24729
 
24734
24730
  // src/lending/user-data/with-permissions/e2e.ts
24735
- async function getMergedUserData(chainId, balanceQueries, permissionParams, lenderState, multicallRetry3, batchSize = MULTICALL_DEFAULT_BATCH_SIZE, maxRetries2 = 3, tokenApprovalParams) {
24731
+ async function getMergedUserData(chainId, balanceQueries, permissionParams, lenderState, multicallRetry, batchSize = MULTICALL_DEFAULT_BATCH_SIZE, maxRetries2 = 3, tokenApprovalParams) {
24736
24732
  const prepared = await prepareMergedMulticallParams(
24737
24733
  chainId,
24738
24734
  balanceQueries,
24739
24735
  permissionParams,
24740
24736
  tokenApprovalParams
24741
24737
  );
24742
- const rawResults = await multicallRetry3(
24743
- chainId,
24744
- prepared.calls,
24745
- prepared.abis,
24738
+ const rawResults = await multicallRetry({
24739
+ chain: chainId,
24740
+ calls: prepared.calls,
24741
+ abi: prepared.abis,
24746
24742
  batchSize,
24747
- maxRetries2
24748
- );
24743
+ maxRetries: maxRetries2
24744
+ });
24749
24745
  return parseMergedResult(chainId, rawResults, prepared, lenderState);
24750
24746
  }
24751
24747
  function toCompoundV2Shares(entry, amount) {
@@ -29057,16 +29053,16 @@ var fetchMainPrices = async (chainIds, rpcOverrides, lists = {}, retries = 3, ba
29057
29053
  ...CometAbi,
29058
29054
  ...VenusLensAbi
29059
29055
  ];
29060
- const result = await multicallRetry(
29061
- chainId,
29062
- allCalls,
29063
- abis,
29056
+ const result = await multicallRetryUniversal({
29057
+ chain: chainId,
29058
+ calls: allCalls,
29059
+ abi: abis,
29064
29060
  batchSize,
29065
- retries,
29066
- 0,
29061
+ maxRetries: retries,
29062
+ providerId: 0,
29067
29063
  allowFailure,
29068
- rpcOverrides
29069
- );
29064
+ overrdies: rpcOverrides
29065
+ });
29070
29066
  return {
29071
29067
  chainId,
29072
29068
  result,
@@ -30365,6 +30361,13 @@ var aaveFetcher = {
30365
30361
  parse: parseAaveResults2,
30366
30362
  getAbi: getAaveAbi
30367
30363
  };
30364
+ function morphoApiAvailable(chainId) {
30365
+ if (chainId === Chain.SONEIUM) return false;
30366
+ if (chainId === Chain.HEMI_NETWORK) return false;
30367
+ if (chainId === Chain.BERACHAIN) return false;
30368
+ if (chainId === Chain.SEI_NETWORK) return false;
30369
+ return true;
30370
+ }
30368
30371
  function generateMarketId(oracle, loanAsset, collateralAsset) {
30369
30372
  return `${oracle}${loanAsset}${collateralAsset}`.replace(/0x/gi, "").toUpperCase();
30370
30373
  }
@@ -30456,6 +30459,111 @@ function parseMorphoResults2(data, meta, context) {
30456
30459
  function getMorphoAbi() {
30457
30460
  return ProxyOracleAbi;
30458
30461
  }
30462
+ var MORPHO_GRAPHQL_URL = "https://blue-api.morpho.org/graphql";
30463
+ var PRICE_QUERY = (first, skip, chainId) => `
30464
+ query GetMarketPrices {
30465
+ markets(first: ${first}, skip: ${skip}, where: {
30466
+ chainId_in: [${chainId}],
30467
+ whitelisted: true
30468
+ },
30469
+ orderBy: SupplyAssetsUsd,
30470
+ orderDirection: Desc
30471
+ ) {
30472
+ items {
30473
+ uniqueKey
30474
+ oracleAddress
30475
+ loanAsset {
30476
+ address
30477
+ decimals
30478
+ priceUsd
30479
+ }
30480
+ collateralAsset {
30481
+ address
30482
+ decimals
30483
+ priceUsd
30484
+ }
30485
+ state {
30486
+ price
30487
+ }
30488
+ }
30489
+ }
30490
+ }
30491
+ `;
30492
+ async function fetchMorphoGraphQLPrices(chainId) {
30493
+ if (!morphoApiAvailable(chainId)) return null;
30494
+ try {
30495
+ const pages = chainId === "1" ? [
30496
+ fetch(MORPHO_GRAPHQL_URL, {
30497
+ method: "POST",
30498
+ headers: { "Content-Type": "application/json" },
30499
+ body: JSON.stringify({
30500
+ query: PRICE_QUERY(200, 0, chainId)
30501
+ })
30502
+ }).then((r) => r.json()),
30503
+ fetch(MORPHO_GRAPHQL_URL, {
30504
+ method: "POST",
30505
+ headers: { "Content-Type": "application/json" },
30506
+ body: JSON.stringify({
30507
+ query: PRICE_QUERY(200, 200, chainId)
30508
+ })
30509
+ }).then((r) => r.json())
30510
+ ] : [
30511
+ fetch(MORPHO_GRAPHQL_URL, {
30512
+ method: "POST",
30513
+ headers: { "Content-Type": "application/json" },
30514
+ body: JSON.stringify({
30515
+ query: PRICE_QUERY(200, 0, chainId)
30516
+ })
30517
+ }).then((r) => r.json())
30518
+ ];
30519
+ const results = await Promise.all(pages);
30520
+ const allMarkets = [];
30521
+ for (const result of results) {
30522
+ const items = result?.data?.markets?.items;
30523
+ if (!Array.isArray(items)) return null;
30524
+ allMarkets.push(...items);
30525
+ }
30526
+ if (allMarkets.length === 0) return null;
30527
+ const entries = [];
30528
+ for (const market of allMarkets) {
30529
+ if (!market.collateralAsset) continue;
30530
+ const oracle = market.oracleAddress;
30531
+ const loanAsset = market.loanAsset.address.toLowerCase();
30532
+ const collateralAsset = market.collateralAsset.address.toLowerCase();
30533
+ const marketId = market.uniqueKey?.replace(/^0x/i, "").toUpperCase() ?? generateMarketId(oracle, loanAsset, collateralAsset);
30534
+ const lenderKey = generateMorphoLenderKey(marketId);
30535
+ const loanPriceUSD = market.loanAsset.priceUsd;
30536
+ const collateralPriceUSD = market.collateralAsset.priceUsd;
30537
+ const statePrice = market.state?.price;
30538
+ const oracleRatio = statePrice != null ? formatMorphoPrice(
30539
+ statePrice,
30540
+ market.loanAsset.decimals,
30541
+ market.collateralAsset.decimals
30542
+ ) : 0;
30543
+ if (collateralPriceUSD != null && collateralPriceUSD > 0) {
30544
+ entries.push({
30545
+ asset: collateralAsset,
30546
+ price: oracleRatio || collateralPriceUSD,
30547
+ priceUSD: collateralPriceUSD,
30548
+ marketUid: createMarketUid(chainId, lenderKey, collateralAsset),
30549
+ targetLender: lenderKey
30550
+ });
30551
+ }
30552
+ if (loanPriceUSD != null && loanPriceUSD > 0) {
30553
+ entries.push({
30554
+ asset: loanAsset,
30555
+ price: oracleRatio > 0 ? 1 / oracleRatio : loanPriceUSD,
30556
+ priceUSD: loanPriceUSD,
30557
+ marketUid: createMarketUid(chainId, lenderKey, loanAsset),
30558
+ targetLender: lenderKey
30559
+ });
30560
+ }
30561
+ }
30562
+ return entries.length > 0 ? entries : null;
30563
+ } catch {
30564
+ return null;
30565
+ }
30566
+ }
30459
30567
  var morphoFetcher = {
30460
30568
  getCalls: getMorphoCalls2,
30461
30569
  parse: parseMorphoResults2,
@@ -30806,162 +30914,447 @@ var eulerV2Fetcher = {
30806
30914
  };
30807
30915
 
30808
30916
  // src/prices/oracle-prices/fetchOraclePrices.ts
30809
- async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3, batchSize = void 0, allowFailure = true, basePrices = {}, morphoMarketOverrides, listaMarketOverrides) {
30917
+ function countFailures(data, offset, count) {
30918
+ let failures = 0;
30919
+ for (let i = offset; i < offset + count; i++) {
30920
+ if (data[i] === "0x" || data[i] === void 0) failures++;
30921
+ }
30922
+ return failures;
30923
+ }
30924
+ function safeGetCalls(fetcherName, fn, errors) {
30925
+ try {
30926
+ return fn();
30927
+ } catch (e) {
30928
+ errors[fetcherName] = e instanceof Error ? e.message : String(e);
30929
+ return [];
30930
+ }
30931
+ }
30932
+ function buildGroup(fetcherName, results, parse, abi) {
30933
+ const group = {
30934
+ fetcherName,
30935
+ calls: [],
30936
+ abi,
30937
+ trackers: []
30938
+ };
30939
+ for (const fr of results) {
30940
+ group.trackers.push({
30941
+ lender: fr.lender,
30942
+ meta: fr.meta,
30943
+ offset: group.calls.length,
30944
+ count: fr.calls.length,
30945
+ parse
30946
+ });
30947
+ group.calls.push(...fr.calls);
30948
+ }
30949
+ return group;
30950
+ }
30951
+ function isFailed(r) {
30952
+ return r === "0x" || r === void 0;
30953
+ }
30954
+ async function executeGroup(group, chainId, chainBatchSize, retries, allowFailure, rpcOverrides, failRetries = 2) {
30955
+ if (group.calls.length === 0) {
30956
+ return { results: [] };
30957
+ }
30958
+ try {
30959
+ const results = await multicallRetryUniversal({
30960
+ chain: chainId,
30961
+ calls: group.calls,
30962
+ abi: group.abi,
30963
+ batchSize: chainBatchSize,
30964
+ maxRetries: retries,
30965
+ providerId: void 0,
30966
+ allowFailure,
30967
+ overrdies: rpcOverrides,
30968
+ logErrors: true
30969
+ });
30970
+ let failedIndices = results.map((r, i) => isFailed(r) ? i : -1).filter((i) => i >= 0);
30971
+ for (let round = 0; round < failRetries && failedIndices.length > 0; round++) {
30972
+ const retryCalls = failedIndices.map((i) => group.calls[i]);
30973
+ try {
30974
+ const retryResults = await multicallRetryUniversal({
30975
+ chain: chainId,
30976
+ calls: retryCalls,
30977
+ abi: group.abi,
30978
+ batchSize: chainBatchSize,
30979
+ maxRetries: retries,
30980
+ providerId: round + 1,
30981
+ // rotate to next RPC provider
30982
+ allowFailure,
30983
+ overrdies: rpcOverrides,
30984
+ logErrors: true
30985
+ });
30986
+ const stillFailed = [];
30987
+ for (let j = 0; j < failedIndices.length; j++) {
30988
+ if (!isFailed(retryResults[j])) {
30989
+ results[failedIndices[j]] = retryResults[j];
30990
+ } else {
30991
+ stillFailed.push(failedIndices[j]);
30992
+ }
30993
+ }
30994
+ failedIndices = stillFailed;
30995
+ } catch {
30996
+ break;
30997
+ }
30998
+ }
30999
+ const failCount = results.filter((r) => isFailed(r)).length;
31000
+ const allFailed = failCount === results.length && results.length > 0;
31001
+ return {
31002
+ results,
31003
+ error: allFailed ? `All ${group.calls.length} calls returned 0x (${group.fetcherName})` : void 0
31004
+ };
31005
+ } catch (e) {
31006
+ const msg = e instanceof Error ? e.message : String(e);
31007
+ return {
31008
+ results: Array(group.calls.length).fill("0x"),
31009
+ error: `multicall threw: ${msg.slice(0, 200)}`
31010
+ };
31011
+ }
31012
+ }
31013
+ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3, batchSize = void 0, allowFailure = true, basePrices = {}, morphoMarketOverrides, listaMarketOverrides, stalenessThresholdSeconds = 3600, onlyFetchers) {
31014
+ const totalStart = Date.now();
30810
31015
  const result = {};
30811
- const combinedAbi = [
30812
- ...AaveOracleAbi,
30813
- ...ProxyOracleAbi,
30814
- ...CompoundV2OracleAbi,
30815
- ...ChainlinkAggregatorAbi,
30816
- ...vaultLensAbi
30817
- ];
30818
31016
  const chainPromises = chainIds.map(async (chainId) => {
31017
+ const chainStart = Date.now();
30819
31018
  const chainResult = {};
30820
31019
  const tokenList = lists[chainId] ?? {};
30821
- const aaveResults = aaveFetcher.getCalls(chainId);
30822
- const compoundV2Results = compoundV2Fetcher.getCalls(chainId);
30823
- const compoundV3Results = compoundV3Fetcher.getCalls(chainId);
30824
- const listaResults = listaFetcher.getCalls(chainId, {
30825
- marketOverrides: listaMarketOverrides
30826
- });
30827
- const eulerResults = eulerV2Fetcher.getCalls(chainId);
30828
- const morphoResults = morphoFetcher.getCalls(chainId, {
30829
- marketOverrides: morphoMarketOverrides
30830
- });
30831
- const allCalls = [];
30832
- const fetcherTracker = [];
30833
- for (const fr of aaveResults) {
30834
- fetcherTracker.push({
30835
- lender: fr.lender,
30836
- meta: fr.meta,
30837
- offset: allCalls.length,
30838
- count: fr.calls.length,
30839
- parse: aaveFetcher.parse
30840
- });
30841
- allCalls.push(...fr.calls);
30842
- }
30843
- for (const fr of compoundV2Results) {
30844
- fetcherTracker.push({
30845
- lender: fr.lender,
30846
- meta: fr.meta,
30847
- offset: allCalls.length,
30848
- count: fr.calls.length,
30849
- parse: compoundV2Fetcher.parse
30850
- });
30851
- allCalls.push(...fr.calls);
30852
- }
30853
- for (const fr of compoundV3Results) {
30854
- fetcherTracker.push({
30855
- lender: fr.lender,
30856
- meta: fr.meta,
30857
- offset: allCalls.length,
30858
- count: fr.calls.length,
30859
- parse: compoundV3Fetcher.parse
30860
- });
30861
- allCalls.push(...fr.calls);
30862
- }
30863
- for (const fr of listaResults) {
30864
- fetcherTracker.push({
30865
- lender: fr.lender,
30866
- meta: fr.meta,
30867
- offset: allCalls.length,
30868
- count: fr.calls.length,
30869
- parse: listaFetcher.parse
30870
- });
30871
- allCalls.push(...fr.calls);
30872
- }
30873
- for (const fr of eulerResults) {
30874
- fetcherTracker.push({
30875
- lender: fr.lender,
30876
- meta: fr.meta,
30877
- offset: allCalls.length,
30878
- count: fr.calls.length,
30879
- parse: eulerV2Fetcher.parse
30880
- });
30881
- allCalls.push(...fr.calls);
30882
- }
30883
- for (const fr of morphoResults) {
30884
- fetcherTracker.push({
30885
- lender: fr.lender,
30886
- meta: fr.meta,
30887
- offset: allCalls.length,
30888
- count: fr.calls.length,
30889
- parse: morphoFetcher.parse
30890
- });
30891
- allCalls.push(...fr.calls);
30892
- }
30893
- if (allCalls.length === 0) {
30894
- return { chainId, data: chainResult };
31020
+ const getCallsErrors = {};
31021
+ const trackerDiags = [];
31022
+ const unresolvedMorphoMarkets = [];
31023
+ const staleFeeds = [];
31024
+ const multicallErrors = [];
31025
+ const active = onlyFetchers ? new Set(onlyFetchers.map((f) => f.toLowerCase())) : null;
31026
+ const isActive = (name) => !active || active.has(name);
31027
+ const aaveResults = isActive("aave") ? safeGetCalls(
31028
+ "aave",
31029
+ () => aaveFetcher.getCalls(chainId),
31030
+ getCallsErrors
31031
+ ) : [];
31032
+ const compoundV2Results = isActive("compoundv2") ? safeGetCalls(
31033
+ "compoundV2",
31034
+ () => compoundV2Fetcher.getCalls(chainId),
31035
+ getCallsErrors
31036
+ ) : [];
31037
+ const compoundV3Results = isActive("compoundv3") ? safeGetCalls(
31038
+ "compoundV3",
31039
+ () => compoundV3Fetcher.getCalls(chainId),
31040
+ getCallsErrors
31041
+ ) : [];
31042
+ const listaResults = isActive("lista") ? safeGetCalls(
31043
+ "lista",
31044
+ () => listaFetcher.getCalls(chainId, {
31045
+ marketOverrides: listaMarketOverrides
31046
+ }),
31047
+ getCallsErrors
31048
+ ) : [];
31049
+ const eulerResults = isActive("eulerv2") ? safeGetCalls(
31050
+ "eulerV2",
31051
+ () => eulerV2Fetcher.getCalls(chainId),
31052
+ getCallsErrors
31053
+ ) : [];
31054
+ const morphoResults = isActive("morpho") ? safeGetCalls(
31055
+ "morpho",
31056
+ () => morphoFetcher.getCalls(chainId, {
31057
+ marketOverrides: morphoMarketOverrides
31058
+ }),
31059
+ getCallsErrors
31060
+ ) : [];
31061
+ const aaveGroup = buildGroup(
31062
+ "aave",
31063
+ aaveResults,
31064
+ aaveFetcher.parse,
31065
+ AaveOracleAbi
31066
+ );
31067
+ const compoundV2Group = buildGroup(
31068
+ "compoundV2",
31069
+ compoundV2Results,
31070
+ compoundV2Fetcher.parse,
31071
+ CompoundV2OracleAbi
31072
+ );
31073
+ const compoundV3Group = buildGroup(
31074
+ "compoundV3",
31075
+ compoundV3Results,
31076
+ compoundV3Fetcher.parse,
31077
+ ChainlinkAggregatorAbi
31078
+ );
31079
+ const listaGroup = buildGroup(
31080
+ "lista",
31081
+ listaResults,
31082
+ listaFetcher.parse,
31083
+ ProxyOracleAbi
31084
+ );
31085
+ const eulerGroup = buildGroup(
31086
+ "eulerV2",
31087
+ eulerResults,
31088
+ eulerV2Fetcher.parse,
31089
+ vaultLensAbi
31090
+ );
31091
+ const morphoGroup = buildGroup(
31092
+ "morpho",
31093
+ morphoResults,
31094
+ morphoFetcher.parse,
31095
+ ProxyOracleAbi
31096
+ );
31097
+ const allGroups = [
31098
+ aaveGroup,
31099
+ compoundV2Group,
31100
+ compoundV3Group,
31101
+ listaGroup,
31102
+ eulerGroup,
31103
+ morphoGroup
31104
+ ];
31105
+ const totalCalls = allGroups.reduce((s, g) => s + g.calls.length, 0);
31106
+ if (totalCalls === 0) {
31107
+ const diag2 = {
31108
+ chainId,
31109
+ totalCalls: 0,
31110
+ totalFailedCalls: 0,
31111
+ totalParsedEntries: 0,
31112
+ durationMs: Date.now() - chainStart,
31113
+ trackers: [],
31114
+ getCallsErrors,
31115
+ unresolvedMorphoMarkets: [],
31116
+ staleFeeds: []
31117
+ };
31118
+ return { chainId, data: chainResult, diagnostic: diag2 };
30895
31119
  }
30896
- const multicallResult = await multicallRetry(
31120
+ const chainBatchSize = batchSize?.[chainId];
31121
+ const morphoGqlPromise = isActive("morpho") ? fetchMorphoGraphQLPrices(chainId) : Promise.resolve(null);
31122
+ const [
31123
+ aaveData,
31124
+ compoundV2Data,
31125
+ compoundV3Data,
31126
+ listaData,
31127
+ eulerData,
31128
+ morphoGqlEntries
31129
+ ] = await Promise.all([
31130
+ executeGroup(
31131
+ aaveGroup,
31132
+ chainId,
31133
+ chainBatchSize,
31134
+ retries,
31135
+ allowFailure,
31136
+ rpcOverrides
31137
+ ),
31138
+ executeGroup(
31139
+ compoundV2Group,
31140
+ chainId,
31141
+ chainBatchSize,
31142
+ retries,
31143
+ allowFailure,
31144
+ rpcOverrides
31145
+ ),
31146
+ executeGroup(
31147
+ compoundV3Group,
31148
+ chainId,
31149
+ chainBatchSize,
31150
+ retries,
31151
+ allowFailure,
31152
+ rpcOverrides
31153
+ ),
31154
+ executeGroup(
31155
+ listaGroup,
31156
+ chainId,
31157
+ chainBatchSize,
31158
+ retries,
31159
+ allowFailure,
31160
+ rpcOverrides
31161
+ ),
31162
+ executeGroup(
31163
+ eulerGroup,
31164
+ chainId,
31165
+ chainBatchSize,
31166
+ retries,
31167
+ allowFailure,
31168
+ rpcOverrides
31169
+ ),
31170
+ morphoGqlPromise
31171
+ ]);
31172
+ const morphoData = morphoGqlEntries != null ? { results: [], error: void 0 } : await executeGroup(
31173
+ morphoGroup,
30897
31174
  chainId,
30898
- allCalls,
30899
- combinedAbi,
30900
- batchSize?.[chainId],
31175
+ chainBatchSize,
30901
31176
  retries,
30902
- void 0,
30903
31177
  allowFailure,
30904
31178
  rpcOverrides
30905
31179
  );
31180
+ const useMorphoGql = morphoGqlEntries != null;
31181
+ const groupResults = [
31182
+ { group: aaveGroup, data: aaveData },
31183
+ { group: compoundV2Group, data: compoundV2Data },
31184
+ { group: compoundV3Group, data: compoundV3Data },
31185
+ { group: listaGroup, data: listaData },
31186
+ { group: eulerGroup, data: eulerData },
31187
+ ...useMorphoGql ? [] : [{ group: morphoGroup, data: morphoData }]
31188
+ ];
31189
+ for (const { group, data } of groupResults) {
31190
+ if (data.error) {
31191
+ multicallErrors.push(`[${group.fetcherName}] ${data.error}`);
31192
+ }
31193
+ }
30906
31194
  const usdPrices = { ...basePrices };
30907
- const parseTracker = (tracker, updatePrices = true) => {
30908
- const dataSlice = multicallResult.slice(
30909
- tracker.offset,
30910
- tracker.offset + tracker.count
30911
- );
30912
- const context = {
30913
- chainId,
30914
- usdPrices,
30915
- tokenList
30916
- };
30917
- const entries = tracker.parse(dataSlice, tracker.meta, context);
30918
- for (const entry of entries) {
30919
- const lender = entry.targetLender ?? tracker.lender;
30920
- if (!chainResult[lender]) {
30921
- chainResult[lender] = [];
30922
- }
30923
- chainResult[lender].push(entry);
30924
- if (updatePrices) {
30925
- const oracleKey = tokenList[entry.asset]?.assetGroup ?? `${chainId}-${entry.asset}`;
30926
- usdPrices[oracleKey] = entry.priceUSD;
30927
- usdPrices[entry.asset] = entry.priceUSD;
31195
+ const parseTrackers = (group, data, updatePrices = true, filter) => {
31196
+ const trackers = filter ? group.trackers.filter(filter) : group.trackers;
31197
+ for (const tracker of trackers) {
31198
+ const failedCalls = countFailures(data, tracker.offset, tracker.count);
31199
+ const diag2 = {
31200
+ lender: tracker.lender,
31201
+ callCount: tracker.count,
31202
+ failedCalls,
31203
+ parsedEntries: 0
31204
+ };
31205
+ try {
31206
+ const dataSlice = data.slice(
31207
+ tracker.offset,
31208
+ tracker.offset + tracker.count
31209
+ );
31210
+ const context = { chainId, usdPrices, tokenList };
31211
+ const entries = tracker.parse(dataSlice, tracker.meta, context);
31212
+ diag2.parsedEntries = entries.length;
31213
+ for (const entry of entries) {
31214
+ const lender = entry.targetLender ?? tracker.lender;
31215
+ if (!chainResult[lender]) {
31216
+ chainResult[lender] = [];
31217
+ }
31218
+ chainResult[lender].push(entry);
31219
+ if (updatePrices) {
31220
+ const oracleKey = tokenList[entry.asset]?.assetGroup ?? `${chainId}-${entry.asset}`;
31221
+ usdPrices[oracleKey] = entry.priceUSD;
31222
+ usdPrices[entry.asset] = entry.priceUSD;
31223
+ }
31224
+ }
31225
+ } catch (e) {
31226
+ diag2.parseError = e instanceof Error ? e.message : String(e);
30928
31227
  }
31228
+ trackerDiags.push(diag2);
30929
31229
  }
30930
31230
  };
30931
- const nonMorphoTrackers = fetcherTracker.filter(
30932
- (t) => t.parse !== morphoFetcher.parse
30933
- );
30934
- const aaveSourceTrackers = nonMorphoTrackers.filter(
30935
- (t) => t.parse === aaveFetcher.parse && !t.meta.baseAssetSource
31231
+ parseTrackers(
31232
+ aaveGroup,
31233
+ aaveData.results,
31234
+ true,
31235
+ (t) => !t.meta.baseAssetSource
30936
31236
  );
30937
- const aaveDependentTrackers = nonMorphoTrackers.filter(
30938
- (t) => t.parse === aaveFetcher.parse && t.meta.baseAssetSource
30939
- );
30940
- const otherTrackers = nonMorphoTrackers.filter(
30941
- (t) => t.parse !== aaveFetcher.parse
30942
- );
30943
- for (const tracker of aaveSourceTrackers) {
30944
- parseTracker(tracker);
30945
- }
30946
- for (const tracker of otherTrackers) {
30947
- parseTracker(tracker);
30948
- }
30949
- for (const tracker of aaveDependentTrackers) {
30950
- parseTracker(tracker);
31237
+ parseTrackers(compoundV2Group, compoundV2Data.results);
31238
+ parseTrackers(compoundV3Group, compoundV3Data.results);
31239
+ parseTrackers(listaGroup, listaData.results);
31240
+ parseTrackers(eulerGroup, eulerData.results);
31241
+ if (stalenessThresholdSeconds > 0) {
31242
+ const nowSeconds = Math.floor(Date.now() / 1e3);
31243
+ for (const tracker of compoundV3Group.trackers) {
31244
+ const meta = tracker.meta;
31245
+ for (let i = 0; i < tracker.count; i++) {
31246
+ const raw = compoundV3Data.results[tracker.offset + i];
31247
+ if (!raw || raw === "0x" || !Array.isArray(raw)) continue;
31248
+ const updatedAt = Number(raw[3]);
31249
+ if (updatedAt > 0) {
31250
+ const staleSeconds = nowSeconds - updatedAt;
31251
+ if (staleSeconds > stalenessThresholdSeconds) {
31252
+ const queryMeta = meta[i];
31253
+ staleFeeds.push({
31254
+ asset: queryMeta?.asset?.toLowerCase() ?? "unknown",
31255
+ lender: queryMeta?.lender ?? tracker.lender,
31256
+ oracle: queryMeta?.oracle ?? "unknown",
31257
+ staleSeconds
31258
+ });
31259
+ }
31260
+ }
31261
+ }
31262
+ }
30951
31263
  }
30952
- const morphoTrackers = fetcherTracker.filter(
30953
- (t) => t.parse === morphoFetcher.parse
31264
+ parseTrackers(
31265
+ aaveGroup,
31266
+ aaveData.results,
31267
+ true,
31268
+ (t) => !!t.meta.baseAssetSource
30954
31269
  );
30955
- for (const tracker of morphoTrackers) {
30956
- parseTracker(tracker, false);
31270
+ if (useMorphoGql) {
31271
+ const morphoGqlDiag = {
31272
+ lender: "MORPHO_BLUE (GraphQL)",
31273
+ callCount: 0,
31274
+ failedCalls: 0,
31275
+ parsedEntries: morphoGqlEntries.length
31276
+ };
31277
+ for (const entry of morphoGqlEntries) {
31278
+ const lender = entry.targetLender ?? "MORPHO_BLUE";
31279
+ if (!chainResult[lender]) chainResult[lender] = [];
31280
+ chainResult[lender].push(entry);
31281
+ }
31282
+ trackerDiags.push(morphoGqlDiag);
31283
+ } else {
31284
+ for (const tracker of morphoGroup.trackers) {
31285
+ const meta = tracker.meta;
31286
+ if (meta.markets) {
31287
+ for (const market of meta.markets) {
31288
+ const loanAsset = market.loanAsset?.toLowerCase();
31289
+ const collateralAsset = market.collateralAsset?.toLowerCase();
31290
+ const loanOracleKey = tokenList[loanAsset]?.assetGroup ?? `${chainId}-${loanAsset}`;
31291
+ const collateralOracleKey = tokenList[collateralAsset]?.assetGroup ?? `${chainId}-${collateralAsset}`;
31292
+ const hasLoanPrice = usdPrices[loanOracleKey] !== void 0 || usdPrices[loanAsset] !== void 0;
31293
+ const hasCollateralPrice = usdPrices[collateralOracleKey] !== void 0 || usdPrices[collateralAsset] !== void 0;
31294
+ if (!hasLoanPrice && !hasCollateralPrice) {
31295
+ unresolvedMorphoMarkets.push(
31296
+ `${market.oracle}:${loanAsset}/${collateralAsset}`
31297
+ );
31298
+ }
31299
+ }
31300
+ }
31301
+ }
31302
+ parseTrackers(morphoGroup, morphoData.results, false);
30957
31303
  }
30958
- return { chainId, data: chainResult };
31304
+ const totalFailedCalls = trackerDiags.reduce(
31305
+ (sum, d) => sum + d.failedCalls,
31306
+ 0
31307
+ );
31308
+ const totalParsedEntries = trackerDiags.reduce(
31309
+ (sum, d) => sum + d.parsedEntries,
31310
+ 0
31311
+ );
31312
+ const diag = {
31313
+ chainId,
31314
+ totalCalls,
31315
+ totalFailedCalls,
31316
+ totalParsedEntries,
31317
+ durationMs: Date.now() - chainStart,
31318
+ trackers: trackerDiags,
31319
+ getCallsErrors,
31320
+ chainError: multicallErrors.length > 0 ? multicallErrors.join("; ") : void 0,
31321
+ unresolvedMorphoMarkets,
31322
+ staleFeeds
31323
+ };
31324
+ return { chainId, data: chainResult, diagnostic: diag };
30959
31325
  });
30960
- const chainResults = await Promise.all(chainPromises);
30961
- for (const { chainId, data } of chainResults) {
30962
- result[chainId] = data;
31326
+ const settled = await Promise.allSettled(chainPromises);
31327
+ const chainDiagnostics = [];
31328
+ const failedChains = [];
31329
+ for (let i = 0; i < settled.length; i++) {
31330
+ const settlement = settled[i];
31331
+ const chainId = chainIds[i];
31332
+ if (settlement.status === "fulfilled") {
31333
+ const { data, diagnostic } = settlement.value;
31334
+ result[chainId] = data;
31335
+ chainDiagnostics.push(diagnostic);
31336
+ } else {
31337
+ failedChains.push(chainId);
31338
+ chainDiagnostics.push({
31339
+ chainId,
31340
+ totalCalls: 0,
31341
+ totalFailedCalls: 0,
31342
+ totalParsedEntries: 0,
31343
+ durationMs: 0,
31344
+ trackers: [],
31345
+ getCallsErrors: {},
31346
+ chainError: settlement.reason instanceof Error ? settlement.reason.message : String(settlement.reason),
31347
+ unresolvedMorphoMarkets: [],
31348
+ staleFeeds: []
31349
+ });
31350
+ }
30963
31351
  }
30964
- return result;
31352
+ const diagnostics = {
31353
+ chains: chainDiagnostics,
31354
+ totalDurationMs: Date.now() - totalStart,
31355
+ failedChains
31356
+ };
31357
+ return { prices: result, diagnostics };
30965
31358
  }
30966
31359
  var DEFAULT_PRIORITY = {
30967
31360
  chainPriority: [
@@ -31175,7 +31568,7 @@ var FLASHLOAN_ENABLED_MASK = BigInt(
31175
31568
  function getFlashLoanEnabled(data) {
31176
31569
  return (data & ~FLASHLOAN_ENABLED_MASK) !== BigInt(0);
31177
31570
  }
31178
- async function fetchFlashLiquidityForChain(chain, multicallRetry3, list = {}) {
31571
+ async function fetchFlashLiquidityForChain(chain, multicallRetry, list = {}) {
31179
31572
  let callLengths = {};
31180
31573
  let aaveAssets = {};
31181
31574
  let aaveCalls = [];
@@ -31290,15 +31683,15 @@ async function fetchFlashLiquidityForChain(chain, multicallRetry3, list = {}) {
31290
31683
  ...balancerV3Calls,
31291
31684
  ...uniswapV4Calls
31292
31685
  ];
31293
- const rawResults = await multicallRetry3(
31686
+ const rawResults = await multicallRetry({
31294
31687
  chain,
31295
31688
  calls,
31296
- FlashAbi,
31297
- DEFAULT_BATCH_SIZE,
31298
- 3,
31299
- 0,
31300
- false
31301
- );
31689
+ abi: FlashAbi,
31690
+ batchSize: DEFAULT_BATCH_SIZE,
31691
+ maxRetries: 3,
31692
+ providerId: 0,
31693
+ allowFailure: false
31694
+ });
31302
31695
  let liquidity = {};
31303
31696
  let currentOffset = 0;
31304
31697
  aaveProtocols.forEach((aave) => {