@1delta/margin-fetcher 0.0.218 → 0.0.220

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.
Files changed (58) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +326 -183
  4. package/dist/index.js.map +1 -1
  5. package/dist/lending/public-data/aave-v2-type/publicCallParse.d.ts.map +1 -1
  6. package/dist/lending/public-data/aave-v3-type/publicCallParse.d.ts.map +1 -1
  7. package/dist/lending/public-data/aave-v4-type/fetcher/normalize.d.ts +88 -34
  8. package/dist/lending/public-data/aave-v4-type/fetcher/normalize.d.ts.map +1 -1
  9. package/dist/lending/public-data/aave-v4-type/fetcher/types.d.ts +35 -0
  10. package/dist/lending/public-data/aave-v4-type/fetcher/types.d.ts.map +1 -1
  11. package/dist/lending/public-data/aave-v4-type/publicCallBuild.d.ts +3 -2
  12. package/dist/lending/public-data/aave-v4-type/publicCallBuild.d.ts.map +1 -1
  13. package/dist/lending/public-data/aave-v4-type/publicCallParse.d.ts.map +1 -1
  14. package/dist/lending/public-data/compound-v2/convert/benqi.d.ts +1 -0
  15. package/dist/lending/public-data/compound-v2/convert/benqi.d.ts.map +1 -1
  16. package/dist/lending/public-data/compound-v2/convert/standard.d.ts +1 -0
  17. package/dist/lending/public-data/compound-v2/convert/standard.d.ts.map +1 -1
  18. package/dist/lending/public-data/compound-v2/convert/sumer.d.ts +1 -0
  19. package/dist/lending/public-data/compound-v2/convert/sumer.d.ts.map +1 -1
  20. package/dist/lending/public-data/compound-v2/convert/takara.d.ts +1 -0
  21. package/dist/lending/public-data/compound-v2/convert/takara.d.ts.map +1 -1
  22. package/dist/lending/public-data/compound-v2/convert/tectonic.d.ts +1 -0
  23. package/dist/lending/public-data/compound-v2/convert/tectonic.d.ts.map +1 -1
  24. package/dist/lending/public-data/compound-v3/publicCallParse.d.ts.map +1 -1
  25. package/dist/lending/public-data/euler/fetcher/normalize.d.ts +1 -0
  26. package/dist/lending/public-data/euler/fetcher/normalize.d.ts.map +1 -1
  27. package/dist/lending/public-data/euler/publicCallParse.d.ts.map +1 -1
  28. package/dist/lending/public-data/init/publicCallParse.d.ts.map +1 -1
  29. package/dist/lending/public-data/lista/getMarketsFromChain.d.ts.map +1 -1
  30. package/dist/lending/public-data/morpho/convertPublic.d.ts.map +1 -1
  31. package/dist/lending/public-data/morpho/getMarketsFromChain.d.ts.map +1 -1
  32. package/dist/lending/user-data/aave-v4-type/createAaveV4UserState.d.ts +16 -6
  33. package/dist/lending/user-data/aave-v4-type/createAaveV4UserState.d.ts.map +1 -1
  34. package/dist/lending/user-data/aave-v4-type/userCallBuild.d.ts +7 -3
  35. package/dist/lending/user-data/aave-v4-type/userCallBuild.d.ts.map +1 -1
  36. package/dist/lending/user-data/aave-v4-type/userCallParse.d.ts +22 -6
  37. package/dist/lending/user-data/aave-v4-type/userCallParse.d.ts.map +1 -1
  38. package/dist/lending/user-data/fetch-balances/parse.d.ts.map +1 -1
  39. package/dist/lending/user-data/utils/types.d.ts +0 -9
  40. package/dist/lending/user-data/utils/types.d.ts.map +1 -1
  41. package/dist/lending/user-data/with-permissions/evaluate.d.ts +1 -0
  42. package/dist/lending/user-data/with-permissions/evaluate.d.ts.map +1 -1
  43. package/dist/lending/user-data/with-permissions/types.d.ts +4 -0
  44. package/dist/lending/user-data/with-permissions/types.d.ts.map +1 -1
  45. package/dist/lending-pools/computeLenderDataFromPools.d.ts.map +1 -1
  46. package/dist/types/apiReturnType.d.ts +1 -11
  47. package/dist/types/apiReturnType.d.ts.map +1 -1
  48. package/dist/types/lender/aave-v2-types.d.ts +1 -0
  49. package/dist/types/lender/aave-v2-types.d.ts.map +1 -1
  50. package/dist/types/lender/aave-v3-types.d.ts +1 -3
  51. package/dist/types/lender/aave-v3-types.d.ts.map +1 -1
  52. package/dist/types/lender/compound-v2-types.d.ts +1 -0
  53. package/dist/types/lender/compound-v2-types.d.ts.map +1 -1
  54. package/dist/types/lender/morpho-types.d.ts +1 -0
  55. package/dist/types/lender/morpho-types.d.ts.map +1 -1
  56. package/dist/types/lenderTypes.d.ts +1 -0
  57. package/dist/types/lenderTypes.d.ts.map +1 -1
  58. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { parseAbi, formatEther, BaseError, encodeFunctionData, formatUnits, decodeFunctionResult, decodeAbiParameters, AbiEncodingLengthMismatchError, concatHex, isAddress, InvalidAddressError, pad, stringToHex, boolToHex, integerRegex, numberToHex, bytesRegex, BytesSizeMismatchError, arrayRegex, UnsupportedPackedAbiType } from './chunk-ZVIJSUIM.js';
2
2
  import './chunk-BYTNVMX7.js';
3
3
  import './chunk-PR4QN5HX.js';
4
- import { Lender, isAaveType, isCompoundV3, isMultiMarket, isInit, isMorphoType, isCompoundV2Type, isVenusType, isSumerType, AAVE_V3_LENDERS, AAVE_V2_LENDERS, isAaveV2Type, isAaveV32Type, isAaveV3Type, isEulerType, isAaveV4Type, isYLDR, isCompoundV3Type, isLista, isTectonicType, isBenqiType } from '@1delta/lender-registry';
4
+ import { Lender, isAaveType, isCompoundV3, isMultiMarket, isAaveV4Type, isInit, isMorphoType, isCompoundV2Type, isVenusType, isSumerType, AAVE_V3_LENDERS, AAVE_V2_LENDERS, isAaveV2Type, isAaveV32Type, isAaveV3Type, isEulerType, isYLDR, isCompoundV3Type, isLista, isTectonicType, isBenqiType } 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
7
  import { getEvmChain, multicallRetryUniversal, getEvmClient, getEvmClientUniversal } from '@1delta/providers';
