@1delta/margin-fetcher 0.0.221 → 0.0.222

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
@@ -6275,9 +6275,7 @@ globalThis[GLOBAL_LENDER_DATA_KEY] = {
6275
6275
  compoundV3Bulker: {},
6276
6276
  eulerConfigs: {},
6277
6277
  eulerVaults: {},
6278
- aaveV4Hubs: {},
6279
6278
  aaveV4Spokes: {},
6280
- aaveV4Reserves: {},
6281
6279
  aaveV4Oracles: {},
6282
6280
  aaveV4Peripherals: {}
6283
6281
  };
@@ -6304,15 +6302,18 @@ var initConfig = () => getGlobalData2()?.initConfig;
6304
6302
  var aaveOraclesConfig = () => getGlobalData2()?.aaveOraclesConfig;
6305
6303
  var eulerConfigs = () => getGlobalData2()?.eulerConfigs;
6306
6304
  var eulerVaults = () => getGlobalData2()?.eulerVaults;
6307
- var aaveV4Hubs = () => getGlobalData2()?.aaveV4Hubs;
6308
6305
  var aaveV4Spokes = () => getGlobalData2()?.aaveV4Spokes;
6309
- var aaveV4Reserves = () => getGlobalData2()?.aaveV4Reserves;
6310
6306
  var aaveV4Oracles = () => getGlobalData2()?.aaveV4Oracles;
6311
- function aaveV4SpokeLenderKey(baseHubLender, spoke) {
6312
- if (!spoke || spoke.length < 4 || !spoke.startsWith("0x")) {
6307
+ function aaveV4SpokeLenderKey(spoke) {
6308
+ if (!spoke || !spoke.startsWith("0x") || spoke.length !== 42) {
6313
6309
  throw new Error(`aaveV4SpokeLenderKey: invalid spoke address ${spoke}`);
6314
6310
  }
6315
- return `${baseHubLender}_${spoke.slice(2).toUpperCase()}`;
6311
+ return `AAVE_V4_${spoke.slice(2).toUpperCase()}`;
6312
+ }
6313
+ function parseAaveV4SpokeLenderKey(lenderKey) {
6314
+ const match = lenderKey.match(/^AAVE_V4_([0-9A-F]{40})$/);
6315
+ if (!match) return void 0;
6316
+ return { spokeAddrLower: "0x" + match[1].toLowerCase() };
6316
6317
  }
6317
6318
  var getListUrl = (chainId) => `https://raw.githubusercontent.com/1delta-DAO/token-lists/main/${chainId}.json`;
6318
6319
  async function fetchTokenList(chainId) {
@@ -7544,9 +7545,10 @@ var getLendersForChain = (c) => {
7544
7545
  if (data[c]?.length > 0) lenders.push(l);
7545
7546
  });
7546
7547
  }
7547
- Object.entries(aaveV4Spokes() ?? {}).forEach(([l, data]) => {
7548
- if (data[c]?.length > 0) lenders.push(l);
7549
- });
7548
+ const v4ChainSpokes = aaveV4Spokes()?.[c] ?? {};
7549
+ for (const spokeAddr of Object.keys(v4ChainSpokes)) {
7550
+ lenders.push(aaveV4SpokeLenderKey(spokeAddr));
7551
+ }
7550
7552
  return lenders;
7551
7553
  };
