@defisaver/positions-sdk 2.1.78-aave-v4-dev → 2.1.79

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 (65) hide show
  1. package/cjs/claiming/spark.js +1 -1
  2. package/cjs/config/contracts.d.ts +0 -1551
  3. package/cjs/config/contracts.js +0 -9
  4. package/cjs/contracts.d.ts +0 -32741
  5. package/cjs/contracts.js +1 -2
  6. package/cjs/helpers/index.d.ts +0 -1
  7. package/cjs/helpers/index.js +1 -2
  8. package/cjs/index.d.ts +1 -2
  9. package/cjs/index.js +1 -3
  10. package/cjs/markets/index.d.ts +0 -1
  11. package/cjs/markets/index.js +1 -3
  12. package/cjs/portfolio/index.js +0 -20
  13. package/cjs/types/index.d.ts +0 -1
  14. package/cjs/types/index.js +0 -1
  15. package/cjs/types/portfolio.d.ts +0 -4
  16. package/esm/claiming/spark.js +1 -1
  17. package/esm/config/contracts.d.ts +0 -1551
  18. package/esm/config/contracts.js +0 -8
  19. package/esm/contracts.d.ts +0 -32741
  20. package/esm/contracts.js +0 -1
  21. package/esm/helpers/index.d.ts +0 -1
  22. package/esm/helpers/index.js +0 -1
  23. package/esm/index.d.ts +1 -2
  24. package/esm/index.js +1 -2
  25. package/esm/markets/index.d.ts +0 -1
  26. package/esm/markets/index.js +0 -1
  27. package/esm/portfolio/index.js +1 -21
  28. package/esm/types/index.d.ts +0 -1
  29. package/esm/types/index.js +0 -1
  30. package/esm/types/portfolio.d.ts +0 -4
  31. package/package.json +2 -2
  32. package/src/claiming/spark.ts +1 -1
  33. package/src/config/contracts.ts +0 -8
  34. package/src/contracts.ts +0 -2
  35. package/src/helpers/index.ts +0 -1
  36. package/src/index.ts +0 -2
  37. package/src/markets/index.ts +1 -6
  38. package/src/portfolio/index.ts +0 -20
  39. package/src/types/index.ts +1 -2
  40. package/src/types/portfolio.ts +0 -4
  41. package/cjs/aaveV4/index.d.ts +0 -7
  42. package/cjs/aaveV4/index.js +0 -298
  43. package/cjs/aaveV4/lend.d.ts +0 -45
  44. package/cjs/aaveV4/lend.js +0 -141
  45. package/cjs/helpers/aaveV4Helpers/index.d.ts +0 -12
  46. package/cjs/helpers/aaveV4Helpers/index.js +0 -117
  47. package/cjs/markets/aaveV4/index.d.ts +0 -28
  48. package/cjs/markets/aaveV4/index.js +0 -140
  49. package/cjs/types/aaveV4.d.ts +0 -153
  50. package/cjs/types/aaveV4.js +0 -19
  51. package/esm/aaveV4/index.d.ts +0 -7
  52. package/esm/aaveV4/index.js +0 -255
  53. package/esm/aaveV4/lend.d.ts +0 -45
  54. package/esm/aaveV4/lend.js +0 -134
  55. package/esm/helpers/aaveV4Helpers/index.d.ts +0 -12
  56. package/esm/helpers/aaveV4Helpers/index.js +0 -108
  57. package/esm/markets/aaveV4/index.d.ts +0 -28
  58. package/esm/markets/aaveV4/index.js +0 -122
  59. package/esm/types/aaveV4.d.ts +0 -153
  60. package/esm/types/aaveV4.js +0 -16
  61. package/src/aaveV4/index.ts +0 -291
  62. package/src/aaveV4/lend.ts +0 -180
  63. package/src/helpers/aaveV4Helpers/index.ts +0 -133
  64. package/src/markets/aaveV4/index.ts +0 -149
  65. package/src/types/aaveV4.ts +0 -169
