@defisaver/positions-sdk 2.1.6-dev-debt-in-front → 2.1.6-dev-plasma-1

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 (134) hide show
  1. package/.mocharc.json +4 -4
  2. package/.nvmrc +1 -1
  3. package/README.md +64 -64
  4. package/cjs/aaveV3/index.js +3 -3
  5. package/cjs/aaveV3/merit.js +3 -0
  6. package/cjs/aaveV3/merkl.d.ts +1 -1
  7. package/cjs/config/contracts.d.ts +17 -0
  8. package/cjs/config/contracts.js +17 -0
  9. package/cjs/helpers/aaveHelpers/index.d.ts +1 -1
  10. package/cjs/helpers/aaveHelpers/index.js +6 -4
  11. package/cjs/helpers/morphoBlueHelpers/index.d.ts +1 -1
  12. package/cjs/helpers/morphoBlueHelpers/index.js +66 -66
  13. package/cjs/liquityV2/index.d.ts +0 -2
  14. package/cjs/liquityV2/index.js +9 -52
  15. package/cjs/markets/aave/index.js +1 -1
  16. package/cjs/markets/aave/marketAssets.d.ts +4 -0
  17. package/cjs/markets/aave/marketAssets.js +5 -1
  18. package/cjs/markets/compound/index.js +11 -0
  19. package/cjs/markets/compound/marketsAssets.d.ts +7 -0
  20. package/cjs/markets/compound/marketsAssets.js +7 -0
  21. package/cjs/markets/spark/marketAssets.d.ts +1 -0
  22. package/cjs/markets/spark/marketAssets.js +1 -0
  23. package/cjs/services/utils.d.ts +8 -4
  24. package/cjs/services/utils.js +30 -10
  25. package/cjs/services/viem.d.ts +54 -15
  26. package/cjs/services/viem.js +2 -0
  27. package/cjs/types/common.d.ts +2 -1
  28. package/cjs/types/common.js +1 -0
  29. package/esm/aaveV3/index.js +4 -4
  30. package/esm/aaveV3/merit.js +3 -0
  31. package/esm/aaveV3/merkl.d.ts +1 -1
  32. package/esm/config/contracts.d.ts +17 -0
  33. package/esm/config/contracts.js +17 -0
  34. package/esm/helpers/aaveHelpers/index.d.ts +1 -1
  35. package/esm/helpers/aaveHelpers/index.js +7 -5
  36. package/esm/helpers/morphoBlueHelpers/index.d.ts +1 -1
  37. package/esm/helpers/morphoBlueHelpers/index.js +66 -66
  38. package/esm/liquityV2/index.d.ts +0 -2
  39. package/esm/liquityV2/index.js +7 -48
  40. package/esm/markets/aave/index.js +1 -1
  41. package/esm/markets/aave/marketAssets.d.ts +4 -0
  42. package/esm/markets/aave/marketAssets.js +4 -0
  43. package/esm/markets/compound/index.js +11 -0
  44. package/esm/markets/compound/marketsAssets.d.ts +7 -0
  45. package/esm/markets/compound/marketsAssets.js +7 -0
  46. package/esm/markets/spark/marketAssets.d.ts +1 -0
  47. package/esm/markets/spark/marketAssets.js +1 -0
  48. package/esm/services/utils.d.ts +8 -4
  49. package/esm/services/utils.js +21 -5
  50. package/esm/services/viem.d.ts +54 -15
  51. package/esm/services/viem.js +3 -1
  52. package/esm/types/common.d.ts +2 -1
  53. package/esm/types/common.js +1 -0
  54. package/package.json +47 -47
  55. package/src/aaveV2/index.ts +240 -240
  56. package/src/aaveV3/index.ts +614 -614
  57. package/src/aaveV3/merit.ts +97 -94
  58. package/src/aaveV3/merkl.ts +74 -74
  59. package/src/claiming/aaveV3.ts +154 -154
  60. package/src/claiming/compV3.ts +22 -22
  61. package/src/claiming/index.ts +12 -12
  62. package/src/claiming/king.ts +66 -66
  63. package/src/claiming/morphoBlue.ts +118 -118
  64. package/src/claiming/spark.ts +225 -225
  65. package/src/compoundV2/index.ts +244 -244
  66. package/src/compoundV3/index.ts +274 -274
  67. package/src/config/contracts.ts +1245 -1228
  68. package/src/constants/index.ts +10 -10
  69. package/src/contracts.ts +120 -120
  70. package/src/curveUsd/index.ts +254 -254
  71. package/src/eulerV2/index.ts +324 -324
  72. package/src/exchange/index.ts +25 -25
  73. package/src/fluid/index.ts +1638 -1638
  74. package/src/helpers/aaveHelpers/index.ts +187 -185
  75. package/src/helpers/compoundHelpers/index.ts +283 -283
  76. package/src/helpers/curveUsdHelpers/index.ts +40 -40
  77. package/src/helpers/eulerHelpers/index.ts +222 -222
  78. package/src/helpers/fluidHelpers/index.ts +326 -326
  79. package/src/helpers/index.ts +10 -10
  80. package/src/helpers/liquityV2Helpers/index.ts +82 -82
  81. package/src/helpers/llamaLendHelpers/index.ts +53 -53
  82. package/src/helpers/makerHelpers/index.ts +52 -52
  83. package/src/helpers/morphoBlueHelpers/index.ts +396 -396
  84. package/src/helpers/sparkHelpers/index.ts +155 -155
  85. package/src/index.ts +47 -47
  86. package/src/liquity/index.ts +159 -159
  87. package/src/liquityV2/index.ts +657 -703
  88. package/src/llamaLend/index.ts +305 -305
  89. package/src/maker/index.ts +223 -223
  90. package/src/markets/aave/index.ts +116 -116
  91. package/src/markets/aave/marketAssets.ts +54 -49
  92. package/src/markets/compound/index.ts +238 -227
  93. package/src/markets/compound/marketsAssets.ts +97 -90
  94. package/src/markets/curveUsd/index.ts +69 -69
  95. package/src/markets/euler/index.ts +26 -26
  96. package/src/markets/fluid/index.ts +2456 -2456
  97. package/src/markets/index.ts +25 -25
  98. package/src/markets/liquityV2/index.ts +102 -102
  99. package/src/markets/llamaLend/contractAddresses.ts +141 -141
  100. package/src/markets/llamaLend/index.ts +235 -235
  101. package/src/markets/morphoBlue/index.ts +895 -895
  102. package/src/markets/spark/index.ts +29 -29
  103. package/src/markets/spark/marketAssets.ts +12 -11
  104. package/src/moneymarket/moneymarketCommonService.ts +80 -80
  105. package/src/morphoBlue/index.ts +274 -274
  106. package/src/portfolio/index.ts +570 -570
  107. package/src/services/priceService.ts +159 -159
  108. package/src/services/utils.ts +115 -99
  109. package/src/services/viem.ts +34 -32
  110. package/src/setup.ts +8 -8
  111. package/src/spark/index.ts +445 -445
  112. package/src/staking/eligibility.ts +59 -59
  113. package/src/staking/index.ts +1 -1
  114. package/src/staking/staking.ts +170 -170
  115. package/src/types/aave.ts +189 -189
  116. package/src/types/claiming.ts +109 -109
  117. package/src/types/common.ts +106 -105
  118. package/src/types/compound.ts +136 -136
  119. package/src/types/curveUsd.ts +123 -123
  120. package/src/types/euler.ts +175 -175
  121. package/src/types/fluid.ts +448 -448
  122. package/src/types/index.ts +13 -13
  123. package/src/types/liquity.ts +30 -30
  124. package/src/types/liquityV2.ts +126 -126
  125. package/src/types/llamaLend.ts +159 -159
  126. package/src/types/maker.ts +63 -63
  127. package/src/types/merit.ts +1 -1
  128. package/src/types/merkl.ts +70 -70
  129. package/src/types/morphoBlue.ts +194 -194
  130. package/src/types/portfolio.ts +60 -60
  131. package/src/types/spark.ts +135 -135
  132. package/src/umbrella/index.ts +69 -69
  133. package/src/umbrella/umbrellaUtils.ts +29 -29
  134. package/CLAUDE.md +0 -32
