@defisaver/positions-sdk 2.1.75 → 2.1.78-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 (71) hide show
  1. package/cjs/aaveV3/merkl.js +1 -1
  2. package/cjs/aaveV4/index.d.ts +7 -0
  3. package/cjs/aaveV4/index.js +298 -0
  4. package/cjs/aaveV4/lend.d.ts +45 -0
  5. package/cjs/aaveV4/lend.js +141 -0
  6. package/cjs/claiming/aaveV3.js +1 -1
  7. package/cjs/config/contracts.d.ts +1551 -0
  8. package/cjs/config/contracts.js +9 -0
  9. package/cjs/contracts.d.ts +32741 -0
  10. package/cjs/contracts.js +2 -1
  11. package/cjs/helpers/aaveV4Helpers/index.d.ts +12 -0
  12. package/cjs/helpers/aaveV4Helpers/index.js +117 -0
  13. package/cjs/helpers/index.d.ts +1 -0
  14. package/cjs/helpers/index.js +2 -1
  15. package/cjs/index.d.ts +2 -1
  16. package/cjs/index.js +3 -1
  17. package/cjs/markets/aaveV4/index.d.ts +28 -0
  18. package/cjs/markets/aaveV4/index.js +140 -0
  19. package/cjs/markets/index.d.ts +1 -0
  20. package/cjs/markets/index.js +3 -1
  21. package/cjs/portfolio/index.js +20 -0
  22. package/cjs/savings/summerVaults/options.js +8 -8
  23. package/cjs/types/aaveV4.d.ts +153 -0
  24. package/cjs/types/aaveV4.js +19 -0
  25. package/cjs/types/index.d.ts +1 -0
  26. package/cjs/types/index.js +1 -0
  27. package/cjs/types/portfolio.d.ts +4 -0
  28. package/esm/aaveV3/merkl.js +1 -1
  29. package/esm/aaveV4/index.d.ts +7 -0
  30. package/esm/aaveV4/index.js +255 -0
  31. package/esm/aaveV4/lend.d.ts +45 -0
  32. package/esm/aaveV4/lend.js +134 -0
  33. package/esm/claiming/aaveV3.js +1 -1
  34. package/esm/config/contracts.d.ts +1551 -0
  35. package/esm/config/contracts.js +8 -0
  36. package/esm/contracts.d.ts +32741 -0
  37. package/esm/contracts.js +1 -0
  38. package/esm/helpers/aaveV4Helpers/index.d.ts +12 -0
  39. package/esm/helpers/aaveV4Helpers/index.js +108 -0
  40. package/esm/helpers/index.d.ts +1 -0
  41. package/esm/helpers/index.js +1 -0
  42. package/esm/index.d.ts +2 -1
  43. package/esm/index.js +2 -1
  44. package/esm/markets/aaveV4/index.d.ts +28 -0
  45. package/esm/markets/aaveV4/index.js +122 -0
  46. package/esm/markets/index.d.ts +1 -0
  47. package/esm/markets/index.js +1 -0
  48. package/esm/portfolio/index.js +21 -1
  49. package/esm/savings/summerVaults/options.js +8 -8
  50. package/esm/types/aaveV4.d.ts +153 -0
  51. package/esm/types/aaveV4.js +16 -0
  52. package/esm/types/index.d.ts +1 -0
  53. package/esm/types/index.js +1 -0
  54. package/esm/types/portfolio.d.ts +4 -0
  55. package/package.json +2 -2
  56. package/src/aaveV3/merkl.ts +1 -1
  57. package/src/aaveV4/index.ts +291 -0
  58. package/src/aaveV4/lend.ts +180 -0
  59. package/src/claiming/aaveV3.ts +1 -1
  60. package/src/config/contracts.ts +8 -0
  61. package/src/contracts.ts +2 -0
  62. package/src/helpers/aaveV4Helpers/index.ts +133 -0
  63. package/src/helpers/index.ts +1 -0
  64. package/src/index.ts +2 -0
  65. package/src/markets/aaveV4/index.ts +149 -0
  66. package/src/markets/index.ts +6 -1
  67. package/src/portfolio/index.ts +20 -0
  68. package/src/savings/summerVaults/options.ts +8 -8
  69. package/src/types/aaveV4.ts +169 -0
  70. package/src/types/index.ts +2 -1
  71. package/src/types/portfolio.ts +4 -0
