@defisaver/positions-sdk 2.0.15-dev → 2.0.15-dev-3

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 (152) hide show
  1. package/.mocharc.json +4 -4
  2. package/.nvmrc +1 -1
  3. package/README.md +64 -64
  4. package/cjs/aaveV2/index.js +9 -5
  5. package/cjs/aaveV3/index.js +50 -40
  6. package/cjs/aaveV3/merit.d.ts +17 -0
  7. package/cjs/aaveV3/merit.js +95 -0
  8. package/cjs/aaveV3/{rewards.d.ts → merkl.d.ts} +7 -2
  9. package/cjs/aaveV3/{rewards.js → merkl.js} +30 -14
  10. package/cjs/compoundV2/index.js +13 -7
  11. package/cjs/compoundV3/index.js +7 -2
  12. package/cjs/config/contracts.d.ts +6510 -1851
  13. package/cjs/config/contracts.js +33 -12
  14. package/cjs/contracts.d.ts +178 -0
  15. package/cjs/eulerV2/index.js +11 -2
  16. package/cjs/fluid/index.js +105 -34
  17. package/cjs/helpers/aaveHelpers/index.js +0 -1
  18. package/cjs/helpers/compoundHelpers/index.d.ts +3 -5
  19. package/cjs/helpers/compoundHelpers/index.js +15 -11
  20. package/cjs/helpers/eulerHelpers/index.d.ts +0 -5
  21. package/cjs/helpers/eulerHelpers/index.js +2 -31
  22. package/cjs/helpers/fluidHelpers/index.js +2 -0
  23. package/cjs/helpers/liquityV2Helpers/index.js +3 -2
  24. package/cjs/helpers/morphoBlueHelpers/index.js +66 -66
  25. package/cjs/liquityV2/index.js +10 -2
  26. package/cjs/llamaLend/index.js +10 -2
  27. package/cjs/morphoBlue/index.js +20 -6
  28. package/cjs/spark/index.js +20 -30
  29. package/cjs/staking/eligibility.d.ts +11 -0
  30. package/cjs/staking/eligibility.js +43 -0
  31. package/cjs/staking/index.d.ts +1 -0
  32. package/cjs/staking/index.js +1 -0
  33. package/cjs/staking/staking.d.ts +1 -7
  34. package/cjs/staking/staking.js +29 -55
  35. package/cjs/types/aave.d.ts +1 -7
  36. package/cjs/types/common.d.ts +16 -4
  37. package/cjs/types/common.js +10 -1
  38. package/cjs/types/euler.d.ts +3 -3
  39. package/cjs/types/fluid.d.ts +3 -5
  40. package/cjs/types/liquityV2.d.ts +3 -3
  41. package/cjs/types/llamaLend.d.ts +3 -1
  42. package/cjs/types/morphoBlue.d.ts +3 -5
  43. package/cjs/types/spark.d.ts +0 -3
  44. package/esm/aaveV2/index.js +9 -5
  45. package/esm/aaveV3/index.js +48 -38
  46. package/esm/aaveV3/merit.d.ts +17 -0
  47. package/esm/aaveV3/merit.js +90 -0
  48. package/esm/aaveV3/{rewards.d.ts → merkl.d.ts} +7 -2
  49. package/esm/aaveV3/{rewards.js → merkl.js} +28 -13
  50. package/esm/compoundV2/index.js +13 -7
  51. package/esm/compoundV3/index.js +7 -2
  52. package/esm/config/contracts.d.ts +6510 -1851
  53. package/esm/config/contracts.js +33 -12
  54. package/esm/contracts.d.ts +178 -0
  55. package/esm/eulerV2/index.js +11 -2
  56. package/esm/fluid/index.js +106 -35
  57. package/esm/helpers/aaveHelpers/index.js +0 -1
  58. package/esm/helpers/compoundHelpers/index.d.ts +3 -5
  59. package/esm/helpers/compoundHelpers/index.js +16 -12
  60. package/esm/helpers/eulerHelpers/index.d.ts +0 -5
  61. package/esm/helpers/eulerHelpers/index.js +2 -30
  62. package/esm/helpers/fluidHelpers/index.js +2 -0
  63. package/esm/helpers/liquityV2Helpers/index.js +3 -2
  64. package/esm/helpers/morphoBlueHelpers/index.js +66 -66
  65. package/esm/liquityV2/index.js +11 -3
  66. package/esm/llamaLend/index.js +11 -3
  67. package/esm/morphoBlue/index.js +21 -7
  68. package/esm/spark/index.js +21 -31
  69. package/esm/staking/eligibility.d.ts +11 -0
  70. package/esm/staking/eligibility.js +36 -0
  71. package/esm/staking/index.d.ts +1 -0
  72. package/esm/staking/index.js +1 -0
  73. package/esm/staking/staking.d.ts +1 -7
  74. package/esm/staking/staking.js +28 -53
  75. package/esm/types/aave.d.ts +1 -7
  76. package/esm/types/common.d.ts +16 -4
  77. package/esm/types/common.js +9 -0
  78. package/esm/types/euler.d.ts +3 -3
  79. package/esm/types/fluid.d.ts +3 -5
  80. package/esm/types/liquityV2.d.ts +3 -3
  81. package/esm/types/llamaLend.d.ts +3 -1
  82. package/esm/types/morphoBlue.d.ts +3 -5
  83. package/esm/types/spark.d.ts +0 -3
  84. package/package.json +47 -47
  85. package/src/aaveV2/index.ts +239 -236
  86. package/src/aaveV3/index.ts +511 -493
  87. package/src/aaveV3/merit.ts +98 -0
  88. package/src/aaveV3/{rewards.ts → merkl.ts} +141 -125
  89. package/src/compoundV2/index.ts +244 -240
  90. package/src/compoundV3/index.ts +274 -270
  91. package/src/config/contracts.ts +1129 -1108
  92. package/src/constants/index.ts +6 -6
  93. package/src/contracts.ts +107 -107
  94. package/src/curveUsd/index.ts +250 -250
  95. package/src/eulerV2/index.ts +324 -314
  96. package/src/exchange/index.ts +25 -25
  97. package/src/fluid/index.ts +1636 -1568
  98. package/src/helpers/aaveHelpers/index.ts +169 -170
  99. package/src/helpers/compoundHelpers/index.ts +267 -261
  100. package/src/helpers/curveUsdHelpers/index.ts +40 -40
  101. package/src/helpers/eulerHelpers/index.ts +222 -259
  102. package/src/helpers/fluidHelpers/index.ts +326 -324
  103. package/src/helpers/index.ts +10 -10
  104. package/src/helpers/liquityV2Helpers/index.ts +82 -80
  105. package/src/helpers/llamaLendHelpers/index.ts +53 -53
  106. package/src/helpers/makerHelpers/index.ts +52 -52
  107. package/src/helpers/morphoBlueHelpers/index.ts +390 -390
  108. package/src/helpers/sparkHelpers/index.ts +155 -155
  109. package/src/index.ts +45 -45
  110. package/src/liquity/index.ts +104 -104
  111. package/src/liquityV2/index.ts +418 -408
  112. package/src/llamaLend/index.ts +305 -296
  113. package/src/maker/index.ts +223 -223
  114. package/src/markets/aave/index.ts +116 -116
  115. package/src/markets/aave/marketAssets.ts +49 -49
  116. package/src/markets/compound/index.ts +227 -227
  117. package/src/markets/compound/marketsAssets.ts +90 -90
  118. package/src/markets/curveUsd/index.ts +69 -69
  119. package/src/markets/euler/index.ts +26 -26
  120. package/src/markets/fluid/index.ts +2456 -2456
  121. package/src/markets/index.ts +25 -25
  122. package/src/markets/liquityV2/index.ts +102 -102
  123. package/src/markets/llamaLend/contractAddresses.ts +141 -141
  124. package/src/markets/llamaLend/index.ts +235 -235
  125. package/src/markets/morphoBlue/index.ts +895 -895
  126. package/src/markets/spark/index.ts +29 -29
  127. package/src/markets/spark/marketAssets.ts +11 -11
  128. package/src/moneymarket/moneymarketCommonService.ts +80 -80
  129. package/src/morphoBlue/index.ts +236 -222
  130. package/src/portfolio/index.ts +285 -285
  131. package/src/services/priceService.ts +159 -159
  132. package/src/services/utils.ts +63 -63
  133. package/src/services/viem.ts +32 -32
  134. package/src/setup.ts +8 -8
  135. package/src/spark/index.ts +444 -456
  136. package/src/staking/eligibility.ts +37 -0
  137. package/src/staking/index.ts +2 -1
  138. package/src/staking/staking.ts +169 -194
  139. package/src/types/aave.ts +189 -195
  140. package/src/types/common.ts +103 -88
  141. package/src/types/compound.ts +136 -136
  142. package/src/types/curveUsd.ts +121 -121
  143. package/src/types/euler.ts +175 -174
  144. package/src/types/fluid.ts +448 -450
  145. package/src/types/index.ts +11 -11
  146. package/src/types/liquity.ts +30 -30
  147. package/src/types/liquityV2.ts +126 -126
  148. package/src/types/llamaLend.ts +159 -157
  149. package/src/types/maker.ts +63 -63
  150. package/src/types/morphoBlue.ts +194 -194
  151. package/src/types/portfolio.ts +60 -60
  152. package/src/types/spark.ts +135 -137
