@defisaver/positions-sdk 2.1.71 → 2.1.72-aave-v4-3-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 (78) hide show
  1. package/cjs/aaveV4/index.d.ts +7 -0
  2. package/cjs/aaveV4/index.js +293 -0
  3. package/cjs/aaveV4/lend.d.ts +45 -0
  4. package/cjs/aaveV4/lend.js +141 -0
  5. package/cjs/config/contracts.d.ts +1551 -0
  6. package/cjs/config/contracts.js +9 -0
  7. package/cjs/contracts.d.ts +32741 -0
  8. package/cjs/contracts.js +2 -1
  9. package/cjs/helpers/aaveV4Helpers/index.d.ts +12 -0
  10. package/cjs/helpers/aaveV4Helpers/index.js +117 -0
  11. package/cjs/helpers/index.d.ts +1 -0
  12. package/cjs/helpers/index.js +2 -1
  13. package/cjs/index.d.ts +2 -1
  14. package/cjs/index.js +3 -1
  15. package/cjs/markets/aave/marketAssets.js +1 -1
  16. package/cjs/markets/aaveV4/index.d.ts +28 -0
  17. package/cjs/markets/aaveV4/index.js +140 -0
  18. package/cjs/markets/index.d.ts +1 -0
  19. package/cjs/markets/index.js +3 -1
  20. package/cjs/portfolio/index.js +20 -0
  21. package/cjs/staking/eligibility.d.ts +6 -0
  22. package/cjs/staking/eligibility.js +37 -19
  23. package/cjs/staking/staking.js +4 -2
  24. package/cjs/types/aaveV4.d.ts +153 -0
  25. package/cjs/types/aaveV4.js +19 -0
  26. package/cjs/types/common.d.ts +2 -1
  27. package/cjs/types/common.js +1 -0
  28. package/cjs/types/index.d.ts +1 -0
  29. package/cjs/types/index.js +1 -0
  30. package/cjs/types/portfolio.d.ts +4 -0
  31. package/esm/aaveV4/index.d.ts +7 -0
  32. package/esm/aaveV4/index.js +250 -0
  33. package/esm/aaveV4/lend.d.ts +45 -0
  34. package/esm/aaveV4/lend.js +134 -0
  35. package/esm/config/contracts.d.ts +1551 -0
  36. package/esm/config/contracts.js +8 -0
  37. package/esm/contracts.d.ts +32741 -0
  38. package/esm/contracts.js +1 -0
  39. package/esm/helpers/aaveV4Helpers/index.d.ts +12 -0
  40. package/esm/helpers/aaveV4Helpers/index.js +108 -0
  41. package/esm/helpers/index.d.ts +1 -0
  42. package/esm/helpers/index.js +1 -0
  43. package/esm/index.d.ts +2 -1
  44. package/esm/index.js +2 -1
  45. package/esm/markets/aave/marketAssets.js +1 -1
  46. package/esm/markets/aaveV4/index.d.ts +28 -0
  47. package/esm/markets/aaveV4/index.js +122 -0
  48. package/esm/markets/index.d.ts +1 -0
  49. package/esm/markets/index.js +1 -0
  50. package/esm/portfolio/index.js +21 -1
  51. package/esm/staking/eligibility.d.ts +6 -0
  52. package/esm/staking/eligibility.js +35 -18
  53. package/esm/staking/staking.js +4 -2
  54. package/esm/types/aaveV4.d.ts +153 -0
  55. package/esm/types/aaveV4.js +16 -0
  56. package/esm/types/common.d.ts +2 -1
  57. package/esm/types/common.js +1 -0
  58. package/esm/types/index.d.ts +1 -0
  59. package/esm/types/index.js +1 -0
  60. package/esm/types/portfolio.d.ts +4 -0
  61. package/package.json +2 -2
  62. package/src/aaveV4/index.ts +286 -0
  63. package/src/aaveV4/lend.ts +180 -0
  64. package/src/config/contracts.ts +9 -1
  65. package/src/contracts.ts +3 -1
  66. package/src/helpers/aaveV4Helpers/index.ts +133 -0
  67. package/src/helpers/index.ts +1 -0
  68. package/src/index.ts +2 -0
  69. package/src/markets/aave/marketAssets.ts +1 -1
  70. package/src/markets/aaveV4/index.ts +149 -0
  71. package/src/markets/index.ts +6 -1
  72. package/src/portfolio/index.ts +20 -0
  73. package/src/staking/eligibility.ts +67 -15
  74. package/src/staking/staking.ts +3 -2
  75. package/src/types/aaveV4.ts +169 -0
  76. package/src/types/common.ts +1 -0
  77. package/src/types/index.ts +2 -1
  78. package/src/types/portfolio.ts +4 -0