@@ -0,0 +1,133 @@
1
+ import Dec from 'decimal.js';
2
+ import { calcLeverageLiqPrice, getAssetsTotal, STABLE_ASSETS } from '../../moneymarket';
3
+ import {
4
+ AaveV4AggregatedPositionData,
5
+ AaveV4AssetsData,
6
+ AaveV4ReserveAssetData,
7
+ AaveV4UsedReserveAsset,
8
+ AaveV4UsedReserveAssets,
9
+ LeverageType,
10
+ NetworkNumber,
11
+ } from '../../types';
12
+
13
+ export const aaveV4GetCollateralFactor = (assetData: AaveV4ReserveAssetData, usedAssetData: AaveV4UsedReserveAsset, useUserCollateralFactor: boolean = false): number => (useUserCollateralFactor ? usedAssetData.collateralFactor : assetData.collateralFactor);
14
+
15
+ export const isLeveragedPosAaveV4 = (usedAssets: AaveV4UsedReserveAssets, dustLimit = 5) => {
16
+ let borrowUnstable = 0;
17
+ let supplyStable = 0;
18
+ let borrowStable = 0;
19
+ let supplyUnstable = 0;
20
+ let longAsset = '';
21
+ let shortAsset = '';
22
+ Object.values(usedAssets).forEach(({
23
+ symbol, suppliedUsd, borrowedUsd, collateral, reserveId,
24
+ }) => {
25
+ const spokeAsset = `${symbol}-${reserveId}`;
26
+ const isSupplied = (+suppliedUsd) > dustLimit; // ignore dust like <limit leftover supply
27
+ const isBorrowed = (+borrowedUsd) > dustLimit; // ignore dust like <limit leftover supply
28
+ if (isSupplied && STABLE_ASSETS.includes(symbol) && collateral) supplyStable += 1;
29
+ if (isBorrowed && STABLE_ASSETS.includes(symbol)) borrowStable += 1;
30
+ if (isBorrowed && !STABLE_ASSETS.includes(symbol)) {
31
+ borrowUnstable += 1;
32
+ shortAsset = spokeAsset;
33
+ }
34
+ if (isSupplied && !STABLE_ASSETS.includes(symbol) && collateral) {
35
+ supplyUnstable += 1;
36
+ longAsset = spokeAsset;
37
+ }
38
+ });
39
+ const isLong = borrowStable > 0 && borrowUnstable === 0 && supplyUnstable === 1 && supplyStable === 0;
40
+ const isShort = supplyStable > 0 && supplyUnstable === 0 && borrowUnstable === 1 && borrowStable === 0;
41
+ const isVolatilePair = supplyUnstable === 1 && borrowUnstable === 1 && supplyStable === 0 && borrowStable === 0;
42
+ if (isLong) {
43
+ return {
44
+ leveragedType: LeverageType.Long,
45
+ leveragedAsset: longAsset,
46
+ };
47
+ }
48
+ if (isShort) {
49
+ return {
50
+ leveragedType: LeverageType.Short,
51
+ leveragedAsset: shortAsset,
52
+ };
53
+ }
54
+ if (isVolatilePair) {
55
+ return {
56
+ leveragedType: LeverageType.VolatilePair,
57
+ leveragedAsset: longAsset,
58
+ };
59
+ }
60
+ return {
61
+ leveragedType: LeverageType.None,
62
+ leveragedAsset: '',
63
+ };
64
+ };
65
+
66
+ export const aaveV4GetAggregatedPositionData = ({
67
+ usedAssets,
68
+ assetsData,
69
+ network,
70
+ useUserCollateralFactor = false,
71
+ }: {
72
+ usedAssets: AaveV4UsedReserveAssets,
73
+ assetsData: AaveV4AssetsData,
74
+ network: NetworkNumber,
75
+ useUserCollateralFactor?: boolean,
76
+ }): AaveV4AggregatedPositionData => {
77
+ const payload = {} as AaveV4AggregatedPositionData;
78
+ payload.suppliedUsd = getAssetsTotal(usedAssets, ({ isSupplied }: { isSupplied: boolean }) => isSupplied, ({ suppliedUsd }: { suppliedUsd: string }) => suppliedUsd);
79
+ payload.suppliedCollateralUsd = getAssetsTotal(usedAssets, ({ isSupplied, collateral }: { isSupplied: boolean, collateral: string }) => isSupplied && collateral, ({ suppliedUsd }: { suppliedUsd: string }) => suppliedUsd);
80
+ payload.borrowLimitUsd = getAssetsTotal(
81
+ usedAssets,
82
+ ({ isSupplied, collateral }: { isSupplied: boolean, collateral: string }) => isSupplied && collateral,
83
+ ({ symbol, suppliedUsd, reserveId }: { symbol: string, suppliedUsd: string, reserveId: number }) => new Dec(suppliedUsd).mul(aaveV4GetCollateralFactor(assetsData[`${symbol}-${reserveId}`], usedAssets[`${symbol}-${reserveId}`], useUserCollateralFactor)),
84
+ );
85
+ payload.liquidationLimitUsd = payload.borrowLimitUsd;
86
+ payload.borrowedUsd = getAssetsTotal(usedAssets, ({ isBorrowed }: { isBorrowed: boolean }) => isBorrowed, ({ borrowedUsd }: { borrowedUsd: string }) => borrowedUsd);
87
+ payload.drawnUsd = getAssetsTotal(usedAssets, ({ isBorrowed }: { isBorrowed: boolean }) => isBorrowed, ({ drawnUsd }: { drawnUsd: string }) => drawnUsd);
88
+ payload.premiumUsd = getAssetsTotal(usedAssets, ({ isBorrowed }: { isBorrowed: boolean }) => isBorrowed, ({ premiumUsd }: { premiumUsd: string }) => premiumUsd);
89
+ const leftToBorrowUsd = new Dec(payload.borrowLimitUsd).sub(payload.borrowedUsd);
90
+ payload.leftToBorrowUsd = leftToBorrowUsd.lte('0') ? '0' : leftToBorrowUsd.toString();
91
+ payload.ratio = +payload.suppliedUsd ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
92
+ payload.collRatio = +payload.suppliedUsd ? new Dec(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
93
+ payload.liqRatio = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).toString();
94
+ payload.liqPercent = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).mul(100).toString();
95
+ const { leveragedType, leveragedAsset } = isLeveragedPosAaveV4(usedAssets);
96
+ payload.leveragedType = leveragedType;
97
+ payload.leveragedAsset = leveragedAsset;
98
+ payload.liquidationPrice = '';
99
+ if (leveragedType !== '') {
100
+ const leveragedAssetData = assetsData[leveragedAsset];
101
+ let assetPrice = leveragedAssetData?.price || '0';
102
+ if (leveragedType === LeverageType.VolatilePair) {
103
+ const borrowedAsset = (Object.values(usedAssets) as AaveV4UsedReserveAsset[]).find(({ borrowedUsd }: { borrowedUsd: string }) => +borrowedUsd > 0);
104
+ const borrowedAssetPrice = assetsData[`${borrowedAsset!.symbol}-${borrowedAsset!.reserveId}`].price;
105
+ const leveragedAssetPrice = assetsData[leveragedAsset].price;
106
+ const isReverse = new Dec(leveragedAssetPrice).lt(borrowedAssetPrice);
107
+ if (isReverse) {
108
+ payload.leveragedType = LeverageType.VolatilePairReverse;
109
+ payload.currentVolatilePairRatio = new Dec(borrowedAssetPrice).div(leveragedAssetPrice).toDP(18).toString();
110
+ assetPrice = new Dec(borrowedAssetPrice).div(assetPrice).toString();
111
+ } else {
112
+ assetPrice = new Dec(assetPrice).div(borrowedAssetPrice).toString();
113
+ payload.currentVolatilePairRatio = new Dec(leveragedAssetPrice).div(borrowedAssetPrice).toDP(18).toString();
114
+ }
115
+ }
116
+ payload.liquidationPrice = calcLeverageLiqPrice(payload.leveragedType, assetPrice, payload.borrowedUsd, payload.liquidationLimitUsd);
117
+ }
118
+ payload.minCollRatio = new Dec(payload.suppliedCollateralUsd).div(payload.borrowLimitUsd).mul(100).toString();
119
+ payload.collLiquidationRatio = new Dec(payload.suppliedCollateralUsd).div(payload.liquidationLimitUsd).mul(100).toString();
120
+ // payload.healthRatio = new Dec(payload.liquidationLimitUsd).div(payload.borrowedUsd).toDP(4).toString();
121
+ payload.minHealthRatio = new Dec(payload.liquidationLimitUsd).div(payload.borrowLimitUsd).toDP(4).toString();
122
+
123
+ // TODO: Re-implement netApy calculation
124
+ // const { netApy, incentiveUsd, totalInterestUsd } = calculateNetApy({
125
+ // usedAssets,
126
+ // assetsData,
127
+ // optionalData: { healthRatio: payload.healthRatio },
128
+ // });
129
+ payload.netApy = '0';
130
+ payload.incentiveUsd = '0';
131
+ payload.totalInterestUsd = '0';
132
+ return payload;
133
+ };
@@ -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';
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,
@@ -0,0 +1,149 @@
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: '0x3Ed2C9829FBCab6015E331a0352F8ae148217D70',
16
+ });
17
+
18
+ export const AAVE_V4_PLUS_HUB = (networkId: NetworkNumber): AaveV4HubInfo => ({
19
+ chainIds: [NetworkNumber.Eth],
20
+ label: 'Plus Hub',
21
+ value: AaveV4HubsType.AaveV4PlusHub,
22
+ address: '0xcb8C80026248f92c6DE735264c23c8e22922C562',
23
+ });
24
+
25
+ export const AAVE_V4_PRIME_HUB = (networkId: NetworkNumber): AaveV4HubInfo => ({
26
+ chainIds: [NetworkNumber.Eth],
27
+ label: 'Prime Hub',
28
+ value: AaveV4HubsType.AaveV4PrimeHub,
29
+ address: '0xea40581231Ca775e6A3d7c129cF231D292B85f20',
30
+ });
31
+
32
+ export const AaveV4Hubs = (networkId: NetworkNumber) => ({
33
+ [AaveV4HubsType.AaveV4CoreHub]: AAVE_V4_CORE_HUB(networkId),
34
+ [AaveV4HubsType.AaveV4PlusHub]: AAVE_V4_PLUS_HUB(networkId),
35
+ [AaveV4HubsType.AaveV4PrimeHub]: AAVE_V4_PRIME_HUB(networkId),
36
+ }) as const;
37
+
38
+ export const getAaveV4HubTypeInfo = (type: AaveV4HubsType, network?: NetworkNumber) => ({ ...AaveV4Hubs(network ?? NetworkNumber.Eth) }[type]);
39
+
40
+ export const getAaveV4HubByAddress = (networkId: NetworkNumber, address: string): AaveV4HubInfo | undefined => Object.values(AaveV4Hubs(networkId)).find(
41
+ hub => hub.address.toLowerCase() === address.toLowerCase(),
42
+ );
43
+
44
+ // SPOKES
45
+
46
+ export const AAVE_V4_BLUECHIP_SPOKE = (networkId: NetworkNumber): AaveV4SpokeInfo => ({
47
+ chainIds: [NetworkNumber.Eth],
48
+ label: 'Bluechip Spoke',
49
+ value: AaveV4SpokesType.AaveV4BluechipSpoke,
50
+ url: 'bluechip',
51
+ address: '0x637F9E189332a2821e5B046E2d7EEFae2405d6c5',
52
+ hubs: [
53
+ AAVE_V4_CORE_HUB(NetworkNumber.Eth).address,
54
+ AAVE_V4_PLUS_HUB(NetworkNumber.Eth).address,
55
+ AAVE_V4_PRIME_HUB(NetworkNumber.Eth).address,
56
+ ],
57
+ });
58
+
59
+ export const AAVE_V4_ETHENA_SPOKE = (networkId: NetworkNumber): AaveV4SpokeInfo => ({
60
+ chainIds: [NetworkNumber.Eth],
61
+ label: 'Ethena Spoke',
62
+ value: AaveV4SpokesType.AaveV4EthenaSpoke,
63
+ url: 'ethena',
64
+ address: '0xf3b207c235f6154120F41eB63D5ACCBAfD4086D1',
65
+ hubs: [
66
+ AAVE_V4_CORE_HUB(NetworkNumber.Eth).address,
67
+ AAVE_V4_PLUS_HUB(NetworkNumber.Eth).address,
68
+ AAVE_V4_PRIME_HUB(NetworkNumber.Eth).address,
69
+ ],
70
+ });
71
+
72
+ export const AAVE_V4_ETHERFI_SPOKE = (networkId: NetworkNumber): AaveV4SpokeInfo => ({
73
+ chainIds: [NetworkNumber.Eth],
74
+ label: 'Etherfi Spoke',
75
+ value: AaveV4SpokesType.AaveV4EtherfiSpoke,
76
+ url: 'etherfi',
77
+ address: '0x4054a9EbfcdB692599a8dF61eb0b3484F2d279D4',
78
+ hubs: [
79
+ AAVE_V4_CORE_HUB(NetworkNumber.Eth).address,
80
+ AAVE_V4_PLUS_HUB(NetworkNumber.Eth).address,
81
+ AAVE_V4_PRIME_HUB(NetworkNumber.Eth).address,
82
+ ],
83
+ });
84
+
85
+ export const AAVE_V4_GOLD_SPOKE = (networkId: NetworkNumber): AaveV4SpokeInfo => ({
86
+ chainIds: [NetworkNumber.Eth],
87
+ label: 'Gold Spoke',
88
+ value: AaveV4SpokesType.AaveV4GoldSpoke,
89
+ url: 'gold',
90
+ address: '0x0DC7ccE912Afab8B49031A0A95DB74531741C2c4',
91
+ hubs: [
92
+ AAVE_V4_CORE_HUB(NetworkNumber.Eth).address,
93
+ AAVE_V4_PLUS_HUB(NetworkNumber.Eth).address,
94
+ AAVE_V4_PRIME_HUB(NetworkNumber.Eth).address,
95
+ ],
96
+ });
97
+
98
+ export const AAVE_V4_KELP_SPOKE = (networkId: NetworkNumber): AaveV4SpokeInfo => ({
99
+ chainIds: [NetworkNumber.Eth],
100
+ label: 'Kelp Spoke',
101
+ value: AaveV4SpokesType.AaveV4KelpSpoke,
102
+ url: 'kelp',
103
+ address: '0x8aC76d950a3D03F9E1d857b5AAFFdA3f86C1e9AA',
104
+ hubs: [
105
+ AAVE_V4_CORE_HUB(NetworkNumber.Eth).address,
106
+ AAVE_V4_PLUS_HUB(NetworkNumber.Eth).address,
107
+ AAVE_V4_PRIME_HUB(NetworkNumber.Eth).address,
108
+ ],
109
+ });
110
+
111
+ export const AAVE_V4_LIDO_SPOKE = (networkId: NetworkNumber): AaveV4SpokeInfo => ({
112
+ chainIds: [NetworkNumber.Eth],
113
+ label: 'Lido Spoke',
114
+ value: AaveV4SpokesType.AaveV4LidoSpoke,
115
+ url: 'lido',
116
+ address: '0x4D4a7b3Ce709b4362D7095a4A0105bDFDb5dA2a7',
117
+ hubs: [
118
+ AAVE_V4_CORE_HUB(NetworkNumber.Eth).address,
119
+ AAVE_V4_PLUS_HUB(NetworkNumber.Eth).address,
120
+ AAVE_V4_PRIME_HUB(NetworkNumber.Eth).address,
121
+ ],
122
+ });
123
+
124
+ export const AAVE_V4_MAIN_SPOKE = (networkId: NetworkNumber): AaveV4SpokeInfo => ({
125
+ chainIds: [NetworkNumber.Eth],
126
+ label: 'Main Spoke',
127
+ value: AaveV4SpokesType.AaveV4MainSpoke,
128
+ url: 'main',
129
+ address: '0x46539e9123A18c427e6b4DFF114c28CF405Cb023',
130
+ hubs: [
131
+ AAVE_V4_CORE_HUB(NetworkNumber.Eth).address,
132
+ AAVE_V4_PLUS_HUB(NetworkNumber.Eth).address,
133
+ AAVE_V4_PRIME_HUB(NetworkNumber.Eth).address,
134
+ ],
135
+ });
136
+
137
+ export const AaveV4Spokes = (networkId: NetworkNumber) => ({
138
+ [AaveV4SpokesType.AaveV4BluechipSpoke]: AAVE_V4_BLUECHIP_SPOKE(networkId),
139
+ [AaveV4SpokesType.AaveV4EthenaSpoke]: AAVE_V4_ETHENA_SPOKE(networkId),
140
+ [AaveV4SpokesType.AaveV4EtherfiSpoke]: AAVE_V4_ETHERFI_SPOKE(networkId),
141
+ [AaveV4SpokesType.AaveV4GoldSpoke]: AAVE_V4_GOLD_SPOKE(networkId),
142
+ [AaveV4SpokesType.AaveV4KelpSpoke]: AAVE_V4_KELP_SPOKE(networkId),
143
+ [AaveV4SpokesType.AaveV4LidoSpoke]: AAVE_V4_LIDO_SPOKE(networkId),
144
+ [AaveV4SpokesType.AaveV4MainSpoke]: AAVE_V4_MAIN_SPOKE(networkId),
145
+ }) as const;
146
+
147
+ export const getAaveV4SpokeTypeInfo = (type: AaveV4SpokesType, network?: NetworkNumber) => ({ ...AaveV4Spokes(network ?? NetworkNumber.Eth) }[type]);
148
+
149
+
@@ -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';
@@ -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([
@@ -3,7 +3,7 @@ import { SummerVault, SummerVaultType } from '../../types';
3
3
 
4
4
  export const SUMMER_VAULT_USDC_MAINNET_LR: SummerVault = {
5
5
  type: SummerVaultType.SummerVaultUSDCMainnetLR,
6
- name: 'Lower Risk USDC',
6
+ name: 'USDC',
7
7
  address: '0x98C49e13bf99D7CAd8069faa2A370933EC9EcF17',
8
8
  asset: 'USDC',
9
9
  network: NetworkNumber.Eth,
@@ -23,7 +23,7 @@ export const SUMMER_VAULT_USDC_MAINNET_HR: SummerVault = {
23
23
 
24
24
  export const SUMMER_VAULT_USDT_MAINNET_LR: SummerVault = {
25
25
  type: SummerVaultType.SummerVaultUSDTMainnetLR,
26
- name: 'Lower Risk USDT',
26
+ name: 'USDT',
27
27
  address: '0x17ee2d03e88b55e762c66c76ec99c3a28a54ad8d',
28
28
  asset: 'USDT',
29
29
  network: NetworkNumber.Eth,
@@ -33,7 +33,7 @@ export const SUMMER_VAULT_USDT_MAINNET_LR: SummerVault = {
33
33
 
34
34
  export const SUMMER_VAULT_ETH_MAINNET_LR: SummerVault = {
35
35
  type: SummerVaultType.SummerVaultETHMainnetLR,
36
- name: 'Lower Risk ETH',
36
+ name: 'ETH',
37
37
  address: '0x67e536797570b3d8919df052484273815a0ab506',
38
38
  asset: 'WETH',
39
39
  network: NetworkNumber.Eth,
@@ -53,7 +53,7 @@ export const SUMMER_VAULT_ETH_MAINNET_HR: SummerVault = {
53
53
 
54
54
  export const SUMMER_VAULT_USDC_ARBITRUM_LR: SummerVault = {
55
55
  type: SummerVaultType.SummerVaultUSDCArbitrumLR,
56
- name: 'Lower Risk USDC',
56
+ name: 'USDC',
57
57
  address: '0x71d77c39db0eb5d086611a2e950198e3077cf58a',
58
58
  asset: 'USDC',
59
59
  network: NetworkNumber.Arb,
@@ -63,7 +63,7 @@ export const SUMMER_VAULT_USDC_ARBITRUM_LR: SummerVault = {
63
63
 
64
64
  export const SUMMER_VAULT_USDT_ARBITRUM_LR: SummerVault = {
65
65
  type: SummerVaultType.SummerVaultUSDTArbitrumLR,
66
- name: 'Lower Risk USDT',
66
+ name: 'USDT',
67
67
  address: '0x98c49e13bf99d7cad8069faa2a370933ec9ecf17',
68
68
  asset: 'USDT',
69
69
  network: NetworkNumber.Arb,
@@ -73,7 +73,7 @@ export const SUMMER_VAULT_USDT_ARBITRUM_LR: SummerVault = {
73
73
 
74
74
  export const SUMMER_VAULT_USDC_BASE_LR: SummerVault = {
75
75
  type: SummerVaultType.SummerVaultUSDCBaseLR,
76
- name: 'Lower Risk USDC',
76
+ name: 'USDC',
77
77
  address: '0x98C49e13bf99D7CAd8069faa2A370933EC9EcF17',
78
78
  asset: 'USDC',
79
79
  network: NetworkNumber.Base,
@@ -83,7 +83,7 @@ export const SUMMER_VAULT_USDC_BASE_LR: SummerVault = {
83
83
 
84
84
  export const SUMMER_VAULT_EURC_BASE_LR: SummerVault = {
85
85
  type: SummerVaultType.SummerVaultEURCBaseLR,
86
- name: 'Lower Risk EURC',
86
+ name: 'EURC',
87
87
  address: '0x64db8f51f1bf7064bb5a361a7265f602d348e0f0',
88
88
  asset: 'EURC',
89
89
  network: NetworkNumber.Base,
@@ -93,7 +93,7 @@ export const SUMMER_VAULT_EURC_BASE_LR: SummerVault = {
93
93
 
94
94
  export const SUMMER_VAULT_ETH_BASE_LR: SummerVault = {
95
95
  type: SummerVaultType.SummerVaultETHBaseLR,
96
- name: 'Lower Risk ETH',
96
+ name: 'ETH',
97
97
  address: '0x2bb9ad69feba5547b7cd57aafe8457d40bf834af',
98
98
  asset: 'WETH',
99
99
  network: NetworkNumber.Base,
@@ -0,0 +1,169 @@
1
+ import {
2
+ EthAddress, IncentiveData, LeverageType, NetworkNumber,
3
+ } from './common';
4
+
5
+ export enum AaveV4HubsType {
6
+ AaveV4CoreHub = 'aave_v4_core_hub',
7
+ AaveV4PlusHub = 'aave_v4_plus_hub',
8
+ AaveV4PrimeHub = 'aave_v4_prime_hub',
9
+ }
10
+
11
+ export enum AaveV4SpokesType {
12
+ AaveV4BluechipSpoke = 'aave_v4_bluechip_spoke',
13
+ AaveV4EthenaSpoke = 'aave_v4_ethena_spoke',
14
+ AaveV4EtherfiSpoke = 'aave_v4_etherfi_spoke',
15
+ AaveV4GoldSpoke = 'aave_v4_gold_spoke',
16
+ AaveV4KelpSpoke = 'aave_v4_kelp_spoke',
17
+ AaveV4LidoSpoke = 'aave_v4_lido_spoke',
18
+ AaveV4MainSpoke = 'aave_v4_main_spoke',
19
+ }
20
+
21
+ export interface AaveV4HubInfo {
22
+ chainIds: NetworkNumber[],
23
+ label: string,
24
+ value: AaveV4HubsType,
25
+ address: EthAddress,
26
+ }
27
+
28
+ export interface AaveV4HubAssetOnChainData {
29
+ assetId: number,
30
+ drawnRate: bigint,
31
+ liquidity: bigint,
32
+ liquidityFee: number,
33
+ swept: bigint,
34
+ totalDrawn: bigint,
35
+ totalDrawnShares: bigint,
36
+ totalPremiumShares: bigint,
37
+ }
38
+
39
+ export interface AaveV4HubOnChainData {
40
+ assets: Record<number, AaveV4HubAssetOnChainData>,
41
+ }
42
+
43
+ export interface AaveV4SpokeInfo {
44
+ chainIds: NetworkNumber[],
45
+ label: string,
46
+ value: AaveV4SpokesType,
47
+ url: string,
48
+ address: EthAddress,
49
+ hubs: EthAddress[],
50
+ }
51
+
52
+ export interface AaveV4SpokeData {
53
+ assetsData: AaveV4AssetsData,
54
+ oracle: EthAddress,
55
+ oracleDecimals: number,
56
+ address: EthAddress,
57
+ }
58
+
59
+ export interface AaveV4ReserveAssetOnChain {
60
+ underlying: EthAddress,
61
+ hub: EthAddress,
62
+ assetId: number,
63
+ decimals: number,
64
+ paused: boolean,
65
+ frozen: boolean,
66
+ borrowable: boolean,
67
+ collateralRisk: number,
68
+ collateralFactor: number,
69
+ maxLiquidationBonus: number,
70
+ liquidationFee: number,
71
+ price: bigint,
72
+ totalSupplied: bigint,
73
+ totalDrawn: bigint,
74
+ totalPremium: bigint,
75
+ totalDebt: bigint,
76
+ supplyCap: bigint,
77
+ borrowCap: bigint,
78
+ deficitRay: bigint,
79
+ spokeActive: boolean,
80
+ spokeHalted: boolean
81
+ }
82
+
83
+ export interface AaveV4ReserveAssetData {
84
+ symbol: string,
85
+ underlying: EthAddress,
86
+ hub: EthAddress,
87
+ hubName: string,
88
+ assetId: number,
89
+ reserveId: number,
90
+ paused: boolean,
91
+ frozen: boolean,
92
+ borrowable: boolean,
93
+ collateralRisk: number,
94
+ collateralFactor: number,
95
+ liquidationFee: number,
96
+ price: string,
97
+ totalSupplied: string,
98
+ totalDrawn: string,
99
+ totalPremium: string,
100
+ totalDebt: string,
101
+ supplyCap: string,
102
+ borrowCap: string,
103
+ spokeActive: boolean,
104
+ spokeHalted: boolean,
105
+ drawnRate: string,
106
+ supplyRate: string,
107
+ borrowRate: string,
108
+ supplyIncentives: IncentiveData[];
109
+ borrowIncentives: IncentiveData[];
110
+ canBeBorrowed: boolean;
111
+ canBeSupplied: boolean;
112
+ canBeWithdrawn: boolean;
113
+ canBePayBacked: boolean;
114
+ utilization: string;
115
+ }
116
+
117
+ export type AaveV4AssetsData = Record<string, AaveV4ReserveAssetData>;
118
+
119
+ export interface AaveV4UsedReserveAsset {
120
+ symbol: string,
121
+ hubName: string,
122
+ assetId: number,
123
+ reserveId: number,
124
+ supplied: string,
125
+ suppliedUsd: string,
126
+ drawn: string,
127
+ drawnUsd: string,
128
+ premium: string,
129
+ premiumUsd: string,
130
+ borrowed: string,
131
+ borrowedUsd: string,
132
+ isSupplied: boolean,
133
+ isBorrowed: boolean,
134
+ collateral: boolean,
135
+ collateralFactor: number,
136
+ }
137
+
138
+ export interface AaveV4AggregatedPositionData {
139
+ suppliedUsd: string,
140
+ suppliedCollateralUsd: string,
141
+ borrowLimitUsd: string,
142
+ liquidationLimitUsd: string,
143
+ borrowedUsd: string,
144
+ drawnUsd: string,
145
+ premiumUsd: string,
146
+ leftToBorrowUsd: string,
147
+ ratio: string,
148
+ collRatio: string,
149
+ liqRatio: string,
150
+ liqPercent: string,
151
+ leveragedType: LeverageType,
152
+ leveragedAsset: string,
153
+ liquidationPrice: string,
154
+ minCollRatio: string,
155
+ collLiquidationRatio: string,
156
+ minHealthRatio: string,
157
+ netApy: string,
158
+ incentiveUsd: string,
159
+ totalInterestUsd: string,
160
+ currentVolatilePairRatio?: string,
161
+ }
162
+
163
+ export type AaveV4UsedReserveAssets = Record<string, AaveV4UsedReserveAsset>;
164
+
165
+ export interface AaveV4AccountData extends AaveV4AggregatedPositionData {
166
+ usedAssets: AaveV4UsedReserveAssets,
167
+ healthFactor: string,
168
+ riskPremiumBps: number,
169
+ }
@@ -13,4 +13,5 @@ export * from './portfolio';
13
13
  export * from './merit';
14
14
  export * from './merkl';
15
15
  export * from './savings';
16
- export * from './common';
16
+ export * from './common';
17
+ export * from './aaveV4';
@@ -1,4 +1,5 @@
1
1
  import { AaveV2PositionData, AaveV3PositionData, AaveVersions } from './aave';
2
+ import { AaveV4AccountData, AaveV4SpokesType } from './aaveV4';
2
3
  import { EthAddress } from './common';
3
4
  import { CompoundV2PositionData, CompoundV3PositionData, CompoundVersions } from './compound';
4
5
  import { CrvUSDUserData, CrvUSDVersions } from './curveUsd';
@@ -54,6 +55,9 @@ export interface PortfolioPositionsDataForAddress {
54
55
  [key: string]: FluidVaultData;
55
56
  };
56
57
  };
58
+ aaveV4: {
59
+ [key in AaveV4SpokesType]?: PortfolioProtocolData<AaveV4AccountData>;
60
+ };
57
61
  }
58
62
 
59
63
  export interface PortfolioPositionsData {