@@ -1,284 +1,284 @@
1
- import Dec from 'decimal.js';
2
- import { assetAmountInWei, getAssetInfo, getAssetInfoByAddress } from '@defisaver/tokens';
3
- import {
4
- BaseAdditionalAssetData, CompoundAggregatedPositionData, CompoundMarketData, CompoundV2AssetsData, CompoundV2UsedAssets, CompoundV3AssetData, CompoundV3AssetsData, CompoundV3UsedAssets, CompoundVersions,
5
- } from '../../types';
6
- import {
7
- addToArrayIf, getEthAmountForDecimals, handleWbtcLegacy, wethToEth,
8
- } from '../../services/utils';
9
- import { BLOCKS_IN_A_YEAR, borrowOperations, SECONDS_PER_YEAR } from '../../constants';
10
- import {
11
- aprToApy, calcLeverageLiqPrice, calculateBorrowingAssetLimit, getAssetsTotal, isLeveragedPos,
12
- } from '../../moneymarket';
13
- import { calculateNetApy, getStakingApy, STAKING_ASSETS } from '../../staking';
14
- import {
15
- EthAddress, EthereumProvider, IncentiveData, IncentiveKind, NetworkNumber,
16
- } from '../../types/common';
17
- import { CompoundLoanInfoContractViem, CompV3ViewContractViem } from '../../contracts';
18
- import { getViemProvider } from '../../services/viem';
19
-
20
- export const formatMarketData = (data: any, network: NetworkNumber, baseAssetPrice: string): CompoundV3AssetData => {
21
- const assetInfo = getAssetInfoByAddress(data.tokenAddr, network);
22
- const isWETH = assetInfo.symbol === 'WETH';
23
- const price = getEthAmountForDecimals(data.price, 8);
24
- return ({
25
- ...data,
26
- borrowCollateralFactor: data.borrowCollateralFactor.toString(),
27
- liquidateCollateralFactor: data.liquidateCollateralFactor.toString(),
28
- liquidationFactor: data.liquidationFactor.toString(),
29
- supplyReserved: data.supplyReserved.toString(),
30
- priceInBaseAsset: getEthAmountForDecimals(data.price, 8),
31
- price: new Dec(price).mul(baseAssetPrice).toString(),
32
- collateralFactor: getEthAmountForDecimals(data.borrowCollateralFactor, 18),
33
- liquidationRatio: getEthAmountForDecimals(data.liquidateCollateralFactor, 18),
34
- supplyCap: getEthAmountForDecimals(data.supplyCap, assetInfo.decimals),
35
- totalSupply: getEthAmountForDecimals(data.totalSupply, assetInfo.decimals),
36
- symbol: isWETH ? 'ETH' : assetInfo.symbol,
37
- supplyRate: '0',
38
- borrowRate: '0',
39
- canBeBorrowed: false,
40
- canBeSupplied: true,
41
- supplyIncentives: [],
42
- borrowIncentives: [],
43
- });
44
- };
45
-
46
- // TODO: maybe not hardcode decimals
47
- export const formatBaseData = (data: any, network: NetworkNumber, baseAssetPrice: string): CompoundV3AssetData & BaseAdditionalAssetData => {
48
- const assetInfo = getAssetInfoByAddress(data.tokenAddr, network);
49
- const totalSupply = getEthAmountForDecimals(new Dec(data.totalSupply).mul(data.supplyIndex).toString(), 15 + assetInfo.decimals);
50
- const totalBorrow = getEthAmountForDecimals(new Dec(data.totalBorrow).mul(data.borrowIndex).toString(), 15 + assetInfo.decimals);
51
- return ({
52
- ...data,
53
- baseBorrowMin: data.baseBorrowMin.toString(),
54
- baseTrackingBorrowRewardsSpeed: data.baseTrackingBorrowRewardsSpeed.toString(),
55
- baseTrackingSupplyRewardsSpeed: data.baseTrackingSupplyRewardsSpeed.toString(),
56
- borrowIndex: data.borrowIndex.toString(),
57
- supplyIndex: data.supplyIndex.toString(),
58
- trackingBorrowIndex: data.trackingBorrowIndex.toString(),
59
- trackingSupplyIndex: data.trackingSupplyIndex.toString(),
60
- supplyRate: aprToApy(new Dec(data.supplyRate).div(1e18).mul(SECONDS_PER_YEAR).mul(100)
61
- .toString()),
62
- borrowRate: aprToApy(new Dec(data.borrowRate).div(1e18).mul(SECONDS_PER_YEAR).mul(100)
63
- .toString()),
64
- utilization: getEthAmountForDecimals(data.utilization, 16), // utilization is totalSupply/totalBorrow in 1e18, but we need % so when we mul with 100 it's 16 decimals
65
- totalSupply,
66
- totalBorrow,
67
- marketLiquidity: new Dec(totalSupply).minus(totalBorrow).toString(),
68
- symbol: wethToEth(assetInfo.symbol),
69
- priceInBaseAsset: getEthAmountForDecimals(data.price, 8),
70
- price: baseAssetPrice,
71
- collateralFactor: '0',
72
- liquidationRatio: '0',
73
- canBeBorrowed: true,
74
- canBeSupplied: true,
75
- supplyCap: '0',
76
- rewardSupplySpeed: getEthAmountForDecimals(data.baseTrackingSupplyRewardsSpeed, 15),
77
- rewardBorrowSpeed: getEthAmountForDecimals(data.baseTrackingBorrowRewardsSpeed, 15),
78
- minDebt: getEthAmountForDecimals(data.baseBorrowMin, assetInfo.decimals),
79
- isBase: true,
80
- });
81
- };
82
-
83
- export const getIncentiveApys = async (
84
- baseData: CompoundV3AssetData & BaseAdditionalAssetData,
85
- compPrice: string,
86
- ): Promise<{
87
- supplyIncentives: IncentiveData[],
88
- borrowIncentives: IncentiveData[],
89
- }> => ({
90
- supplyIncentives: [{
91
- token: 'COMP',
92
- apy: aprToApy((100 * SECONDS_PER_YEAR * +baseData.rewardSupplySpeed * +compPrice) / +baseData.price / +baseData.totalSupply).toString(),
93
- incentiveKind: IncentiveKind.Reward,
94
- description: 'Eligible for protocol-level COMP incentives.',
95
- },
96
- ...addToArrayIf(STAKING_ASSETS.includes(baseData.symbol), {
97
- apy: await getStakingApy(baseData.symbol),
98
- token: baseData.symbol,
99
- incentiveKind: IncentiveKind.Staking,
100
- description: `Native ${baseData.symbol} yield.`,
101
- }),
102
- ],
103
- borrowIncentives: [{
104
- token: 'COMP',
105
- apy: aprToApy((100 * SECONDS_PER_YEAR * +baseData.rewardBorrowSpeed * +compPrice) / +baseData.price / +baseData.totalBorrow).toString(),
106
- incentiveKind: IncentiveKind.Reward,
107
- description: 'Eligible for protocol-level COMP incentives.',
108
- },
109
- ...addToArrayIf(STAKING_ASSETS.includes(baseData.symbol), {
110
- apy: new Dec(await getStakingApy(baseData.symbol)).mul(-1).toString(),
111
- token: baseData.symbol,
112
- incentiveKind: IncentiveKind.Staking,
113
- description: `Due to the native yield of ${baseData.symbol}, the value of the debt would increase over time.`,
114
- }),
115
- ],
116
- });
117
-
118
- export const getCompoundV2AggregatedData = ({
119
- usedAssets, assetsData, ...rest
120
- }: { usedAssets: CompoundV2UsedAssets, assetsData: CompoundV2AssetsData }) => {
121
- const payload = {} as CompoundAggregatedPositionData;
122
- payload.suppliedUsd = getAssetsTotal(usedAssets, ({ isSupplied }: { isSupplied: boolean }) => isSupplied, ({ suppliedUsd }: { suppliedUsd: string }) => suppliedUsd);
123
- payload.suppliedCollateralUsd = getAssetsTotal(usedAssets, ({ isSupplied, collateral }: { isSupplied: boolean, collateral: boolean }) => isSupplied && collateral, ({ suppliedUsd }: { suppliedUsd: string }) => suppliedUsd);
124
- payload.borrowedUsd = getAssetsTotal(usedAssets, ({ isBorrowed }: { isBorrowed: boolean }) => isBorrowed, ({ borrowedUsd }: { borrowedUsd: string }) => borrowedUsd);
125
- payload.borrowLimitUsd = getAssetsTotal(usedAssets, ({ isSupplied, collateral }: { isSupplied: boolean, collateral: boolean }) => isSupplied && collateral, ({ symbol, suppliedUsd }: { symbol: string, suppliedUsd: string }) => new Dec(suppliedUsd).mul(assetsData[symbol].collateralFactor));
126
-
127
- const leftToBorrowUsd = new Dec(payload.borrowLimitUsd).sub(payload.borrowedUsd).toString();
128
-
129
- payload.leftToBorrowUsd = leftToBorrowUsd;
130
- payload.borrowLimitUsd = new Dec(leftToBorrowUsd).add(payload.borrowedUsd).toString();
131
-
132
- payload.liquidationLimitUsd = payload.borrowLimitUsd;
133
- payload.ratio = payload.borrowedUsd && payload.borrowedUsd !== '0'
134
- ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString()
135
- : '0';
136
- payload.minRatio = '100';
137
- payload.collRatio = payload.borrowedUsd && payload.borrowedUsd !== '0'
138
- ? new Dec(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString()
139
- : '0';
140
-
141
- // Calculate borrow limits per asset
142
- Object.values(usedAssets).forEach((item) => {
143
- if (item.isBorrowed) {
144
- // eslint-disable-next-line no-param-reassign
145
- item.limit = calculateBorrowingAssetLimit(item.borrowedUsd, payload.borrowLimitUsd);
146
- }
147
- });
148
-
149
- const { netApy, incentiveUsd, totalInterestUsd } = calculateNetApy({ usedAssets, assetsData });
150
- payload.netApy = netApy;
151
- payload.incentiveUsd = incentiveUsd;
152
- payload.totalInterestUsd = totalInterestUsd;
153
-
154
- const { leveragedType, leveragedAsset } = isLeveragedPos(usedAssets);
155
- payload.leveragedType = leveragedType;
156
- if (leveragedType !== '') {
157
- payload.leveragedAsset = leveragedAsset;
158
- const assetPrice = assetsData[handleWbtcLegacy(leveragedAsset)].price;
159
- payload.liquidationPrice = calcLeverageLiqPrice(leveragedType, assetPrice, payload.borrowedUsd, payload.liquidationLimitUsd);
160
- }
161
-
162
- return payload;
163
- };
164
-
165
- export const getCompoundV3AggregatedData = ({
166
- usedAssets, assetsData, network, selectedMarket, ...rest
167
- }: { usedAssets: CompoundV3UsedAssets, assetsData: CompoundV3AssetsData, network: NetworkNumber, selectedMarket: CompoundMarketData }) => {
168
- const payload = {} as CompoundAggregatedPositionData;
169
- payload.suppliedUsd = getAssetsTotal(usedAssets, ({ isSupplied }: { isSupplied: boolean }) => isSupplied, ({ suppliedUsd }: { suppliedUsd: string }) => suppliedUsd);
170
- payload.suppliedCollateralUsd = getAssetsTotal(usedAssets, ({ isSupplied, collateral }: { isSupplied: boolean, collateral: boolean }) => isSupplied && collateral, ({ suppliedUsd }: { suppliedUsd: string }) => suppliedUsd);
171
- payload.borrowedUsd = getAssetsTotal(usedAssets, ({ isBorrowed }: { isBorrowed: boolean }) => isBorrowed, ({ borrowedUsd }: { borrowedUsd: string }) => borrowedUsd);
172
- payload.borrowLimitUsd = getAssetsTotal(usedAssets, ({ isSupplied, collateral }: { isSupplied: boolean, collateral: boolean }) => isSupplied && collateral, ({ symbol, suppliedUsd }: { symbol: string, suppliedUsd: string }) => new Dec(suppliedUsd).mul(assetsData[symbol].collateralFactor));
173
- payload.liquidationLimitUsd = getAssetsTotal(usedAssets, ({ isSupplied, collateral }: { isSupplied: boolean, collateral: boolean }) => isSupplied && collateral, ({ symbol, suppliedUsd }: { symbol: string, suppliedUsd: string }) => new Dec(suppliedUsd).mul(assetsData[symbol].liquidationRatio));
174
- payload.debtTooLow = new Dec(usedAssets[selectedMarket.baseAsset]?.borrowed || 0).gt(0) && new Dec(usedAssets[selectedMarket.baseAsset].borrowed).lt(assetsData[selectedMarket.baseAsset].minDebt);
175
- const leftToBorrowUsd = new Dec(payload.borrowLimitUsd).sub(payload.borrowedUsd);
176
- payload.leftToBorrowUsd = leftToBorrowUsd.lte('0') ? '0' : leftToBorrowUsd.toString();
177
- payload.ratio = +payload.suppliedUsd ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
178
- payload.collRatio = +payload.suppliedUsd ? new Dec(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
179
- const { netApy, incentiveUsd, totalInterestUsd } = calculateNetApy({ usedAssets, assetsData });
180
- payload.netApy = netApy;
181
- payload.incentiveUsd = incentiveUsd;
182
- payload.totalInterestUsd = totalInterestUsd;
183
- payload.minRatio = '100';
184
- payload.liqRatio = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).toString();
185
- payload.liqPercent = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).mul(100).toString();
186
- payload.minDebt = assetsData[selectedMarket.baseAsset].minDebt;
187
- const { leveragedType, leveragedAsset } = isLeveragedPos(usedAssets, selectedMarket.value === CompoundVersions.CompoundV3ETH ? 0.001 : 5);
188
- payload.leveragedType = leveragedType;
189
- if (leveragedType !== '') {
190
- payload.leveragedAsset = leveragedAsset;
191
- let assetPrice = assetsData[leveragedAsset].price;
192
- if (leveragedType === 'lsd-leverage') {
193
- payload.leveragedLsdAssetRatio = new Dec(assetsData[leveragedAsset].price).div(assetsData.ETH.price).toString();
194
- assetPrice = new Dec(assetPrice).div(assetsData.ETH.price).toString();
195
- }
196
- payload.liquidationPrice = calcLeverageLiqPrice(leveragedType, assetPrice, payload.borrowedUsd, payload.liquidationLimitUsd);
197
- }
198
- payload.minCollRatio = new Dec(payload.suppliedCollateralUsd).div(payload.borrowLimitUsd).mul(100).toString();
199
- payload.collLiquidationRatio = new Dec(payload.suppliedCollateralUsd).div(payload.liquidationLimitUsd).mul(100).toString();
200
-
201
- // TO DO: handle strategies
202
- /* const subscribedStrategies = rest.compoundStrategies
203
- ? compoundV3GetSubscribedStrategies({ selectedMarket, compoundStrategies: rest.compoundStrategies })
204
- : []; */
205
-
206
- // TODO possibly move to global helper, since every protocol has the same graphData?
207
- // payload.ratioTooLow = false;
208
- // payload.ratioTooHigh = false;
209
-
210
- // TO DO: handle strategies
211
- /* if (subscribedStrategies.length) {
212
- subscribedStrategies.forEach(({ graphData }) => {
213
- payload.ratioTooLow = parseFloat(payload.ratio) < parseFloat(graphData.minRatio);
214
- payload.ratioTooHigh = graphData.boostEnabled && parseFloat(payload.ratio) > parseFloat(graphData.maxRatio);
215
- });
216
- } */
217
-
218
- return payload;
219
- };
220
-
221
- export const getApyAfterValuesEstimationCompoundV2 = async (actions: [{ action: string, amount: string, asset: string }], provider: EthereumProvider) => {
222
- const client = getViemProvider(provider, NetworkNumber.Eth);
223
- const compViewContract = CompoundLoanInfoContractViem(client, NetworkNumber.Eth);
224
- const params = actions.map(({ action, asset, amount }) => {
225
- const isBorrowOperation = borrowOperations.includes(action);
226
- const amountInWei = assetAmountInWei(amount, asset);
227
- const assetInfo = getAssetInfo(`c${asset}`);
228
- let liquidityAdded;
229
- let liquidityTaken;
230
- if (isBorrowOperation) {
231
- liquidityAdded = action === 'payback' ? amountInWei : '0';
232
- liquidityTaken = action === 'borrow' ? amountInWei : '0';
233
- } else {
234
- liquidityAdded = action === 'collateral' ? amountInWei : '0';
235
- liquidityTaken = action === 'withdraw' ? amountInWei : '0';
236
- }
237
- return {
238
- cTokenAddr: assetInfo.address as EthAddress,
239
- liquidityAdded: BigInt(liquidityAdded),
240
- liquidityTaken: BigInt(liquidityTaken),
241
- isBorrowOperation,
242
- };
243
- });
244
- const data = await compViewContract.read.getApyAfterValuesEstimation(
245
- [params],
246
- );
247
- const rates: { [key: string]: { supplyRate: string, borrowRate: string } } = {};
248
- data.forEach((d) => {
249
- const asset = wethToEth(getAssetInfoByAddress(d.cTokenAddr).underlyingAsset);
250
- rates[asset] = {
251
- supplyRate: aprToApy(new Dec(BLOCKS_IN_A_YEAR).times(d.supplyRate.toString()).div(1e16).toString()).toString(),
252
- borrowRate: aprToApy(new Dec(BLOCKS_IN_A_YEAR).times(d.borrowRate.toString()).div(1e16).toString()).toString(),
253
- };
254
- });
255
- return rates;
256
- };
257
-
258
- export const getApyAfterValuesEstimationCompoundV3 = async (selectedMarket: CompoundMarketData, action: string, asset: string, amount: string, account: EthAddress, provider: EthereumProvider, network: NetworkNumber) => {
259
- const client = getViemProvider(provider, NetworkNumber.Eth);
260
- const compV3ViewContract = CompV3ViewContractViem(client, network);
261
- const isBorrowOperation = borrowOperations.includes(action);
262
- const amountInWei = assetAmountInWei(amount, asset);
263
- let liquidityAdded;
264
- let liquidityTaken;
265
- if (isBorrowOperation) {
266
- liquidityAdded = action === 'payback' ? amountInWei : '0';
267
- liquidityTaken = action === 'borrow' ? amountInWei : '0';
268
- } else {
269
- liquidityAdded = action === 'collateral' ? amountInWei : '0';
270
- liquidityTaken = action === 'withdraw' ? amountInWei : '0';
271
- }
272
- const [_, supplyRate, borrowRate] = await compV3ViewContract.read.getApyAfterValuesEstimation([
273
- selectedMarket.baseMarketAddress,
274
- account,
275
- BigInt(liquidityAdded),
276
- BigInt(liquidityTaken),
277
- ]);
278
- return {
279
- supplyRate: aprToApy(new Dec(supplyRate).div(1e18).mul(SECONDS_PER_YEAR).mul(100)
280
- .toString()),
281
- borrowRate: aprToApy(new Dec(borrowRate).div(1e18).mul(SECONDS_PER_YEAR).mul(100)
282
- .toString()),
283
- };
1
+ import Dec from 'decimal.js';
2
+ import { assetAmountInWei, getAssetInfo, getAssetInfoByAddress } from '@defisaver/tokens';
3
+ import {
4
+ BaseAdditionalAssetData, CompoundAggregatedPositionData, CompoundMarketData, CompoundV2AssetsData, CompoundV2UsedAssets, CompoundV3AssetData, CompoundV3AssetsData, CompoundV3UsedAssets, CompoundVersions,
5
+ } from '../../types';
6
+ import {
7
+ addToArrayIf, getEthAmountForDecimals, handleWbtcLegacy, wethToEth,
8
+ } from '../../services/utils';
9
+ import { BLOCKS_IN_A_YEAR, borrowOperations, SECONDS_PER_YEAR } from '../../constants';
10
+ import {
11
+ aprToApy, calcLeverageLiqPrice, calculateBorrowingAssetLimit, getAssetsTotal, isLeveragedPos,
12
+ } from '../../moneymarket';
13
+ import { calculateNetApy, getStakingApy, STAKING_ASSETS } from '../../staking';
14
+ import {
15
+ EthAddress, EthereumProvider, IncentiveData, IncentiveKind, NetworkNumber,
16
+ } from '../../types/common';
17
+ import { CompoundLoanInfoContractViem, CompV3ViewContractViem } from '../../contracts';
18
+ import { getViemProvider } from '../../services/viem';
19
+
20
+ export const formatMarketData = (data: any, network: NetworkNumber, baseAssetPrice: string): CompoundV3AssetData => {
21
+ const assetInfo = getAssetInfoByAddress(data.tokenAddr, network);
22
+ const isWETH = assetInfo.symbol === 'WETH';
23
+ const price = getEthAmountForDecimals(data.price, 8);
24
+ return ({
25
+ ...data,
26
+ borrowCollateralFactor: data.borrowCollateralFactor.toString(),
27
+ liquidateCollateralFactor: data.liquidateCollateralFactor.toString(),
28
+ liquidationFactor: data.liquidationFactor.toString(),
29
+ supplyReserved: data.supplyReserved.toString(),
30
+ priceInBaseAsset: getEthAmountForDecimals(data.price, 8),
31
+ price: new Dec(price).mul(baseAssetPrice).toString(),
32
+ collateralFactor: getEthAmountForDecimals(data.borrowCollateralFactor, 18),
33
+ liquidationRatio: getEthAmountForDecimals(data.liquidateCollateralFactor, 18),
34
+ supplyCap: getEthAmountForDecimals(data.supplyCap, assetInfo.decimals),
35
+ totalSupply: getEthAmountForDecimals(data.totalSupply, assetInfo.decimals),
36
+ symbol: isWETH ? 'ETH' : assetInfo.symbol,
37
+ supplyRate: '0',
38
+ borrowRate: '0',
39
+ canBeBorrowed: false,
40
+ canBeSupplied: true,
41
+ supplyIncentives: [],
42
+ borrowIncentives: [],
43
+ });
44
+ };
45
+
46
+ // TODO: maybe not hardcode decimals
47
+ export const formatBaseData = (data: any, network: NetworkNumber, baseAssetPrice: string): CompoundV3AssetData & BaseAdditionalAssetData => {
48
+ const assetInfo = getAssetInfoByAddress(data.tokenAddr, network);
49
+ const totalSupply = getEthAmountForDecimals(new Dec(data.totalSupply).mul(data.supplyIndex).toString(), 15 + assetInfo.decimals);
50
+ const totalBorrow = getEthAmountForDecimals(new Dec(data.totalBorrow).mul(data.borrowIndex).toString(), 15 + assetInfo.decimals);
51
+ return ({
52
+ ...data,
53
+ baseBorrowMin: data.baseBorrowMin.toString(),
54
+ baseTrackingBorrowRewardsSpeed: data.baseTrackingBorrowRewardsSpeed.toString(),
55
+ baseTrackingSupplyRewardsSpeed: data.baseTrackingSupplyRewardsSpeed.toString(),
56
+ borrowIndex: data.borrowIndex.toString(),
57
+ supplyIndex: data.supplyIndex.toString(),
58
+ trackingBorrowIndex: data.trackingBorrowIndex.toString(),
59
+ trackingSupplyIndex: data.trackingSupplyIndex.toString(),
60
+ supplyRate: aprToApy(new Dec(data.supplyRate).div(1e18).mul(SECONDS_PER_YEAR).mul(100)
61
+ .toString()),
62
+ borrowRate: aprToApy(new Dec(data.borrowRate).div(1e18).mul(SECONDS_PER_YEAR).mul(100)
63
+ .toString()),
64
+ utilization: getEthAmountForDecimals(data.utilization, 16), // utilization is totalSupply/totalBorrow in 1e18, but we need % so when we mul with 100 it's 16 decimals
65
+ totalSupply,
66
+ totalBorrow,
67
+ marketLiquidity: new Dec(totalSupply).minus(totalBorrow).toString(),
68
+ symbol: wethToEth(assetInfo.symbol),
69
+ priceInBaseAsset: getEthAmountForDecimals(data.price, 8),
70
+ price: baseAssetPrice,
71
+ collateralFactor: '0',
72
+ liquidationRatio: '0',
73
+ canBeBorrowed: true,
74
+ canBeSupplied: true,
75
+ supplyCap: '0',
76
+ rewardSupplySpeed: getEthAmountForDecimals(data.baseTrackingSupplyRewardsSpeed, 15),
77
+ rewardBorrowSpeed: getEthAmountForDecimals(data.baseTrackingBorrowRewardsSpeed, 15),
78
+ minDebt: getEthAmountForDecimals(data.baseBorrowMin, assetInfo.decimals),
79
+ isBase: true,
80
+ });
81
+ };
82
+
83
+ export const getIncentiveApys = async (
84
+ baseData: CompoundV3AssetData & BaseAdditionalAssetData,
85
+ compPrice: string,
86
+ ): Promise<{
87
+ supplyIncentives: IncentiveData[],
88
+ borrowIncentives: IncentiveData[],
89
+ }> => ({
90
+ supplyIncentives: [{
91
+ token: 'COMP',
92
+ apy: aprToApy((100 * SECONDS_PER_YEAR * +baseData.rewardSupplySpeed * +compPrice) / +baseData.price / +baseData.totalSupply).toString(),
93
+ incentiveKind: IncentiveKind.Reward,
94
+ description: 'Eligible for protocol-level COMP incentives.',
95
+ },
96
+ ...addToArrayIf(STAKING_ASSETS.includes(baseData.symbol), {
97
+ apy: await getStakingApy(baseData.symbol),
98
+ token: baseData.symbol,
99
+ incentiveKind: IncentiveKind.Staking,
100
+ description: `Native ${baseData.symbol} yield.`,
101
+ }),
102
+ ],
103
+ borrowIncentives: [{
104
+ token: 'COMP',
105
+ apy: aprToApy((100 * SECONDS_PER_YEAR * +baseData.rewardBorrowSpeed * +compPrice) / +baseData.price / +baseData.totalBorrow).toString(),
106
+ incentiveKind: IncentiveKind.Reward,
107
+ description: 'Eligible for protocol-level COMP incentives.',
108
+ },
109
+ ...addToArrayIf(STAKING_ASSETS.includes(baseData.symbol), {
110
+ apy: new Dec(await getStakingApy(baseData.symbol)).mul(-1).toString(),
111
+ token: baseData.symbol,
112
+ incentiveKind: IncentiveKind.Staking,
113
+ description: `Due to the native yield of ${baseData.symbol}, the value of the debt would increase over time.`,
114
+ }),
115
+ ],
116
+ });
117
+
118
+ export const getCompoundV2AggregatedData = ({
119
+ usedAssets, assetsData, ...rest
120
+ }: { usedAssets: CompoundV2UsedAssets, assetsData: CompoundV2AssetsData }) => {
121
+ const payload = {} as CompoundAggregatedPositionData;
122
+ payload.suppliedUsd = getAssetsTotal(usedAssets, ({ isSupplied }: { isSupplied: boolean }) => isSupplied, ({ suppliedUsd }: { suppliedUsd: string }) => suppliedUsd);
123
+ payload.suppliedCollateralUsd = getAssetsTotal(usedAssets, ({ isSupplied, collateral }: { isSupplied: boolean, collateral: boolean }) => isSupplied && collateral, ({ suppliedUsd }: { suppliedUsd: string }) => suppliedUsd);
124
+ payload.borrowedUsd = getAssetsTotal(usedAssets, ({ isBorrowed }: { isBorrowed: boolean }) => isBorrowed, ({ borrowedUsd }: { borrowedUsd: string }) => borrowedUsd);
125
+ payload.borrowLimitUsd = getAssetsTotal(usedAssets, ({ isSupplied, collateral }: { isSupplied: boolean, collateral: boolean }) => isSupplied && collateral, ({ symbol, suppliedUsd }: { symbol: string, suppliedUsd: string }) => new Dec(suppliedUsd).mul(assetsData[symbol].collateralFactor));
126
+
127
+ const leftToBorrowUsd = new Dec(payload.borrowLimitUsd).sub(payload.borrowedUsd).toString();
128
+
129
+ payload.leftToBorrowUsd = leftToBorrowUsd;
130
+ payload.borrowLimitUsd = new Dec(leftToBorrowUsd).add(payload.borrowedUsd).toString();
131
+
132
+ payload.liquidationLimitUsd = payload.borrowLimitUsd;
133
+ payload.ratio = payload.borrowedUsd && payload.borrowedUsd !== '0'
134
+ ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString()
135
+ : '0';
136
+ payload.minRatio = '100';
137
+ payload.collRatio = payload.borrowedUsd && payload.borrowedUsd !== '0'
138
+ ? new Dec(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString()
139
+ : '0';
140
+
141
+ // Calculate borrow limits per asset
142
+ Object.values(usedAssets).forEach((item) => {
143
+ if (item.isBorrowed) {
144
+ // eslint-disable-next-line no-param-reassign
145
+ item.limit = calculateBorrowingAssetLimit(item.borrowedUsd, payload.borrowLimitUsd);
146
+ }
147
+ });
148
+
149
+ const { netApy, incentiveUsd, totalInterestUsd } = calculateNetApy({ usedAssets, assetsData });
150
+ payload.netApy = netApy;
151
+ payload.incentiveUsd = incentiveUsd;
152
+ payload.totalInterestUsd = totalInterestUsd;
153
+
154
+ const { leveragedType, leveragedAsset } = isLeveragedPos(usedAssets);
155
+ payload.leveragedType = leveragedType;
156
+ if (leveragedType !== '') {
157
+ payload.leveragedAsset = leveragedAsset;
158
+ const assetPrice = assetsData[handleWbtcLegacy(leveragedAsset)].price;
159
+ payload.liquidationPrice = calcLeverageLiqPrice(leveragedType, assetPrice, payload.borrowedUsd, payload.liquidationLimitUsd);
160
+ }
161
+
162
+ return payload;
163
+ };
164
+
165
+ export const getCompoundV3AggregatedData = ({
166
+ usedAssets, assetsData, network, selectedMarket, ...rest
167
+ }: { usedAssets: CompoundV3UsedAssets, assetsData: CompoundV3AssetsData, network: NetworkNumber, selectedMarket: CompoundMarketData }) => {
168
+ const payload = {} as CompoundAggregatedPositionData;
169
+ payload.suppliedUsd = getAssetsTotal(usedAssets, ({ isSupplied }: { isSupplied: boolean }) => isSupplied, ({ suppliedUsd }: { suppliedUsd: string }) => suppliedUsd);
170
+ payload.suppliedCollateralUsd = getAssetsTotal(usedAssets, ({ isSupplied, collateral }: { isSupplied: boolean, collateral: boolean }) => isSupplied && collateral, ({ suppliedUsd }: { suppliedUsd: string }) => suppliedUsd);
171
+ payload.borrowedUsd = getAssetsTotal(usedAssets, ({ isBorrowed }: { isBorrowed: boolean }) => isBorrowed, ({ borrowedUsd }: { borrowedUsd: string }) => borrowedUsd);
172
+ payload.borrowLimitUsd = getAssetsTotal(usedAssets, ({ isSupplied, collateral }: { isSupplied: boolean, collateral: boolean }) => isSupplied && collateral, ({ symbol, suppliedUsd }: { symbol: string, suppliedUsd: string }) => new Dec(suppliedUsd).mul(assetsData[symbol].collateralFactor));
173
+ payload.liquidationLimitUsd = getAssetsTotal(usedAssets, ({ isSupplied, collateral }: { isSupplied: boolean, collateral: boolean }) => isSupplied && collateral, ({ symbol, suppliedUsd }: { symbol: string, suppliedUsd: string }) => new Dec(suppliedUsd).mul(assetsData[symbol].liquidationRatio));
174
+ payload.debtTooLow = new Dec(usedAssets[selectedMarket.baseAsset]?.borrowed || 0).gt(0) && new Dec(usedAssets[selectedMarket.baseAsset].borrowed).lt(assetsData[selectedMarket.baseAsset].minDebt);
175
+ const leftToBorrowUsd = new Dec(payload.borrowLimitUsd).sub(payload.borrowedUsd);
176
+ payload.leftToBorrowUsd = leftToBorrowUsd.lte('0') ? '0' : leftToBorrowUsd.toString();
177
+ payload.ratio = +payload.suppliedUsd ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
178
+ payload.collRatio = +payload.suppliedUsd ? new Dec(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
179
+ const { netApy, incentiveUsd, totalInterestUsd } = calculateNetApy({ usedAssets, assetsData });
180
+ payload.netApy = netApy;
181
+ payload.incentiveUsd = incentiveUsd;
182
+ payload.totalInterestUsd = totalInterestUsd;
183
+ payload.minRatio = '100';
184
+ payload.liqRatio = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).toString();
185
+ payload.liqPercent = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).mul(100).toString();
186
+ payload.minDebt = assetsData[selectedMarket.baseAsset].minDebt;
187
+ const { leveragedType, leveragedAsset } = isLeveragedPos(usedAssets, selectedMarket.value === CompoundVersions.CompoundV3ETH ? 0.001 : 5);
188
+ payload.leveragedType = leveragedType;
189
+ if (leveragedType !== '') {
190
+ payload.leveragedAsset = leveragedAsset;
191
+ let assetPrice = assetsData[leveragedAsset].price;
192
+ if (leveragedType === 'lsd-leverage') {
193
+ payload.leveragedLsdAssetRatio = new Dec(assetsData[leveragedAsset].price).div(assetsData.ETH.price).toString();
194
+ assetPrice = new Dec(assetPrice).div(assetsData.ETH.price).toString();
195
+ }
196
+ payload.liquidationPrice = calcLeverageLiqPrice(leveragedType, assetPrice, payload.borrowedUsd, payload.liquidationLimitUsd);
197
+ }
198
+ payload.minCollRatio = new Dec(payload.suppliedCollateralUsd).div(payload.borrowLimitUsd).mul(100).toString();
199
+ payload.collLiquidationRatio = new Dec(payload.suppliedCollateralUsd).div(payload.liquidationLimitUsd).mul(100).toString();
200
+
201
+ // TO DO: handle strategies
202
+ /* const subscribedStrategies = rest.compoundStrategies
203
+ ? compoundV3GetSubscribedStrategies({ selectedMarket, compoundStrategies: rest.compoundStrategies })
204
+ : []; */
205
+
206
+ // TODO possibly move to global helper, since every protocol has the same graphData?
207
+ // payload.ratioTooLow = false;
208
+ // payload.ratioTooHigh = false;
209
+
210
+ // TO DO: handle strategies
211
+ /* if (subscribedStrategies.length) {
212
+ subscribedStrategies.forEach(({ graphData }) => {
213
+ payload.ratioTooLow = parseFloat(payload.ratio) < parseFloat(graphData.minRatio);
214
+ payload.ratioTooHigh = graphData.boostEnabled && parseFloat(payload.ratio) > parseFloat(graphData.maxRatio);
215
+ });
216
+ } */
217
+
218
+ return payload;
219
+ };
220
+
221
+ export const getApyAfterValuesEstimationCompoundV2 = async (actions: [{ action: string, amount: string, asset: string }], provider: EthereumProvider) => {
222
+ const client = getViemProvider(provider, NetworkNumber.Eth);
223
+ const compViewContract = CompoundLoanInfoContractViem(client, NetworkNumber.Eth);
224
+ const params = actions.map(({ action, asset, amount }) => {
225
+ const isBorrowOperation = borrowOperations.includes(action);
226
+ const amountInWei = assetAmountInWei(amount, asset);
227
+ const assetInfo = getAssetInfo(`c${asset}`);
228
+ let liquidityAdded;
229
+ let liquidityTaken;
230
+ if (isBorrowOperation) {
231
+ liquidityAdded = action === 'payback' ? amountInWei : '0';
232
+ liquidityTaken = action === 'borrow' ? amountInWei : '0';
233
+ } else {
234
+ liquidityAdded = action === 'collateral' ? amountInWei : '0';
235
+ liquidityTaken = action === 'withdraw' ? amountInWei : '0';
236
+ }
237
+ return {
238
+ cTokenAddr: assetInfo.address as EthAddress,
239
+ liquidityAdded: BigInt(liquidityAdded),
240
+ liquidityTaken: BigInt(liquidityTaken),
241
+ isBorrowOperation,
242
+ };
243
+ });
244
+ const data = await compViewContract.read.getApyAfterValuesEstimation(
245
+ [params],
246
+ );
247
+ const rates: { [key: string]: { supplyRate: string, borrowRate: string } } = {};
248
+ data.forEach((d) => {
249
+ const asset = wethToEth(getAssetInfoByAddress(d.cTokenAddr).underlyingAsset);
250
+ rates[asset] = {
251
+ supplyRate: aprToApy(new Dec(BLOCKS_IN_A_YEAR).times(d.supplyRate.toString()).div(1e16).toString()).toString(),
252
+ borrowRate: aprToApy(new Dec(BLOCKS_IN_A_YEAR).times(d.borrowRate.toString()).div(1e16).toString()).toString(),
253
+ };
254
+ });
255
+ return rates;
256
+ };
257
+
258
+ export const getApyAfterValuesEstimationCompoundV3 = async (selectedMarket: CompoundMarketData, action: string, asset: string, amount: string, account: EthAddress, provider: EthereumProvider, network: NetworkNumber) => {
259
+ const client = getViemProvider(provider, NetworkNumber.Eth);
260
+ const compV3ViewContract = CompV3ViewContractViem(client, network);
261
+ const isBorrowOperation = borrowOperations.includes(action);
262
+ const amountInWei = assetAmountInWei(amount, asset);
263
+ let liquidityAdded;
264
+ let liquidityTaken;
265
+ if (isBorrowOperation) {
266
+ liquidityAdded = action === 'payback' ? amountInWei : '0';
267
+ liquidityTaken = action === 'borrow' ? amountInWei : '0';
268
+ } else {
269
+ liquidityAdded = action === 'collateral' ? amountInWei : '0';
270
+ liquidityTaken = action === 'withdraw' ? amountInWei : '0';
271
+ }
272
+ const [_, supplyRate, borrowRate] = await compV3ViewContract.read.getApyAfterValuesEstimation([
273
+ selectedMarket.baseMarketAddress,
274
+ account,
275
+ BigInt(liquidityAdded),
276
+ BigInt(liquidityTaken),
277
+ ]);
278
+ return {
279
+ supplyRate: aprToApy(new Dec(supplyRate).div(1e18).mul(SECONDS_PER_YEAR).mul(100)
280
+ .toString()),
281
+ borrowRate: aprToApy(new Dec(borrowRate).div(1e18).mul(SECONDS_PER_YEAR).mul(100)
282
+ .toString()),
283
+ };
284
284
  };