@@ -0,0 +1,153 @@
1
+ import { EthAddress, IncentiveData, LeverageType, NetworkNumber } from './common';
2
+ export declare enum AaveV4HubsType {
3
+ AaveV4CoreHub = "aave_v4_core_hub",
4
+ AaveV4PlusHub = "aave_v4_plus_hub",
5
+ AaveV4PrimeHub = "aave_v4_prime_hub"
6
+ }
7
+ export declare enum AaveV4SpokesType {
8
+ AaveV4BluechipSpoke = "aave_v4_bluechip_spoke",
9
+ AaveV4EthenaSpoke = "aave_v4_ethena_spoke",
10
+ AaveV4EtherfiSpoke = "aave_v4_etherfi_spoke",
11
+ AaveV4GoldSpoke = "aave_v4_gold_spoke",
12
+ AaveV4KelpSpoke = "aave_v4_kelp_spoke",
13
+ AaveV4LidoSpoke = "aave_v4_lido_spoke",
14
+ AaveV4MainSpoke = "aave_v4_main_spoke"
15
+ }
16
+ export interface AaveV4HubInfo {
17
+ chainIds: NetworkNumber[];
18
+ label: string;
19
+ value: AaveV4HubsType;
20
+ address: EthAddress;
21
+ }
22
+ export interface AaveV4HubAssetOnChainData {
23
+ assetId: number;
24
+ drawnRate: bigint;
25
+ liquidity: bigint;
26
+ liquidityFee: number;
27
+ swept: bigint;
28
+ totalDrawn: bigint;
29
+ totalDrawnShares: bigint;
30
+ totalPremiumShares: bigint;
31
+ }
32
+ export interface AaveV4HubOnChainData {
33
+ assets: Record<number, AaveV4HubAssetOnChainData>;
34
+ }
35
+ export interface AaveV4SpokeInfo {
36
+ chainIds: NetworkNumber[];
37
+ label: string;
38
+ value: AaveV4SpokesType;
39
+ url: string;
40
+ address: EthAddress;
41
+ hubs: EthAddress[];
42
+ }
43
+ export interface AaveV4SpokeData {
44
+ assetsData: AaveV4AssetsData;
45
+ oracle: EthAddress;
46
+ oracleDecimals: number;
47
+ address: EthAddress;
48
+ }
49
+ export interface AaveV4ReserveAssetOnChain {
50
+ underlying: EthAddress;
51
+ hub: EthAddress;
52
+ assetId: number;
53
+ decimals: number;
54
+ paused: boolean;
55
+ frozen: boolean;
56
+ borrowable: boolean;
57
+ collateralRisk: number;
58
+ collateralFactor: number;
59
+ maxLiquidationBonus: number;
60
+ liquidationFee: number;
61
+ price: bigint;
62
+ totalSupplied: bigint;
63
+ totalDrawn: bigint;
64
+ totalPremium: bigint;
65
+ totalDebt: bigint;
66
+ supplyCap: bigint;
67
+ borrowCap: bigint;
68
+ deficitRay: bigint;
69
+ spokeActive: boolean;
70
+ spokeHalted: boolean;
71
+ }
72
+ export interface AaveV4ReserveAssetData {
73
+ symbol: string;
74
+ underlying: EthAddress;
75
+ hub: EthAddress;
76
+ hubName: string;
77
+ assetId: number;
78
+ reserveId: number;
79
+ paused: boolean;
80
+ frozen: boolean;
81
+ borrowable: boolean;
82
+ collateralRisk: number;
83
+ collateralFactor: number;
84
+ liquidationFee: number;
85
+ price: string;
86
+ totalSupplied: string;
87
+ totalDrawn: string;
88
+ totalPremium: string;
89
+ totalDebt: string;
90
+ supplyCap: string;
91
+ borrowCap: string;
92
+ spokeActive: boolean;
93
+ spokeHalted: boolean;
94
+ drawnRate: string;
95
+ supplyRate: string;
96
+ borrowRate: string;
97
+ supplyIncentives: IncentiveData[];
98
+ borrowIncentives: IncentiveData[];
99
+ canBeBorrowed: boolean;
100
+ canBeSupplied: boolean;
101
+ canBeWithdrawn: boolean;
102
+ canBePayBacked: boolean;
103
+ utilization: string;
104
+ }
105
+ export type AaveV4AssetsData = Record<string, AaveV4ReserveAssetData>;
106
+ export interface AaveV4UsedReserveAsset {
107
+ symbol: string;
108
+ hubName: string;
109
+ assetId: number;
110
+ reserveId: number;
111
+ supplied: string;
112
+ suppliedUsd: string;
113
+ drawn: string;
114
+ drawnUsd: string;
115
+ premium: string;
116
+ premiumUsd: string;
117
+ borrowed: string;
118
+ borrowedUsd: string;
119
+ isSupplied: boolean;
120
+ isBorrowed: boolean;
121
+ collateral: boolean;
122
+ collateralFactor: number;
123
+ }
124
+ export interface AaveV4AggregatedPositionData {
125
+ suppliedUsd: string;
126
+ suppliedCollateralUsd: string;
127
+ borrowLimitUsd: string;
128
+ liquidationLimitUsd: string;
129
+ borrowedUsd: string;
130
+ drawnUsd: string;
131
+ premiumUsd: string;
132
+ leftToBorrowUsd: string;
133
+ ratio: string;
134
+ collRatio: string;
135
+ liqRatio: string;
136
+ liqPercent: string;
137
+ leveragedType: LeverageType;
138
+ leveragedAsset: string;
139
+ liquidationPrice: string;
140
+ minCollRatio: string;
141
+ collLiquidationRatio: string;
142
+ minHealthRatio: string;
143
+ netApy: string;
144
+ incentiveUsd: string;
145
+ totalInterestUsd: string;
146
+ currentVolatilePairRatio?: string;
147
+ }
148
+ export type AaveV4UsedReserveAssets = Record<string, AaveV4UsedReserveAsset>;
149
+ export interface AaveV4AccountData extends AaveV4AggregatedPositionData {
150
+ usedAssets: AaveV4UsedReserveAssets;
151
+ healthFactor: string;
152
+ riskPremiumBps: number;
153
+ }
@@ -0,0 +1,16 @@
1
+ export var AaveV4HubsType;
2
+ (function (AaveV4HubsType) {
3
+ AaveV4HubsType["AaveV4CoreHub"] = "aave_v4_core_hub";
4
+ AaveV4HubsType["AaveV4PlusHub"] = "aave_v4_plus_hub";
5
+ AaveV4HubsType["AaveV4PrimeHub"] = "aave_v4_prime_hub";
6
+ })(AaveV4HubsType || (AaveV4HubsType = {}));
7
+ export var AaveV4SpokesType;
8
+ (function (AaveV4SpokesType) {
9
+ AaveV4SpokesType["AaveV4BluechipSpoke"] = "aave_v4_bluechip_spoke";
10
+ AaveV4SpokesType["AaveV4EthenaSpoke"] = "aave_v4_ethena_spoke";
11
+ AaveV4SpokesType["AaveV4EtherfiSpoke"] = "aave_v4_etherfi_spoke";
12
+ AaveV4SpokesType["AaveV4GoldSpoke"] = "aave_v4_gold_spoke";
13
+ AaveV4SpokesType["AaveV4KelpSpoke"] = "aave_v4_kelp_spoke";
14
+ AaveV4SpokesType["AaveV4LidoSpoke"] = "aave_v4_lido_spoke";
15
+ AaveV4SpokesType["AaveV4MainSpoke"] = "aave_v4_main_spoke";
16
+ })(AaveV4SpokesType || (AaveV4SpokesType = {}));
@@ -6,7 +6,8 @@ export declare enum IncentiveEligibilityId {
6
6
  AaveV3EthenaLiquidLeverage = "0x8014e0076e5393e62c49a7134070d8fccc922e46BORROW_BL",
7
7
  AaveV3ArbitrumEthSupply = "0x5d16261c6715a653248269861bbacf68a9774cde",
8
8
  AaveV3ArbitrumETHLSBorrow = "0x0c84331e39d6658Cd6e6b9ba04736cC4c4734351",
9
- AaveV3EthenaLiquidLeveragePlasma = "0xeefac321069fbecc9d6b2aed2948f6d5503d8633BORROW_BL"
9
+ AaveV3EthenaLiquidLeveragePlasma = "0xeefac321069fbecc9d6b2aed2948f6d5503d8633BORROW_BL",
10
+ AaveV3EthenaLiquidLeveragePlasmaGHO = "replace_when_known"
10
11
  }
