@defisaver/positions-sdk 0.0.166 → 0.0.168

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.
@@ -151,6 +151,14 @@ export const getSparkMarketsData = async (web3: Web3, network: NetworkNumber, se
151
151
  if (STAKING_ASSETS.includes(market.symbol)) {
152
152
  market.incentiveSupplyApy = await getStakingApy(market.symbol, mainnetWeb3);
153
153
  market.incentiveSupplyToken = market.symbol;
154
+ if (!market.supplyIncentives) {
155
+ market.supplyIncentives = [];
156
+ }
157
+
158
+ market.supplyIncentives.push({
159
+ apy: market.incentiveSupplyApy || '0',
160
+ token: market.symbol,
161
+ });
154
162
  }
155
163
 
156
164
  if (market.symbol === 'sDAI') {
@@ -159,37 +167,66 @@ export const getSparkMarketsData = async (web3: Web3, network: NetworkNumber, se
159
167
  }
160
168
 
161
169
  if (market.canBeBorrowed && market.incentiveSupplyApy) {
162
- market.incentiveBorrowApy = `-${market.incentiveSupplyApy}`;
170
+ market.incentiveBorrowApy = market.incentiveSupplyApy;
163
171
  market.incentiveBorrowToken = market.incentiveSupplyToken;
172
+ if (!market.borrowIncentives) {
173
+ market.borrowIncentives = [];
174
+ }
175
+ market.borrowIncentives.push({
176
+ apy: market.incentiveBorrowApy,
177
+ token: market.incentiveBorrowToken!!,
178
+ });
164
179
  }
165
180
 
166
181
  if (!rewardForMarket) return;
167
- const supplyRewardData = rewardForMarket.aIncentiveData.rewardsTokenInformation[0];
168
- if (supplyRewardData) {
169
- if (supplyRewardData.emissionEndTimestamp * 1000 < Date.now()) return;
170
- market.incentiveSupplyToken = supplyRewardData.rewardTokenSymbol;
171
- const supplyEmissionPerSecond = supplyRewardData.emissionPerSecond;
172
- const supplyRewardPrice = new Dec(supplyRewardData.rewardPriceFeed).div(10 ** supplyRewardData.priceFeedDecimals).toString();
173
- market.incentiveSupplyApy = new Dec(supplyEmissionPerSecond).div((10 ** supplyRewardData.rewardTokenDecimals) / 100)
174
- .mul(365 * 24 * 3600)
175
- .mul(supplyRewardPrice)
176
- .div(market.price)
177
- .div(market.totalSupply)
178
- .toString();
179
- }
180
- const borrowRewardData = rewardForMarket.vIncentiveData.rewardsTokenInformation[0];
181
- if (borrowRewardData) {
182
- if (borrowRewardData.emissionEndTimestamp * 1000 < Date.now()) return;
183
- market.incentiveBorrowToken = borrowRewardData.rewardTokenSymbol;
184
- const supplyEmissionPerSecond = borrowRewardData.emissionPerSecond;
185
- const supplyRewardPrice = new Dec(borrowRewardData.rewardPriceFeed).div(10 ** borrowRewardData.priceFeedDecimals).toString();
186
- market.incentiveBorrowApy = new Dec(supplyEmissionPerSecond).div((10 ** borrowRewardData.rewardTokenDecimals) / 100)
187
- .mul(365 * 24 * 3600)
188
- .mul(supplyRewardPrice)
189
- .div(market.price)
190
- .div(market.totalBorrowVar)
191
- .toString();
192
- }
182
+ (rewardForMarket.aIncentiveData.rewardsTokenInformation as any[]).forEach(supplyRewardData => {
183
+ if (supplyRewardData) {
184
+ if (supplyRewardData.emissionEndTimestamp * 1000 < Date.now()) return;
185
+ market.incentiveSupplyToken = supplyRewardData.rewardTokenSymbol;
186
+ const supplyEmissionPerSecond = supplyRewardData.emissionPerSecond;
187
+ const supplyRewardPrice = new Dec(supplyRewardData.rewardPriceFeed).div(10 ** supplyRewardData.priceFeedDecimals)
188
+ .toString();
189
+ const rewardApy = new Dec(supplyEmissionPerSecond).div((10 ** supplyRewardData.rewardTokenDecimals) / 100)
190
+ .mul(365 * 24 * 3600)
191
+ .mul(supplyRewardPrice)
192
+ .div(market.price)
193
+ .div(market.totalSupply)
194
+ .toString();
195
+ market.incentiveSupplyApy = new Dec(market.incentiveSupplyApy || '0').add(rewardApy).toString();
196
+
197
+ if (!market.supplyIncentives) {
198
+ market.supplyIncentives = [];
199
+ }
200
+ market.supplyIncentives.push({
201
+ token: supplyRewardData.rewardTokenSymbol,
202
+ apy: rewardApy,
203
+ });
204
+ }
205
+ });
206
+ (rewardForMarket.vIncentiveData.rewardsTokenInformation as any[]).forEach(borrowRewardData => {
207
+ if (borrowRewardData) {
208
+ if (borrowRewardData.emissionEndTimestamp * 1000 < Date.now()) return;
209
+ market.incentiveBorrowToken = borrowRewardData.rewardTokenSymbol;
210
+ const supplyEmissionPerSecond = borrowRewardData.emissionPerSecond;
211
+ const supplyRewardPrice = new Dec(borrowRewardData.rewardPriceFeed).div(10 ** borrowRewardData.priceFeedDecimals)
212
+ .toString();
213
+ const rewardApy = new Dec(supplyEmissionPerSecond).div((10 ** borrowRewardData.rewardTokenDecimals) / 100)
214
+ .mul(365 * 24 * 3600)
215
+ .mul(supplyRewardPrice)
216
+ .div(market.price)
217
+ .div(market.totalBorrowVar)
218
+ .toString();
219
+ market.incentiveBorrowApy = new Dec(market.incentiveBorrowApy || '0').add(rewardApy).toString();
220
+
221
+ if (!market.borrowIncentives) {
222
+ market.borrowIncentives = [];
223
+ }
224
+ market.borrowIncentives.push({
225
+ token: borrowRewardData.rewardTokenSymbol,
226
+ apy: rewardApy,
227
+ });
228
+ }
229
+ });
193
230
  /* eslint-enable no-param-reassign */
194
231
  }));