@@ -1,291 +0,0 @@
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
- // TODO AaveV4: Will be used for after values, onchain data is available when fetching position data
50
- const calcUserRiskPremiumBps = (usedAssets: AaveV4UsedReserveAssets, assetsData: AaveV4AssetsData): number => {
51
- type CollateralInfo = { riskBps: number; valueUsd: Dec };
52
- type DebtInfo = { valueUsd: Dec };
53
-
54
- const collaterals: CollateralInfo[] = [];
55
- const debts: DebtInfo[] = [];
56
-
57
- Object.entries(usedAssets).forEach(([identifier, asset]) => {
58
- const reserveData = assetsData[identifier];
59
- if (!reserveData) return;
60
-
61
- const borrowedUsdDec = new Dec(asset.borrowedUsd || '0');
62
- if (asset.isBorrowed && borrowedUsdDec.gt(0)) {
63
- debts.push({ valueUsd: borrowedUsdDec });
64
- }
65
-
66
- const suppliedUsdDec = new Dec(asset.suppliedUsd || '0');
67
- const isActiveCollateral = asset.collateral
68
- && asset.isSupplied
69
- && asset.collateralFactor > 0
70
- && suppliedUsdDec.gt(0);
71
-
72
- if (isActiveCollateral) {
73
- // collateralRisk is stored as a fraction (e.g. 0.25), convert back to bps
74
- const riskBps = new Dec(reserveData.collateralRisk).mul(10000).toNumber();
75
- collaterals.push({
76
- riskBps,
77
- valueUsd: suppliedUsdDec,
78
- });
79
- }
80
- });
81
-
82
- const totalDebtUsd = debts.reduce((sum, d) => sum.add(d.valueUsd), new Dec(0));
83
-
84
- if (totalDebtUsd.lte(0)) {
85
- return 0;
86
- }
87
-
88
- // sort by risk ASC, value DESC
89
- collaterals.sort((a, b) => {
90
- if (a.riskBps !== b.riskBps) return a.riskBps - b.riskBps;
91
- return b.valueUsd.comparedTo(a.valueUsd);
92
- });
93
-
94
- let debtLeftToCover = totalDebtUsd;
95
- let numerator = new Dec(0); // sum(coveredUsd * riskBps)
96
- let coveredDebt = new Dec(0); // sum(coveredUsd)
97
-
98
- collaterals.forEach(({ riskBps, valueUsd }) => {
99
- if (debtLeftToCover.lte(0)) return;
100
-
101
- const coveredUsd = Dec.min(valueUsd, debtLeftToCover);
102
-
103
- numerator = numerator.add(coveredUsd.mul(riskBps));
104
- coveredDebt = coveredDebt.add(coveredUsd);
105
-
106
- debtLeftToCover = debtLeftToCover.sub(coveredUsd);
107
- });
108
-
109
- if (coveredDebt.lte(0)) {
110
- return 0;
111
- }
112
-
113
- const riskPremiumBps = numerator.div(coveredDebt);
114
- return riskPremiumBps.toNumber();
115
- };
116
-
117
- const formatReserveAsset = async (reserveAsset: AaveV4ReserveAssetOnChain, hubAsset: AaveV4HubAssetOnChainData, reserveId: number, oracleDecimals: number, network: NetworkNumber): Promise<AaveV4ReserveAssetData> => {
118
- const assetInfo = getAssetInfoByAddress(reserveAsset.underlying, network);
119
- const symbol = wethToEth(assetInfo.symbol);
120
- const hubInfo = getAaveV4HubByAddress(network, reserveAsset.hub);
121
- if (!hubInfo) {
122
- throw new Error(`Hub not found with address: ${reserveAsset.hub}`);
123
- }
124
-
125
- const isStakingAsset = STAKING_ASSETS.includes(symbol);
126
- const supplyIncentives: IncentiveData[] = [];
127
- const borrowIncentives: IncentiveData[] = [];
128
-
129
- if (isStakingAsset) {
130
- const yieldApy = await getStakingApy(symbol, network as NetworkNumber);
131
- supplyIncentives.push({
132
- apy: yieldApy,
133
- token: symbol,
134
- incentiveKind: IncentiveKind.Staking,
135
- description: `Native ${symbol} yield.`,
136
- });
137
- if (reserveAsset.borrowable) {
138
- // When borrowing assets whose value increases over time
139
- borrowIncentives.push({
140
- apy: new Dec(yieldApy).mul(-1).toString(),
141
- token: symbol,
142
- incentiveKind: IncentiveKind.Reward,
143
- description: `Due to the native yield of ${symbol}, the value of the debt would increase over time.`,
144
- });
145
- }
146
- }
147
-
148
- const totalSuppliedRaw = reserveAsset.totalSupplied ?? 0;
149
- const totalDrawnRaw = reserveAsset.totalDrawn ?? 0;
150
- const totalPremiumRaw = reserveAsset.totalPremium ?? 0;
151
- const totalDebtRaw = reserveAsset.totalDebt ?? 0;
152
- const supplyCapRaw = reserveAsset.supplyCap ?? 0;
153
- const borrowCapRaw = reserveAsset.borrowCap ?? 0;
154
- const totalSuppliedDec = new Dec(totalSuppliedRaw.toString());
155
- const totalDrawnDec = new Dec(totalDrawnRaw.toString());
156
- const utilization = totalSuppliedDec.isZero() ? '0' : totalDrawnDec.times(100).div(totalSuppliedDec).toString();
157
-
158
- /** @DEV Hub related calculations */
159
- const drawnRate = new Dec(hubAsset.drawnRate.toString()).div(new Dec(10).pow(27));
160
- const borrowApr = drawnRate.mul(100);
161
- const totalDrawn = new Dec(hubAsset.totalDrawn.toString());
162
- const liquidity = new Dec(hubAsset.liquidity.toString());
163
- const swept = new Dec(hubAsset.swept.toString());
164
- const hubUtilizationDenominator = totalDrawn.add(swept).add(liquidity);
165
- const hubUtilization = hubUtilizationDenominator.isZero() ? new Dec(0) : totalDrawn.div(hubUtilizationDenominator);
166
- const liquidityFee = new Dec(hubAsset.liquidityFee.toString()).div(new Dec(10).pow(4));
167
- const totalDrawnShares = new Dec(hubAsset.totalDrawnShares.toString());
168
- const totalPremiumShares = new Dec(hubAsset.totalPremiumShares.toString());
169
- // TODO JK@JK premiumMultiplier should be added to supplyApr calculation (.mul(premiumMultiplier)
170
- // TODO JKJ@JK when we confirm that this is the right way to calculate it
171
- const premiumMultiplier = totalDrawnShares.isZero() ? new Dec(1) : totalDrawnShares.add(totalPremiumShares).div(totalDrawnShares);
172
- const supplyApr = borrowApr.mul(hubUtilization).mul(new Dec(1).minus(liquidityFee));
173
-
174
- return ({
175
- symbol,
176
- underlying: reserveAsset.underlying,
177
- hub: hubInfo.address,
178
- hubName: hubInfo?.label,
179
- assetId: reserveAsset.assetId,
180
- reserveId,
181
- paused: reserveAsset.paused,
182
- frozen: reserveAsset.frozen,
183
- borrowable: reserveAsset.borrowable,
184
- collateralRisk: new Dec(reserveAsset.collateralRisk).div(10000).toNumber(),
185
- collateralFactor: new Dec(reserveAsset.collateralFactor).div(10000).toNumber(),
186
- liquidationFee: new Dec(reserveAsset.liquidationFee).div(10000).toNumber(),
187
- price: new Dec(reserveAsset.price).div(new Dec(10).pow(oracleDecimals)).toString(),
188
- totalSupplied: assetAmountInEth(totalSuppliedRaw.toString(), symbol),
189
- totalDrawn: assetAmountInEth(totalDrawnRaw.toString(), symbol),
190
- totalPremium: assetAmountInEth(totalPremiumRaw.toString(), symbol),
191
- totalDebt: assetAmountInEth(totalDebtRaw.toString(), symbol),
192
- supplyCap: assetAmountInEth(supplyCapRaw.toString(), symbol),
193
- borrowCap: assetAmountInEth(borrowCapRaw.toString(), symbol),
194
- spokeActive: reserveAsset.spokeActive,
195
- spokeHalted: reserveAsset.spokeHalted,
196
- drawnRate: drawnRate.toString(),
197
- borrowRate: aprToApy(borrowApr.toString()),
198
- supplyRate: aprToApy(supplyApr.toString()),
199
- supplyIncentives,
200
- borrowIncentives,
201
- canBeBorrowed: reserveAsset.spokeActive && !reserveAsset.spokeHalted && !reserveAsset.paused && !reserveAsset.frozen,
202
- canBeSupplied: reserveAsset.spokeActive && !reserveAsset.spokeHalted && !reserveAsset.paused && !reserveAsset.frozen,
203
- canBeWithdrawn: reserveAsset.spokeActive && !reserveAsset.spokeHalted && !reserveAsset.paused,
204
- canBePayBacked: reserveAsset.spokeActive && !reserveAsset.spokeHalted && !reserveAsset.paused,
205
- utilization,
206
- });
207
- };
208
-
209
- export async function _getAaveV4SpokeData(provider: Client, network: NetworkNumber, market: AaveV4SpokeInfo, blockNumber: 'latest' | number = 'latest'): Promise<AaveV4SpokeData> {
210
- const viewContract = AaveV4ViewContractViem(provider, network, blockNumber);
211
-
212
- const hubsData: Record<EthAddress, AaveV4HubOnChainData> = {};
213
- const [spokeData] = await Promise.all([
214
- viewContract.read.getSpokeDataFull([market.address]),
215
- ...market.hubs.map(async (hubAddress) => {
216
- hubsData[hubAddress] = await fetchHubData(viewContract, hubAddress);
217
- }),
218
- ]);
219
-
220
- 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)));
221
-
222
- return {
223
- assetsData: reserveAssetsArray.reduce((acc: Record<string, AaveV4ReserveAssetData>, reserveAsset: AaveV4ReserveAssetData) => {
224
- acc[`${reserveAsset.symbol}-${reserveAsset.reserveId}`] = reserveAsset;
225
- return acc;
226
- }, {}),
227
- oracle: spokeData[0].oracle,
228
- oracleDecimals: +spokeData[0].oracleDecimals.toString(),
229
- address: market.address,
230
- };
231
- }
232
-
233
- export async function getAaveV4SpokeData(provider: EthereumProvider, network: NetworkNumber, spoke: AaveV4SpokeInfo, blockNumber: 'latest' | number = 'latest'): Promise<AaveV4SpokeData> {
234
- return _getAaveV4SpokeData(getViemProvider(provider, network), network, spoke, blockNumber);
235
- }
236
-
237
- export async function _getAaveV4AccountData(provider: Client, network: NetworkNumber, spokeData: AaveV4SpokeData, address: EthAddress, blockNumber: 'latest' | number = 'latest'): Promise<AaveV4AccountData> {
238
- const viewContract = AaveV4ViewContractViem(provider, network, blockNumber);
239
-
240
- const loanData = await viewContract.read.getLoanData([spokeData.address, address]);
241
-
242
- const healthFactor = new Dec(loanData.healthFactor).div(1e18).toString();
243
- const usedAssets = loanData.reserves.reduce((acc: AaveV4UsedReserveAssets, usedReserveAsset) => {
244
- const identifier = `${wethToEth(getAssetInfoByAddress(usedReserveAsset.underlying, network).symbol)}-${+usedReserveAsset.reserveId.toString()}`;
245
- const reserveData = spokeData.assetsData[identifier];
246
- const price = reserveData.price;
247
- const supplied = assetAmountInEth(usedReserveAsset.supplied.toString(), reserveData.symbol);
248
- const drawn = assetAmountInEth(usedReserveAsset.drawn.toString(), reserveData.symbol);
249
- const premium = assetAmountInEth(usedReserveAsset.premium.toString(), reserveData.symbol);
250
- const borrowed = assetAmountInEth(usedReserveAsset.totalDebt.toString(), reserveData.symbol);
251
- acc[identifier] = {
252
- symbol: reserveData.symbol,
253
- hubName: reserveData.hubName,
254
- assetId: reserveData.assetId,
255
- reserveId: +usedReserveAsset.reserveId.toString(),
256
- supplied,
257
- suppliedUsd: new Dec(supplied).mul(price).toString(),
258
- drawn,
259
- drawnUsd: new Dec(drawn).mul(price).toString(),
260
- premium,
261
- premiumUsd: new Dec(premium).mul(price).toString(),
262
- borrowed,
263
- borrowedUsd: new Dec(borrowed).mul(price).toString(),
264
- isSupplied: !new Dec(supplied).eq(0),
265
- isBorrowed: usedReserveAsset.isBorrowing,
266
- collateral: usedReserveAsset.isUsingAsCollateral,
267
- collateralFactor: new Dec(usedReserveAsset.collateralFactor).div(10000).toNumber(),
268
- };
269
- return acc;
270
- }, {});
271
-
272
- const aggregated = aaveV4GetAggregatedPositionData({
273
- usedAssets,
274
- assetsData: spokeData.assetsData,
275
- network,
276
- useUserCollateralFactor: true,
277
- });
278
-
279
- const riskPremiumBps = calcUserRiskPremiumBps(usedAssets, spokeData.assetsData);
280
-
281
- return {
282
- ...aggregated,
283
- usedAssets,
284
- healthFactor,
285
- riskPremiumBps,
286
- };
287
- }
288
-
289
- export async function getAaveV4AccountData(provider: EthereumProvider, network: NetworkNumber, marketData: AaveV4SpokeData, address: EthAddress, blockNumber: 'latest' | number = 'latest'): Promise<any> {
290
- return _getAaveV4AccountData(getViemProvider(provider, network), network, marketData, address, blockNumber);
291
- }
@@ -1,180 +0,0 @@
1
- import { assetAmountInEth, getAssetInfoByAddress } from '@defisaver/tokens';
2
- import { AaveV4ViewContractViem } from '../contracts';
3
- import { getViemProvider } from '../services/viem';
4
- import { wethToEth } from '../services/utils';
5
- import {
6
- EthAddress,
7
- EthereumProvider,
8
- NetworkNumber,
9
- } from '../types/common';
10
-
11
- export interface AaveV4TokenizationSpokeData {
12
- underlyingAsset: EthAddress;
13
- assetId: string;
14
- decimals: number;
15
- spoke: EthAddress;
16
- spokeActive: boolean;
17
- spokeHalted: boolean;
18
- spokeDepositCap: string;
19
- spokeTotalAssets: string;
20
- spokeTotalShares: string;
21
- hub: EthAddress;
22
- hubLiquidity: string;
23
- hubDrawnRate: string;
24
- convertToShares: string;
25
- convertToAssets: string;
26
- user: EthAddress;
27
- userSuppliedAssets: string;
28
- userSuppliedShares: string;
29
- }
30
-
31
- export const AAVE_V4_TOKENIZED_SPOKES: Record<string, EthAddress> = {
32
- AAVE_CORE: '0x08309234884cF7E015b07Bf22569017Aa035cdeF',
33
- EURC_CORE: '0x73596dED4B2Eb0aC85e477b3c8dB56FC427E6774',
34
- GHO_CORE: '0xf7E1f1b43922527e5054bD77E7f863Cf182b194D',
35
- GHO_PRIME: '0xeF1cAd5c6a2C9cb83c952b4B96bbD35b3F61F18f',
36
- LBTC_CORE: '0x8f4D423590F22833131e3493bf67A27213398f8e',
37
- LINK_CORE: '0xBE1197750b423e30137E97d9183065d33E903BE6',
38
- PT_USDe_PLUS: '0x8cA27Ab284F2aA2BcF33D9129e11c101aD2d16de',
39
- PT_sUSDe_PLUS: '0xb8A464EC56071a98c854f30fE19CfeCc41FA6233',
40
- PYUSD_CORE: '0x203FB463087005698d50768FcA837047f738632d',
41
- RLUSD_CORE: '0xa9afdd0c54fb153CaE39cE86E49626B5e9d15513',
42
- USDC_CORE: '0xa2e476f4cbB06C7bFA8Ad51bCcbF198cd32CfD35',
43
- USDC_PLUS: '0x320Bec4fB7a25e64c003A007D0AeF7AB3D6C30d7',
44
- USDC_PRIME: '0x0A0507F7A1129892b5cf74b8B4e911442c466b87',
45
- USDG_CORE: '0x87c224256f09a014C1BC3e9FbB094C3AdD8fBaCC',
46
- USDT_CORE: '0x3f12BD5999b9172550893FF52691c980676f9E73',
47
- USDT_PLUS: '0xa4E74a78bED2d3ab8971e8AB26fb39f26DD8eEd9',
48
- USDT_PRIME: '0xF565fB55bc96d65561887898bfeb25C1dE7e06d2',
49
- USDe_PLUS: '0xA0d346ab2699B689AC67aba5174164A84206BB73',
50
- WBTC_CORE: '0x837Ab872A665e0CF467d41cF56a054031b4A38bc',
51
- WBTC_PRIME: '0xeae98b8a1798738182B2123DF1eB93d97BD29F34',
52
- WETH_CORE: '0x3961a75099E986F59a1a31c6f945061641dFD2b2',
53
- WETH_PRIME: '0xa411826a6ef5d289c0FAa7d5B45FE8aAB52257F6',
54
- XAUt_CORE: '0x470341bC0e2B833C54D0120642713BdF762A494F',
55
- cbBTC_CORE: '0xe8D5E595d5b6b5EFf84B7064765fd0e8DfD214C9',
56
- cbBTC_PRIME: '0x0E986545150DcDDe46Ea9df355D0fD2af33bd75D',
57
- frxUSD_CORE: '0x00C8A6a42947Cc4E7B6f27963Cab0143ccaaD2B5',
58
- frxUSD_PLUS: '0xCAB288d37CAb5a9db7b503F086455276Dcde61F1',
59
- rsETH_CORE: '0x6eEce89caE2163584bA7Ff9743861B9633c245E0',
60
- sUSDe_PLUS: '0xdf47fc43c88B06edC47753b7d647ff18037D2F3d',
61
- weETH_CORE: '0xB67F20bFF413C8E5d633B54BD28899c4c9e33ed0',
62
- wstETH_CORE: '0x474602394d0B02F43AC3D7C8c5cFc0814b03fd40',
63
- wstETH_PRIME: '0xAcCdAb49ECB9A801CfF62a92fc80D52339b33770',
64
- };
65
-
66
- export const AAVE_V4_TOKENIZED_SPOKE_ADDRESSES: Partial<Record<NetworkNumber, EthAddress[]>> = {
67
- [NetworkNumber.Eth]: Object.values(AAVE_V4_TOKENIZED_SPOKES),
68
- };
69
-
70
- export type AaveV4TokenizedHubKey = 'CORE' | 'PLUS' | 'PRIME';
71
-
72
- export const aaveV4GetTokenizedHubKey = (hubNameOrKey?: string | null): AaveV4TokenizedHubKey | null => {
73
- if (!hubNameOrKey) return null;
74
- const normalized = hubNameOrKey.trim().toUpperCase();
75
-
76
- // TODO AaveV4 Maybe turn into constants
77
- if (normalized === 'CORE' || normalized === 'CORE HUB') return 'CORE';
78
- if (normalized === 'PLUS' || normalized === 'PLUS HUB') return 'PLUS';
79
- if (normalized === 'PRIME' || normalized === 'PRIME HUB') return 'PRIME';
80
-
81
- if (normalized.includes('CORE')) return 'CORE';
82
- if (normalized.includes('PLUS')) return 'PLUS';
83
- if (normalized.includes('PRIME')) return 'PRIME';
84
-
85
- return null;
86
- };
87
-
88
- export const aaveV4GetTokenizedVaultKey = (
89
- symbol: string,
90
- hubNameOrKey?: string | null,
91
- ): string | null => {
92
- if (!symbol) return null;
93
- const hubKey = aaveV4GetTokenizedHubKey(hubNameOrKey);
94
- if (!hubKey) return null;
95
-
96
- const normalizedSymbol = symbol.trim().replace(/-/g, '_');
97
-
98
- return `${normalizedSymbol}_${hubKey}`;
99
- };
100
-
101
- export const aaveV4GetTokenizedVaultAddress = (
102
- network: NetworkNumber,
103
- symbol: string,
104
- hubNameOrKey?: string | null,
105
- ): EthAddress | undefined => {
106
- if (network !== NetworkNumber.Eth) return undefined;
107
- const key = aaveV4GetTokenizedVaultKey(symbol, hubNameOrKey);
108
- if (!key) return undefined;
109
- return AAVE_V4_TOKENIZED_SPOKES[key];
110
- };
111
-
112
- /** Parsed tokenization spoke data with human-readable supplied amounts for display */
113
- export interface AaveV4TokenizationSpokeDataParsed {
114
- vaultAddress: EthAddress;
115
- key: string | null;
116
- symbol: string;
117
- hubKey: string;
118
- userSuppliedAssetsEth: string;
119
- userSuppliedSharesEth: string;
120
- userSuppliedAssets: string;
121
- userSuppliedShares: string;
122
- underlyingAsset: EthAddress;
123
- spoke: EthAddress;
124
- decimals: number;
125
- }
126
-
127
- const AAVE_V4_TOKENIZED_SPOKE_ADDRESS_TO_KEY: Record<string, string> = Object.entries(
128
- AAVE_V4_TOKENIZED_SPOKES,
129
- ).reduce((acc, [k, v]) => {
130
- acc[v.toLowerCase()] = k;
131
- return acc;
132
- }, {} as Record<string, string>);
133
-
134
- /**
135
- * Fetches tokenization vault data for the given user via getTokenizationSpokesData.
136
- * Returns parsed data including userSuppliedAssets in human-readable form for each vault.
137
- */
138
- export async function getAaveV4TokenizationSpokesData(
139
- provider: EthereumProvider,
140
- network: NetworkNumber,
141
- userAddress: EthAddress,
142
- ): Promise<AaveV4TokenizationSpokeDataParsed[]> {
143
- const spokes = AAVE_V4_TOKENIZED_SPOKE_ADDRESSES[network] ?? [];
144
- if (spokes.length === 0) return [];
145
-
146
- const client = getViemProvider(provider, network);
147
- const viewContract = AaveV4ViewContractViem(client, network);
148
- const raw = await viewContract.read.getTokenizationSpokesData([spokes, userAddress]);
149
-
150
- return raw.map((r: any, i: number) => {
151
- const vaultAddress = spokes[i];
152
- const key = AAVE_V4_TOKENIZED_SPOKE_ADDRESS_TO_KEY[vaultAddress.toLowerCase()] ?? null;
153
- const symbol = wethToEth(getAssetInfoByAddress(r.underlyingAsset, network).symbol);
154
- if (symbol === '?') { // unsupported asset
155
- return null;
156
- }
157
- const hubKey = key ? key.split('_').pop() ?? '' : '';
158
- const decimals = Number(r.decimals ?? 18);
159
- const userSuppliedAssetsRaw = r.userSuppliedAssets ?? 0;
160
- const userSuppliedSharesRaw = r.userSuppliedShares ?? 0;
161
-
162
- const userSuppliedAssetsEth = assetAmountInEth(userSuppliedAssetsRaw.toString(), symbol);
163
- const userSuppliedSharesEth = assetAmountInEth(userSuppliedSharesRaw.toString(), symbol);
164
- return {
165
- vaultAddress,
166
- key,
167
- symbol,
168
- hubKey,
169
- userSuppliedAssetsEth,
170
- userSuppliedSharesEth,
171
- userSuppliedAssets: userSuppliedAssetsRaw.toString(),
172
- userSuppliedShares: userSuppliedSharesRaw.toString(),
173
- underlyingAsset: r.underlyingAsset,
174
- spoke: r.spoke,
175
- decimals,
176
- };
177
- }).filter(item => item != null);
178
- }
179
-
180
-
@@ -1,133 +0,0 @@
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
- };