11
12
  export declare enum LeverageType {
12
13
  Long = "long",
@@ -9,6 +9,7 @@ export var IncentiveEligibilityId;
9
9
  IncentiveEligibilityId["AaveV3ArbitrumEthSupply"] = "0x5d16261c6715a653248269861bbacf68a9774cde";
10
10
  IncentiveEligibilityId["AaveV3ArbitrumETHLSBorrow"] = "0x0c84331e39d6658Cd6e6b9ba04736cC4c4734351";
11
11
  IncentiveEligibilityId["AaveV3EthenaLiquidLeveragePlasma"] = "0xeefac321069fbecc9d6b2aed2948f6d5503d8633BORROW_BL";
12
+ IncentiveEligibilityId["AaveV3EthenaLiquidLeveragePlasmaGHO"] = "replace_when_known";
12
13
  })(IncentiveEligibilityId || (IncentiveEligibilityId = {}));
13
14
  export var LeverageType;
14
15
  (function (LeverageType) {
@@ -14,3 +14,4 @@ export * from './merit';
14
14
  export * from './merkl';
15
15
  export * from './savings';
16
16
  export * from './common';
17
+ export * from './aaveV4';
@@ -14,3 +14,4 @@ export * from './merit';
14
14
  export * from './merkl';
15
15
  export * from './savings';
16
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';
@@ -51,6 +52,9 @@ export interface PortfolioPositionsDataForAddress {
51
52
  [key: string]: FluidVaultData;
52
53
  };
53
54
  };
55
+ aaveV4: {
56
+ [key in AaveV4SpokesType]?: PortfolioProtocolData<AaveV4AccountData>;
57
+ };
54
58
  }