7552
7554
  var filterLendersByProtocol = (allLenders, protocolList) => {
@@ -17925,156 +17927,106 @@ var MAX_HUB_ASSETS = 25;
17925
17927
  function isValidAddress(addr) {
17926
17928
  return !!addr && addr !== "0x" && addr.length > 2;
17927
17929
  }
17928
- function getSpokeReserves(reservesMap, spokeAddr) {
17929
- return reservesMap[spokeAddr.toLowerCase()] ?? reservesMap[spokeAddr] ?? [];
17930
- }
17931
- function getReserveAssetId(entry) {
17932
- if (typeof entry === "object" && entry != null) {
17933
- const v = entry.assetId;
17934
- if (typeof v === "number") return v;
17935
- }
17936
- return void 0;
17937
- }
17938
17930
  function getDynamicConfigCount(spokeEntry) {
17939
- const max = spokeEntry.dynamicConfigKeyMax ?? 0;
17931
+ const max = spokeEntry?.dynamicConfigKeyMax ?? 0;
17940
17932
  return max + 1;
17941
17933
  }
17934
+ function resolveSpokeEntry(chainId, lender) {
17935
+ const parsed = parseAaveV4SpokeLenderKey(lender);
17936
+ if (!parsed) return void 0;
17937
+ return aaveV4Spokes()?.[chainId]?.[parsed.spokeAddrLower];
17938
+ }
17939
+ function distinctHubsInOrder(reserves) {
17940
+ const seen = /* @__PURE__ */ new Set();
17941
+ const out = [];
17942
+ for (const r of reserves) {
17943
+ const h = (r?.hub ?? "").toLowerCase();
17944
+ if (!h || !isValidAddress(h)) continue;
17945
+ if (seen.has(h)) continue;
17946
+ seen.add(h);
17947
+ out.push(h);
17948
+ }
17949
+ return out;
17950
+ }
17942
17951
  var buildAaveV4LenderReserveCall = (chainId, lender) => {
17943
- const spokes = aaveV4Spokes()?.[lender]?.[chainId] ?? [];
17944
- const reservesMap = aaveV4Reserves()?.[lender]?.[chainId] ?? {};
17945
- if (spokes.length === 0) return [];
17952
+ const spokeEntry = resolveSpokeEntry(chainId, lender);
17953
+ if (!spokeEntry) return [];
17954
+ const spokeAddr = spokeEntry.spoke.toLowerCase();
17955
+ if (!isValidAddress(spokeAddr)) return [];
17956
+ const reserves = spokeEntry.reserves ?? [];
17957
+ const dynConfigCount = getDynamicConfigCount(spokeEntry);
17946
17958
  const calls = [];
17947
- for (const spokeEntry of spokes) {
17948
- if (!isValidAddress(spokeEntry.spoke)) continue;
17949
- const spokeAddr = spokeEntry.spoke;
17950
- const reserves = getSpokeReserves(reservesMap, spokeAddr);
17951
- const dynConfigCount = getDynamicConfigCount(spokeEntry);
17952
- for (const entry of reserves) {
17953
- const rid = typeof entry === "number" ? entry : entry.reserveId;
17954
- calls.push(
17955
- {
17956
- address: spokeAddr,
17957
- name: "getReserve",
17958
- params: [rid]
17959
- },
17960
- {
17961
- address: spokeAddr,
17962
- name: "getReserveConfig",
17963
- params: [rid]
17964
- },
17965
- {
17966
- address: spokeAddr,
17967
- name: "getReserveSuppliedAssets",
17968
- params: [rid]
17969
- },
17970
- {
17971
- address: spokeAddr,
17972
- name: "getReserveDebt",
17973
- params: [rid]
17974
- },
17975
- {
17976
- address: spokeAddr,
17977
- name: "getReserveTotalDebt",
17978
- params: [rid]
17979
- }
17980
- );
17981
- for (let key = 0; key < dynConfigCount; key++) {
17982
- calls.push({
17983
- address: spokeAddr,
17984
- name: "getDynamicReserveConfig",
17985
- params: [rid, key]
17986
- });
17987
- }
17988
- }
17989
- calls.push({
17990
- address: spokeAddr,
17991
- name: "getLiquidationConfig",
17992
- params: []
17993
- });
17994
- }
17995
- for (const spokeEntry of spokes) {
17996
- if (!isValidAddress(spokeEntry.spoke)) continue;
17997
- const reserves = getSpokeReserves(reservesMap, spokeEntry.spoke);
17998
- const rids = reserves.map(
17999
- (e) => typeof e === "number" ? e : e.reserveId
17959
+ for (const r of reserves) {
17960
+ const rid = r.reserveId;
17961
+ calls.push(
17962
+ { address: spokeAddr, name: "getReserve", params: [rid] },
17963
+ { address: spokeAddr, name: "getReserveConfig", params: [rid] },
17964
+ { address: spokeAddr, name: "getReserveSuppliedAssets", params: [rid] },
17965
+ { address: spokeAddr, name: "getReserveDebt", params: [rid] },
17966
+ { address: spokeAddr, name: "getReserveTotalDebt", params: [rid] }
18000
17967
  );
18001
- if (rids.length > 0 && isValidAddress(spokeEntry.oracle)) {
17968
+ for (let key = 0; key < dynConfigCount; key++) {
18002
17969
  calls.push({
18003
- address: spokeEntry.oracle,
18004
- name: "getReservesPrices",
18005
- params: [rids]
17970
+ address: spokeAddr,
17971
+ name: "getDynamicReserveConfig",
17972
+ params: [rid, key]
18006
17973
  });
18007
17974
  }
18008
17975
  }
18009
- const hubEntry = aaveV4Hubs()?.[lender]?.[chainId];
18010
- if (hubEntry?.hub && isValidAddress(hubEntry.hub)) {
18011
- const hubAddr = hubEntry.hub.toLowerCase();
17976
+ calls.push({
17977
+ address: spokeAddr,
17978
+ name: "getLiquidationConfig",
17979
+ params: []
17980
+ });
17981
+ const reserveIds = reserves.map((r) => r.reserveId);
17982
+ if (reserveIds.length > 0 && isValidAddress(spokeEntry.oracle)) {
18012
17983
  calls.push({
18013
- address: hubAddr,
18014
- name: "getAssetCount",
18015
- params: []
17984
+ address: spokeEntry.oracle.toLowerCase(),
17985
+ name: "getReservesPrices",
17986
+ params: [reserveIds]
18016
17987
  });
17988
+ }
17989
+ const distinctHubs = distinctHubsInOrder(reserves);
17990
+ for (const hub of distinctHubs) {
17991
+ calls.push({ address: hub, name: "getAssetCount", params: [] });
18017
17992
  for (let i = 0; i < MAX_HUB_ASSETS; i++) {
18018
17993
  calls.push(
18019
- {
18020
- address: hubAddr,
18021
- name: "getAsset",
18022
- params: [i]
18023
- },
18024
- {
18025
- address: hubAddr,
18026
- name: "getAddedAssets",
18027
- params: [i]
18028
- },
18029
- {
18030
- address: hubAddr,
18031
- name: "getAssetTotalOwed",
18032
- params: [i]
18033
- }
17994
+ { address: hub, name: "getAsset", params: [i] },
17995
+ { address: hub, name: "getAddedAssets", params: [i] },
17996
+ { address: hub, name: "getAssetTotalOwed", params: [i] }
18034
17997
  );
18035
17998
  }
18036
- for (const spokeEntry of spokes) {
18037
- if (!isValidAddress(spokeEntry.spoke)) continue;
18038
- const spokeAddr = spokeEntry.spoke;
18039
- const reserves = getSpokeReserves(reservesMap, spokeAddr);
18040
- for (const entry of reserves) {
18041
- const assetId = getReserveAssetId(entry);
18042
- if (assetId == null) continue;
18043
- calls.push({
18044
- address: hubAddr,
18045
- name: "getSpoke",
18046
- params: [assetId, spokeAddr]
18047
- });
18048
- }
17999
+ for (const r of reserves) {
18000
+ if ((r?.hub ?? "").toLowerCase() !== hub) continue;
18001
+ const assetId = r.assetId;
18002
+ if (typeof assetId !== "number") continue;
18003
+ calls.push({
18004
+ address: hub,
18005
+ name: "getSpoke",
18006
+ params: [assetId, spokeAddr]
18007
+ });
18049
18008
  }
18050
18009
  }
18051
18010
  return calls;
18052
18011
  };
18053
18012
  var getAaveV4ExpectedCallCount = (chainId, lender) => {
18054
- const spokes = aaveV4Spokes()?.[lender]?.[chainId] ?? [];
18055
- const reservesMap = aaveV4Reserves()?.[lender]?.[chainId] ?? {};
18013
+ const spokeEntry = resolveSpokeEntry(chainId, lender);
18014
+ if (!spokeEntry) return 0;
18015
+ if (!isValidAddress(spokeEntry.spoke)) return 0;
18016
+ const reserves = spokeEntry.reserves ?? [];
18017
+ const dynConfigCount = getDynamicConfigCount(spokeEntry);
18056
18018
  let count = 0;
18057
- for (const spokeEntry of spokes) {
18058
- if (!isValidAddress(spokeEntry.spoke)) continue;
18059
- const reserves = getSpokeReserves(reservesMap, spokeEntry.spoke);
18060
- const dynConfigCount = getDynamicConfigCount(spokeEntry);
18061
- count += reserves.length * (BASE_CALLS_PER_RESERVE + dynConfigCount) + CALLS_PER_SPOKE_TAIL;
18062
- const rids = reserves.map(
18063
- (e) => typeof e === "number" ? e : e.reserveId
18064
- );
18065
- if (rids.length > 0 && isValidAddress(spokeEntry.oracle)) {
18066
- count += 1;
18067
- }
18019
+ count += reserves.length * (BASE_CALLS_PER_RESERVE + dynConfigCount);
18020
+ count += CALLS_PER_SPOKE_TAIL;
18021
+ if (reserves.length > 0 && isValidAddress(spokeEntry.oracle)) {
18022
+ count += 1;
18068
18023
  }
18069
- const hubEntry = aaveV4Hubs()?.[lender]?.[chainId];
18070
- if (hubEntry?.hub && isValidAddress(hubEntry.hub)) {
18024
+ const distinctHubs = distinctHubsInOrder(reserves);
18025
+ for (const hub of distinctHubs) {
18071
18026
  count += 1 + MAX_HUB_ASSETS * 3;
18072
- for (const spokeEntry of spokes) {
18073
- if (!isValidAddress(spokeEntry.spoke)) continue;
18074
- const reserves = getSpokeReserves(reservesMap, spokeEntry.spoke);
18075
- for (const entry of reserves) {
18076
- if (getReserveAssetId(entry) != null) count += 1;
18077
- }
18027
+ for (const r of reserves) {
18028
+ if ((r?.hub ?? "").toLowerCase() !== hub) continue;
18029
+ if (typeof r.assetId === "number") count += 1;
18078
18030
  }
18079
18031
  }
18080
18032
  return count;
@@ -18109,23 +18061,24 @@ function rayRateToApr(rateRay) {
18109
18061
  if (rateRay === 0n) return 0;
18110
18062
  return Number(rateRay) / RAY2 * 100;
18111
18063
  }
18112
- function normalizeAaveV4(spokeDataList, chainId, baseHubLender, prices, additionalYields, tokenList, lenderShortNameFn, createMarketUidFn, toOracleKeyFn, toGenericPriceKeyFn, expectedHub) {
18113
- const out = {};
18114
- const hubFilter = expectedHub?.toLowerCase();
18115
- for (const spokeData of spokeDataList) {
18064
+ function normalizeAaveV4(spokeDataList, chainId, spokeLenderKeyArg, prices, additionalYields, tokenList, lenderShortNameFn, createMarketUidFn, toOracleKeyFn, toGenericPriceKeyFn) {
18065
+ const spokeData = spokeDataList[0];
18066
+ if (!spokeData) return void 0;
18067
+ {
18116
18068
  const spokeAddr = spokeData.spoke.toLowerCase();
18117
- const spokeLenderKey = aaveV4SpokeLenderKey(baseHubLender, spokeAddr);
18118
- let spokeHub = "";
18069
+ const parsedFromArg = parseAaveV4SpokeLenderKey(spokeLenderKeyArg);
18070
+ const spokeLenderKey = parsedFromArg && parsedFromArg.spokeAddrLower === spokeAddr ? spokeLenderKeyArg : aaveV4SpokeLenderKey(spokeAddr);
18119
18071
  const spokeReserves = spokeData.reserves;
18120
18072
  const data = {};
18121
18073
  for (const reserve of spokeReserves) {
18122
- const reserveHub = reserve.reserve.hub?.toLowerCase();
18123
- if (hubFilter && reserveHub && reserveHub !== hubFilter)
18124
- continue;
18125
- if (!spokeHub) spokeHub = reserveHub ?? "";
18074
+ const reserveHub = (reserve.reserve.hub ?? "").toLowerCase();
18126
18075
  const underlying = reserve.reserve.underlying.toLowerCase();
18127
18076
  const decimals = reserve.reserve.decimals;
18128
- const marketUid = createMarketUidFn(chainId, spokeLenderKey, underlying);
18077
+ const marketUid = createMarketUidFn(
18078
+ chainId,
18079
+ spokeLenderKey,
18080
+ String(reserve.reserveId)
18081
+ );
18129
18082
  const assetMeta = tokenList[underlying];
18130
18083
  const oracleKey = toOracleKeyFn(assetMeta?.assetGroup ?? null) ?? toGenericPriceKeyFn(underlying, chainId);
18131
18084
  let price = 0;
@@ -18180,7 +18133,7 @@ function normalizeAaveV4(spokeDataList, chainId, baseHubLender, prices, addition
18180
18133
  reserve.dynamicConfigs
18181
18134
  )) {
18182
18135
  config[keyStr] = {
18183
- category: keyStr,
18136
+ category: Number(keyStr),
18184
18137
  label: `${spokeData.label} / Config ${keyStr}`,
18185
18138
  borrowCollateralFactor: dynCfg.collateralFactor / BPS,
18186
18139
  collateralFactor: dynCfg.collateralFactor / BPS,
@@ -18191,7 +18144,7 @@ function normalizeAaveV4(spokeDataList, chainId, baseHubLender, prices, addition
18191
18144
  }
18192
18145
  if (Object.keys(config).length === 0) {
18193
18146
  config["0"] = {
18194
- category: "0",
18147
+ category: 0,
18195
18148
  label: `${spokeData.label} / Default`,
18196
18149
  borrowCollateralFactor: 0,
18197
18150
  collateralFactor: 0,
@@ -18205,7 +18158,7 @@ function normalizeAaveV4(spokeDataList, chainId, baseHubLender, prices, addition
18205
18158
  );
18206
18159
  data[marketUid] = {
18207
18160
  marketUid,
18208
- name: lenderShortNameFn(baseHubLender) + " " + (assetMeta?.symbol ?? ""),
18161
+ name: lenderShortNameFn(spokeLenderKey) + " " + (assetMeta?.symbol ?? ""),
18209
18162
  poolId: underlying,
18210
18163
  underlying,
18211
18164
  asset: assetMeta,
@@ -18238,167 +18191,155 @@ function normalizeAaveV4(spokeDataList, chainId, baseHubLender, prices, addition
18238
18191
  params: {
18239
18192
  metadata: {
18240
18193
  assetId: reserve.reserve.assetId,
18241
- reserveId: reserve.reserveId
18194
+ reserveId: reserve.reserveId,
18195
+ hub: reserveHub
18242
18196
  }
18243
18197
  },
18244
18198
  collateralRiskBps,
18245
18199
  riskPremiumThresholdBps
18246
18200
  };
18247
18201
  }
18248
- if (Object.keys(data).length > 0) {
18249
- out[spokeLenderKey] = {
18250
- data,
18251
- chainId,
18252
- params: {
18253
- spoke: spokeAddr,
18254
- hub: spokeHub,
18255
- oracle: spokeData.oracle.toLowerCase(),
18256
- baseHubLender,
18257
- label: spokeData.label
18258
- }
18259
- };
18260
- }
18202
+ if (Object.keys(data).length === 0) return void 0;
18203
+ return {
18204
+ data,
18205
+ chainId,
18206
+ params: {
18207
+ spoke: spokeAddr,
18208
+ oracle: spokeData.oracle.toLowerCase(),
18209
+ label: spokeData.label
18210
+ }
18211
+ };
18261
18212
  }
18262
- return out;
18263
18213
  }
18264
18214
 
18265
18215
  // src/lending/public-data/aave-v4-type/publicCallParse.ts
18266
18216
  function isValidAddress2(addr) {
18267
18217
  return !!addr && addr !== "0x" && addr.length > 2;
18268
18218
  }
18269
- function getSpokeReserves2(reservesMap, spokeAddr) {
18270
- return reservesMap[spokeAddr.toLowerCase()] ?? reservesMap[spokeAddr] ?? [];
18271
- }
18272
18219
  var getAaveV4ReservesDataConverter = (lender, chainId, prices, additionalYields, tokenList = {}) => {
18273
18220
  const expectedCalls = getAaveV4ExpectedCallCount(chainId, lender);
18274
18221
  const converter = (data) => {
18275
18222
  if (data.length !== expectedCalls) return void 0;
18276
- const spokes = aaveV4Spokes()?.[lender]?.[chainId] ?? [];
18277
- const reservesMap = aaveV4Reserves()?.[lender]?.[chainId] ?? {};
18223
+ const parsed = parseAaveV4SpokeLenderKey(lender);
18224
+ if (!parsed) return void 0;
18225
+ const spokeEntry = aaveV4Spokes()?.[chainId]?.[parsed.spokeAddrLower];
18226
+ if (!spokeEntry) return void 0;
18227
+ const spokeAddr = spokeEntry.spoke.toLowerCase();
18228
+ const reserves = spokeEntry.reserves ?? [];
18229
+ const dynConfigCount = (spokeEntry.dynamicConfigKeyMax ?? 0) + 1;
18278
18230
  let offset = 0;
18279
- const spokeDataList = [];
18280
- for (const spokeEntry of spokes) {
18281
- if (!isValidAddress2(spokeEntry.spoke)) continue;
18282
- const spokeAddr = spokeEntry.spoke;
18283
- const reserves = getSpokeReserves2(reservesMap, spokeAddr);
18284
- const dynConfigCount = (spokeEntry.dynamicConfigKeyMax ?? 0) + 1;
18285
- const parsedReserves = [];
18286
- for (let i = 0; i < reserves.length; i++) {
18287
- const entry = reserves[i];
18288
- const reserveId = typeof entry === "number" ? entry : entry.reserveId;
18289
- const rawReserve = data[offset];
18290
- const rawConfig = data[offset + 1];
18291
- const rawSupplied = data[offset + 2];
18292
- const rawDebt = data[offset + 3];
18293
- const rawTotalDebt = data[offset + 4];
18294
- offset += BASE_CALLS_PER_RESERVE;
18295
- const dynamicConfigs = {};
18296
- for (let key = 0; key < dynConfigCount; key++) {
18297
- const rawDynConfig = data[offset];
18298
- offset += 1;
18299
- if (rawDynConfig && rawDynConfig !== "0x") {
18300
- dynamicConfigs[key] = {
18301
- collateralFactor: Number(
18302
- rawDynConfig?.collateralFactor ?? 0
18303
- ),
18304
- maxLiquidationBonus: Number(
18305
- rawDynConfig?.maxLiquidationBonus ?? 0
18306
- ),
18307
- liquidationFee: Number(
18308
- rawDynConfig?.liquidationFee ?? 0
18309
- )
18310
- };
18311
- }
18312
- }
18313
- const reserve = {
18314
- underlying: rawReserve?.underlying ?? "",
18315
- hub: rawReserve?.hub ?? "",
18316
- assetId: Number(rawReserve?.assetId ?? 0),
18317
- decimals: Number(rawReserve?.decimals ?? 18),
18318
- collateralRisk: Number(
18319
- rawReserve?.collateralRisk ?? 0
18320
- ),
18321
- flags: Number(rawReserve?.flags ?? 0),
18322
- dynamicConfigKey: Number(
18323
- rawReserve?.dynamicConfigKey ?? 0
18324
- )
18325
- };
18326
- const config = {
18327
- collateralRisk: Number(rawConfig?.collateralRisk ?? 0),
18328
- paused: rawConfig?.paused ?? false,
18329
- frozen: rawConfig?.frozen ?? false,
18330
- borrowable: rawConfig?.borrowable ?? false,
18331
- receiveSharesEnabled: rawConfig?.receiveSharesEnabled ?? false
18332
- };
18333
- let drawnDebt = 0n;
18334
- let premiumDebt = 0n;
18335
- if (Array.isArray(rawDebt)) {
18336
- drawnDebt = BigInt(rawDebt[0] ?? 0);
18337
- premiumDebt = BigInt(rawDebt[1] ?? 0);
18338
- } else {
18339
- drawnDebt = BigInt(rawDebt ?? 0);
18231
+ const parsedReserves = [];
18232
+ for (const r of reserves) {
18233
+ const reserveId = r.reserveId;
18234
+ const rawReserve = data[offset];
18235
+ const rawConfig = data[offset + 1];
18236
+ const rawSupplied = data[offset + 2];
18237
+ const rawDebt = data[offset + 3];
18238
+ const rawTotalDebt = data[offset + 4];
18239
+ offset += BASE_CALLS_PER_RESERVE;
18240
+ const dynamicConfigs = {};
18241
+ for (let key = 0; key < dynConfigCount; key++) {
18242
+ const rawDynConfig = data[offset];
18243
+ offset += 1;
18244
+ if (rawDynConfig && rawDynConfig !== "0x") {
18245
+ dynamicConfigs[key] = {
18246
+ collateralFactor: Number(rawDynConfig?.collateralFactor ?? 0),
18247
+ maxLiquidationBonus: Number(
18248
+ rawDynConfig?.maxLiquidationBonus ?? 0
18249
+ ),
18250
+ liquidationFee: Number(rawDynConfig?.liquidationFee ?? 0)
18251
+ };
18340
18252
  }
18341
- parsedReserves.push({
18342
- reserveId,
18343
- reserve,
18344
- config,
18345
- dynamicConfigs,
18346
- suppliedAssets: BigInt(rawSupplied ?? 0),
18347
- drawnDebt,
18348
- premiumDebt,
18349
- totalDebt: BigInt(rawTotalDebt ?? 0),
18350
- hubAsset: { drawnRate: 0n },
18351
- price: 0n
18352
- });
18353
18253
  }
18354
- const rawLiqConfig = data[offset];
18355
- offset += CALLS_PER_SPOKE_TAIL;
18356
- const liquidationConfig = {
18357
- targetHealthFactor: BigInt(
18358
- rawLiqConfig?.targetHealthFactor ?? 0
18359
- ),
18360
- healthFactorForMaxBonus: BigInt(
18361
- rawLiqConfig?.healthFactorForMaxBonus ?? 0
18362
- ),
18363
- liquidationBonusFactor: Number(
18364
- rawLiqConfig?.liquidationBonusFactor ?? 0
18365
- )
18254
+ const onChainHub = (rawReserve?.hub ?? "").toLowerCase();
18255
+ const reserveHub = isValidAddress2(onChainHub) ? onChainHub : (r.hub ?? "").toLowerCase();
18256
+ const reserve = {
18257
+ underlying: rawReserve?.underlying ?? r.underlying ?? "",
18258
+ hub: reserveHub,
18259
+ assetId: Number(rawReserve?.assetId ?? r.assetId ?? 0),
18260
+ decimals: Number(rawReserve?.decimals ?? 18),
18261
+ collateralRisk: Number(rawReserve?.collateralRisk ?? 0),
18262
+ flags: Number(rawReserve?.flags ?? 0),
18263
+ dynamicConfigKey: Number(rawReserve?.dynamicConfigKey ?? 0)
18366
18264
  };
18367
- spokeDataList.push({
18368
- spoke: spokeAddr,
18369
- oracle: spokeEntry.oracle,
18370
- label: spokeEntry.label,
18371
- oracleDecimals: 8,
18372
- liquidationConfig,
18373
- reserves: parsedReserves
18265
+ const config = {
18266
+ collateralRisk: Number(rawConfig?.collateralRisk ?? 0),
18267
+ paused: rawConfig?.paused ?? false,
18268
+ frozen: rawConfig?.frozen ?? false,
18269
+ borrowable: rawConfig?.borrowable ?? false,
18270
+ receiveSharesEnabled: rawConfig?.receiveSharesEnabled ?? false
18271
+ };
18272
+ let drawnDebt = 0n;
18273
+ let premiumDebt = 0n;
18274
+ if (Array.isArray(rawDebt)) {
18275
+ drawnDebt = BigInt(rawDebt[0] ?? 0);
18276
+ premiumDebt = BigInt(rawDebt[1] ?? 0);
18277
+ } else {
18278
+ drawnDebt = BigInt(rawDebt ?? 0);
18279
+ }
18280
+ parsedReserves.push({
18281
+ reserveId,
18282
+ reserve,
18283
+ config,
18284
+ dynamicConfigs,
18285
+ suppliedAssets: BigInt(rawSupplied ?? 0),
18286
+ drawnDebt,
18287
+ premiumDebt,
18288
+ totalDebt: BigInt(rawTotalDebt ?? 0),
18289
+ hubAsset: { drawnRate: 0n },
18290
+ price: 0n
18374
18291
  });
18375
18292
  }
18376
- for (let si = 0; si < spokeDataList.length; si++) {
18377
- const sd = spokeDataList[si];
18378
- const reserves = getSpokeReserves2(reservesMap, sd.spoke);
18379
- const rids = reserves.map(
18380
- (e) => typeof e === "number" ? e : e.reserveId
18381
- );
18382
- if (rids.length > 0 && isValidAddress2(sd.oracle)) {
18383
- const rawPrices = data[offset];
18384
- offset += 1;
18385
- const priceArray = Array.isArray(rawPrices) ? rawPrices : [];
18386
- for (let ri = 0; ri < sd.reserves.length; ri++) {
18387
- if (ri < priceArray.length) {
18388
- sd.reserves[ri].price = BigInt(priceArray[ri] ?? 0);
18389
- }
18293
+ const rawLiqConfig = data[offset];
18294
+ offset += CALLS_PER_SPOKE_TAIL;
18295
+ const liquidationConfig = {
18296
+ targetHealthFactor: BigInt(rawLiqConfig?.targetHealthFactor ?? 0),
18297
+ healthFactorForMaxBonus: BigInt(
18298
+ rawLiqConfig?.healthFactorForMaxBonus ?? 0
18299
+ ),
18300
+ liquidationBonusFactor: Number(
18301
+ rawLiqConfig?.liquidationBonusFactor ?? 0
18302
+ )
18303
+ };
18304
+ const spokeData = {
18305
+ spoke: spokeAddr,
18306
+ oracle: spokeEntry.oracle,
18307
+ label: spokeEntry.label,
18308
+ oracleDecimals: 8,
18309
+ liquidationConfig,
18310
+ reserves: parsedReserves
18311
+ };
18312
+ if (parsedReserves.length > 0 && isValidAddress2(spokeEntry.oracle)) {
18313
+ const rawPrices = data[offset];
18314
+ offset += 1;
18315
+ const priceArray = Array.isArray(rawPrices) ? rawPrices : [];
18316
+ for (let ri = 0; ri < parsedReserves.length; ri++) {
18317
+ if (ri < priceArray.length) {
18318
+ parsedReserves[ri].price = BigInt(priceArray[ri] ?? 0);
18390
18319
  }
18391
18320
  }
18392
18321
  }
18393
- const hubEntry = aaveV4Hubs()?.[lender]?.[chainId];
18322
+ const distinctHubs = [];
18323
+ {
18324
+ const seen = /* @__PURE__ */ new Set();
18325
+ for (const r of reserves) {
18326
+ const h = (r?.hub ?? "").toLowerCase();
18327
+ if (!h || !isValidAddress2(h)) continue;
18328
+ if (seen.has(h)) continue;
18329
+ seen.add(h);
18330
+ distinctHubs.push(h);
18331
+ }
18332
+ }
18394
18333
  const hubAssetMap = /* @__PURE__ */ new Map();
18395
- if (hubEntry?.hub && isValidAddress2(hubEntry.hub)) {
18334
+ for (const hub of distinctHubs) {
18396
18335
  const rawAssetCount = data[offset];
18397
18336
  offset += 1;
18398
18337
  const assetCount = Math.min(
18399
18338
  Number(rawAssetCount ?? 0),
18400
18339
  MAX_HUB_ASSETS
18401
18340
  );
18341
+ const inner = /* @__PURE__ */ new Map();
18342
+ hubAssetMap.set(hub, inner);
18402
18343
  for (let i = 0; i < MAX_HUB_ASSETS; i++) {
18403
18344
  const baseIdx = offset + i * 3;
18404
18345
  const rawHubAsset = data[baseIdx];
@@ -18408,15 +18349,13 @@ var getAaveV4ReservesDataConverter = (lender, chainId, prices, additionalYields,
18408
18349
  continue;
18409
18350
  const underlying = (rawHubAsset?.underlying ?? "").toLowerCase();
18410
18351
  if (!underlying) continue;
18411
- hubAssetMap.set(underlying, {
18352
+ inner.set(underlying, {
18412
18353
  liquidity: BigInt(rawHubAsset?.liquidity ?? 0),
18413
18354
  realizedFees: BigInt(rawHubAsset?.realizedFees ?? 0),
18414
18355
  decimals: Number(rawHubAsset?.decimals ?? 18),
18415
18356
  addedShares: BigInt(rawHubAsset?.addedShares ?? 0),
18416
18357
  swept: BigInt(rawHubAsset?.swept ?? 0),
18417
- premiumOffsetRay: BigInt(
18418
- rawHubAsset?.premiumOffsetRay ?? 0
18419
- ),
18358
+ premiumOffsetRay: BigInt(rawHubAsset?.premiumOffsetRay ?? 0),
18420
18359
  drawnShares: BigInt(rawHubAsset?.drawnShares ?? 0),
18421
18360
  premiumShares: BigInt(rawHubAsset?.premiumShares ?? 0),
18422
18361
  liquidityFee: Number(rawHubAsset?.liquidityFee ?? 0),
@@ -18435,49 +18374,36 @@ var getAaveV4ReservesDataConverter = (lender, chainId, prices, additionalYields,
18435
18374
  });
18436
18375
  }
18437
18376
  offset += MAX_HUB_ASSETS * 3;
18438
- for (const spokeData of spokeDataList) {
18439
- const spokeReservesMeta = getSpokeReserves2(
18440
- reservesMap,
18441
- spokeData.spoke
18377
+ for (const r of reserves) {
18378
+ if ((r?.hub ?? "").toLowerCase() !== hub) continue;
18379
+ if (typeof r.assetId !== "number") continue;
18380
+ const rawBinding = data[offset];
18381
+ offset += 1;
18382
+ if (!rawBinding || rawBinding === "0x") continue;
18383
+ const binding = {
18384
+ riskPremiumThreshold: Number(
18385
+ rawBinding?.riskPremiumThreshold ?? 0
18386
+ ),
18387
+ active: Boolean(rawBinding?.active ?? false),
18388
+ halted: Boolean(rawBinding?.halted ?? false),
18389
+ addCap: Number(rawBinding?.addCap ?? 0),
18390
+ drawCap: Number(rawBinding?.drawCap ?? 0)
18391
+ };
18392
+ const target = parsedReserves.find(
18393
+ (pr) => pr.reserveId === r.reserveId
18442
18394
  );
18443
- for (let ri = 0; ri < spokeReservesMeta.length; ri++) {
18444
- const meta = spokeReservesMeta[ri];
18445
- const assetId = typeof meta === "object" && meta != null ? meta.assetId : void 0;
18446
- if (typeof assetId !== "number") continue;
18447
- const rawBinding = data[offset];
18448
- offset += 1;
18449
- if (!rawBinding || rawBinding === "0x") continue;
18450
- const binding = {
18451
- riskPremiumThreshold: Number(
18452
- rawBinding?.riskPremiumThreshold ?? 0
18453
- ),
18454
- active: Boolean(rawBinding?.active ?? false),
18455
- halted: Boolean(rawBinding?.halted ?? false),
18456
- addCap: Number(rawBinding?.addCap ?? 0),
18457
- drawCap: Number(rawBinding?.drawCap ?? 0)
18458
- };
18459
- const targetReserveId = typeof meta === "number" ? meta : meta.reserveId;
18460
- const target = spokeData.reserves.find(
18461
- (r) => r.reserveId === targetReserveId
18462
- );
18463
- if (target) target.spokeBinding = binding;
18464
- }
18395
+ if (target) target.spokeBinding = binding;
18465
18396
  }
18466
18397
  }
18467
- for (const spokeData of spokeDataList) {
18468
- for (const reserve of spokeData.reserves) {
18469
- const underlying = reserve.reserve.underlying?.toLowerCase?.() ?? "";
18470
- if (underlying) {
18471
- const hubAsset = hubAssetMap.get(underlying);
18472
- if (hubAsset) {
18473
- reserve.hubAsset = hubAsset;
18474
- }
18475
- }
18476
- }
18398
+ for (const pr of parsedReserves) {
18399
+ const hub = pr.reserve.hub?.toLowerCase?.() ?? "";
18400
+ const underlying = pr.reserve.underlying?.toLowerCase?.() ?? "";
18401
+ if (!hub || !underlying) continue;
18402
+ const hubAsset = hubAssetMap.get(hub)?.get(underlying);
18403
+ if (hubAsset) pr.hubAsset = hubAsset;
18477
18404
  }
18478
- const expectedHub = hubEntry?.hub;
18479
18405
  return normalizeAaveV4(
18480
- spokeDataList,
18406
+ [spokeData],
18481
18407
  chainId,
18482
18408
  lender,
18483
18409
  prices,
@@ -18486,8 +18412,7 @@ var getAaveV4ReservesDataConverter = (lender, chainId, prices, additionalYields,
18486
18412
  lenderShortName,
18487
18413
  createMarketUid,
18488
18414
  toOracleKey,
18489
- toGenericPriceKey,
18490
- expectedHub
18415
+ toGenericPriceKey
18491
18416
  );
18492
18417
  };
18493
18418
  return [converter, expectedCalls];
@@ -19145,40 +19070,42 @@ var buildEulerUserCall = async (chainId, lender, account, subAccountIndexes) =>
19145
19070
 
19146
19071
  // src/lending/user-data/aave-v4-type/userCallBuild.ts
19147
19072
  var USER_CALLS_PER_RESERVE = 4;
19073
+ function resolveSpokeEntry2(chainId, lender) {
19074
+ const parsed = parseAaveV4SpokeLenderKey(lender);
19075
+ if (!parsed) return void 0;
19076
+ return aaveV4Spokes()?.[chainId]?.[parsed.spokeAddrLower];
19077
+ }
19148
19078
  var buildAaveV4UserCall = (chainId, lender, account) => {
19149
- const spokes = aaveV4Spokes()?.[lender]?.[chainId] ?? [];
19150
- const reservesMap = aaveV4Reserves()?.[lender]?.[chainId] ?? {};
19151
- if (spokes.length === 0) return [];
19079
+ const spokeEntry = resolveSpokeEntry2(chainId, lender);
19080
+ if (!spokeEntry) return [];
19081
+ const spokeAddr = spokeEntry.spoke;
19082
+ if (!spokeAddr || spokeAddr === "0x" || spokeAddr.length <= 2) return [];
19083
+ const reserves = spokeEntry.reserves ?? [];
19152
19084
  const calls = [];
19153
- for (const spokeEntry of spokes) {
19154
- const spokeAddr = spokeEntry.spoke;
19155
- if (!spokeAddr || spokeAddr === "0x" || spokeAddr.length <= 2) continue;
19156
- const reserveIds = reservesMap[spokeAddr.toLowerCase()] ?? reservesMap[spokeAddr] ?? [];
19157
- for (const entry of reserveIds) {
19158
- const rid = typeof entry === "number" ? entry : entry.reserveId;
19159
- calls.push(
19160
- {
19161
- address: spokeAddr,
19162
- name: "getUserSuppliedAssets",
19163
- params: [rid, account]
19164
- },
19165
- {
19166
- address: spokeAddr,
19167
- name: "getUserDebt",
19168
- params: [rid, account]
19169
- },
19170
- {
19171
- address: spokeAddr,
19172
- name: "getUserReserveStatus",
19173
- params: [rid, account]
19174
- },
19175
- {
19176
- address: spokeAddr,
19177
- name: "getUserPosition",
19178
- params: [rid, account]
19179
- }
19180
- );
19181
- }
19085
+ for (const r of reserves) {
19086
+ const rid = r.reserveId;
19087
+ calls.push(
19088
+ {
19089
+ address: spokeAddr,
19090
+ name: "getUserSuppliedAssets",
19091
+ params: [rid, account]
19092
+ },
19093
+ {
19094
+ address: spokeAddr,
19095
+ name: "getUserDebt",
19096
+ params: [rid, account]
19097
+ },
19098
+ {
19099
+ address: spokeAddr,
19100
+ name: "getUserReserveStatus",
19101
+ params: [rid, account]
19102
+ },
19103
+ {
19104
+ address: spokeAddr,
19105
+ name: "getUserPosition",
19106
+ params: [rid, account]
19107
+ }
19108
+ );
19182
19109
  }
19183
19110
  return calls;
19184
19111
  };
@@ -20582,61 +20509,30 @@ function createAaveV4UserState(payload, lenderData, totalDeposits24h = 0, totalD
20582
20509
  }
20583
20510
 
20584
20511
  // src/lending/user-data/aave-v4-type/userCallParse.ts
20585
- var getAaveV4UserDataConverter = (lender, chainId, account, metaMap) => {
20586
- const spokes = aaveV4Spokes()?.[lender]?.[chainId] ?? [];
20587
- const reservesMap = aaveV4Reserves()?.[lender]?.[chainId] ?? {};
20588
- const flatMeta = {};
20589
- if (metaMap) {
20590
- const expectedPrefix = lender + "_";
20591
- for (const [topKey, lenderMetaSubMap] of Object.entries(metaMap)) {
20592
- if (!topKey.startsWith(expectedPrefix)) continue;
20593
- for (const [marketUid, meta] of Object.entries(
20594
- lenderMetaSubMap
20595
- )) {
20596
- flatMeta[marketUid] = meta;
20597
- }
20598
- }
20599
- }
20600
- const oracleEntries = aaveV4Oracles()?.[lender]?.[chainId] ?? [];
20601
- const spokeReserveToUnderlying = /* @__PURE__ */ new Map();
20602
- for (const oe of oracleEntries) {
20603
- if (oe.underlying && oe.spoke) {
20604
- spokeReserveToUnderlying.set(
20605
- `${oe.spoke.toLowerCase()}:${oe.reserveId}`,
20606
- oe.underlying.toLowerCase()
20607
- );
20608
- }
20609
- }
20610
- const reserveEntries = [];
20611
- for (const spokeEntry of spokes) {
20612
- const spokeAddr = spokeEntry.spoke;
20613
- if (!spokeAddr || spokeAddr === "0x" || spokeAddr.length <= 2) continue;
20614
- const spokeAddrLc = spokeAddr.toLowerCase();
20615
- const spokeLenderKey = aaveV4SpokeLenderKey(lender, spokeAddrLc);
20616
- const reserves = reservesMap[spokeAddrLc] ?? reservesMap[spokeAddr] ?? [];
20617
- for (const entry of reserves) {
20618
- const rid = typeof entry === "number" ? entry : entry.reserveId;
20619
- const underlying = ((typeof entry === "object" ? entry.underlying : void 0) ?? spokeReserveToUnderlying.get(`${spokeAddrLc}:${rid}`) ?? "").toLowerCase();
20620
- reserveEntries.push({
20621
- spokeAddr,
20622
- spokeAddrLc,
20623
- spokeLenderKey,
20624
- reserveId: rid,
20625
- underlying
20626
- });
20627
- }
20628
- }
20629
- const expectedNumberOfCalls = reserveEntries.length * USER_CALLS_PER_RESERVE;
20512
+ var getAaveV4UserDataConverter = (lender, chainId, account, meta) => {
20513
+ const parsed = parseAaveV4SpokeLenderKey(lender);
20514
+ const spokeEntry = parsed ? aaveV4Spokes()?.[chainId]?.[parsed.spokeAddrLower] : void 0;
20515
+ if (!spokeEntry) {
20516
+ return [() => void 0, 0];
20517
+ }
20518
+ const spokeAddr = spokeEntry.spoke;
20519
+ const spokeAddrLc = spokeAddr.toLowerCase();
20520
+ const reserves = spokeEntry.reserves ?? [];
20521
+ const flatMeta = meta ?? {};
20522
+ const expectedNumberOfCalls = reserves.length * USER_CALLS_PER_RESERVE;
20630
20523
  return [
20631
20524
  (data) => {
20632
20525
  if (data.length !== expectedNumberOfCalls) {
20633
20526
  return void 0;
20634
20527
  }
20635
- const perSpoke = {};
20636
- for (let i = 0; i < reserveEntries.length; i++) {
20637
- const { underlying, spokeAddrLc, spokeLenderKey } = reserveEntries[i];
20528
+ const lendingPositions = {};
20529
+ let totalDeposits24h = 0;
20530
+ let totalDebt24h = 0;
20531
+ for (let i = 0; i < reserves.length; i++) {
20532
+ const r = reserves[i];
20533
+ const underlying = (r.underlying ?? "").toLowerCase();
20638
20534
  if (!underlying) continue;
20639
- const key = createMarketUid(chainId, spokeLenderKey, underlying);
20535
+ const key = createMarketUid(chainId, lender, String(r.reserveId));
20640
20536
  const metaEntity = flatMeta[key];
20641
20537
  if (!metaEntity) continue;
20642
20538
  const base = i * USER_CALLS_PER_RESERVE;
@@ -20653,30 +20549,21 @@ var getAaveV4UserDataConverter = (lender, chainId, account, metaMap) => {
20653
20549
  );
20654
20550
  if (!dataForAsset) continue;
20655
20551
  dataForAsset.userConfigKey = String(userDynConfigKey);
20656
- const bucket = perSpoke[spokeLenderKey] ?? (perSpoke[spokeLenderKey] = {
20657
- lendingPositions: {},
20658
- totalDebt24h: 0,
20659
- totalDeposits24h: 0
20660
- });
20661
- bucket.totalDebt24h += addedDebt;
20662
- bucket.totalDeposits24h += addedDeposits;
20663
- bucket.lendingPositions[key] = dataForAsset;
20664
- }
20665
- const out = {};
20666
- for (const [spokeLenderKey, bucket] of Object.entries(perSpoke)) {
20667
- const payload = {
20668
- chainId,
20669
- account,
20670
- lendingPositions: bucket.lendingPositions,
20671
- rewards: []};
20672
- out[spokeLenderKey] = createAaveV4UserState(
20673
- payload,
20674
- flatMeta,
20675
- bucket.totalDeposits24h,
20676
- bucket.totalDebt24h
20677
- );
20552
+ totalDebt24h += addedDebt;
20553
+ totalDeposits24h += addedDeposits;
20554
+ lendingPositions[key] = dataForAsset;
20678
20555
  }
20679
- return out;
20556
+ const payload = {
20557
+ chainId,
20558
+ account,
20559
+ lendingPositions,
20560
+ rewards: []};
20561
+ return createAaveV4UserState(
20562
+ payload,
20563
+ flatMeta,
20564
+ totalDeposits24h,
20565
+ totalDebt24h
20566
+ );
20680
20567
  },
20681
20568
  expectedNumberOfCalls
20682
20569
  ];
@@ -20738,7 +20625,12 @@ function createAaveV4Entry(base, data, key, meta, spokeAddr) {
20738
20625
  // src/lending/user-data/fetch-balances/parse.ts
20739
20626
  function getUserDataConverter(lender, chainId, account, params, meta) {
20740
20627
  if (isAaveV4Type(lender))
20741
- return getAaveV4UserDataConverter(lender, chainId, account, meta);
20628
+ return getAaveV4UserDataConverter(
20629
+ lender,
20630
+ chainId,
20631
+ account,
20632
+ meta?.[lender]
20633
+ );
20742
20634
  if (isYLDR(lender))
20743
20635
  return getYldrUserDataConverter(lender, chainId, account, meta?.[lender]);
20744
20636
  if (isAaveV2Type(lender))
@@ -32265,49 +32157,33 @@ var eulerV2Fetcher = {
32265
32157
  getAbi: getEulerV2Abi
32266
32158
  };
32267
32159
  function getAaveV4OracleGroups(chainId) {
32268
- const oracles = aaveV4Oracles() ?? {};
32269
- const spokes = aaveV4Spokes() ?? {};
32270
- const groups = [];
32271
- for (const [fork, chains] of Object.entries(oracles)) {
32272
- const oracleEntries = chains[chainId] ?? [];
32273
- if (oracleEntries.length === 0) continue;
32274
- const spokeToHub = /* @__PURE__ */ new Map();
32275
- for (const s of spokes[fork]?.[chainId] ?? []) {
32276
- if (s.hub) spokeToHub.set(s.spoke.toLowerCase(), s.hub.toLowerCase());
32277
- }
32278
- const byOracle = /* @__PURE__ */ new Map();
32279
- for (const entry of oracleEntries) {
32280
- if (!entry.oracle || entry.oracle === "0x") continue;
32281
- const key = entry.oracle.toLowerCase();
32282
- let group = byOracle.get(key);
32283
- if (!group) {
32284
- group = { decimals: entry.decimals ?? 8, entries: [] };
32285
- byOracle.set(key, group);
32286
- }
32287
- const spokeLc = entry.spoke.toLowerCase();
32288
- const hub = spokeToHub.get(spokeLc) ?? "";
32289
- group.entries.push({
32290
- underlying: entry.underlying.toLowerCase(),
32291
- hub,
32292
- reserveId: entry.reserveId,
32293
- spoke: spokeLc
32294
- });
32295
- }
32296
- for (const [oracle, group] of byOracle) {
32297
- groups.push({
32298
- fork,
32299
- oracle,
32300
- decimals: group.decimals,
32301
- entries: group.entries
32302
- });
32160
+ const oracleEntries = aaveV4Oracles()?.[chainId] ?? [];
32161
+ const byOracle = /* @__PURE__ */ new Map();
32162
+ for (const entry of oracleEntries) {
32163
+ if (!entry?.oracle || entry.oracle === "0x") continue;
32164
+ if (!entry.spoke) continue;
32165
+ const key = entry.oracle.toLowerCase();
32166
+ let group = byOracle.get(key);
32167
+ if (!group) {
32168
+ group = { decimals: entry.decimals ?? 8, entries: [] };
32169
+ byOracle.set(key, group);
32303
32170
  }
32171
+ group.entries.push({
32172
+ underlying: entry.underlying.toLowerCase(),
32173
+ reserveId: entry.reserveId,
32174
+ spoke: entry.spoke.toLowerCase()
32175
+ });
32176
+ }
32177
+ const groups = [];
32178
+ for (const [oracle, group] of byOracle) {
32179
+ groups.push({ oracle, decimals: group.decimals, entries: group.entries });
32304
32180
  }
32305
32181
  return groups;
32306
32182
  }
32307
32183
  function getAaveV4Calls(chainId) {
32308
32184
  const groups = getAaveV4OracleGroups(chainId);
32309
32185
  const results = [];
32310
- for (const { fork, oracle, decimals, entries } of groups) {
32186
+ for (const { oracle, decimals, entries } of groups) {
32311
32187
  const calls = entries.map((e) => ({
32312
32188
  address: oracle,
32313
32189
  name: "getReservePrice",
@@ -32318,10 +32194,9 @@ function getAaveV4Calls(chainId) {
32318
32194
  meta: {
32319
32195
  oracle,
32320
32196
  oracleDecimals: decimals,
32321
- entries,
32322
- fork
32197
+ entries
32323
32198
  },
32324
- lender: fork
32199
+ lender: "AAVE_V4"
32325
32200
  });
32326
32201
  }
32327
32202
  return results;
@@ -32338,12 +32213,16 @@ function parseAaveV4Results(data, meta, context) {
32338
32213
  try {
32339
32214
  const priceNum = Number(BigInt(rawPrice.toString())) / divisor;
32340
32215
  if (isNaN(priceNum) || priceNum === 0) continue;
32341
- const spokeLenderKey = aaveV4SpokeLenderKey(meta.fork, entry.spoke);
32216
+ const spokeLenderKey = aaveV4SpokeLenderKey(entry.spoke);
32342
32217
  entries.push({
32343
32218
  asset: entry.underlying,
32344
32219
  price: priceNum,
32345
32220
  priceUSD: priceNum,
32346
- marketUid: createMarketUid(chainId, spokeLenderKey, entry.underlying),
32221
+ marketUid: createMarketUid(
32222
+ chainId,
32223
+ spokeLenderKey,
32224
+ String(entry.reserveId)
32225
+ ),
32347
32226
  // Route into the per-spoke lender bucket so price entries live under
32348
32227
  // the same lender key as the lending data (mirrors Morpho's pattern).
32349
32228
  targetLender: spokeLenderKey,