195
232
 
@@ -7,9 +7,10 @@ import { MMAssetsData, MMUsedAssets, NetworkNumber } from '../types/common';
7
7
  import { ContractEventLog } from '../types/contracts/generated/types';
8
8
  import { BLOCKS_IN_A_YEAR, SECONDS_PER_YEAR, AVG_BLOCK_TIME } from '../constants';
9
9
  import { multicall } from '../multicall';
10
+ import { aprToApy } from '../moneymarket';
10
11
 
11
12
 
12
- export const getStETHApr = async (web3: Web3, fromBlock = 17900000, blockNumber: 'latest' | number = 'latest') => {
13
+ export const getStETHApy = async (web3: Web3, fromBlock = 17900000, blockNumber: 'latest' | number = 'latest') => {
13
14
  try {
14
15
  const tokenRebasedEvents: ContractEventLog<{ [key: string]: any }>[] = await LidoContract(web3, NetworkNumber.Eth).getPastEvents('TokenRebased', { fromBlock, toBlock: blockNumber });
15
16
  tokenRebasedEvents.sort((a, b) => b.blockNumber - a.blockNumber); // sort from highest to lowest block number
@@ -21,17 +22,16 @@ export const getStETHApr = async (web3: Web3, fromBlock = 17900000, blockNumber:
21
22
  .div(event.timeElapsed.toString()).mul(100)
22
23
  .toNumber();
23
24
  });
24
- return aprs.reduce((a, b) => a + b, 0) / aprs.length;
25
+ return aprToApy(aprs.reduce((a, b) => a + b, 0) / aprs.length);
25
26
  } catch (e) {
26
27
  console.warn('Failed to fetch stETH APY from events, falling back to Lido API');
27
28
  const res = await fetch('https://eth-api.lido.fi/v1/protocol/steth/apr/sma');
28
29
  const data = await res.json();
29
- return data.data.smaApr;
30
+ return aprToApy(data.data.smaApr);
30
31
  }
31
32
  };
32
33
 