55
59
  export interface PortfolioPositionsData {
56
60
  [key: EthAddress]: PortfolioPositionsDataForAddress;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defisaver/positions-sdk",
3
- "version": "2.1.71",
3
+ "version": "2.1.72-aave-v4-3-dev",
4
4
  "description": "",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./esm/index.js",
@@ -21,7 +21,7 @@
21
21
  "author": "",
22
22
  "license": "ISC",
23
23
  "dependencies": {
24
- "@defisaver/tokens": "^1.7.25",
24
+ "@defisaver/tokens": "^1.7.26",
25
25
  "@types/lodash": "^4.17.15",
26
26
  "@types/memoizee": "^0.4.12",
27
27
  "decimal.js": "^10.6.0",
@@ -0,0 +1,286 @@
1
+ import { Client } from 'viem';
2
+ import Dec from 'decimal.js';
3
+ import { assetAmountInEth, getAssetInfoByAddress } from '@defisaver/tokens';
4
+ import { getViemProvider } from '../services/viem';
5
+ import {
6
+ AaveV4AccountData,
7
+ AaveV4HubAssetOnChainData,
8
+ AaveV4HubOnChainData,
9
+ AaveV4ReserveAssetData,
10
+ AaveV4ReserveAssetOnChain,
11
+ AaveV4SpokeData,
12
+ AaveV4SpokeInfo,
13
+ AaveV4UsedReserveAssets,
14
+ AaveV4AssetsData,
15
+ EthAddress,
16
+ EthereumProvider,
17
+ IncentiveData,
18
+ IncentiveKind,
19
+ NetworkNumber,
20
+ } from '../types';
21
+ import { AaveV4ViewContractViem } from '../contracts';
22
+ import { getStakingApy, STAKING_ASSETS } from '../staking';
23
+ import { wethToEth } from '../services/utils';
24
+ import { aaveV4GetAggregatedPositionData } from '../helpers/aaveV4Helpers';
25
+ import { getAaveV4HubByAddress } from '../markets/aaveV4';
26
+ import { aprToApy } from '../moneymarket';
27
+
28
+ export * as lend from './lend';
29
+
30
+ const fetchHubData = async (viewContract: ReturnType<typeof AaveV4ViewContractViem>, hubAddress: EthAddress): Promise<AaveV4HubOnChainData> => {
31
+ const hubData = await viewContract.read.getHubAllAssetsData([hubAddress]);
32
+ return {
33
+ assets: hubData.reduce((acc: Record<number, AaveV4HubAssetOnChainData>, assetOnChainData) => {
34
+ acc[assetOnChainData.assetId] = {
35
+ assetId: assetOnChainData.assetId,
36
+ drawnRate: assetOnChainData.drawnRate,
37
+ liquidity: assetOnChainData.liquidity,
38
+ liquidityFee: assetOnChainData.liquidityFee,
39
+ swept: assetOnChainData.swept,
40
+ totalDrawn: assetOnChainData.totalDrawn,
41
+ totalDrawnShares: assetOnChainData.totalDrawnShares,
42
+ totalPremiumShares: assetOnChainData.totalPremiumShares,
43
+ };
44
+ return acc;
45
+ }, {}),
46
+ };
47
+ };
48
+
49
+ const calcUserRiskPremiumBps = (usedAssets: AaveV4UsedReserveAssets, assetsData: AaveV4AssetsData): number => {
50
+ type CollateralInfo = { riskBps: number; valueUsd: Dec };
51
+ type DebtInfo = { valueUsd: Dec };
52
+
53
+ const collaterals: CollateralInfo[] = [];
54
+ const debts: DebtInfo[] = [];
55
+
56
+ Object.entries(usedAssets).forEach(([identifier, asset]) => {
57
+ const reserveData = assetsData[identifier];
58
+ if (!reserveData) return;
59
+
60
+ const borrowedUsdDec = new Dec(asset.borrowedUsd || '0');
61
+ if (asset.isBorrowed && borrowedUsdDec.gt(0)) {
62
+ debts.push({ valueUsd: borrowedUsdDec });
63
+ }
64
+
65
+ const suppliedUsdDec = new Dec(asset.suppliedUsd || '0');
66
+ const isActiveCollateral = asset.collateral
67
+ && asset.isSupplied
68
+ && asset.collateralFactor > 0
69
+ && suppliedUsdDec.gt(0);
70
+
71
+ if (isActiveCollateral) {
72
+ // collateralRisk is stored as a fraction (e.g. 0.25), convert back to bps
73
+ const riskBps = new Dec(reserveData.collateralRisk).mul(10000).toNumber();
74
+ collaterals.push({
75
+ riskBps,
76
+ valueUsd: suppliedUsdDec,
77
+ });
78
+ }
79
+ });
80
+
81
+ const totalDebtUsd = debts.reduce((sum, d) => sum.add(d.valueUsd), new Dec(0));
82
+
83
+ if (totalDebtUsd.lte(0)) {
84
+ return 0;
85
+ }
86
+
87
+ // sort by risk ASC, value DESC
88
+ collaterals.sort((a, b) => {
89
+ if (a.riskBps !== b.riskBps) return a.riskBps - b.riskBps;
90
+ return b.valueUsd.comparedTo(a.valueUsd);
91
+ });
92
+
93
+ let debtLeftToCover = totalDebtUsd;
94
+ let numerator = new Dec(0); // sum(coveredUsd * riskBps)
95
+ let coveredDebt = new Dec(0); // sum(coveredUsd)
96
+
97
+ collaterals.forEach(({ riskBps, valueUsd }) => {
98
+ if (debtLeftToCover.lte(0)) return;
99
+
100
+ const coveredUsd = Dec.min(valueUsd, debtLeftToCover);
101
+
102
+ numerator = numerator.add(coveredUsd.mul(riskBps));
103
+ coveredDebt = coveredDebt.add(coveredUsd);
104
+
105
+ debtLeftToCover = debtLeftToCover.sub(coveredUsd);
106
+ });
107
+
108
+ if (coveredDebt.lte(0)) {
109
+ return 0;
110
+ }
111
+
112
+ const riskPremiumBps = numerator.div(coveredDebt);
113
+ return riskPremiumBps.toNumber();
114
+ };
115
+
116
+ const formatReserveAsset = async (reserveAsset: AaveV4ReserveAssetOnChain, hubAsset: AaveV4HubAssetOnChainData, reserveId: number, oracleDecimals: number, network: NetworkNumber): Promise<AaveV4ReserveAssetData> => {
117
+ const assetInfo = getAssetInfoByAddress(reserveAsset.underlying, network);
118
+ const symbol = wethToEth(assetInfo.symbol);
119
+ const hubInfo = getAaveV4HubByAddress(network, reserveAsset.hub);
120
+ if (!hubInfo) {
121
+ throw new Error(`Hub not found with address: ${reserveAsset.hub}`);
122
+ }
123
+
124
+ const isStakingAsset = STAKING_ASSETS.includes(symbol);
125
+ const supplyIncentives: IncentiveData[] = [];
126
+ const borrowIncentives: IncentiveData[] = [];
127
+
128
+ if (isStakingAsset) {
129
+ const yieldApy = await getStakingApy(symbol, network as NetworkNumber);
130
+ supplyIncentives.push({
131
+ apy: yieldApy,
132
+ token: symbol,
133
+ incentiveKind: IncentiveKind.Staking,
134
+ description: `Native ${symbol} yield.`,
135
+ });
136
+ if (reserveAsset.borrowable) {
137
+ // when borrowing assets whose value increases over time
138
+ borrowIncentives.push({
139
+ apy: new Dec(yieldApy).mul(-1).toString(),
140
+ token: symbol,
141
+ incentiveKind: IncentiveKind.Reward,
142
+ description: `Due to the native yield of ${symbol}, the value of the debt would increase over time.`,
143
+ });
144
+ }
145
+ }
146
+
147
+ const totalSuppliedRaw = reserveAsset.totalSupplied ?? 0;
148
+ const totalDrawnRaw = reserveAsset.totalDrawn ?? 0;
149
+ const totalPremiumRaw = reserveAsset.totalPremium ?? 0;
150
+ const totalDebtRaw = reserveAsset.totalDebt ?? 0;
151
+ const supplyCapRaw = reserveAsset.supplyCap ?? 0;
152
+ const borrowCapRaw = reserveAsset.borrowCap ?? 0;
153
+
154
+ /** @DEV Hub related calculations */
155
+ const drawnRate = new Dec(hubAsset.drawnRate.toString()).div(new Dec(10).pow(27));
156
+ const borrowApr = drawnRate.mul(100);
157
+ const totalDrawn = new Dec(hubAsset.totalDrawn.toString());
158
+ const liquidity = new Dec(hubAsset.liquidity.toString());
159
+ const swept = new Dec(hubAsset.swept.toString());
160
+ const hubUtilization = totalDrawn.div(totalDrawn.add(swept).add(liquidity));
161
+ const liquidityFee = new Dec(hubAsset.liquidityFee.toString()).div(new Dec(10).pow(4));
162
+ const totalDrawnShares = new Dec(hubAsset.totalDrawnShares.toString());
163
+ const totalPremiumShares = new Dec(hubAsset.totalPremiumShares.toString());
164
+ // TODO JK@JK premiumMultiplier should be added to supplyApr calculation (.mul(premiumMultiplier)
165
+ // TODO JKJ@JK when we confirm that this is the right way to calculate it
166
+ const premiumMultiplier = totalDrawnShares.add(totalPremiumShares).div(totalDrawnShares);
167
+ const supplyApr = borrowApr.mul(hubUtilization).mul(new Dec(1).minus(liquidityFee));
168
+
169
+ return ({
170
+ symbol,
171
+ underlying: reserveAsset.underlying,
172
+ hub: hubInfo.address,
173
+ hubName: hubInfo?.label,
174
+ assetId: reserveAsset.assetId,
175
+ reserveId,
176
+ paused: reserveAsset.paused,
177
+ frozen: reserveAsset.frozen,
178
+ borrowable: reserveAsset.borrowable,
179
+ collateralRisk: new Dec(reserveAsset.collateralRisk).div(10000).toNumber(),
180
+ collateralFactor: new Dec(reserveAsset.collateralFactor).div(10000).toNumber(),
181
+ liquidationFee: new Dec(reserveAsset.liquidationFee).div(10000).toNumber(),
182
+ price: new Dec(reserveAsset.price).div(new Dec(10).pow(oracleDecimals)).toString(),
183
+ totalSupplied: assetAmountInEth(totalSuppliedRaw.toString(), symbol),
184
+ totalDrawn: assetAmountInEth(totalDrawnRaw.toString(), symbol),
185
+ totalPremium: assetAmountInEth(totalPremiumRaw.toString(), symbol),
186
+ totalDebt: assetAmountInEth(totalDebtRaw.toString(), symbol),
187
+ supplyCap: assetAmountInEth(supplyCapRaw.toString(), symbol),
188
+ borrowCap: assetAmountInEth(borrowCapRaw.toString(), symbol),
189
+ spokeActive: reserveAsset.spokeActive,
190
+ spokeHalted: reserveAsset.spokeHalted,
191
+ drawnRate: drawnRate.toString(),
192
+ borrowRate: aprToApy(borrowApr.toString()),
193
+ supplyRate: aprToApy(supplyApr.toString()),
194
+ supplyIncentives,
195
+ borrowIncentives,
196
+ canBeBorrowed: reserveAsset.spokeActive && !reserveAsset.spokeHalted && !reserveAsset.paused && !reserveAsset.frozen,
197
+ canBeSupplied: reserveAsset.spokeActive && !reserveAsset.spokeHalted && !reserveAsset.paused && !reserveAsset.frozen,
198
+ canBeWithdrawn: reserveAsset.spokeActive && !reserveAsset.spokeHalted && !reserveAsset.paused,
199
+ canBePayBacked: reserveAsset.spokeActive && !reserveAsset.spokeHalted && !reserveAsset.paused,
200
+ utilization: new Dec(reserveAsset.totalDrawn.toString()).times(100).div(new Dec(reserveAsset.totalSupplied.toString())).toString(),
201
+ });
202
+ };
203
+
204
+ export async function _getAaveV4SpokeData(provider: Client, network: NetworkNumber, market: AaveV4SpokeInfo, blockNumber: 'latest' | number = 'latest'): Promise<AaveV4SpokeData> {
205
+ const viewContract = AaveV4ViewContractViem(provider, network, blockNumber);
206
+
207
+ const hubsData: Record<EthAddress, AaveV4HubOnChainData> = {};
208
+ const [spokeData] = await Promise.all([
209
+ viewContract.read.getSpokeDataFull([market.address]),
210
+ ...market.hubs.map(async (hubAddress) => {
211
+ hubsData[hubAddress] = await fetchHubData(viewContract, hubAddress);
212
+ }),
213
+ ]);
214
+
215
+ const reserveAssetsArray = await Promise.all(spokeData[1].map(async (reserveAssetOnChain: AaveV4ReserveAssetOnChain, index: number) => formatReserveAsset(reserveAssetOnChain, hubsData[reserveAssetOnChain.hub].assets[reserveAssetOnChain.assetId], index, +spokeData[0].oracleDecimals.toString(), network)));
216
+
217
+ return {
218
+ assetsData: reserveAssetsArray.reduce((acc: Record<string, AaveV4ReserveAssetData>, reserveAsset: AaveV4ReserveAssetData) => {
219
+ acc[`${reserveAsset.symbol}-${reserveAsset.reserveId}`] = reserveAsset;
220
+ return acc;
221
+ }, {}),
222
+ oracle: spokeData[0].oracle,
223
+ oracleDecimals: +spokeData[0].oracleDecimals.toString(),
224
+ address: market.address,
225
+ };
226
+ }
227
+
228
+ export async function getAaveV4SpokeData(provider: EthereumProvider, network: NetworkNumber, spoke: AaveV4SpokeInfo, blockNumber: 'latest' | number = 'latest'): Promise<AaveV4SpokeData> {
229
+ return _getAaveV4SpokeData(getViemProvider(provider, network), network, spoke, blockNumber);
230
+ }
231
+
232
+ export async function _getAaveV4AccountData(provider: Client, network: NetworkNumber, spokeData: AaveV4SpokeData, address: EthAddress, blockNumber: 'latest' | number = 'latest'): Promise<AaveV4AccountData> {
233
+ const viewContract = AaveV4ViewContractViem(provider, network, blockNumber);
234
+
235
+ const loanData = await viewContract.read.getLoanData([spokeData.address, address]);
236
+
237
+ const healthFactor = new Dec(loanData.healthFactor).div(1e18).toString();
238
+ const usedAssets = loanData.reserves.reduce((acc: AaveV4UsedReserveAssets, usedReserveAsset) => {
239
+ const identifier = `${wethToEth(getAssetInfoByAddress(usedReserveAsset.underlying, network).symbol)}-${+usedReserveAsset.reserveId.toString()}`;
240
+ const reserveData = spokeData.assetsData[identifier];
241
+ const price = reserveData.price;
242
+ const supplied = assetAmountInEth(usedReserveAsset.supplied.toString(), reserveData.symbol);
243
+ const drawn = assetAmountInEth(usedReserveAsset.drawn.toString(), reserveData.symbol);
244
+ const premium = assetAmountInEth(usedReserveAsset.premium.toString(), reserveData.symbol);
245
+ const borrowed = assetAmountInEth(usedReserveAsset.totalDebt.toString(), reserveData.symbol);
246
+ acc[identifier] = {
247
+ symbol: reserveData.symbol,
248
+ hubName: reserveData.hubName,
249
+ assetId: reserveData.assetId,
250
+ reserveId: +usedReserveAsset.reserveId.toString(),
251
+ supplied,
252
+ suppliedUsd: new Dec(supplied).mul(price).toString(),
253
+ drawn,
254
+ drawnUsd: new Dec(drawn).mul(price).toString(),
255
+ premium,
256
+ premiumUsd: new Dec(premium).mul(price).toString(),
257
+ borrowed,
258
+ borrowedUsd: new Dec(borrowed).mul(price).toString(),
259
+ isSupplied: !new Dec(supplied).eq(0),
260
+ isBorrowed: usedReserveAsset.isBorrowing,
261
+ collateral: usedReserveAsset.isUsingAsCollateral,
262
+ collateralFactor: new Dec(usedReserveAsset.collateralFactor).div(10000).toNumber(),
263
+ };
264
+ return acc;
265
+ }, {});
266
+
267
+ const aggregated = aaveV4GetAggregatedPositionData({
268
+ usedAssets,
269
+ assetsData: spokeData.assetsData,
270
+ network,
271
+ useUserCollateralFactor: true,
272
+ });
273
+
274
+ const riskPremiumBps = calcUserRiskPremiumBps(usedAssets, spokeData.assetsData);
275
+
276
+ return {
277
+ ...aggregated,
278
+ usedAssets,
279
+ healthFactor,
280
+ riskPremiumBps,
281
+ };
282
+ }
283
+
284
+ export async function getAaveV4AccountData(provider: EthereumProvider, network: NetworkNumber, marketData: AaveV4SpokeData, address: EthAddress, blockNumber: 'latest' | number = 'latest'): Promise<any> {
285
+ return _getAaveV4AccountData(getViemProvider(provider, network), network, marketData, address, blockNumber);
286
+ }