@defisaver/positions-sdk 2.1.59 → 2.1.61-aave-v4-dev

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 (163) hide show
  1. package/cjs/aaveV3/index.d.ts +1 -0
  2. package/cjs/aaveV3/index.js +1 -0
  3. package/cjs/aaveV4/index.d.ts +7 -0
  4. package/cjs/aaveV4/index.js +174 -0
  5. package/cjs/compoundV2/index.d.ts +1 -0
  6. package/cjs/compoundV2/index.js +1 -0
  7. package/cjs/compoundV3/index.d.ts +1 -0
  8. package/cjs/compoundV3/index.js +1 -0
  9. package/cjs/config/contracts.d.ts +1277 -0
  10. package/cjs/config/contracts.js +9 -0
  11. package/cjs/contracts.d.ts +23120 -0
  12. package/cjs/contracts.js +2 -1
  13. package/cjs/eulerV2/index.d.ts +1 -0
  14. package/cjs/eulerV2/index.js +1 -0
  15. package/cjs/fluid/index.d.ts +3 -0
  16. package/cjs/helpers/aaveHelpers/index.js +1 -0
  17. package/cjs/helpers/aaveV4Helpers/index.d.ts +13 -0
  18. package/cjs/helpers/aaveV4Helpers/index.js +117 -0
  19. package/cjs/helpers/compoundHelpers/index.js +2 -0
  20. package/cjs/helpers/curveUsdHelpers/index.js +1 -0
  21. package/cjs/helpers/eulerHelpers/index.js +1 -0
  22. package/cjs/helpers/fluidHelpers/index.js +1 -0
  23. package/cjs/helpers/index.d.ts +1 -0
  24. package/cjs/helpers/index.js +2 -1
  25. package/cjs/helpers/liquityV2Helpers/index.js +1 -0
  26. package/cjs/helpers/llamaLendHelpers/index.js +1 -0
  27. package/cjs/helpers/morphoBlueHelpers/index.js +3 -2
  28. package/cjs/helpers/sparkHelpers/index.js +1 -0
  29. package/cjs/index.d.ts +2 -1
  30. package/cjs/index.js +3 -1
  31. package/cjs/liquity/index.js +2 -0
  32. package/cjs/maker/index.js +2 -0
  33. package/cjs/markets/aaveV4/index.d.ts +16 -0
  34. package/cjs/markets/aaveV4/index.js +59 -0
  35. package/cjs/markets/index.d.ts +1 -0
  36. package/cjs/markets/index.js +3 -1
  37. package/cjs/moneymarket/moneymarketCommonService.d.ts +1 -0
  38. package/cjs/moneymarket/moneymarketCommonService.js +8 -1
  39. package/cjs/portfolio/index.js +20 -0
  40. package/cjs/services/utils.d.ts +1 -0
  41. package/cjs/services/utils.js +2 -1
  42. package/cjs/spark/index.d.ts +1 -0
  43. package/cjs/spark/index.js +1 -0
  44. package/cjs/types/aave.d.ts +1 -0
  45. package/cjs/types/aaveV4.d.ts +139 -0
  46. package/cjs/types/aaveV4.js +13 -0
  47. package/cjs/types/common.d.ts +1 -0
  48. package/cjs/types/compound.d.ts +1 -0
  49. package/cjs/types/curveUsd.d.ts +2 -0
  50. package/cjs/types/euler.d.ts +1 -0
  51. package/cjs/types/fluid.d.ts +1 -0
  52. package/cjs/types/index.d.ts +1 -0
  53. package/cjs/types/index.js +1 -0
  54. package/cjs/types/liquity.d.ts +1 -0
  55. package/cjs/types/liquityV2.d.ts +2 -0
  56. package/cjs/types/llamaLend.d.ts +2 -0
  57. package/cjs/types/maker.d.ts +1 -0
  58. package/cjs/types/morphoBlue.d.ts +2 -0
  59. package/cjs/types/portfolio.d.ts +4 -0
  60. package/cjs/types/spark.d.ts +1 -0
  61. package/esm/aaveV3/index.d.ts +1 -0
  62. package/esm/aaveV3/index.js +1 -0
  63. package/esm/aaveV4/index.d.ts +7 -0
  64. package/esm/aaveV4/index.js +165 -0
  65. package/esm/compoundV2/index.d.ts +1 -0
  66. package/esm/compoundV2/index.js +1 -0
  67. package/esm/compoundV3/index.d.ts +1 -0
  68. package/esm/compoundV3/index.js +1 -0
  69. package/esm/config/contracts.d.ts +1277 -0
  70. package/esm/config/contracts.js +8 -0
  71. package/esm/contracts.d.ts +23120 -0
  72. package/esm/contracts.js +1 -0
  73. package/esm/eulerV2/index.d.ts +1 -0
  74. package/esm/eulerV2/index.js +1 -0
  75. package/esm/fluid/index.d.ts +3 -0
  76. package/esm/helpers/aaveHelpers/index.js +2 -1
  77. package/esm/helpers/aaveV4Helpers/index.d.ts +13 -0
  78. package/esm/helpers/aaveV4Helpers/index.js +108 -0
  79. package/esm/helpers/compoundHelpers/index.js +3 -1
  80. package/esm/helpers/curveUsdHelpers/index.js +2 -1
  81. package/esm/helpers/eulerHelpers/index.js +2 -1
  82. package/esm/helpers/fluidHelpers/index.js +2 -1
  83. package/esm/helpers/index.d.ts +1 -0
  84. package/esm/helpers/index.js +1 -0
  85. package/esm/helpers/liquityV2Helpers/index.js +2 -1
  86. package/esm/helpers/llamaLendHelpers/index.js +2 -1
  87. package/esm/helpers/morphoBlueHelpers/index.js +5 -4
  88. package/esm/helpers/sparkHelpers/index.js +2 -1
  89. package/esm/index.d.ts +2 -1
  90. package/esm/index.js +2 -1
  91. package/esm/liquity/index.js +2 -0
  92. package/esm/maker/index.js +2 -0
  93. package/esm/markets/aaveV4/index.d.ts +16 -0
  94. package/esm/markets/aaveV4/index.js +47 -0
  95. package/esm/markets/index.d.ts +1 -0
  96. package/esm/markets/index.js +1 -0
  97. package/esm/moneymarket/moneymarketCommonService.d.ts +1 -0
  98. package/esm/moneymarket/moneymarketCommonService.js +6 -0
  99. package/esm/portfolio/index.js +21 -1
  100. package/esm/services/utils.d.ts +1 -0
  101. package/esm/services/utils.js +1 -0
  102. package/esm/spark/index.d.ts +1 -0
  103. package/esm/spark/index.js +1 -0
  104. package/esm/types/aave.d.ts +1 -0
  105. package/esm/types/aaveV4.d.ts +139 -0
  106. package/esm/types/aaveV4.js +10 -0
  107. package/esm/types/common.d.ts +1 -0
  108. package/esm/types/compound.d.ts +1 -0
  109. package/esm/types/curveUsd.d.ts +2 -0
  110. package/esm/types/euler.d.ts +1 -0
  111. package/esm/types/fluid.d.ts +1 -0
  112. package/esm/types/index.d.ts +1 -0
  113. package/esm/types/index.js +1 -0
  114. package/esm/types/liquity.d.ts +1 -0
  115. package/esm/types/liquityV2.d.ts +2 -0
  116. package/esm/types/llamaLend.d.ts +2 -0
  117. package/esm/types/maker.d.ts +1 -0
  118. package/esm/types/morphoBlue.d.ts +2 -0
  119. package/esm/types/portfolio.d.ts +4 -0
  120. package/esm/types/spark.d.ts +1 -0
  121. package/package.json +1 -1
  122. package/src/aaveV3/index.ts +1 -0
  123. package/src/aaveV4/index.ts +176 -0
  124. package/src/compoundV2/index.ts +1 -0
  125. package/src/compoundV3/index.ts +1 -0
  126. package/src/config/contracts.ts +8 -0
  127. package/src/contracts.ts +3 -1
  128. package/src/eulerV2/index.ts +1 -0
  129. package/src/helpers/aaveHelpers/index.ts +2 -1
  130. package/src/helpers/aaveV4Helpers/index.ts +128 -0
  131. package/src/helpers/compoundHelpers/index.ts +3 -1
  132. package/src/helpers/curveUsdHelpers/index.ts +5 -1
  133. package/src/helpers/eulerHelpers/index.ts +2 -1
  134. package/src/helpers/fluidHelpers/index.ts +4 -1
  135. package/src/helpers/index.ts +1 -0
  136. package/src/helpers/liquityV2Helpers/index.ts +4 -1
  137. package/src/helpers/llamaLendHelpers/index.ts +4 -1
  138. package/src/helpers/morphoBlueHelpers/index.ts +5 -4
  139. package/src/helpers/sparkHelpers/index.ts +2 -1
  140. package/src/index.ts +2 -0
  141. package/src/liquity/index.ts +2 -0
  142. package/src/maker/index.ts +2 -0
  143. package/src/markets/aaveV4/index.ts +68 -0
  144. package/src/markets/index.ts +6 -1
  145. package/src/moneymarket/moneymarketCommonService.ts +6 -0
  146. package/src/portfolio/index.ts +20 -0
  147. package/src/services/utils.ts +1 -0
  148. package/src/spark/index.ts +1 -0
  149. package/src/types/aave.ts +1 -0
  150. package/src/types/aaveV4.ts +155 -0
  151. package/src/types/common.ts +1 -0
  152. package/src/types/compound.ts +1 -0
  153. package/src/types/curveUsd.ts +2 -0
  154. package/src/types/euler.ts +1 -0
  155. package/src/types/fluid.ts +2 -1
  156. package/src/types/index.ts +2 -1
  157. package/src/types/liquity.ts +1 -0
  158. package/src/types/liquityV2.ts +2 -0
  159. package/src/types/llamaLend.ts +2 -0
  160. package/src/types/maker.ts +1 -0
  161. package/src/types/morphoBlue.ts +2 -0
  162. package/src/types/portfolio.ts +4 -0
  163. package/src/types/spark.ts +1 -0