33
-
34
- export const getCbETHApr = async (web3: Web3, blockNumber: 'latest' | number = 'latest') => {
34
+ export const getCbETHApy = async (web3: Web3, blockNumber: 'latest' | number = 'latest') => {
35
35
  let currentBlock = blockNumber;
36
36
  if (blockNumber === 'latest') currentBlock = await web3.eth.getBlockNumber();
37
37
  const blockDiff = 6 * 24 * 60 * 60 / AVG_BLOCK_TIME;
@@ -45,11 +45,11 @@ export const getCbETHApr = async (web3: Web3, blockNumber: 'latest' | number = '
45
45
  .mul(BLOCKS_IN_A_YEAR / blockDiff)
46
46
  .mul(100)
47
47
  .toString();
48
- return apr;
48
+ return aprToApy(apr);
49
49
  };
50
50
 
51
51
 
52
- export const getREthApr = async (web3: Web3, blockNumber: 'latest' | number = 'latest') => {
52
+ export const getREthApy = async (web3: Web3, blockNumber: 'latest' | number = 'latest') => {
53
53
  let currentBlock = blockNumber;
54
54
  if (blockNumber === 'latest') currentBlock = await web3.eth.getBlockNumber();
55
55
  const blockDiff = 8 * 24 * 60 * 60 / AVG_BLOCK_TIME;
@@ -64,7 +64,7 @@ export const getREthApr = async (web3: Web3, blockNumber: 'latest' | number = 'l
64
64
  .mul(100)
65
65
  .toString();
66
66
 
67
- return apr;
67
+ return aprToApy(apr);
68
68
  };
69
69
 
70
70
  export const getDsrApy = async (web3: Web3, blockNumber: 'latest' | number = 'latest') => {
@@ -84,7 +84,6 @@ export const getSsrApy = async () => {
84
84
  };
85
85
 
86
86
  const getSuperOETHApy = async () => {
87
- console.log('getSuperOETHApy');
88
87
  const res = await fetch('https://origin.squids.live/origin-squid/graphql', {
89
88
  method: 'POST',
90
89
  headers: {
@@ -106,17 +105,20 @@ const getSuperOETHApy = async () => {
106
105
  const getApyFromDfsApi = async (asset: string) => {
107
106
  const res = await fetch(`https://app.defisaver.com/api/staking/apy?asset=${asset}`);
108
107
  const data = await res.json();
108
+ // if our server returns apr, transform it into apy
109
+ if (['weETH'].includes(asset)) {
110
+ return aprToApy(data.apy);
111
+ }
109
112
  return data.apy;
110
113
  };
111
114
 
112
115
  export const STAKING_ASSETS = ['cbETH', 'wstETH', 'cbETH', 'rETH', 'sDAI', 'weETH', 'sUSDe', 'osETH', 'ezETH', 'ETHx', 'rsETH', 'pufETH', 'wrsETH', 'wsuperOETHb', 'sUSDS'];
113
116
 
114
117
  export const getStakingApy = (asset: string, web3: Web3, blockNumber: 'latest' | number = 'latest', fromBlock: number | undefined = undefined) => {
115
- console.log('getStakingApy', asset, blockNumber, fromBlock);
116
118
  try {
117
- if (asset === 'stETH' || asset === 'wstETH') return getStETHApr(web3, fromBlock, blockNumber);
118
- if (asset === 'cbETH') return getCbETHApr(web3, blockNumber);
119
- if (asset === 'rETH') return getREthApr(web3, blockNumber);
119
+ if (asset === 'stETH' || asset === 'wstETH') return getStETHApy(web3, fromBlock, blockNumber);
120
+ if (asset === 'cbETH') return getCbETHApy(web3, blockNumber);
121
+ if (asset === 'rETH') return getREthApy(web3, blockNumber);
120
122
  if (asset === 'sDAI') return getDsrApy(web3);
121
123
  if (asset === 'sUSDe') return getApyFromDfsApi('sUSDe');
122
124
  if (asset === 'weETH') return getApyFromDfsApi('weETH');
package/src/types/aave.ts CHANGED
@@ -84,6 +84,11 @@ export interface AaveV2AssetData extends AaveAssetData {
84
84
  export interface MorphoAaveV2AssetData extends AaveV2AssetData {
85
85
  }
86
86
 
87
+ export interface IncentiveData {
88
+ token: string,
89
+ apy: string,
90
+ }
91
+
87
92
  export interface AaveV3AssetData extends AaveAssetData {
88
93
  isIsolated: boolean,
89
94
  isSiloed: boolean,
@@ -99,6 +104,8 @@ export interface AaveV3AssetData extends AaveAssetData {
99
104
  isPaused: boolean,
100
105
  isFlashLoanEnabled: boolean,
101
106
  assetId: string | null,
107
+ supplyIncentives?: IncentiveData[];
108
+ borrowIncentives?: IncentiveData[];
102
109
  }
103
110
 
104
111
  export type EModeCategoriesData = Record<number, EModeCategoryData>;
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  MMAssetData, MMPositionData, MMUsedAsset, NetworkNumber,
3
3
  } from './common';
4
+ import { IncentiveData } from './aave';
4
5
 
5
6
  export enum SparkVersions {
6
7
  SparkV1 = 'v1default',
@@ -55,6 +56,8 @@ export interface SparkAssetData extends MMAssetData {
55
56
  eModeCategory: number,
56
57
  eModeCategoryData: SparkEModeCategoryData,
57
58
  liquidationRatio: string,
59
+ supplyIncentives?: IncentiveData[];
60
+ borrowIncentives?: IncentiveData[];
58
61
  }
59
62
 
60
63
  export interface SparkAssetsData {
@@ -125,4 +128,4 @@ export interface SparkPositionData extends MMPositionData {
125
128
  isInIsolationMode: boolean,
126
129
  isInSiloedMode: boolean,
127
130
  eModeCategories: { [key: number]: SparkEModeCategoryDataMapping },
128
- }
131
+ }