@@ -1,315 +1,325 @@
1
- import Dec from 'decimal.js';
2
- import { assetAmountInEth, getAssetInfoByAddress } from '@defisaver/tokens';
3
- import { Client } from 'viem';
4
- import { EthAddress, EthereumProvider, NetworkNumber } from '../types/common';
5
- import { getStakingApy, STAKING_ASSETS } from '../staking';
6
- import {
7
- compareAddresses, getEthAmountForDecimals, isMaxuint, wethToEth, wethToEthByAddress,
8
- } from '../services/utils';
9
- import {
10
- EulerV2AssetData,
11
- EulerV2AssetsData,
12
- EulerV2FullMarketData,
13
- EulerV2Market,
14
- EulerV2MarketInfoData,
15
- EulerV2PositionData,
16
- EulerV2UsedAssets,
17
- EulerV2VaultType,
18
- } from '../types';
19
- import {
20
- getEulerV2AggregatedData,
21
- getEulerV2BorrowRate,
22
- getEulerV2SupplyRate,
23
- getUtilizationRate,
24
- } from '../helpers/eulerHelpers';
25
- import { ZERO_ADDRESS } from '../constants';
26
- import { EulerV2ViewContractViem } from '../contracts';
27
- import { getViemProvider } from '../services/viem';
28
-
29
- export const EMPTY_USED_ASSET = {
30
- isSupplied: false,
31
- isBorrowed: false,
32
- supplied: '0',
33
- suppliedUsd: '0',
34
- borrowed: '0',
35
- borrowedUsd: '0',
36
- symbol: '',
37
- collateral: false,
38
- vaultAddress: '',
39
- };
40
-
41
- const UnitOfAccountUSD = '0x0000000000000000000000000000000000000348';
42
-
43
- export const _getEulerV2MarketsData = async (provider: Client, network: NetworkNumber, selectedMarket: EulerV2Market): Promise<EulerV2FullMarketData> => {
44
- const contract = EulerV2ViewContractViem(provider, network);
45
-
46
- const data = await contract.read.getVaultInfoFull([selectedMarket.marketAddress]);
47
- const isInUSD = compareAddresses(UnitOfAccountUSD, data.unitOfAccount);
48
-
49
- const usdPrice = getEthAmountForDecimals(data.unitOfAccountInUsd.toString(), 8);
50
-
51
- // parse collateral tokens
52
- // imma use address as key for assetsData because there can be more collateral vaults with the same name
53
- const colls: EulerV2AssetData[] = data.collaterals.map((collateral) => {
54
- const decimals = collateral.decimals.toString();
55
- const assetInfo = getAssetInfoByAddress(collateral.assetAddr);
56
- const borrowRate = getEulerV2BorrowRate(collateral.interestRate.toString());
57
- const utilizationRate = getUtilizationRate(collateral.totalBorrows.toString(), new Dec(collateral.totalBorrows.toString()).plus(collateral.cash.toString()).toString());
58
-
59
- const supplyRate = getEulerV2SupplyRate(borrowRate, utilizationRate, collateral.interestFee.toString());
60
-
61
- const isEscrow = collateral.isEscrowed;
62
- const isGoverned = !compareAddresses(collateral.governorAdmin, ZERO_ADDRESS);
63
-
64
- const vaultType = isEscrow
65
- ? EulerV2VaultType.Escrow
66
- : (
67
- isGoverned ? EulerV2VaultType.Governed : EulerV2VaultType.Ungoverned
68
- );
69
- return ({
70
- vaultAddress: collateral.vaultAddr,
71
- assetAddress: wethToEthByAddress(collateral.assetAddr),
72
- symbol: wethToEth(assetInfo.symbol),
73
- vaultSymbol: collateral.vaultSymbol,
74
- name: collateral.name,
75
- vaultType,
76
- decimals,
77
- liquidationRatio: new Dec(collateral.liquidationLTV).div(10_000).toString(),
78
- collateralFactor: new Dec(collateral.borrowLTV).div(10_000).toString(),
79
- totalBorrow: getEthAmountForDecimals(collateral.totalBorrows.toString(), decimals), // parse
80
- cash: getEthAmountForDecimals(collateral.cash.toString(), decimals),
81
- supplyCap: isMaxuint(collateral.supplyCap.toString()) ? collateral.supplyCap.toString() : getEthAmountForDecimals(collateral.supplyCap.toString(), decimals),
82
- borrowCap: '0',
83
- price: isInUSD ? assetAmountInEth(collateral.assetPriceInUnit.toString()) : new Dec(assetAmountInEth(collateral.assetPriceInUnit.toString())).mul(usdPrice).toString(), // 1e18 -> price in unitOfAccount (so it could be USD or any other token)
84
- canBeBorrowed: false,
85
- canBeSupplied: true,
86
- borrowRate,
87
- supplyRate,
88
- utilization: new Dec(utilizationRate).mul(100).toString(),
89
- governorAdmin: collateral.governorAdmin,
90
- });
91
- });
92
- for (const coll of colls) {
93
- if (STAKING_ASSETS.includes(coll.symbol)) {
94
- coll.incentiveSupplyApy = await getStakingApy(coll.symbol);
95
- coll.incentiveSupplyToken = coll.symbol;
96
- }
97
- }
98
- const isEscrow = data.collaterals.length === 0;
99
- const isGoverned = !compareAddresses(data.governorAdmin, ZERO_ADDRESS);
100
-
101
- const vaultType = isEscrow ? EulerV2VaultType.Escrow : (
102
- isGoverned ? EulerV2VaultType.Governed : EulerV2VaultType.Ungoverned
103
- );
104
- const decimals = data.decimals.toString();
105
-
106
- // (1 + SPY/10**27) ** secondsPerYear - 1
107
-
108
- const interestRate = data.interestRate.toString();
109
-
110
- const borrowRate = getEulerV2BorrowRate(interestRate);
111
-
112
- const utilizationRate = getUtilizationRate(data.totalBorrows.toString(), data.totalAssets.toString());
113
- const supplyRate = getEulerV2SupplyRate(borrowRate, utilizationRate, data.interestFee.toString());
114
-
115
- const marketAsset = {
116
- assetAddress: data.assetAddr,
117
- vaultAddress: data.vaultAddr,
118
- symbol: selectedMarket.asset,
119
- vaultSymbol: selectedMarket.shortLabel,
120
- decimals,
121
- totalBorrow: getEthAmountForDecimals(data.totalBorrows.toString(), decimals), // parse
122
- cash: getEthAmountForDecimals(data.cash.toString(), decimals),
123
- supplyCap: isMaxuint(data.supplyCap.toString()) ? data.supplyCap.toString() : getEthAmountForDecimals(data.supplyCap.toString(), decimals),
124
- borrowCap: isMaxuint(data.supplyCap.toString()) ? data.borrowCap.toString() : getEthAmountForDecimals(data.borrowCap.toString(), decimals),
125
- price: isInUSD ? assetAmountInEth(data.assetPriceInUnit.toString()) : new Dec(assetAmountInEth(data.assetPriceInUnit.toString())).mul(usdPrice).toString(), // 1e18 -> price in unitOfAccount (so it could be USD or any other token)
126
- sortIndex: 0,
127
- canBeBorrowed: true,
128
- canBeSupplied: false,
129
- borrowRate,
130
- supplyRate,
131
- collateralFactor: '0',
132
- liquidationRatio: '0',
133
- utilization: new Dec(utilizationRate).mul(100).toString(),
134
- governorAdmin: data.governorAdmin,
135
- vaultType,
136
- name: data.name,
137
- };
138
-
139
- const assetsData: EulerV2AssetsData = {
140
- [data.vaultAddr.toLowerCase()]: marketAsset,
141
- };
142
-
143
- colls
144
- .sort((coll1, coll2) => {
145
- const aMarket = new Dec(coll1.price).times(coll1.totalBorrow).toString();
146
- const bMarket = new Dec(coll2.price).times(coll2.totalBorrow).toString();
147
-
148
- return new Dec(bMarket).minus(aMarket).toNumber();
149
- })
150
- .forEach((market, i) => {
151
- assetsData[market.vaultAddress.toLowerCase()] = { ...market, sortIndex: i + 1 };
152
- });
153
-
154
- const marketData: EulerV2MarketInfoData = {
155
- name: data.name,
156
- symbol: data.symbol,
157
- decimals: data.decimals.toString(),
158
- irm: data.irm,
159
- creator: data.creator,
160
- governorAdmin: data.governorAdmin,
161
- unitOfAccount: data.unitOfAccount,
162
- unitOfAccountUsdPrice: usdPrice,
163
- isInUSD,
164
- oracle: data.oracle,
165
- collaterals: data.collaterals.map((collateral) => collateral.vaultAddr),
166
- isEscrow,
167
- isGoverned,
168
- vaultType,
169
- vaultAddress: data.vaultAddr,
170
- };
171
-
172
- return {
173
- marketData,
174
- assetsData,
175
- };
176
- };
177
-
178
- export const getEulerV2MarketsData = async (
179
- provider: EthereumProvider,
180
- network: NetworkNumber,
181
- selectedMarket: EulerV2Market,
182
- ): Promise<EulerV2FullMarketData> => _getEulerV2MarketsData(getViemProvider(provider, network), network, selectedMarket);
183
-
184
- export const EMPTY_EULER_V2_DATA = {
185
- usedAssets: {},
186
- suppliedUsd: '0',
187
- borrowedUsd: '0',
188
- borrowLimitUsd: '0',
189
- leftToBorrowUsd: '0',
190
- ratio: '0',
191
- minRatio: '0',
192
- netApy: '0',
193
- incentiveUsd: '0',
194
- totalInterestUsd: '0',
195
- isSubscribedToAutomation: false,
196
- automationResubscribeRequired: false,
197
- borrowVault: '',
198
- borrowAmountInUnit: '0',
199
- inLockDownMode: false,
200
- inPermitDisabledMode: false,
201
- lastUpdated: Date.now(),
202
- hasBorrowInDifferentVault: false,
203
- addressSpaceTakenByAnotherAccount: false,
204
- };
205
-
206
- export const _getEulerV2AccountData = async (
207
- provider: Client,
208
- network: NetworkNumber,
209
- addressForPosition: EthAddress,
210
- ownerAddress: EthAddress,
211
- extractedState: ({
212
- selectedMarket: EulerV2Market,
213
- assetsData: EulerV2AssetsData,
214
- marketData: EulerV2MarketInfoData,
215
- }),
216
- ): Promise<EulerV2PositionData> => {
217
- if (!addressForPosition) throw new Error('No address provided');
218
-
219
- const {
220
- selectedMarket, assetsData, marketData,
221
- } = extractedState;
222
-
223
- let payload = {
224
- ...EMPTY_EULER_V2_DATA,
225
- lastUpdated: Date.now(),
226
- };
227
-
228
- const isInUSD = marketData.isInUSD;
229
-
230
- const parsingDecimals = isInUSD ? 18 : getAssetInfoByAddress(marketData.unitOfAccount).decimals;
231
- const contract = EulerV2ViewContractViem(provider, network);
232
-
233
- const loanData = await contract.read.getUserData([addressForPosition]);
234
- const usedAssets: EulerV2UsedAssets = {};
235
- // there is no user position check for a specific market, only global check
236
- // but we need to make sure it works for the UI and show position only for the selected market
237
- if (!compareAddresses(loanData.borrowVault, selectedMarket.marketAddress)) {
238
- payload = {
239
- ...payload,
240
- borrowVault: ZERO_ADDRESS,
241
- borrowAmountInUnit: '0',
242
- inLockDownMode: false,
243
- inPermitDisabledMode: false,
244
- hasBorrowInDifferentVault: !compareAddresses(loanData.borrowVault, ZERO_ADDRESS),
245
- addressSpaceTakenByAnotherAccount: !compareAddresses(loanData.owner, ownerAddress) && !compareAddresses(loanData.owner, ZERO_ADDRESS),
246
- };
247
- } else {
248
- payload = {
249
- ...payload,
250
- borrowVault: loanData.borrowVault,
251
- borrowAmountInUnit: loanData.borrowAmountInUnit.toString(),
252
- inLockDownMode: loanData.inLockDownMode,
253
- inPermitDisabledMode: loanData.inPermitDisabledMode,
254
- addressSpaceTakenByAnotherAccount: !compareAddresses(loanData.owner, ownerAddress) && !compareAddresses(loanData.owner, ZERO_ADDRESS),
255
- };
256
-
257
- const borrowedInUnit = getEthAmountForDecimals(loanData.borrowAmountInUnit.toString(), parsingDecimals);
258
- const borrowedInAsset = getEthAmountForDecimals(loanData.borrowAmountInAsset.toString(), marketData.decimals);
259
- const borrowVault = loanData.borrowVault;
260
-
261
- if (borrowVault && !compareAddresses(ZERO_ADDRESS, borrowVault) && borrowedInUnit) {
262
- const borrowInfo = assetsData[borrowVault.toLowerCase()];
263
- usedAssets[borrowVault.toLowerCase()] = {
264
- ...EMPTY_USED_ASSET,
265
- isBorrowed: true,
266
- borrowed: borrowedInAsset,
267
- borrowedUsd: isInUSD ? borrowedInUnit : new Dec(borrowedInUnit).mul(marketData.unitOfAccountUsdPrice).toString(),
268
- vaultAddress: loanData.borrowVault,
269
- symbol: borrowInfo.symbol,
270
- };
271
- }
272
- }
273
-
274
- loanData.collaterals.forEach((collateral, i) => {
275
- const key = collateral.collateralVault.toLowerCase();
276
- const collInfo = assetsData[key];
277
-
278
- if (!collInfo || !marketData.collaterals.map(a => a.toLowerCase()).includes(key)) return; // this is a token supplied but not being used as a collateral for the market
279
-
280
- const suppliedInUnit = getEthAmountForDecimals(collateral.collateralAmountInUnit.toString(), parsingDecimals);
281
- const suppliedInAsset = getEthAmountForDecimals(collateral.collateralAmountInAsset.toString(), collInfo.decimals);
282
- const collateralAmountInUSD = getEthAmountForDecimals(collateral.collateralAmountInUSD.toString(), 18);
283
- usedAssets[key] = {
284
- ...EMPTY_USED_ASSET,
285
- collateral: true,
286
- isSupplied: !new Dec(suppliedInAsset).eq(0),
287
- supplied: suppliedInAsset,
288
- suppliedUsd: collateralAmountInUSD,
289
- vaultAddress: collateral.collateralVault,
290
- symbol: collInfo.symbol,
291
- };
292
- });
293
-
294
- payload = {
295
- ...payload,
296
- usedAssets,
297
- ...getEulerV2AggregatedData({
298
- usedAssets, assetsData, network,
299
- }),
300
- };
301
-
302
- return payload;
303
- };
304
-
305
- export const getEulerV2AccountData = async (
306
- provider: EthereumProvider,
307
- network: NetworkNumber,
308
- addressForPosition: EthAddress,
309
- ownerAddress: EthAddress,
310
- extractedState: ({
311
- selectedMarket: EulerV2Market,
312
- assetsData: EulerV2AssetsData,
313
- marketData: EulerV2MarketInfoData,
314
- }),
1
+ import Dec from 'decimal.js';
2
+ import { assetAmountInEth, getAssetInfoByAddress } from '@defisaver/tokens';
3
+ import { Client } from 'viem';
4
+ import {
5
+ EthAddress, EthereumProvider, IncentiveKind, NetworkNumber,
6
+ } from '../types/common';
7
+ import { getStakingApy, STAKING_ASSETS } from '../staking';
8
+ import {
9
+ compareAddresses, getEthAmountForDecimals, isMaxuint, wethToEth, wethToEthByAddress,
10
+ } from '../services/utils';
11
+ import {
12
+ EulerV2AssetData,
13
+ EulerV2AssetsData,
14
+ EulerV2FullMarketData,
15
+ EulerV2Market,
16
+ EulerV2MarketInfoData,
17
+ EulerV2PositionData,
18
+ EulerV2UsedAssets,
19
+ EulerV2VaultType,
20
+ } from '../types';
21
+ import {
22
+ getEulerV2AggregatedData,
23
+ getEulerV2BorrowRate,
24
+ getEulerV2SupplyRate,
25
+ getUtilizationRate,
26
+ } from '../helpers/eulerHelpers';
27
+ import { ZERO_ADDRESS } from '../constants';
28
+ import { EulerV2ViewContractViem } from '../contracts';
29
+ import { getViemProvider } from '../services/viem';
30
+
31
+ export const EMPTY_USED_ASSET = {
32
+ isSupplied: false,
33
+ isBorrowed: false,
34
+ supplied: '0',
35
+ suppliedUsd: '0',
36
+ borrowed: '0',
37
+ borrowedUsd: '0',
38
+ symbol: '',
39
+ collateral: false,
40
+ vaultAddress: '',
41
+ };
42
+
43
+ const UnitOfAccountUSD = '0x0000000000000000000000000000000000000348';
44
+
45
+ export const _getEulerV2MarketsData = async (provider: Client, network: NetworkNumber, selectedMarket: EulerV2Market): Promise<EulerV2FullMarketData> => {
46
+ const contract = EulerV2ViewContractViem(provider, network);
47
+
48
+ const data = await contract.read.getVaultInfoFull([selectedMarket.marketAddress]);
49
+ const isInUSD = compareAddresses(UnitOfAccountUSD, data.unitOfAccount);
50
+
51
+ const usdPrice = getEthAmountForDecimals(data.unitOfAccountInUsd.toString(), 8);
52
+
53
+ // parse collateral tokens
54
+ // imma use address as key for assetsData because there can be more collateral vaults with the same name
55
+ const colls: EulerV2AssetData[] = data.collaterals.map((collateral) => {
56
+ const decimals = collateral.decimals.toString();
57
+ const assetInfo = getAssetInfoByAddress(collateral.assetAddr);
58
+ const borrowRate = getEulerV2BorrowRate(collateral.interestRate.toString());
59
+ const utilizationRate = getUtilizationRate(collateral.totalBorrows.toString(), new Dec(collateral.totalBorrows.toString()).plus(collateral.cash.toString()).toString());
60
+
61
+ const supplyRate = getEulerV2SupplyRate(borrowRate, utilizationRate, collateral.interestFee.toString());
62
+
63
+ const isEscrow = collateral.isEscrowed;
64
+ const isGoverned = !compareAddresses(collateral.governorAdmin, ZERO_ADDRESS);
65
+
66
+ const vaultType = isEscrow
67
+ ? EulerV2VaultType.Escrow
68
+ : (
69
+ isGoverned ? EulerV2VaultType.Governed : EulerV2VaultType.Ungoverned
70
+ );
71
+ return ({
72
+ vaultAddress: collateral.vaultAddr,
73
+ assetAddress: wethToEthByAddress(collateral.assetAddr),
74
+ symbol: wethToEth(assetInfo.symbol),
75
+ vaultSymbol: collateral.vaultSymbol,
76
+ name: collateral.name,
77
+ vaultType,
78
+ decimals,
79
+ liquidationRatio: new Dec(collateral.liquidationLTV).div(10_000).toString(),
80
+ collateralFactor: new Dec(collateral.borrowLTV).div(10_000).toString(),
81
+ totalBorrow: getEthAmountForDecimals(collateral.totalBorrows.toString(), decimals), // parse
82
+ cash: getEthAmountForDecimals(collateral.cash.toString(), decimals),
83
+ supplyCap: isMaxuint(collateral.supplyCap.toString()) ? collateral.supplyCap.toString() : getEthAmountForDecimals(collateral.supplyCap.toString(), decimals),
84
+ borrowCap: '0',
85
+ price: isInUSD ? assetAmountInEth(collateral.assetPriceInUnit.toString()) : new Dec(assetAmountInEth(collateral.assetPriceInUnit.toString())).mul(usdPrice).toString(), // 1e18 -> price in unitOfAccount (so it could be USD or any other token)
86
+ canBeBorrowed: false,
87
+ canBeSupplied: true,
88
+ borrowRate,
89
+ supplyRate,
90
+ utilization: new Dec(utilizationRate).mul(100).toString(),
91
+ governorAdmin: collateral.governorAdmin,
92
+ supplyIncentives: [],
93
+ borrowIncentives: [],
94
+ });
95
+ });
96
+ for (const coll of colls) {
97
+ if (STAKING_ASSETS.includes(coll.symbol)) {
98
+ coll.supplyIncentives.push({
99
+ apy: await getStakingApy(coll.symbol),
100
+ token: coll.symbol,
101
+ incentiveKind: IncentiveKind.Staking,
102
+ description: `Native ${coll.symbol} yield.`,
103
+ });
104
+ }
105
+ }
106
+ const isEscrow = data.collaterals.length === 0;
107
+ const isGoverned = !compareAddresses(data.governorAdmin, ZERO_ADDRESS);
108
+
109
+ const vaultType = isEscrow ? EulerV2VaultType.Escrow : (
110
+ isGoverned ? EulerV2VaultType.Governed : EulerV2VaultType.Ungoverned
111
+ );
112
+ const decimals = data.decimals.toString();
113
+
114
+ // (1 + SPY/10**27) ** secondsPerYear - 1
115
+
116
+ const interestRate = data.interestRate.toString();
117
+
118
+ const borrowRate = getEulerV2BorrowRate(interestRate);
119
+
120
+ const utilizationRate = getUtilizationRate(data.totalBorrows.toString(), data.totalAssets.toString());
121
+ const supplyRate = getEulerV2SupplyRate(borrowRate, utilizationRate, data.interestFee.toString());
122
+
123
+ const marketAsset = {
124
+ assetAddress: data.assetAddr,
125
+ vaultAddress: data.vaultAddr,
126
+ symbol: selectedMarket.asset,
127
+ vaultSymbol: selectedMarket.shortLabel,
128
+ decimals,
129
+ totalBorrow: getEthAmountForDecimals(data.totalBorrows.toString(), decimals), // parse
130
+ cash: getEthAmountForDecimals(data.cash.toString(), decimals),
131
+ supplyCap: isMaxuint(data.supplyCap.toString()) ? data.supplyCap.toString() : getEthAmountForDecimals(data.supplyCap.toString(), decimals),
132
+ borrowCap: isMaxuint(data.supplyCap.toString()) ? data.borrowCap.toString() : getEthAmountForDecimals(data.borrowCap.toString(), decimals),
133
+ price: isInUSD ? assetAmountInEth(data.assetPriceInUnit.toString()) : new Dec(assetAmountInEth(data.assetPriceInUnit.toString())).mul(usdPrice).toString(), // 1e18 -> price in unitOfAccount (so it could be USD or any other token)
134
+ sortIndex: 0,
135
+ canBeBorrowed: true,
136
+ canBeSupplied: false,
137
+ borrowRate,
138
+ supplyRate,
139
+ collateralFactor: '0',
140
+ liquidationRatio: '0',
141
+ utilization: new Dec(utilizationRate).mul(100).toString(),
142
+ governorAdmin: data.governorAdmin,
143
+ vaultType,
144
+ name: data.name,
145
+ supplyIncentives: [],
146
+ borrowIncentives: [],
147
+ };
148
+
149
+ const assetsData: EulerV2AssetsData = {
150
+ [data.vaultAddr.toLowerCase()]: marketAsset,
151
+ };
152
+
153
+ colls
154
+ .sort((coll1, coll2) => {
155
+ const aMarket = new Dec(coll1.price).times(coll1.totalBorrow).toString();
156
+ const bMarket = new Dec(coll2.price).times(coll2.totalBorrow).toString();
157
+
158
+ return new Dec(bMarket).minus(aMarket).toNumber();
159
+ })
160
+ .forEach((market, i) => {
161
+ assetsData[market.vaultAddress.toLowerCase()] = { ...market, sortIndex: i + 1 };
162
+ });
163
+
164
+ const marketData: EulerV2MarketInfoData = {
165
+ name: data.name,
166
+ symbol: data.symbol,
167
+ decimals: data.decimals.toString(),
168
+ irm: data.irm,
169
+ creator: data.creator,
170
+ governorAdmin: data.governorAdmin,
171
+ unitOfAccount: data.unitOfAccount,
172
+ unitOfAccountUsdPrice: usdPrice,
173
+ isInUSD,
174
+ oracle: data.oracle,
175
+ collaterals: data.collaterals.map((collateral) => collateral.vaultAddr),
176
+ isEscrow,
177
+ isGoverned,
178
+ vaultType,
179
+ vaultAddress: data.vaultAddr,
180
+ };
181
+
182
+ return {
183
+ marketData,
184
+ assetsData,
185
+ };
186
+ };
187
+
188
+ export const getEulerV2MarketsData = async (
189
+ provider: EthereumProvider,
190
+ network: NetworkNumber,
191
+ selectedMarket: EulerV2Market,
192
+ ): Promise<EulerV2FullMarketData> => _getEulerV2MarketsData(getViemProvider(provider, network), network, selectedMarket);
193
+
194
+ export const EMPTY_EULER_V2_DATA = {
195
+ usedAssets: {},
196
+ suppliedUsd: '0',
197
+ borrowedUsd: '0',
198
+ borrowLimitUsd: '0',
199
+ leftToBorrowUsd: '0',
200
+ ratio: '0',
201
+ minRatio: '0',
202
+ netApy: '0',
203
+ incentiveUsd: '0',
204
+ totalInterestUsd: '0',
205
+ isSubscribedToAutomation: false,
206
+ automationResubscribeRequired: false,
207
+ borrowVault: '',
208
+ borrowAmountInUnit: '0',
209
+ inLockDownMode: false,
210
+ inPermitDisabledMode: false,
211
+ lastUpdated: Date.now(),
212
+ hasBorrowInDifferentVault: false,
213
+ addressSpaceTakenByAnotherAccount: false,
214
+ };
215
+
216
+ export const _getEulerV2AccountData = async (
217
+ provider: Client,
218
+ network: NetworkNumber,
219
+ addressForPosition: EthAddress,
220
+ ownerAddress: EthAddress,
221
+ extractedState: ({
222
+ selectedMarket: EulerV2Market,
223
+ assetsData: EulerV2AssetsData,
224
+ marketData: EulerV2MarketInfoData,
225
+ }),
226
+ ): Promise<EulerV2PositionData> => {
227
+ if (!addressForPosition) throw new Error('No address provided');
228
+
229
+ const {
230
+ selectedMarket, assetsData, marketData,
231
+ } = extractedState;
232
+
233
+ let payload = {
234
+ ...EMPTY_EULER_V2_DATA,
235
+ lastUpdated: Date.now(),
236
+ };
237
+
238
+ const isInUSD = marketData.isInUSD;
239
+
240
+ const parsingDecimals = isInUSD ? 18 : getAssetInfoByAddress(marketData.unitOfAccount).decimals;
241
+ const contract = EulerV2ViewContractViem(provider, network);
242
+
243
+ const loanData = await contract.read.getUserData([addressForPosition]);
244
+ const usedAssets: EulerV2UsedAssets = {};
245
+ // there is no user position check for a specific market, only global check
246
+ // but we need to make sure it works for the UI and show position only for the selected market
247
+ if (!compareAddresses(loanData.borrowVault, selectedMarket.marketAddress)) {
248
+ payload = {
249
+ ...payload,
250
+ borrowVault: ZERO_ADDRESS,
251
+ borrowAmountInUnit: '0',
252
+ inLockDownMode: false,
253
+ inPermitDisabledMode: false,
254
+ hasBorrowInDifferentVault: !compareAddresses(loanData.borrowVault, ZERO_ADDRESS),
255
+ addressSpaceTakenByAnotherAccount: !compareAddresses(loanData.owner, ownerAddress) && !compareAddresses(loanData.owner, ZERO_ADDRESS),
256
+ };
257
+ } else {
258
+ payload = {
259
+ ...payload,
260
+ borrowVault: loanData.borrowVault,
261
+ borrowAmountInUnit: loanData.borrowAmountInUnit.toString(),
262
+ inLockDownMode: loanData.inLockDownMode,
263
+ inPermitDisabledMode: loanData.inPermitDisabledMode,
264
+ addressSpaceTakenByAnotherAccount: !compareAddresses(loanData.owner, ownerAddress) && !compareAddresses(loanData.owner, ZERO_ADDRESS),
265
+ };
266
+
267
+ const borrowedInUnit = getEthAmountForDecimals(loanData.borrowAmountInUnit.toString(), parsingDecimals);
268
+ const borrowedInAsset = getEthAmountForDecimals(loanData.borrowAmountInAsset.toString(), marketData.decimals);
269
+ const borrowVault = loanData.borrowVault;
270
+
271
+ if (borrowVault && !compareAddresses(ZERO_ADDRESS, borrowVault) && borrowedInUnit) {
272
+ const borrowInfo = assetsData[borrowVault.toLowerCase()];
273
+ usedAssets[borrowVault.toLowerCase()] = {
274
+ ...EMPTY_USED_ASSET,
275
+ isBorrowed: true,
276
+ borrowed: borrowedInAsset,
277
+ borrowedUsd: isInUSD ? borrowedInUnit : new Dec(borrowedInUnit).mul(marketData.unitOfAccountUsdPrice).toString(),
278
+ vaultAddress: loanData.borrowVault,
279
+ symbol: borrowInfo.symbol,
280
+ };
281
+ }
282
+ }
283
+
284
+ loanData.collaterals.forEach((collateral, i) => {
285
+ const key = collateral.collateralVault.toLowerCase();
286
+ const collInfo = assetsData[key];
287
+
288
+ if (!collInfo || !marketData.collaterals.map(a => a.toLowerCase()).includes(key)) return; // this is a token supplied but not being used as a collateral for the market
289
+
290
+ const suppliedInUnit = getEthAmountForDecimals(collateral.collateralAmountInUnit.toString(), parsingDecimals);
291
+ const suppliedInAsset = getEthAmountForDecimals(collateral.collateralAmountInAsset.toString(), collInfo.decimals);
292
+ const collateralAmountInUSD = getEthAmountForDecimals(collateral.collateralAmountInUSD.toString(), 18);
293
+ usedAssets[key] = {
294
+ ...EMPTY_USED_ASSET,
295
+ collateral: true,
296
+ isSupplied: !new Dec(suppliedInAsset).eq(0),
297
+ supplied: suppliedInAsset,
298
+ suppliedUsd: collateralAmountInUSD,
299
+ vaultAddress: collateral.collateralVault,
300
+ symbol: collInfo.symbol,
301
+ };
302
+ });
303
+
304
+ payload = {
305
+ ...payload,
306
+ usedAssets,
307
+ ...getEulerV2AggregatedData({
308
+ usedAssets, assetsData, network,
309
+ }),
310
+ };
311
+
312
+ return payload;
313
+ };
314
+
315
+ export const getEulerV2AccountData = async (
316
+ provider: EthereumProvider,
317
+ network: NetworkNumber,
318
+ addressForPosition: EthAddress,
319
+ ownerAddress: EthAddress,
320
+ extractedState: ({
321
+ selectedMarket: EulerV2Market,
322
+ assetsData: EulerV2AssetsData,
323
+ marketData: EulerV2MarketInfoData,
324
+ }),
315
325
  ): Promise<EulerV2PositionData> => _getEulerV2AccountData(getViemProvider(provider, network), network, addressForPosition, ownerAddress, extractedState);