@@ -211,6 +211,7 @@ export const EMPTY_EULER_V2_DATA = {
211
211
  lastUpdated: Date.now(),
212
212
  hasBorrowInDifferentVault: false,
213
213
  addressSpaceTakenByAnotherAccount: false,
214
+ exposure: 'N/A',
214
215
  };
215
216
 
216
217
  export const _getEulerV2AccountData = async (
@@ -6,7 +6,7 @@ import {
6
6
  } from '../../types';
7
7
  import { getNativeAssetFromWrapped, getWrappedNativeAssetFromUnwrapped } from '../../services/utils';
8
8
  import {
9
- aprToApy, calcLeverageLiqPrice, getAssetsTotal, isLeveragedPos,
9
+ aprToApy, calcLeverageLiqPrice, getAssetsTotal, getExposure, isLeveragedPos,
10
10
  } from '../../moneymarket';
11
11
  import { calculateNetApy } from '../../staking';
12
12
  import { borrowOperations } from '../../constants';
@@ -146,6 +146,7 @@ export const aaveAnyGetAggregatedPositionData = ({
146
146
  payload.netApy = netApy;
147
147
  payload.incentiveUsd = incentiveUsd;
148
148
  payload.totalInterestUsd = totalInterestUsd;
149
+ payload.exposure = getExposure(payload.borrowedUsd, payload.suppliedUsd);
149
150
  return payload;
150
151
  };
151
152
 
@@ -0,0 +1,128 @@
1
+ import Dec from 'decimal.js';
2
+ import { calcLeverageLiqPrice, getAssetsTotal, STABLE_ASSETS } from '../../moneymarket';
3
+ import {
4
+ AaveV4AggregatedPositionData, AaveV4AssetsData, AaveV4ReserveAssetData, AaveV4UsedReserveAsset, AaveV4UsedReserveAssets,
5
+ } from '../../types';
6
+ import { LeverageType, NetworkNumber } from '../../types/common';
7
+
8
+ export const aaveV4GetCollateralFactor = (assetData: AaveV4ReserveAssetData, usedAssetData: AaveV4UsedReserveAsset, useUserCollateralFactor: boolean = false): number => (useUserCollateralFactor ? usedAssetData.collateralFactor : assetData.collateralFactor);
9
+
10
+ export const isLeveragedPosAaveV4 = (usedAssets: AaveV4UsedReserveAssets, dustLimit = 5) => {
11
+ let borrowUnstable = 0;
12
+ let supplyStable = 0;
13
+ let borrowStable = 0;
14
+ let supplyUnstable = 0;
15
+ let longAsset = '';
16
+ let shortAsset = '';
17
+ Object.values(usedAssets).forEach(({
18
+ symbol, suppliedUsd, borrowedUsd, collateral, reserveId,
19
+ }) => {
20
+ const spokeAsset = `${symbol}-${reserveId}`;
21
+ const isSupplied = (+suppliedUsd) > dustLimit; // ignore dust like <limit leftover supply
22
+ const isBorrowed = (+borrowedUsd) > dustLimit; // ignore dust like <limit leftover supply
23
+ if (isSupplied && STABLE_ASSETS.includes(symbol) && collateral) supplyStable += 1;
24
+ if (isBorrowed && STABLE_ASSETS.includes(symbol)) borrowStable += 1;
25
+ if (isBorrowed && !STABLE_ASSETS.includes(symbol)) {
26
+ borrowUnstable += 1;
27
+ shortAsset = spokeAsset;
28
+ }
29
+ if (isSupplied && !STABLE_ASSETS.includes(symbol) && collateral) {
30
+ supplyUnstable += 1;
31
+ longAsset = spokeAsset;
32
+ }
33
+ });
34
+ const isLong = borrowStable > 0 && borrowUnstable === 0 && supplyUnstable === 1 && supplyStable === 0;
35
+ const isShort = supplyStable > 0 && supplyUnstable === 0 && borrowUnstable === 1 && borrowStable === 0;
36
+ const isVolatilePair = supplyUnstable === 1 && borrowUnstable === 1 && supplyStable === 0 && borrowStable === 0;
37
+ if (isLong) {
38
+ return {
39
+ leveragedType: LeverageType.Long,
40
+ leveragedAsset: longAsset,
41
+ };
42
+ }
43
+ if (isShort) {
44
+ return {
45
+ leveragedType: LeverageType.Short,
46
+ leveragedAsset: shortAsset,
47
+ };
48
+ }
49
+ if (isVolatilePair) {
50
+ return {
51
+ leveragedType: LeverageType.VolatilePair,
52
+ leveragedAsset: longAsset,
53
+ };
54
+ }
55
+ return {
56
+ leveragedType: LeverageType.None,
57
+ leveragedAsset: '',
58
+ };
59
+ };
60
+
61
+ export const aaveV4GetAggregatedPositionData = ({
62
+ usedAssets,
63
+ assetsData,
64
+ network,
65
+ useUserCollateralFactor = false,
66
+ }: {
67
+ usedAssets: AaveV4UsedReserveAssets,
68
+ assetsData: AaveV4AssetsData,
69
+ network: NetworkNumber,
70
+ useUserCollateralFactor?: boolean,
71
+ }): AaveV4AggregatedPositionData => {
72
+ const payload = {} as AaveV4AggregatedPositionData;
73
+ payload.suppliedUsd = getAssetsTotal(usedAssets, ({ isSupplied }: { isSupplied: boolean }) => isSupplied, ({ suppliedUsd }: { suppliedUsd: string }) => suppliedUsd);
74
+ payload.suppliedCollateralUsd = getAssetsTotal(usedAssets, ({ isSupplied, collateral }: { isSupplied: boolean, collateral: string }) => isSupplied && collateral, ({ suppliedUsd }: { suppliedUsd: string }) => suppliedUsd);
75
+ payload.borrowLimitUsd = getAssetsTotal(
76
+ usedAssets,
77
+ ({ isSupplied, collateral }: { isSupplied: boolean, collateral: string }) => isSupplied && collateral,
78
+ ({ symbol, suppliedUsd, reserveId }: { symbol: string, suppliedUsd: string, reserveId: number }) => new Dec(suppliedUsd).mul(aaveV4GetCollateralFactor(assetsData[`${symbol}-${reserveId}`], usedAssets[`${symbol}-${reserveId}`], useUserCollateralFactor)),
79
+ );
80
+ payload.liquidationLimitUsd = payload.borrowLimitUsd;
81
+ payload.borrowedUsd = getAssetsTotal(usedAssets, ({ isBorrowed }: { isBorrowed: boolean }) => isBorrowed, ({ borrowedUsd }: { borrowedUsd: string }) => borrowedUsd);
82
+ payload.drawnUsd = getAssetsTotal(usedAssets, ({ isBorrowed }: { isBorrowed: boolean }) => isBorrowed, ({ drawnUsd }: { drawnUsd: string }) => drawnUsd);
83
+ payload.premiumUsd = getAssetsTotal(usedAssets, ({ isBorrowed }: { isBorrowed: boolean }) => isBorrowed, ({ premiumUsd }: { premiumUsd: string }) => premiumUsd);
84
+ const leftToBorrowUsd = new Dec(payload.borrowLimitUsd).sub(payload.borrowedUsd);
85
+ payload.leftToBorrowUsd = leftToBorrowUsd.lte('0') ? '0' : leftToBorrowUsd.toString();
86
+ payload.ratio = +payload.suppliedUsd ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
87
+ payload.collRatio = +payload.suppliedUsd ? new Dec(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
88
+ payload.liqRatio = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).toString();
89
+ payload.liqPercent = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).mul(100).toString();
90
+ const { leveragedType, leveragedAsset } = isLeveragedPosAaveV4(usedAssets);
91
+ payload.leveragedType = leveragedType;
92
+ payload.leveragedAsset = leveragedAsset;
93
+ payload.liquidationPrice = '';
94
+ if (leveragedType !== '') {
95
+ const leveragedAssetData = assetsData[leveragedAsset];
96
+ let assetPrice = leveragedAssetData?.price || '0';
97
+ if (leveragedType === LeverageType.VolatilePair) {
98
+ const borrowedAsset = (Object.values(usedAssets) as AaveV4UsedReserveAsset[]).find(({ borrowedUsd }: { borrowedUsd: string }) => +borrowedUsd > 0);
99
+ const borrowedAssetPrice = assetsData[`${borrowedAsset!.symbol}-${borrowedAsset!.reserveId}`].price;
100
+ const leveragedAssetPrice = assetsData[leveragedAsset].price;
101
+ const isReverse = new Dec(leveragedAssetPrice).lt(borrowedAssetPrice);
102
+ if (isReverse) {
103
+ payload.leveragedType = LeverageType.VolatilePairReverse;
104
+ payload.currentVolatilePairRatio = new Dec(borrowedAssetPrice).div(leveragedAssetPrice).toDP(18).toString();
105
+ assetPrice = new Dec(borrowedAssetPrice).div(assetPrice).toString();
106
+ } else {
107
+ assetPrice = new Dec(assetPrice).div(borrowedAssetPrice).toString();
108
+ payload.currentVolatilePairRatio = new Dec(leveragedAssetPrice).div(borrowedAssetPrice).toDP(18).toString();
109
+ }
110
+ }
111
+ payload.liquidationPrice = calcLeverageLiqPrice(payload.leveragedType, assetPrice, payload.borrowedUsd, payload.liquidationLimitUsd);
112
+ }
113
+ payload.minCollRatio = new Dec(payload.suppliedCollateralUsd).div(payload.borrowLimitUsd).mul(100).toString();
114
+ payload.collLiquidationRatio = new Dec(payload.suppliedCollateralUsd).div(payload.liquidationLimitUsd).mul(100).toString();
115
+ // payload.healthRatio = new Dec(payload.liquidationLimitUsd).div(payload.borrowedUsd).toDP(4).toString();
116
+ payload.minHealthRatio = new Dec(payload.liquidationLimitUsd).div(payload.borrowLimitUsd).toDP(4).toString();
117
+
118
+ // TODO: Re-implement netApy calculation
119
+ // const { netApy, incentiveUsd, totalInterestUsd } = calculateNetApy({
120
+ // usedAssets,
121
+ // assetsData,
122
+ // optionalData: { healthRatio: payload.healthRatio },
123
+ // });
124
+ payload.netApy = '0';
125
+ payload.incentiveUsd = '0';
126
+ payload.totalInterestUsd = '0';
127
+ return payload;
128
+ };
@@ -8,7 +8,7 @@ import {
8
8
  } from '../../services/utils';
9
9
  import { BLOCKS_IN_A_YEAR, borrowOperations, SECONDS_PER_YEAR } from '../../constants';
10
10
  import {
11
- aprToApy, calcLeverageLiqPrice, calculateBorrowingAssetLimit, getAssetsTotal, isLeveragedPos,
11
+ aprToApy, calcLeverageLiqPrice, calculateBorrowingAssetLimit, getAssetsTotal, getExposure, isLeveragedPos,
12
12
  } from '../../moneymarket';
13
13
  import { calculateNetApy, getStakingApy, STAKING_ASSETS } from '../../staking';
14
14
  import {
@@ -158,6 +158,7 @@ export const getCompoundV2AggregatedData = ({
158
158
  const assetPrice = assetsData[handleWbtcLegacy(leveragedAsset)].price;
159
159
  payload.liquidationPrice = calcLeverageLiqPrice(leveragedType, assetPrice, payload.borrowedUsd, payload.liquidationLimitUsd);
160
160
  }
161
+ payload.exposure = getExposure(payload.borrowedUsd, payload.suppliedUsd);
161
162
 
162
163
  return payload;
163
164
  };
@@ -207,6 +208,7 @@ export const getCompoundV3AggregatedData = ({
207
208
  }
208
209
  payload.minCollRatio = new Dec(payload.suppliedCollateralUsd).div(payload.borrowLimitUsd).mul(100).toString();
209
210
  payload.collLiquidationRatio = new Dec(payload.suppliedCollateralUsd).div(payload.liquidationLimitUsd).mul(100).toString();
211
+ payload.exposure = getExposure(payload.borrowedUsd, payload.suppliedUsd);
210
212
 
211
213
  return payload;
212
214
  };
@@ -1,7 +1,9 @@
1
1
  import Dec from 'decimal.js';
2
2
  import { CrvUSDAggregatedPositionData, CrvUSDMarketData, CrvUSDUsedAssets } from '../../types';
3
3
  import { MMUsedAssets, NetworkNumber } from '../../types/common';
4
- import { calcLeverageLiqPrice, getAssetsTotal, isLeveragedPos } from '../../moneymarket';
4
+ import {
5
+ calcLeverageLiqPrice, getAssetsTotal, getExposure, isLeveragedPos,
6
+ } from '../../moneymarket';
5
7
  import { mapRange } from '../../services/utils';
6
8
 
7
9
  export const getCrvUsdAggregatedData = ({
@@ -37,5 +39,7 @@ export const getCrvUsdAggregatedData = ({
37
39
  payload.liquidationPrice = calcLeverageLiqPrice(leveragedType, usedAssets[selectedMarket.collAsset].price, payload.borrowedUsd, payload.borrowLimitUsd);
38
40
  }
39
41
 
42
+ payload.exposure = getExposure(payload.borrowedUsd, payload.suppliedUsd);
43
+
40
44
  return payload;
41
45
  };
@@ -4,7 +4,7 @@ import {
4
4
  EthAddress, EthereumProvider, LeverageType, MMAssetsData, NetworkNumber,
5
5
  } from '../../types/common';
6
6
  import {
7
- calcLeverageLiqPrice, getAssetsTotal, STABLE_ASSETS,
7
+ calcLeverageLiqPrice, getAssetsTotal, getExposure, STABLE_ASSETS,
8
8
  } from '../../moneymarket';
9
9
  import { calculateNetApy } from '../../staking';
10
10
  import {
@@ -117,6 +117,7 @@ export const getEulerV2AggregatedData = ({
117
117
  }
118
118
  payload.minCollRatio = new Dec(payload.suppliedCollateralUsd).div(payload.borrowLimitUsd).mul(100).toString();
119
119
  payload.collLiquidationRatio = new Dec(payload.suppliedCollateralUsd).div(payload.liquidationLimitUsd).mul(100).toString();
120
+ payload.exposure = getExposure(payload.borrowedUsd, payload.suppliedUsd);
120
121
  return payload;
121
122
  };
122
123
 
@@ -7,7 +7,9 @@ import {
7
7
  FluidVaultType,
8
8
  InnerFluidMarketData,
9
9
  } from '../../types';
10
- import { calcLeverageLiqPrice, getAssetsTotal, isLeveragedPos } from '../../moneymarket';
10
+ import {
11
+ calcLeverageLiqPrice, getAssetsTotal, getExposure, isLeveragedPos,
12
+ } from '../../moneymarket';
11
13
  import { calculateNetApy } from '../../staking';
12
14
  import { LeverageType, MMAssetsData } from '../../types/common';
13
15
  import { getEthAmountForDecimals } from '../../services/utils';
@@ -103,6 +105,7 @@ borrowShares?: string,
103
105
 
104
106
  payload.minCollRatio = new Dec(payload.suppliedUsd).div(payload.borrowLimitUsd).mul(100).toString();
105
107
  payload.collLiquidationRatio = new Dec(payload.suppliedUsd).div(payload.liquidationLimitUsd).mul(100).toString();
108
+ payload.exposure = getExposure(payload.borrowedUsd, payload.suppliedUsd);
106
109
 
107
110
  return payload;
108
111
  };
@@ -8,3 +8,4 @@ export * as llamaLendHelpers from './llamaLendHelpers';
8
8
  export * as liquityV2Helpers from './liquityV2Helpers';
9
9
  export * as eulerV2Helpers from './eulerHelpers';
10
10
  export * as fluidHelpers from './fluidHelpers';
11
+ export * as aaveV4Helpers from './aaveV4Helpers';
@@ -1,5 +1,7 @@
1
1
  import Dec from 'decimal.js';
2
- import { calcLeverageLiqPrice, getAssetsTotal, isLeveragedPos } from '../../moneymarket';
2
+ import {
3
+ calcLeverageLiqPrice, getAssetsTotal, getExposure, isLeveragedPos,
4
+ } from '../../moneymarket';
3
5
  import {
4
6
  LiquityV2AggregatedTroveData, LiquityV2AssetsData, LiquityV2UsedAsset, LiquityV2UsedAssets,
5
7
  } from '../../types';
@@ -77,6 +79,7 @@ export const getLiquityV2AggregatedPositionData = ({
77
79
  const assetPrice = assetsData[leveragedAsset].price;
78
80
  payload.liquidationPrice = calcLeverageLiqPrice(leveragedType, assetPrice, payload.borrowedUsd, payload.borrowLimitUsd);
79
81
  }
82
+ payload.exposure = getExposure(payload.borrowedUsd, payload.suppliedUsd);
80
83
 
81
84
  return payload;
82
85
  };
@@ -3,7 +3,9 @@ import {
3
3
  LlamaLendAggregatedPositionData, LlamaLendAssetsData, LlamaLendMarketData, LlamaLendUsedAssets,
4
4
  } from '../../types';
5
5
  import { MMAssetsData, MMUsedAssets, NetworkNumber } from '../../types/common';
6
- import { calcLeverageLiqPrice, getAssetsTotal, isLeveragedPos } from '../../moneymarket';
6
+ import {
7
+ calcLeverageLiqPrice, getAssetsTotal, getExposure, isLeveragedPos,
8
+ } from '../../moneymarket';
7
9
  import { mapRange } from '../../services/utils';
8
10
  import { calculateNetApy } from '../../staking';
9
11
 
@@ -49,5 +51,6 @@ export const getLlamaLendAggregatedData = ({
49
51
  payload.liquidationPrice = calcLeverageLiqPrice(leveragedType, usedAssets[collAsset].price, payload.borrowedUsd, payload.borrowLimitUsd);
50
52
  }
51
53
 
54
+ payload.exposure = getExposure(payload.borrowedUsd, payload.suppliedUsd);
52
55
  return payload;
53
56
  };
@@ -1,7 +1,7 @@
1
1
  import Dec from 'decimal.js';
2
2
  import { assetAmountInWei, getAssetInfo, getAssetInfoByAddress } from '@defisaver/tokens';
3
3
  import {
4
- aprToApy, calcLeverageLiqPrice, getAssetsTotal, isLeveragedPos,
4
+ aprToApy, calcLeverageLiqPrice, getAssetsTotal, getExposure, isLeveragedPos,
5
5
  } from '../../moneymarket';
6
6
  import { calculateNetApy } from '../../staking';
7
7
  import {
@@ -14,7 +14,7 @@ import {
14
14
  } from '../../types';
15
15
  import { borrowOperations, SECONDS_PER_YEAR, WAD } from '../../constants';
16
16
  import { MorphoBlueViewContractViem } from '../../contracts';
17
- import { compareAddresses, DEFAULT_TIMEOUT, wethToEth } from '../../services/utils';
17
+ import { compareAddresses, LONGER_TIMEOUT, wethToEth } from '../../services/utils';
18
18
  import { getViemProvider } from '../../services/viem';
19
19
 
20
20
  export const getMorphoBlueAggregatedPositionData = ({ usedAssets, assetsData, marketInfo }: { usedAssets: MMUsedAssets, assetsData: MorphoBlueAssetsData, marketInfo: MorphoBlueMarketInfo }): MorphoBlueAggregatedPositionData => {
@@ -76,6 +76,7 @@ export const getMorphoBlueAggregatedPositionData = ({ usedAssets, assetsData, ma
76
76
  }
77
77
  payload.minCollRatio = new Dec(payload.suppliedCollateralUsd).div(payload.borrowLimitUsd).mul(100).toString();
78
78
  payload.collLiquidationRatio = new Dec(payload.suppliedCollateralUsd).div(payload.liquidationLimitUsd).mul(100).toString();
79
+ payload.exposure = getExposure(payload.borrowedUsd, payload.suppliedUsd);
79
80
 
80
81
  return payload;
81
82
  };
@@ -231,7 +232,7 @@ export const getReallocatableLiquidity = async (marketId: string, network: Netwo
231
232
  query: MARKET_QUERY,
232
233
  variables: { uniqueKey: marketId, chainId: network },
233
234
  }),
234
- signal: AbortSignal.timeout(DEFAULT_TIMEOUT),
235
+ signal: AbortSignal.timeout(LONGER_TIMEOUT),
235
236
  });
236
237
 
237
238
  const data: { data: { marketByUniqueKey: MorphoBlueRealloactionMarketData } } = await response.json();
@@ -296,7 +297,7 @@ export const getReallocation = async (market: MorphoBlueMarketData, assetsData:
296
297
  query: MARKET_QUERY,
297
298
  variables: { uniqueKey: marketId, chainId: network },
298
299
  }),
299
- signal: AbortSignal.timeout(DEFAULT_TIMEOUT),
300
+ signal: AbortSignal.timeout(LONGER_TIMEOUT),
300
301
  });