@@ -6278,7 +6278,8 @@ globalThis[GLOBAL_LENDER_DATA_KEY] = {
6278
6278
  aaveV4Hubs: {},
6279
6279
  aaveV4Spokes: {},
6280
6280
  aaveV4Reserves: {},
6281
- aaveV4Oracles: {}
6281
+ aaveV4Oracles: {},
6282
+ aaveV4Peripherals: {}
6282
6283
  };
6283
6284
  function getGlobalData2() {
6284
6285
  return globalThis[GLOBAL_LENDER_DATA_KEY];
@@ -6307,6 +6308,12 @@ var aaveV4Hubs = () => getGlobalData2()?.aaveV4Hubs;
6307
6308
  var aaveV4Spokes = () => getGlobalData2()?.aaveV4Spokes;
6308
6309
  var aaveV4Reserves = () => getGlobalData2()?.aaveV4Reserves;
6309
6310
  var aaveV4Oracles = () => getGlobalData2()?.aaveV4Oracles;
6311
+ function aaveV4SpokeLenderKey(baseHubLender, spoke) {
6312
+ if (!spoke || spoke.length < 4 || !spoke.startsWith("0x")) {
6313
+ throw new Error(`aaveV4SpokeLenderKey: invalid spoke address ${spoke}`);
6314
+ }
6315
+ return `${baseHubLender}_${spoke.slice(2).toUpperCase()}`;
6316
+ }
6310
6317
  var getListUrl = (chainId) => `https://raw.githubusercontent.com/1delta-DAO/token-lists/main/${chainId}.json`;
6311
6318
  async function fetchTokenList(chainId) {
6312
6319
  const data = await fetch(getListUrl(chainId));
@@ -8219,6 +8226,7 @@ var getAaveV2ReservesDataConverter = (lender, chainId, prices, additionalYields,
8219
8226
  // flags
8220
8227
  collateralActive,
8221
8228
  borrowingEnabled,
8229
+ depositsEnabled: true,
8222
8230
  hasStable: configData?.[7 /* stableBorrowRateEnabled */],
8223
8231
  isActive: configData?.[8 /* isActive */],
8224
8232
  isFrozen: configData?.[9 /* isFrozen */]
@@ -8371,6 +8379,7 @@ var getAaveV3ReservesDataConverter = (lender, chainId, prices, additionalYields,
8371
8379
  // flags
8372
8380
  collateralActive: usageAsCollateralEnabled,
8373
8381
  borrowingEnabled,
8382
+ depositsEnabled: true,
8374
8383
  hasStable: configData?.[7 /* stableBorrowRateEnabled */],
8375
8384
  isActive: configData?.[8 /* isActive */],
8376
8385
  isFrozen: configData?.[9 /* isFrozen */],
@@ -8579,6 +8588,7 @@ function parseYLDRCall(chainId, lender, additionalYields, prices, tokenList) {
8579
8588
  // flags
8580
8589
  collateralActive: usageAsCollateralEnabled,
8581
8590
  borrowingEnabled,
8591
+ depositsEnabled: true,
8582
8592
  hasStable: false,
8583
8593
  isActive: configData?.[7 /* isActive */],
8584
8594
  isFrozen: configData?.[8 /* isFrozen */]
@@ -8599,8 +8609,7 @@ function parseYLDRCall(chainId, lender, additionalYields, prices, tokenList) {
8599
8609
  }
8600
8610
  return {
8601
8611
  data: resultReserves,
8602
- chainId,
8603
- eModes: {}
8612
+ chainId
8604
8613
  };
8605
8614
  },
8606
8615
  expectedNumberOfCalls
@@ -8720,6 +8729,7 @@ function parseAave32(chainId, lender, prices, additionalYields, tokenList) {
8720
8729
  // flags
8721
8730
  collateralActive: usageAsCollateralEnabled,
8722
8731
  borrowingEnabled,
8732
+ depositsEnabled: true,
8723
8733
  hasStable: configData?.[7 /* stableBorrowRateEnabled */],
8724
8734
  isActive: configData?.[8 /* isActive */],
8725
8735
  isFrozen: configData?.[9 /* isFrozen */],
@@ -8829,6 +8839,7 @@ var getInitReservesDataConverter = (lender, chainId, prices, additionalYields, t
8829
8839
  rewards: [],
8830
8840
  config: {},
8831
8841
  borrowingEnabled: totalDebt !== "0",
8842
+ depositsEnabled: true,
8832
8843
  params
8833
8844
  };
8834
8845
  });
@@ -8961,7 +8972,8 @@ var getCompoundV3ReservesDataConverter = (lender, chainId, prices, additionalYie
8961
8972
  collateralActive: true,
8962
8973
  isActive: true,
8963
8974
  isFrozen: false,
8964
- borrowingEnabled: false
8975
+ borrowingEnabled: false,
8976
+ depositsEnabled: true
8965
8977
  };
8966
8978
  }
8967
8979
  const baseMeta = tokenList[baseAssetData.baseAsset];
@@ -9036,6 +9048,7 @@ var getCompoundV3ReservesDataConverter = (lender, chainId, prices, additionalYie
9036
9048
  }
9037
9049
  ] : [],
9038
9050
  borrowingEnabled: true,
9051
+ depositsEnabled: true,
9039
9052
  collateralActive: false,
9040
9053
  isActive: true,
9041
9054
  isFrozen: false,
@@ -12164,6 +12177,7 @@ function convertMarketsToMorphoResponse(response, chainId, additionalYields = {
12164
12177
  },
12165
12178
  collateralActive: false,
12166
12179
  borrowingEnabled: true,
12180
+ depositsEnabled: true,
12167
12181
  hasStable: false,
12168
12182
  isActive: true,
12169
12183
  isFrozen: false
@@ -12214,6 +12228,7 @@ function convertMarketsToMorphoResponse(response, chainId, additionalYields = {
12214
12228
  },
12215
12229
  collateralActive: true,
12216
12230
  borrowingEnabled: false,
12231
+ depositsEnabled: true,
12217
12232
  hasStable: false,
12218
12233
  isActive: true,
12219
12234
  isFrozen: false
@@ -12914,6 +12929,7 @@ function getListaMarketDataConverter(lender, chainId, prices, additionalYields =
12914
12929
  },
12915
12930
  collateralActive: false,
12916
12931
  borrowingEnabled: true,
12932
+ depositsEnabled: true,
12917
12933
  hasStable: false,
12918
12934
  isActive: true,
12919
12935
  isFrozen: false
@@ -12954,6 +12970,7 @@ function getListaMarketDataConverter(lender, chainId, prices, additionalYields =
12954
12970
  },
12955
12971
  collateralActive: true,
12956
12972
  borrowingEnabled: false,
12973
+ depositsEnabled: true,
12957
12974
  hasStable: false,
12958
12975
  isActive: true,
12959
12976
  isFrozen: false
@@ -13121,6 +13138,7 @@ function getMorphoMarketDataConverter(lender, chainId, prices, additionalYields
13121
13138
  },
13122
13139
  collateralActive: false,
13123
13140
  borrowingEnabled: true,
13141
+ depositsEnabled: true,
13124
13142
  hasStable: false,
13125
13143
  isActive: true,
13126
13144
  isFrozen: false
@@ -13166,6 +13184,7 @@ function getMorphoMarketDataConverter(lender, chainId, prices, additionalYields
13166
13184
  },
13167
13185
  collateralActive: true,
13168
13186
  borrowingEnabled: false,
13187
+ depositsEnabled: true,
13169
13188
  hasStable: false,
13170
13189
  isActive: true,
13171
13190
  isFrozen: false
@@ -15763,6 +15782,7 @@ function convertSingleEntry(opts) {
15763
15782
  rewards: [],
15764
15783
  collateralActive,
15765
15784
  borrowingEnabled,
15785
+ depositsEnabled: !pausedActions[0 /* MINT */],
15766
15786
  params: {
15767
15787
  metadata: {
15768
15788
  cToken,
@@ -15853,6 +15873,7 @@ function convertSumerEntry(opts) {
15853
15873
  rewards: [],
15854
15874
  collateralActive,
15855
15875
  borrowingEnabled,
15876
+ depositsEnabled: true,
15856
15877
  params: {
15857
15878
  metadata: {
15858
15879
  cToken,
@@ -15924,6 +15945,7 @@ function convertTakaraEntry(opts) {
15924
15945
  rewards: [],
15925
15946
  collateralActive: info.isListed,
15926
15947
  borrowingEnabled: info.isListed,
15948
+ depositsEnabled: true,
15927
15949
  params: {
15928
15950
  metadata: {
15929
15951
  cToken,
@@ -15988,6 +16010,7 @@ function convertTectonicEntry(opts) {
15988
16010
  rewards: [],
15989
16011
  collateralActive: info.asCollateralEnabled,
15990
16012
  borrowingEnabled: info.asCollateralEnabled,
16013
+ depositsEnabled: true,
15991
16014
  params: {
15992
16015
  metadata: {
15993
16016
  cToken,
@@ -16151,6 +16174,7 @@ function convertBenqiEntry(opts) {
16151
16174
  rewards: [],
16152
16175
  collateralActive,
16153
16176
  borrowingEnabled,
16177
+ depositsEnabled: !parsed.mintPaused,
16154
16178
  params: {
16155
16179
  metadata: {
16156
16180
  cToken,
@@ -17732,6 +17756,7 @@ function buildTokenEntry(info, config, collateralActive, borrowVaults, opts) {
17732
17756
  config,
17733
17757
  collateralActive,
17734
17758
  borrowingEnabled: isBorrowVault,
17759
+ depositsEnabled: true,
17735
17760
  hasStable: false,
17736
17761
  isActive: true,
17737
17762
  isFrozen: false,
@@ -17869,6 +17894,7 @@ var getEulerV2ReservesDataConverter = (lender, chainId, prices, additionalYields
17869
17894
  // flags
17870
17895
  collateralActive: entry.collateralActive,
17871
17896
  borrowingEnabled: entry.borrowingEnabled,
17897
+ depositsEnabled: entry.depositsEnabled,
17872
17898
  hasStable: entry.hasStable,
17873
17899
  isActive: entry.isActive,
17874
17900
  isFrozen: entry.isFrozen,
@@ -17894,7 +17920,7 @@ var getEulerV2ReservesDataConverter = (lender, chainId, prices, additionalYields
17894
17920
 
17895
17921
  // src/lending/public-data/aave-v4-type/publicCallBuild.ts
17896
17922
  var BASE_CALLS_PER_RESERVE = 5;
17897
- var CALLS_PER_SPOKE_TAIL = 2;
17923
+ var CALLS_PER_SPOKE_TAIL = 1;
17898
17924
  var MAX_HUB_ASSETS = 25;
17899
17925
  function isValidAddress(addr) {
17900
17926
  return !!addr && addr !== "0x" && addr.length > 2;
@@ -17902,6 +17928,13 @@ function isValidAddress(addr) {
17902
17928
  function getSpokeReserves(reservesMap, spokeAddr) {
17903
17929
  return reservesMap[spokeAddr.toLowerCase()] ?? reservesMap[spokeAddr] ?? [];
17904
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
+ }
17905
17938
  function getDynamicConfigCount(spokeEntry) {
17906
17939
  const max = spokeEntry.dynamicConfigKeyMax ?? 0;
17907
17940
  return max + 1;
@@ -17953,18 +17986,11 @@ var buildAaveV4LenderReserveCall = (chainId, lender) => {
17953
17986
  });
17954
17987
  }
17955
17988
  }
17956
- calls.push(
17957
- {
17958
- address: spokeAddr,
17959
- name: "getLiquidationConfig",
17960
- params: []
17961
- },
17962
- {
17963
- address: spokeAddr,
17964
- name: "ORACLE",
17965
- params: []
17966
- }
17967
- );
17989
+ calls.push({
17990
+ address: spokeAddr,
17991
+ name: "getLiquidationConfig",
17992
+ params: []
17993
+ });
17968
17994
  }
17969
17995
  for (const spokeEntry of spokes) {
17970
17996
  if (!isValidAddress(spokeEntry.spoke)) continue;
@@ -18007,6 +18033,20 @@ var buildAaveV4LenderReserveCall = (chainId, lender) => {
18007
18033
  }
18008
18034
  );
18009
18035
  }
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
+ }
18049
+ }
18010
18050
  }
18011
18051
  return calls;
18012
18052
  };
@@ -18029,6 +18069,13 @@ var getAaveV4ExpectedCallCount = (chainId, lender) => {
18029
18069
  const hubEntry = aaveV4Hubs()?.[lender]?.[chainId];
18030
18070
  if (hubEntry?.hub && isValidAddress(hubEntry.hub)) {
18031
18071
  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
+ }
18078
+ }
18032
18079
  }
18033
18080
  return count;
18034
18081
  };
@@ -18036,52 +18083,49 @@ var getAaveV4ExpectedCallCount = (chainId, lender) => {
18036
18083
  // src/lending/public-data/aave-v4-type/fetcher/normalize.ts
18037
18084
  function toTokenAmount2(raw, decimals) {
18038
18085
  if (raw === 0n) return "0";
18039
- const divisor = 10 ** decimals;
18040
- return (Number(raw) / divisor).toString();
18086
+ const negative = raw < 0n;
18087
+ const abs = negative ? -raw : raw;
18088
+ const s = abs.toString();
18089
+ let intPart;
18090
+ let fracPart;
18091
+ if (s.length <= decimals) {
18092
+ intPart = "0";
18093
+ fracPart = "0".repeat(decimals - s.length) + s;
18094
+ } else {
18095
+ intPart = s.slice(0, s.length - decimals);
18096
+ fracPart = s.slice(s.length - decimals);
18097
+ }
18098
+ fracPart = fracPart.replace(/0+$/, "");
18099
+ const out = fracPart ? `${intPart}.${fracPart}` : intPart;
18100
+ return negative ? `-${out}` : out;
18041
18101
  }
18042
18102
  function toTokenNumber(raw, decimals) {
18043
18103
  if (raw === 0n) return 0;
18044
18104
  return Number(raw) / 10 ** decimals;
18045
18105
  }
18046
18106
  var RAY2 = 1e27;
18047
- var SECONDS_PER_YEAR4 = 31536e3;
18107
+ var MAX_SPOKE_CAP = 2 ** 40 - 1;
18048
18108
  function rayRateToApr(rateRay) {
18049
18109
  if (rateRay === 0n) return 0;
18050
- return (Number(rateRay) / RAY2 - 1) * SECONDS_PER_YEAR4 * 100;
18110
+ return Number(rateRay) / RAY2 * 100;
18051
18111
  }
18052
- function normalizeAaveV4(spokeDataList, chainId, lender, prices, additionalYields, tokenList, lenderShortNameFn, createMarketUidFn, toOracleKeyFn, toGenericPriceKeyFn, expectedHub) {
18053
- const data = {};
18054
- const eModes = {};
18112
+ function normalizeAaveV4(spokeDataList, chainId, baseHubLender, prices, additionalYields, tokenList, lenderShortNameFn, createMarketUidFn, toOracleKeyFn, toGenericPriceKeyFn, expectedHub) {
18113
+ const out = {};
18055
18114
  const hubFilter = expectedHub?.toLowerCase();
18056
18115
  for (const spokeData of spokeDataList) {
18057
18116
  const spokeAddr = spokeData.spoke.toLowerCase();
18117
+ const spokeLenderKey = aaveV4SpokeLenderKey(baseHubLender, spokeAddr);
18118
+ let spokeHub = "";
18058
18119
  const spokeReserves = spokeData.reserves;
18120
+ const data = {};
18059
18121
  for (const reserve of spokeReserves) {
18060
18122
  const reserveHub = reserve.reserve.hub?.toLowerCase();
18061
18123
  if (hubFilter && reserveHub && reserveHub !== hubFilter)
18062
18124
  continue;
18063
- for (const [keyStr, dynCfg] of Object.entries(
18064
- reserve.dynamicConfigs
18065
- )) {
18066
- const configKey = `${spokeAddr}:${keyStr}`;
18067
- if (!eModes[configKey] && dynCfg.collateralFactor > 0) {
18068
- eModes[configKey] = {
18069
- category: configKey,
18070
- label: `${spokeData.label} / Config ${keyStr}`,
18071
- borrowCollateralFactor: dynCfg.collateralFactor / BPS,
18072
- collateralFactor: dynCfg.collateralFactor / BPS,
18073
- priceSource: spokeData.oracle
18074
- };
18075
- }
18076
- }
18077
- }
18078
- for (const reserve of spokeReserves) {
18079
- const reserveHub = reserve.reserve.hub?.toLowerCase();
18080
- if (hubFilter && reserveHub && reserveHub !== hubFilter)
18081
- continue;
18125
+ if (!spokeHub) spokeHub = reserveHub ?? "";
18082
18126
  const underlying = reserve.reserve.underlying.toLowerCase();
18083
18127
  const decimals = reserve.reserve.decimals;
18084
- const marketUid = createMarketUidFn(chainId, lender, underlying);
18128
+ const marketUid = createMarketUidFn(chainId, spokeLenderKey, underlying);
18085
18129
  const assetMeta = tokenList[underlying];
18086
18130
  const oracleKey = toOracleKeyFn(assetMeta?.assetGroup ?? null) ?? toGenericPriceKeyFn(underlying, chainId);
18087
18131
  let price = 0;
@@ -18090,21 +18134,34 @@ function normalizeAaveV4(spokeDataList, chainId, lender, prices, additionalYield
18090
18134
  } else {
18091
18135
  price = prices[oracleKey] ?? 0;
18092
18136
  }
18093
- const totalDeposits = toTokenAmount2(
18137
+ const totalDepositsStr = toTokenAmount2(
18094
18138
  reserve.suppliedAssets,
18095
18139
  decimals
18096
18140
  );
18097
- const totalDebt = toTokenAmount2(reserve.totalDebt, decimals);
18141
+ const totalDebtStr = toTokenAmount2(reserve.totalDebt, decimals);
18098
18142
  const totalDepositsNum = toTokenNumber(
18099
18143
  reserve.suppliedAssets,
18100
18144
  decimals
18101
18145
  );
18102
18146
  const totalDebtNum = toTokenNumber(reserve.totalDebt, decimals);
18103
- const liquidity = totalDepositsNum - totalDebtNum;
18104
- const variableBorrowRate = rayRateToApr(
18105
- reserve.hubAsset.drawnRate
18106
- );
18147
+ const totalDepositsUSD = totalDepositsNum * price;
18148
+ const totalDebtUSD = totalDebtNum * price;
18149
+ const supplyCap = reserve.spokeBinding?.addCap ?? 0;
18150
+ const borrowCap = reserve.spokeBinding?.drawCap ?? 0;
18107
18151
  const hubDecimals = reserve.hubAsset.decimals || decimals;
18152
+ const hubLiquidityNum = toTokenNumber(
18153
+ reserve.hubAsset.liquidity ?? 0n,
18154
+ hubDecimals
18155
+ );
18156
+ let borrowLiquidityNum = hubLiquidityNum;
18157
+ if (borrowCap > 0 && borrowCap < MAX_SPOKE_CAP) {
18158
+ const spokeHeadroom = borrowCap - totalDebtNum;
18159
+ if (spokeHeadroom < borrowLiquidityNum)
18160
+ borrowLiquidityNum = spokeHeadroom;
18161
+ }
18162
+ if (borrowLiquidityNum < 0) borrowLiquidityNum = 0;
18163
+ const borrowLiquidityUSD = borrowLiquidityNum * price;
18164
+ const variableBorrowRate = rayRateToApr(reserve.hubAsset.drawnRate);
18108
18165
  const hubTotalSupply = toTokenNumber(
18109
18166
  reserve.hubAsset.totalAddedAssets ?? 0n,
18110
18167
  hubDecimals
@@ -18116,13 +18173,14 @@ function normalizeAaveV4(spokeDataList, chainId, lender, prices, additionalYield
18116
18173
  const hubUtilization = hubTotalSupply > 0 ? hubTotalOwed / hubTotalSupply : 0;
18117
18174
  const feeRate = reserve.hubAsset.liquidityFee ? reserve.hubAsset.liquidityFee / BPS : 0;
18118
18175
  const depositRate = variableBorrowRate * hubUtilization * (1 - feeRate);
18176
+ const collateralRiskBps = reserve.config.collateralRisk || reserve.reserve.collateralRisk || 0;
18177
+ const riskPremiumThresholdBps = reserve.spokeBinding?.riskPremiumThreshold ?? 0;
18119
18178
  const config = {};
18120
18179
  for (const [keyStr, dynCfg] of Object.entries(
18121
18180
  reserve.dynamicConfigs
18122
18181
  )) {
18123
- const configKey = `${spokeAddr}:${keyStr}`;
18124
- config[configKey] = {
18125
- category: configKey,
18182
+ config[keyStr] = {
18183
+ category: keyStr,
18126
18184
  label: `${spokeData.label} / Config ${keyStr}`,
18127
18185
  borrowCollateralFactor: dynCfg.collateralFactor / BPS,
18128
18186
  collateralFactor: dynCfg.collateralFactor / BPS,
@@ -18132,9 +18190,8 @@ function normalizeAaveV4(spokeDataList, chainId, lender, prices, additionalYield
18132
18190
  };
18133
18191
  }
18134
18192
  if (Object.keys(config).length === 0) {
18135
- const defaultKey = `${spokeAddr}:0`;
18136
- config[defaultKey] = {
18137
- category: defaultKey,
18193
+ config["0"] = {
18194
+ category: "0",
18138
18195
  label: `${spokeData.label} / Default`,
18139
18196
  borrowCollateralFactor: 0,
18140
18197
  collateralFactor: 0,
@@ -18143,62 +18200,66 @@ function normalizeAaveV4(spokeDataList, chainId, lender, prices, additionalYield
18143
18200
  debtDisabled: !reserve.config.borrowable || reserve.config.paused
18144
18201
  };
18145
18202
  }
18146
- if (data[marketUid]) {
18147
- Object.assign(data[marketUid].config, config);
18148
- if (!data[marketUid].collateralActive) {
18149
- data[marketUid].collateralActive = Object.values(reserve.dynamicConfigs).some(
18150
- (c) => c.collateralFactor > 0
18151
- );
18152
- }
18153
- if (!data[marketUid].borrowingEnabled) {
18154
- data[marketUid].borrowingEnabled = reserve.config.borrowable;
18155
- }
18156
- } else {
18157
- data[marketUid] = {
18158
- marketUid,
18159
- name: lenderShortNameFn(lender) + " " + (assetMeta?.symbol ?? ""),
18160
- poolId: underlying,
18161
- underlying,
18162
- asset: assetMeta,
18163
- totalDeposits,
18164
- totalDebtStable: "0",
18165
- totalDebt,
18166
- totalLiquidity: liquidity,
18167
- totalDepositsUSD: totalDepositsNum * price,
18168
- totalDebtStableUSD: 0,
18169
- totalDebtUSD: totalDebtNum * price,
18170
- totalLiquidityUSD: liquidity * price,
18171
- depositRate,
18172
- variableBorrowRate,
18173
- stableBorrowRate: 0,
18174
- intrinsicYield: additionalYields?.intrinsicYields?.[oracleKey] ?? 0,
18175
- rewards: [],
18176
- decimals,
18177
- config,
18178
- collateralActive: Object.values(reserve.dynamicConfigs).some(
18179
- (c) => c.collateralFactor > 0
18180
- ),
18181
- borrowingEnabled: reserve.config.borrowable,
18182
- hasStable: false,
18183
- isActive: !reserve.config.paused,
18184
- isFrozen: reserve.config.frozen,
18185
- borrowCap: 0,
18186
- supplyCap: 0,
18187
- debtCeiling: 0,
18188
- params: {
18189
- metadata: {
18190
- spoke: spokeAddr,
18191
- hub: reserve.reserve.hub.toLowerCase(),
18192
- assetId: reserve.reserve.assetId,
18193
- reserveId: reserve.reserveId,
18194
- oracle: spokeData.oracle.toLowerCase()
18195
- }
18203
+ const collateralActive = Object.values(reserve.dynamicConfigs).some(
18204
+ (c) => c.collateralFactor > 0
18205
+ );
18206
+ data[marketUid] = {
18207
+ marketUid,
18208
+ name: lenderShortNameFn(baseHubLender) + " " + (assetMeta?.symbol ?? ""),
18209
+ poolId: underlying,
18210
+ underlying,
18211
+ asset: assetMeta,
18212
+ totalDeposits: totalDepositsStr,
18213
+ totalDebtStable: "0",
18214
+ totalDebt: totalDebtStr,
18215
+ // V4 borrow liquidity comes from the hub, not from local supplies.
18216
+ // See the comment block where `borrowLiquidityNum` is computed.
18217
+ totalLiquidity: borrowLiquidityNum,
18218
+ totalDepositsUSD,
18219
+ totalDebtStableUSD: 0,
18220
+ totalDebtUSD,
18221
+ totalLiquidityUSD: borrowLiquidityUSD,
18222
+ depositRate,
18223
+ variableBorrowRate,
18224
+ stableBorrowRate: 0,
18225
+ intrinsicYield: additionalYields?.intrinsicYields?.[oracleKey] ?? 0,
18226
+ rewards: [],
18227
+ decimals,
18228
+ config,
18229
+ collateralActive,
18230
+ borrowingEnabled: reserve.config.borrowable,
18231
+ depositsEnabled: reserve.config.receiveSharesEnabled && !reserve.config.paused,
18232
+ hasStable: false,
18233
+ isActive: !reserve.config.paused,
18234
+ isFrozen: reserve.config.frozen,
18235
+ borrowCap,
18236
+ supplyCap,
18237
+ debtCeiling: 0,
18238
+ params: {
18239
+ metadata: {
18240
+ assetId: reserve.reserve.assetId,
18241
+ reserveId: reserve.reserveId
18196
18242
  }
18197
- };
18198
- }
18243
+ },
18244
+ collateralRiskBps,
18245
+ riskPremiumThresholdBps
18246
+ };
18247
+ }
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
+ };
18199
18260
  }
18200
18261
  }
18201
- return { data, chainId, eModes };
18262
+ return out;
18202
18263
  }
18203
18264
 
18204
18265
  // src/lending/public-data/aave-v4-type/publicCallParse.ts
@@ -18291,7 +18352,6 @@ var getAaveV4ReservesDataConverter = (lender, chainId, prices, additionalYields,
18291
18352
  });
18292
18353
  }
18293
18354
  const rawLiqConfig = data[offset];
18294
- const rawOracle = data[offset + 1];
18295
18355
  offset += CALLS_PER_SPOKE_TAIL;
18296
18356
  const liquidationConfig = {
18297
18357
  targetHealthFactor: BigInt(
@@ -18306,7 +18366,7 @@ var getAaveV4ReservesDataConverter = (lender, chainId, prices, additionalYields,
18306
18366
  };
18307
18367
  spokeDataList.push({
18308
18368
  spoke: spokeAddr,
18309
- oracle: rawOracle ?? spokeEntry.oracle,
18369
+ oracle: spokeEntry.oracle,
18310
18370
  label: spokeEntry.label,
18311
18371
  oracleDecimals: 8,
18312
18372
  liquidationConfig,
@@ -18375,6 +18435,34 @@ var getAaveV4ReservesDataConverter = (lender, chainId, prices, additionalYields,
18375
18435
  });
18376
18436
  }
18377
18437
  offset += MAX_HUB_ASSETS * 3;
18438
+ for (const spokeData of spokeDataList) {
18439
+ const spokeReservesMeta = getSpokeReserves2(
18440
+ reservesMap,
18441
+ spokeData.spoke
18442
+ );
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
+ }
18465
+ }
18378
18466
  }
18379
18467
  for (const spokeData of spokeDataList) {
18380
18468
  for (const reserve of spokeData.reserves) {
@@ -20257,31 +20345,58 @@ var getEulerUserDataConverter = (lender, chainId, account, metaMap, subAccountIn
20257
20345
  };
20258
20346
 
20259
20347
  // src/lending/user-data/aave-v4-type/createAaveV4UserState.ts
20260
- function resolveV4Config(configs, userConfigKey) {
20261
- if (!configs) return { config: void 0, spokeAddr: void 0 };
20262
- if (userConfigKey && configs[userConfigKey]) {
20263
- return {
20264
- config: configs[userConfigKey],
20265
- spokeAddr: userConfigKey.split(":")[0]
20266
- };
20267
- }
20268
- const entries = Object.entries(configs);
20269
- if (entries.length === 0) return { config: void 0, spokeAddr: void 0 };
20270
- const [key, config] = entries[0];
20271
- const spokeAddr = key.split(":")[0];
20272
- return { config, spokeAddr };
20348
+ function resolveDynamicConfig(configs, userConfigKey) {
20349
+ if (!configs) return void 0;
20350
+ if (userConfigKey && configs[userConfigKey]) return configs[userConfigKey];
20351
+ const entries = Object.values(configs);
20352
+ return entries.length > 0 ? entries[0] : void 0;
20273
20353
  }
20274
- function getConfigScopedPrice(meta, spokeAddr) {
20275
- if (spokeAddr) {
20276
- const byConfig = meta?.oraclePrice?.byConfig;
20277
- const configPrice = byConfig?.[spokeAddr]?.oraclePriceUsd;
20278
- if (configPrice != null && configPrice > 0) return configPrice;
20279
- }
20354
+ function getSpokeScopedPrice(meta) {
20280
20355
  return getOraclePrice(meta);
20281
20356
  }
20282
20357
  function createAaveV4UserState(payload, lenderData, totalDeposits24h = 0, totalDebt24h = 0) {
20283
- const assetKeys = getMarketUidsFromMeta(lenderData);
20284
20358
  const { chainId, account } = payload;
20359
+ const positions = payload.lendingPositions ?? {};
20360
+ const positionMarketUids = Object.keys(positions);
20361
+ const spokeLenderKey = positionMarketUids.length > 0 ? positionMarketUids[0].split(":")[0] : "";
20362
+ const allMarketUids = getMarketUidsFromMeta(lenderData);
20363
+ const spokeMarketUids = spokeLenderKey ? allMarketUids.filter((uid) => uid.startsWith(spokeLenderKey + ":")) : [];
20364
+ const collaterals = [];
20365
+ let totalDebtForPremium = 0;
20366
+ for (const marketUid of positionMarketUids) {
20367
+ const meta = lenderData?.[marketUid];
20368
+ const pos = positions[marketUid];
20369
+ if (!meta || !pos) continue;
20370
+ const userConfigKey = pos.userConfigKey;
20371
+ const userConfig2 = resolveDynamicConfig(
20372
+ meta.configs ?? null,
20373
+ userConfigKey
20374
+ );
20375
+ const collateralFactor = userConfig2?.collateralFactor ?? 0;
20376
+ const depositsUSDOracle = pos.depositsUSDOracle ?? pos.depositsUSD ?? 0;
20377
+ const debtUSDOracle = pos.debtUSDOracle ?? pos.debtUSD ?? 0;
20378
+ if (pos.collateralEnabled && !userConfig2?.collateralDisabled && collateralFactor > 0 && depositsUSDOracle > 0) {
20379
+ const riskBps = Number(meta.collateralRiskBps ?? 0);
20380
+ collaterals.push({ riskBps, valueUsd: depositsUSDOracle });
20381
+ }
20382
+ if (debtUSDOracle > 0) {
20383
+ totalDebtForPremium += debtUSDOracle;
20384
+ }
20385
+ }
20386
+ let riskPremiumBps = 0;
20387
+ if (totalDebtForPremium > 0) {
20388
+ const sorted = collaterals.slice().sort((a, b) => a.riskBps - b.riskBps);
20389
+ let debtLeft = totalDebtForPremium;
20390
+ let weightedSum = 0;
20391
+ for (const c of sorted) {
20392
+ if (debtLeft <= 0) break;
20393
+ const used = Math.min(c.valueUsd, debtLeft);
20394
+ weightedSum += used * c.riskBps;
20395
+ debtLeft -= used;
20396
+ }
20397
+ const covered = totalDebtForPremium - debtLeft;
20398
+ riskPremiumBps = covered > 0 ? weightedSum / covered : 0;
20399
+ }
20285
20400
  let depositInterest = 0;
20286
20401
  let borrowInterest = 0;
20287
20402
  let rewardDepositAccrual = 0;
@@ -20296,10 +20411,10 @@ function createAaveV4UserState(payload, lenderData, totalDeposits24h = 0, totalD
20296
20411
  let borrowDiscountedCollateralAllActive = 0;
20297
20412
  let collateralAllActive = 0;
20298
20413
  let rewardsPerAsset = {};
20299
- for (const marketUid of assetKeys) {
20300
- if (!lenderData?.[marketUid] || !payload.lendingPositions[marketUid])
20301
- continue;
20302
- const pos = payload.lendingPositions[marketUid];
20414
+ for (const marketUid of positionMarketUids) {
20415
+ const meta = lenderData?.[marketUid];
20416
+ const pos = positions[marketUid];
20417
+ if (!meta || !pos) continue;
20303
20418
  const { depositsUSD, debtStableUSD, debtUSD, collateralEnabled } = pos;
20304
20419
  const depositsUSDOracle = pos.depositsUSDOracle ?? depositsUSD;
20305
20420
  const debtUSDOracle = pos.debtUSDOracle ?? debtUSD;
@@ -20311,11 +20426,19 @@ function createAaveV4UserState(payload, lenderData, totalDeposits24h = 0, totalD
20311
20426
  rewards,
20312
20427
  flags,
20313
20428
  configs
20314
- } = lenderData[marketUid];
20315
- const { config: userConfigForAsset } = resolveV4Config(
20429
+ } = meta;
20430
+ const userConfigForAsset = resolveDynamicConfig(
20316
20431
  configs,
20317
20432
  pos.userConfigKey
20318
20433
  );
20434
+ const positionThresholdBps = Number(
20435
+ meta.riskPremiumThresholdBps ?? 0
20436
+ );
20437
+ const clampedPremiumBps = positionThresholdBps > 0 ? Math.min(riskPremiumBps, positionThresholdBps) : riskPremiumBps;
20438
+ const userPremiumMultiplier = 1 + clampedPremiumBps / 1e4;
20439
+ const effectiveVariableBorrowRate = (variableBorrowRate ?? 0) * userPremiumMultiplier;
20440
+ pos.variableBorrowRate = effectiveVariableBorrowRate;
20441
+ pos.riskPremiumBps = clampedPremiumBps;
20319
20442
  deposits += depositsUSD;
20320
20443
  debt += debtUSD + (debtStableUSD ?? 0);
20321
20444
  oracleDebt += debtUSDOracle + (pos.debtStableUSDOracle ?? debtStableUSD ?? 0);
@@ -20341,7 +20464,7 @@ function createAaveV4UserState(payload, lenderData, totalDeposits24h = 0, totalD
20341
20464
  collateralAllActive += (userConfigForAsset?.collateralFactor ?? 1) * depositsUSDOracle;
20342
20465
  }
20343
20466
  depositInterest += (depositRate ?? 0) * depositsUSD;
20344
- borrowInterest += debtUSD * (variableBorrowRate ?? 0) + (debtStableUSD ?? 0) * (stableBorrowRate ?? 0);
20467
+ borrowInterest += debtUSD * effectiveVariableBorrowRate + (debtStableUSD ?? 0) * (stableBorrowRate ?? 0);
20345
20468
  }
20346
20469
  const nav = deposits - debt;
20347
20470
  const balanceData2 = {
@@ -20379,16 +20502,16 @@ function createAaveV4UserState(payload, lenderData, totalDeposits24h = 0, totalD
20379
20502
  0,
20380
20503
  borrowDiscountedCollateral - balanceData2.adjustedDebt
20381
20504
  );
20382
- for (const marketUid of assetKeys) {
20383
- if (!lenderData?.[marketUid]) continue;
20384
- const meta = lenderData[marketUid];
20505
+ for (const marketUid of spokeMarketUids) {
20506
+ const meta = lenderData?.[marketUid];
20507
+ if (!meta) continue;
20385
20508
  const { configs, flags, borrowLiquidity, withdrawLiquidity } = meta;
20386
- const pos = payload.lendingPositions[marketUid];
20387
- const { config, spokeAddr } = resolveV4Config(
20509
+ const pos = positions[marketUid];
20510
+ const config = resolveDynamicConfig(
20388
20511
  configs,
20389
20512
  pos ? pos.userConfigKey : void 0
20390
20513
  );
20391
- const price = getConfigScopedPrice(meta, spokeAddr);
20514
+ const price = getSpokeScopedPrice(meta);
20392
20515
  const bcf = config?.borrowCollateralFactor ?? 1;
20393
20516
  const bf = config?.borrowFactor ?? 1;
20394
20517
  if (pos) {
@@ -20424,7 +20547,7 @@ function createAaveV4UserState(payload, lenderData, totalDeposits24h = 0, totalD
20424
20547
  if (borrowLiquidity != null) {
20425
20548
  borrowable = String(Math.min(Number(borrowable), borrowLiquidity));
20426
20549
  }
20427
- payload.lendingPositions[marketUid] = {
20550
+ positions[marketUid] = {
20428
20551
  marketUid,
20429
20552
  deposits: "0",
20430
20553
  debt: "0",
@@ -20452,7 +20575,7 @@ function createAaveV4UserState(payload, lenderData, totalDeposits24h = 0, totalD
20452
20575
  balanceData: balanceData2,
20453
20576
  aprData: aprData2,
20454
20577
  userConfig,
20455
- positions: Object.values(payload.lendingPositions)
20578
+ positions: Object.values(positions)
20456
20579
  }
20457
20580
  ]
20458
20581
  };
@@ -20462,6 +20585,18 @@ function createAaveV4UserState(payload, lenderData, totalDeposits24h = 0, totalD
20462
20585
  var getAaveV4UserDataConverter = (lender, chainId, account, metaMap) => {
20463
20586
  const spokes = aaveV4Spokes()?.[lender]?.[chainId] ?? [];
20464
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
+ }
20465
20600
  const oracleEntries = aaveV4Oracles()?.[lender]?.[chainId] ?? [];
20466
20601
  const spokeReserveToUnderlying = /* @__PURE__ */ new Map();
20467
20602
  for (const oe of oracleEntries) {
@@ -20476,12 +20611,16 @@ var getAaveV4UserDataConverter = (lender, chainId, account, metaMap) => {
20476
20611
  for (const spokeEntry of spokes) {
20477
20612
  const spokeAddr = spokeEntry.spoke;
20478
20613
  if (!spokeAddr || spokeAddr === "0x" || spokeAddr.length <= 2) continue;
20479
- const reserves = reservesMap[spokeAddr.toLowerCase()] ?? reservesMap[spokeAddr] ?? [];
20614
+ const spokeAddrLc = spokeAddr.toLowerCase();
20615
+ const spokeLenderKey = aaveV4SpokeLenderKey(lender, spokeAddrLc);
20616
+ const reserves = reservesMap[spokeAddrLc] ?? reservesMap[spokeAddr] ?? [];
20480
20617
  for (const entry of reserves) {
20481
20618
  const rid = typeof entry === "number" ? entry : entry.reserveId;
20482
- const underlying = ((typeof entry === "object" ? entry.underlying : void 0) ?? spokeReserveToUnderlying.get(`${spokeAddr.toLowerCase()}:${rid}`) ?? "").toLowerCase();
20619
+ const underlying = ((typeof entry === "object" ? entry.underlying : void 0) ?? spokeReserveToUnderlying.get(`${spokeAddrLc}:${rid}`) ?? "").toLowerCase();
20483
20620
  reserveEntries.push({
20484
20621
  spokeAddr,
20622
+ spokeAddrLc,
20623
+ spokeLenderKey,
20485
20624
  reserveId: rid,
20486
20625
  underlying
20487
20626
  });
@@ -20493,23 +20632,14 @@ var getAaveV4UserDataConverter = (lender, chainId, account, metaMap) => {
20493
20632
  if (data.length !== expectedNumberOfCalls) {
20494
20633
  return void 0;
20495
20634
  }
20496
- const lendingPositions = {};
20497
- const underlyingToUid = /* @__PURE__ */ new Map();
20498
- if (metaMap) {
20499
- for (const [uid, meta] of Object.entries(metaMap)) {
20500
- const addr = (meta?.underlying ?? "").toLowerCase();
20501
- if (addr) underlyingToUid.set(addr, uid);
20502
- }
20503
- }
20504
- let totalDebt24h = 0;
20505
- let totalDeposits24h = 0;
20635
+ const perSpoke = {};
20506
20636
  for (let i = 0; i < reserveEntries.length; i++) {
20507
- const { underlying, spokeAddr } = reserveEntries[i];
20508
- const key = underlying ? createMarketUid(chainId, lender, underlying) : underlyingToUid.get(underlying) ?? "";
20509
- const metaEntity = metaMap?.[key];
20637
+ const { underlying, spokeAddrLc, spokeLenderKey } = reserveEntries[i];
20638
+ if (!underlying) continue;
20639
+ const key = createMarketUid(chainId, spokeLenderKey, underlying);
20640
+ const metaEntity = flatMeta[key];
20510
20641
  if (!metaEntity) continue;
20511
20642
  const base = i * USER_CALLS_PER_RESERVE;
20512
- const spokeLc = spokeAddr.toLowerCase();
20513
20643
  const userPositionResult = data[base + 3];
20514
20644
  const userDynConfigKey = Number(
20515
20645
  userPositionResult?.dynamicConfigKey ?? 0
@@ -20519,26 +20649,34 @@ var getAaveV4UserDataConverter = (lender, chainId, account, metaMap) => {
20519
20649
  data,
20520
20650
  key,
20521
20651
  metaEntity,
20522
- spokeLc
20652
+ spokeAddrLc
20523
20653
  );
20524
20654
  if (!dataForAsset) continue;
20525
- dataForAsset.userConfigKey = `${spokeLc}:${userDynConfigKey}`;
20526
- totalDebt24h += addedDebt;
20527
- totalDeposits24h += addedDeposits;
20528
- lendingPositions[key] = dataForAsset;
20655
+ 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;
20529
20664
  }
20530
- const payload = {
20531
- chainId,
20532
- account,
20533
- lendingPositions,
20534
- rewards: []};
20535
- const userData = createAaveV4UserState(
20536
- payload,
20537
- metaMap,
20538
- totalDeposits24h,
20539
- totalDebt24h
20540
- );
20541
- return userData;
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
+ );
20678
+ }
20679
+ return out;
20542
20680
  },
20543
20681
  expectedNumberOfCalls
20544
20682
  ];
@@ -20600,7 +20738,7 @@ function createAaveV4Entry(base, data, key, meta, spokeAddr) {
20600
20738
  // src/lending/user-data/fetch-balances/parse.ts
20601
20739
  function getUserDataConverter(lender, chainId, account, params, meta) {
20602
20740
  if (isAaveV4Type(lender))
20603
- return getAaveV4UserDataConverter(lender, chainId, account, meta?.[lender]);
20741
+ return getAaveV4UserDataConverter(lender, chainId, account, meta);
20604
20742
  if (isYLDR(lender))
20605
20743
  return getYldrUserDataConverter(lender, chainId, account, meta?.[lender]);
20606
20744
  if (isAaveV2Type(lender))
@@ -25392,7 +25530,6 @@ function unflattenLenderData(pools) {
25392
25530
  if (!result[chainId].data[lender]) {
25393
25531
  result[chainId].data[lender] = {
25394
25532
  data: {},
25395
- eModes: {},
25396
25533
  chainId: String(chainId)
25397
25534
  };
25398
25535
  }
@@ -25742,6 +25879,12 @@ function resolveDebitDataKey(chainId, lender, tokenAddress, cToken) {
25742
25879
  function needsLenderApproval(params) {
25743
25880
  const { lender, lenderDebitData, tokenAddress, amount, chainId, cToken } = params;
25744
25881
  if (!lenderDebitData) return true;
25882
+ if (isAaveV4Type(lender)) {
25883
+ const key2 = (params.aaveV4Spoke ?? tokenAddress).toLowerCase();
25884
+ const entry2 = lenderDebitData[key2];
25885
+ if (!entry2 || entry2.amount === void 0) return true;
25886
+ return entry2.amount === 0n;
25887
+ }
25745
25888
  if (isInit(lender) || isMorphoType(lender) || isCompoundV3(lender)) {
25746
25889
  const entry2 = Object.values(lenderDebitData)[0];
25747
25890
  if (!entry2 || entry2.amount === void 0) return true;
@@ -27148,7 +27291,7 @@ function generateLendingPairs(lenderData, prices, histPrices) {
27148
27291
  apr: totalApr,
27149
27292
  baseApr,
27150
27293
  rewardApr,
27151
- eMode: long.eMode?.category ?? 0,
27294
+ eMode: Number(leverageParams.eModeConfigId) || 0,
27152
27295
  eModeConfigId: leverageParams.eModeConfigId,
27153
27296
  borrowCollateralFactorLong: leverageParams.borrowCollateralFactorLong,
27154
27297
  collateralFactorLong: leverageParams.collateralFactorLong,