301
302
 
302
303
  const data: { data: { marketByUniqueKey: MorphoBlueRealloactionMarketData } } = await response.json();
@@ -1,7 +1,7 @@
1
1
  import Dec from 'decimal.js';
2
2
  import { assetAmountInWei, getAssetInfo, getAssetInfoByAddress } from '@defisaver/tokens';
3
3
  import {
4
- aprToApy, calcLeverageLiqPrice, getAssetsTotal, isLeveragedPos,
4
+ aprToApy, calcLeverageLiqPrice, getAssetsTotal, getExposure, isLeveragedPos,
5
5
  } from '../../moneymarket';
6
6
  import {
7
7
  SparkAggregatedPositionData,
@@ -127,6 +127,7 @@ export const sparkGetAggregatedPositionData = ({
127
127
  payload.collLiquidationRatio = new Dec(payload.suppliedCollateralUsd).div(payload.liquidationLimitUsd).mul(100).toString();
128
128
  payload.healthRatio = new Dec(payload.liquidationLimitUsd).div(payload.borrowedUsd).toDP(4).toString();
129
129
  payload.minHealthRatio = new Dec(payload.liquidationLimitUsd).div(payload.borrowLimitUsd).toDP(4).toString();
130
+ payload.exposure = getExposure(payload.borrowedUsd, payload.suppliedUsd);
130
131
  return payload;
131
132
  };
132
133
 
package/src/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import './setup';
2
2
 
3
3
  import * as fluid from './fluid';
4
+ import * as aaveV4 from './aaveV4';
4
5
  import * as aaveV3 from './aaveV3';
5
6
  import * as aaveV2 from './aaveV2';
6
7
  import * as compoundV3 from './compoundV3';
@@ -27,6 +28,7 @@ export * from './types';
27
28
  export {
28
29
  aaveV2,
29
30
  aaveV3,
31
+ aaveV4,
30
32
  compoundV2,
31
33
  compoundV3,
32
34
  spark,
@@ -17,6 +17,7 @@ import { LIQUITY_TROVE_STATUS_ENUM, LiquityTroveInfo } from '../types';
17
17
  import { ZERO_ADDRESS } from '../constants';
18
18
  import { getViemProvider, setViemBlockNumber } from '../services/viem';
19
19
  import { getEthAmountForDecimals } from '../services/utils';
20
+ import { getExposure } from '../moneymarket';
20
21
 
21
22
  export const LIQUITY_NORMAL_MODE_RATIO = 110; // MCR
22
23
  export const LIQUITY_RECOVERY_MODE_RATIO = 150; // CCR
@@ -104,6 +105,7 @@ export const _getLiquityTroveInfo = async (provider: Client, network: NetworkNum
104
105
  minCollateralRatio: recoveryMode ? LIQUITY_RECOVERY_MODE_RATIO : LIQUITY_NORMAL_MODE_RATIO,
105
106
  priceForRecovery: new Dec(recoveryMode ? LIQUITY_RECOVERY_MODE_RATIO : LIQUITY_NORMAL_MODE_RATIO).mul(totalLUSD).div(totalETH).div(100)
106
107
  .toString(),
108
+ exposure: getExposure(assetAmountInEth(troveInfo[2].toString()), new Dec(assetAmountInEth(troveInfo[1].toString())).mul(assetPrice).toString()),
107
109
  };
108
110
 
109
111
  return payload;
@@ -13,6 +13,7 @@ import { CdpData, CdpInfo, CdpType } from '../types';
13
13
  import { wethToEth } from '../services/utils';
14
14
  import { parseCollateralInfo } from '../helpers/makerHelpers';
15
15
  import { getViemProvider, setViemBlockNumber } from '../services/viem';
16
+ import { getExposure } from '../moneymarket';
16
17
 
17
18
  export const _getMakerAccountBalances = async (provider: PublicClient, network: NetworkNumber, block: Blockish, addressMapping: boolean, cdpId: string, _managerAddress?: EthAddress): Promise<PositionBalances> => {
18
19
  let balances: PositionBalances = {
@@ -214,6 +215,7 @@ export const _getMakerCdpData = async (provider: Client, network: NetworkNumber,
214
215
  globalDebtCurrent: collInfo.globalDebtCurrent,
215
216
  liquidationFee: collInfo.liquidationFee,
216
217
  lastUpdated: Date.now(),
218
+ exposure: getExposure(assetAmountInEth(debt, 'DAI'), collateralUsd),
217
219
  };
218
220
  };
219
221
 
@@ -0,0 +1,68 @@
1
+ import {
2
+ AaveV4HubInfo,
3
+ AaveV4HubsType,
4
+ AaveV4SpokeInfo,
5
+ AaveV4SpokesType,
6
+ NetworkNumber,
7
+ } from '../../types';
8
+
9
+ // HUBS
10
+
11
+ export const AAVE_V4_CORE_HUB = (networkId: NetworkNumber): AaveV4HubInfo => ({
12
+ chainIds: [NetworkNumber.Eth],
13
+ label: 'Core Hub',
14
+ value: AaveV4HubsType.AaveV4CoreHub,
15
+ address: '0xaD905aD5EA5B98cD50AE40Cfe368344686a21366',
16
+ });
17
+
18
+ export const AAVE_V4_YIELD_SEEKING_HUB = (networkId: NetworkNumber): AaveV4HubInfo => ({
19
+ chainIds: [NetworkNumber.Eth],
20
+ label: 'Yield Seeking Hub',
21
+ value: AaveV4HubsType.AaveV4YieldSeekingHub,
22
+ address: '0x86F37ba3b480c5fE22A7eb1ba2B2D49c94089FBB',
23
+ });
24
+
25
+ export const AaveV4Hubs = (networkId: NetworkNumber) => ({
26
+ [AaveV4HubsType.AaveV4CoreHub]: AAVE_V4_CORE_HUB(networkId),
27
+ [AaveV4HubsType.AaveV4YieldSeekingHub]: AAVE_V4_YIELD_SEEKING_HUB(networkId),
28
+ }) as const;
29
+
30
+ export const getAaveV4HubTypeInfo = (type: AaveV4HubsType, network?: NetworkNumber) => ({ ...AaveV4Hubs(network ?? NetworkNumber.Eth) }[type]);
31
+
32
+ export const getAaveV4HubByAddress = (networkId: NetworkNumber, address: string): AaveV4HubInfo | undefined => Object.values(AaveV4Hubs(networkId)).find(
33
+ hub => hub.address.toLowerCase() === address.toLowerCase(),
34
+ );
35
+
36
+ // SPOKES
37
+
38
+ export const AAVE_V4_CORE_SPOKE = (networkId: NetworkNumber): AaveV4SpokeInfo => ({
39
+ chainIds: [NetworkNumber.Eth],
40
+ label: 'Core Spoke',
41
+ value: AaveV4SpokesType.AaveV4CoreSpoke,
42
+ url: 'core',
43
+ address: '0xBa97c5E52cd5BC3D7950Ae70779F8FfE92d40CdC',
44
+ hubs: [
45
+ AAVE_V4_CORE_HUB(NetworkNumber.Eth).address,
46
+ ],
47
+ });
48
+
49
+ export const AAVE_V4_YIELD_SEEKING_SPOKE = (networkId: NetworkNumber): AaveV4SpokeInfo => ({
50
+ chainIds: [NetworkNumber.Eth],
51
+ label: 'Yield Seeking Spoke',
52
+ value: AaveV4SpokesType.AaveV4YieldSeekingSpoke,
53
+ url: 'yield-seeking',
54
+ address: '0x2559e4e04f2ca7180e5f20c2872d22ec89601b56',
55
+ hubs: [
56
+ AAVE_V4_CORE_HUB(NetworkNumber.Eth).address,
57
+ AAVE_V4_YIELD_SEEKING_HUB(NetworkNumber.Eth).address,
58
+ ],
59
+ });
60
+
61
+ export const AaveV4Spokes = (networkId: NetworkNumber) => ({
62
+ [AaveV4SpokesType.AaveV4CoreSpoke]: AAVE_V4_CORE_SPOKE(networkId),
63
+ [AaveV4SpokesType.AaveV4YieldSeekingSpoke]: AAVE_V4_YIELD_SEEKING_SPOKE(networkId),
64
+ }) as const;
65
+
66
+ export const getAaveV4SpokeTypeInfo = (type: AaveV4SpokesType, network?: NetworkNumber) => ({ ...AaveV4Spokes(network ?? NetworkNumber.Eth) }[type]);
67
+
68
+
@@ -21,5 +21,10 @@ export { LlamaLendMarkets } from './llamaLend';
21
21
  export { LiquityV2Markets, findLiquityV2MarketByAddress } from './liquityV2';
22
22
  export { EulerV2Markets } from './euler';
23
23
  export {
24
- FluidMarkets, getFluidVersionsDataForNetwork, getFluidMarketInfoById, getFTokenAddress, getFluidMarketInfoByAddress,
24
+ FluidMarkets,
25
+ getFluidVersionsDataForNetwork,
26
+ getFluidMarketInfoById,
27
+ getFTokenAddress,
28
+ getFluidMarketInfoByAddress,
25
29
  } from './fluid';
30
+ export { AaveV4Spokes } from './aaveV4';
@@ -82,3 +82,9 @@ export const aprToApy = (interest:string | number, frequency = BLOCKS_IN_A_YEAR)
82
82
  .minus(1)
83
83
  .times(100)
84
84
  .toString();
85
+
86
+ export const getExposure = (borrowedUsd: string, suppliedUsd: string) => {
87
+ if (borrowedUsd === '0' || suppliedUsd === '0') return 'N/A';
88
+ const balanceUsd = new Dec(suppliedUsd).sub(borrowedUsd).toString();
89
+ return new Dec(suppliedUsd).div(balanceUsd).toDecimalPlaces(2).toString();
90
+ };
@@ -2,6 +2,7 @@ import Dec from 'decimal.js';
2
2
  import { EthAddress, EthereumProvider, NetworkNumber } from '../types/common';
3
3
  import {
4
4
  AaveMarkets,
5
+ AaveV4Spokes,
5
6
  CompoundMarkets,
6
7
  CrvUsdMarkets,
7
8
  EulerV2Markets,
@@ -14,6 +15,7 @@ import { _getMorphoBlueAccountData, _getMorphoBlueMarketData, getMorphoEarn } fr
14
15
  import {
15
16
  AaveV2MarketData,
16
17
  AaveV3MarketData,
18
+ AaveV4SpokeData,
17
19
  AaveVersions,
18
20
  CdpInfo,
19
21
  CompoundV2MarketsData,
@@ -49,6 +51,7 @@ import { fetchSparkAirdropRewards, fetchSparkRewards } from '../claiming/spark';
49
51
  import { fetchMorphoBlueRewards } from '../claiming/morphoBlue';
50
52
  import { getKingRewards } from '../claiming/king';
51
53
  import { fetchEthenaAirdropRewards } from '../claiming/ethena';
54
+ import { _getAaveV4AccountData, _getAaveV4SpokeData } from '../aaveV4';
52
55
 
53
56
  export async function getPortfolioData(provider: EthereumProvider, network: NetworkNumber, defaultProvider: EthereumProvider, addresses: EthAddress[], isSim = false): Promise<{
54
57
  positions: PortfolioPositionsData;
@@ -71,6 +74,7 @@ export async function getPortfolioData(provider: EthereumProvider, network: Netw
71
74
  const llamaLendMarkets = [NetworkNumber.Eth, NetworkNumber.Arb].includes(network) ? Object.values(LlamaLendMarkets(network)).filter((market) => market.chainIds.includes(network)) : [];
72
75
  const liquityV2Markets = [NetworkNumber.Eth].includes(network) ? Object.values(LiquityV2Markets(network)) : [];
73
76
  const liquityV2MarketsStaking = [NetworkNumber.Eth].includes(network) ? Object.values(LiquityV2Markets(network)).filter(market => !market.isLegacy) : [];
77
+ const aaveV4Spokes = Object.values(AaveV4Spokes(network)).filter((market) => market.chainIds.includes(network));
74
78
 
75
79
  const args: [NetworkNumber, any?] = [network, { batch: { multicall: { batchSize: isSim ? 500_000 : 2_500_000 } } }];
76
80
  const client = getViemProvider(provider, ...args);
@@ -87,6 +91,7 @@ export async function getPortfolioData(provider: EthereumProvider, network: Netw
87
91
  const crvUsdMarketsData: Record<string, CrvUSDGlobalMarketData> = {};
88
92
  const llamaLendMarketsData: Record<string, LlamaLendGlobalMarketData> = {};
89
93
  const liquityV2MarketsData: Record<string, LiquityV2MarketData> = {};
94
+ const aaveV4SpokesData: Record<string, AaveV4SpokeData> = {};
90
95
 
91
96
  const markets = {
92
97
  morphoMarketsData,
@@ -99,6 +104,7 @@ export async function getPortfolioData(provider: EthereumProvider, network: Netw
99
104
  crvUsdMarketsData,
100
105
  llamaLendMarketsData,
101
106
  liquityV2MarketsData,
107
+ aaveV4SpokesData,
102
108
  };
103
109
 
104
110
  const positions: PortfolioPositionsData = {};
@@ -109,6 +115,7 @@ export async function getPortfolioData(provider: EthereumProvider, network: Netw
109
115
  for (const address of allAddresses) {
110
116
  positions[address.toLowerCase() as EthAddress] = {
111
117
  aaveV3: {},
118
+ aaveV4: {},
112
119
  morphoBlue: {},
113
120
  compoundV3: {},
114
121
  spark: {},
@@ -177,6 +184,10 @@ export async function getPortfolioData(provider: EthereumProvider, network: Netw
177
184
  const marketData = await _getAaveV3MarketData(client, network, market);
178
185
  aaveV3MarketsData[market.value] = marketData;
179
186
  }),
187
+ ...aaveV4Spokes.map(async (spoke) => {
188
+ const spokeData = await _getAaveV4SpokeData(client, network, spoke);
189
+ aaveV4SpokesData[spoke.value] = spokeData;
190
+ }),
180
191
  ...aaveV2Markets.map(async (market) => {
181
192
  const marketData = await _getAaveV2MarketsData(client, network, market);
182
193
  aaveV2MarketsData[market.value] = marketData;
@@ -429,6 +440,15 @@ export async function getPortfolioData(provider: EthereumProvider, network: Netw
429
440
  positions[address.toLowerCase() as EthAddress].aaveV3[market.value] = { error: `Error fetching AaveV3 account data for address ${address} on market ${market.value}`, data: null };
430
441
  }
431
442
  })).flat(),
443
+ ...aaveV4Spokes.map((spoke) => allAddresses.map(async (address) => {
444
+ try {
445
+ const accData = await _getAaveV4AccountData(client, network, aaveV4SpokesData[spoke.value], address);
446
+ if (new Dec(accData.suppliedUsd).gt(0)) positions[address.toLowerCase() as EthAddress].aaveV4[spoke.value] = { error: '', data: accData };
447
+ } catch (error) {
448
+ console.error(`Error fetching AaveV4 account data for address ${address} on spoke ${spoke.value}:`, error);
449
+ positions[address.toLowerCase() as EthAddress].aaveV4[spoke.value] = { error: `Error fetching AaveV4 account data for address ${address} on spoke ${spoke.value}`, data: null };
450
+ }
451
+ })).flat(),
432
452
  ...morphoMarkets.map((market) => addresses.map(async (address) => {
433
453
  try {
434
454
  const [accDataPromise, earnDataPromise] = await Promise.allSettled([
@@ -54,6 +54,7 @@ export const isMaxuint = (amount: string) => compareAddresses(MAXUINT, amount);
54
54
  export const isMainnetNetwork = (network: NetworkNumber) => network === NetworkNumber.Eth;
55
55
 
56
56
  export const DEFAULT_TIMEOUT = 2000; // 2 seconds
57
+ export const LONGER_TIMEOUT = 5000; // 5 seconds
57
58
 
58
59
  /**
59
60
  * Converts web3 hybrid response (that can be used as objects and arrays, so has duplicated values) to objects.
@@ -264,6 +264,7 @@ export const EMPTY_SPARK_DATA = {
264
264
  suppliedCollateralUsd: '0',
265
265
  totalSupplied: '0',
266
266
  eModeCategories: [],
267
+ exposure: 'N/A',
267
268
  };
268
269
 
269
270
  export const _getSparkAccountBalances = async (provider: Client, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress): Promise<PositionBalances> => {
package/src/types/aave.ts CHANGED
@@ -179,6 +179,7 @@ export interface AaveV3AggregatedPositionData {
179
179
  liqRatio: string,
180
180
  liqPercent: string,
181
181
  leveragedType: LeverageType,
182
+ exposure: string,
182
183
  leveragedAsset?: string,
183
184
  liquidationPrice?: string,
184
185
  minCollRatio?: string,