@defisaver/positions-sdk 2.0.13 → 2.0.15-dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -25,6 +25,7 @@ const utils_1 = require("../services/utils");
25
25
  const staking_1 = require("../staking");
26
26
  const common_1 = require("../types/common");
27
27
  const viem_1 = require("../services/viem");
28
+ const rewards_1 = require("./rewards");
28
29
  const aaveV3EmodeCategoriesMapping = (extractedState, usedAssets) => {
29
30
  const { eModeCategoriesData } = extractedState;
30
31
  const usedAssetsValues = Object.values(usedAssets);
@@ -60,11 +61,12 @@ function _getAaveV3MarketData(provider_1, network_1, market_1) {
60
61
  const marketAddress = market.providerAddress;
61
62
  const networksWithIncentives = [common_1.NetworkNumber.Eth, common_1.NetworkNumber.Arb, common_1.NetworkNumber.Opt, common_1.NetworkNumber.Linea];
62
63
  // eslint-disable-next-line prefer-const
63
- let [loanInfo, eModesInfo, isBorrowAllowed, rewardInfo] = yield Promise.all([
64
+ let [loanInfo, eModesInfo, isBorrowAllowed, rewardInfo, merkleRewardsMap] = yield Promise.all([
64
65
  loanInfoContract.read.getFullTokensInfo([marketAddress, _addresses], (0, viem_1.setViemBlockNumber)(blockNumber)),
65
66
  loanInfoContract.read.getAllEmodes([marketAddress], (0, viem_1.setViemBlockNumber)(blockNumber)),
66
67
  loanInfoContract.read.isBorrowAllowed([marketAddress], (0, viem_1.setViemBlockNumber)(blockNumber)), // Used on L2s check for PriceOracleSentinel (mainnet will always return true)
67
68
  networksWithIncentives.includes(network) ? aaveIncentivesContract.read.getReservesIncentivesData([marketAddress], (0, viem_1.setViemBlockNumber)(blockNumber)) : null,
69
+ (0, rewards_1.getMerkleCampaigns)(network),
68
70
  ]);
69
71
  isBorrowAllowed = (0, utils_1.isLayer2Network)(network) ? isBorrowAllowed : true;
70
72
  const eModeCategoriesData = {};
@@ -146,10 +148,13 @@ function _getAaveV3MarketData(provider_1, network_1, market_1) {
146
148
  isolationModeBorrowingEnabled: tokenMarket.isolationModeBorrowingEnabled,
147
149
  isFlashLoanEnabled: tokenMarket.isFlashLoanEnabled,
148
150
  aTokenAddress: tokenMarket.aTokenAddress,
151
+ supplyIncentives: [],
152
+ borrowIncentives: [],
149
153
  });
150
154
  })));
151
155
  // Get incentives data
152
- yield Promise.all(assetsData.map((_market) => __awaiter(this, void 0, void 0, function* () {
156
+ yield Promise.all(assetsData.map((_market, index) => __awaiter(this, void 0, void 0, function* () {
157
+ var _a;
153
158
  /* eslint-disable no-param-reassign */
154
159
  // @ts-ignore
155
160
  const rewardForMarket = rewardInfo === null || rewardInfo === void 0 ? void 0 : rewardInfo[_market.underlyingTokenAddress];
@@ -157,38 +162,44 @@ function _getAaveV3MarketData(provider_1, network_1, market_1) {
157
162
  if (isStakingAsset) {
158
163
  _market.incentiveSupplyApy = yield (0, staking_1.getStakingApy)(_market.symbol);
159
164
  _market.incentiveSupplyToken = _market.symbol;
160
- if (!_market.supplyIncentives) {
161
- _market.supplyIncentives = [];
162
- }
163
165
  _market.supplyIncentives.push({
164
166
  apy: _market.incentiveSupplyApy || '0',
165
167
  token: _market.symbol,
166
168
  incentiveKind: 'staking',
169
+ description: `Native ${_market.symbol} yield.`,
167
170
  });
168
- }
169
- if (_market.canBeBorrowed && _market.incentiveSupplyApy) {
170
- _market.incentiveBorrowApy = _market.incentiveSupplyApy;
171
- _market.incentiveBorrowToken = _market.incentiveSupplyToken;
172
- if (!_market.borrowIncentives) {
173
- _market.borrowIncentives = [];
171
+ if (_market.canBeBorrowed) {
172
+ // when borrowing assets whose value increases over time
173
+ _market.incentiveBorrowApy = new decimal_js_1.default(_market.incentiveSupplyApy).mul(-1).toString();
174
+ _market.incentiveBorrowToken = _market.symbol;
175
+ _market.borrowIncentives.push({
176
+ apy: _market.incentiveBorrowApy,
177
+ token: _market.incentiveBorrowToken,
178
+ incentiveKind: 'reward',
179
+ description: `Due to the native yield of ${_market.symbol}, the value of the debt would increase over time.`,
180
+ });
174
181
  }
175
- _market.borrowIncentives.push({
176
- apy: _market.incentiveBorrowApy,
177
- token: _market.incentiveBorrowToken,
178
- incentiveKind: 'reward',
179
- });
180
182
  }
181
- if (_market.symbol === 'USDe') {
182
- const merklApy = yield (0, staking_1.getStakingApy)(_market.symbol);
183
- if (!_market.supplyIncentives) {
184
- _market.supplyIncentives = [];
185
- }
183
+ const aTokenAddress = _market.aTokenAddress.toLowerCase(); // DEV: Should aTokenAddress be in AaveV3AssetData type?
184
+ if ((_a = merkleRewardsMap[aTokenAddress]) === null || _a === void 0 ? void 0 : _a.supply) {
185
+ const { apr, rewardTokenSymbol, description } = merkleRewardsMap[aTokenAddress].supply;
186
186
  _market.supplyIncentives.push({
187
- apy: merklApy || '0',
188
- token: _market.symbol,
187
+ apy: (0, moneymarket_1.aprToApy)(apr),
188
+ token: rewardTokenSymbol,
189
189
  incentiveKind: 'reward',
190
+ description,
190
191
  });
191
192
  }
193
+ // const aTokenDebtAddress = '0xTODO';
194
+ // if (merkleRewardsMap[aTokenDebtAddress]?.supply) {
195
+ // const { apr, rewardTokenSymbol, description } = merkleRewardsMap[aTokenDebtAddress].supply;
196
+ // _market.borrowIncentives.push({
197
+ // apy: aprToApy(apr),
198
+ // token: rewardTokenSymbol,
199
+ // incentiveKind: 'reward',
200
+ // description,
201
+ // });
202
+ // }
192
203
  if (!rewardForMarket)
193
204
  return;
194
205
  // @ts-ignore
@@ -211,13 +222,11 @@ function _getAaveV3MarketData(provider_1, network_1, market_1) {
211
222
  .toString();
212
223
  _market.incentiveSupplyApy = new decimal_js_1.default(_market.incentiveSupplyApy || '0').add(rewardApy)
213
224
  .toString();
214
- if (!_market.supplyIncentives) {
215
- _market.supplyIncentives = [];
216
- }
217
225
  _market.supplyIncentives.push({
218
- token: supplyRewardData.rewardTokenSymbol,
226
+ token: (0, rewards_1.getAaveUnderlyingSymbol)(supplyRewardData.rewardTokenSymbol),
219
227
  apy: rewardApy,
220
228
  incentiveKind: 'reward',
229
+ description: 'Eligible for protocol-level incentives.',
221
230
  });
222
231
  }
223
232
  });
@@ -240,13 +249,11 @@ function _getAaveV3MarketData(provider_1, network_1, market_1) {
240
249
  .toString();
241
250
  _market.incentiveBorrowApy = new decimal_js_1.default(_market.incentiveBorrowApy || '0').add(rewardApy)
242
251
  .toString();
243
- if (!_market.borrowIncentives) {
244
- _market.borrowIncentives = [];
245
- }
246
252
  _market.borrowIncentives.push({
247
- token: borrowRewardData.rewardTokenSymbol,
253
+ token: (0, rewards_1.getAaveUnderlyingSymbol)(borrowRewardData.rewardTokenSymbol),
248
254
  apy: rewardApy,
249
255
  incentiveKind: 'reward',
256
+ description: 'Eligible for protocol-level incentives.',
250
257
  });
251
258
  }
252
259
  });
@@ -0,0 +1,14 @@
1
+ import { EthAddress, NetworkNumber } from '../types/common';
2
+ type RewardInfo = {
3
+ apr: number;
4
+ rewardToken: EthAddress;
5
+ rewardTokenSymbol: string;
6
+ description: string;
7
+ };
8
+ type MerkleRewardMap = Record<EthAddress, {
9
+ supply?: RewardInfo;
10
+ borrow?: RewardInfo;
11
+ }>;
12
+ export declare const getAaveUnderlyingSymbol: (_symbol?: string) => any;
13
+ export declare const getMerkleCampaigns: (chainId: NetworkNumber) => Promise<MerkleRewardMap>;
14
+ export {};
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getMerkleCampaigns = exports.getAaveUnderlyingSymbol = void 0;
13
+ const utils_1 = require("../services/utils");
14
+ var OpportunityAction;
15
+ (function (OpportunityAction) {
16
+ OpportunityAction["LEND"] = "LEND";
17
+ OpportunityAction["BORROW"] = "BORROW";
18
+ })(OpportunityAction || (OpportunityAction = {}));
19
+ var OpportunityStatus;
20
+ (function (OpportunityStatus) {
21
+ OpportunityStatus["LIVE"] = "LIVE";
22
+ OpportunityStatus["PAST"] = "PAST";
23
+ OpportunityStatus["UPCOMING"] = "UPCOMING";
24
+ })(OpportunityStatus || (OpportunityStatus = {}));
25
+ const getAaveUnderlyingSymbol = (_symbol = '') => {
26
+ let symbol = _symbol
27
+ .replace(/^aEthLido/, '')
28
+ .replace(/^aEthEtherFi/, '')
29
+ .replace(/^aEth/, '')
30
+ .replace(/^aArb/, '')
31
+ .replace(/^aOpt/, '')
32
+ .replace(/^aBas/, '')
33
+ .replace(/^aLin/, '');
34
+ if (symbol.startsWith('a'))
35
+ symbol = symbol.slice(1);
36
+ return (0, utils_1.wethToEth)(symbol);
37
+ };
38
+ exports.getAaveUnderlyingSymbol = getAaveUnderlyingSymbol;
39
+ const getMerkleCampaigns = (chainId) => __awaiter(void 0, void 0, void 0, function* () {
40
+ try {
41
+ const res = yield fetch('https://api.merkl.xyz/v4/opportunities?mainProtocolId=aave', {
42
+ signal: AbortSignal.timeout(utils_1.DEFAULT_TIMEOUT),
43
+ });
44
+ if (!res.ok)
45
+ throw new Error('Failed to fetch Merkle campaigns');
46
+ const opportunities = yield res.json();
47
+ const relevantOpportunities = opportunities
48
+ .filter((o) => o.chainId === chainId)
49
+ .filter((o) => o.liveCampaigns > 0);
50
+ return relevantOpportunities.reduce((acc, opportunity) => {
51
+ const rewardToken = opportunity.rewardsRecord.breakdowns[0].token;
52
+ if (opportunity.action === OpportunityAction.LEND) {
53
+ const supplyAToken = opportunity.explorerAddress.toLowerCase();
54
+ if (!acc[supplyAToken])
55
+ acc[supplyAToken] = {};
56
+ acc[supplyAToken].supply = {
57
+ apr: opportunity.apr,
58
+ rewardToken: rewardToken.address,
59
+ rewardTokenSymbol: (0, exports.getAaveUnderlyingSymbol)(rewardToken.symbol),
60
+ description: `Eligible for incentives through Merkl. \n${opportunity.description}`,
61
+ };
62
+ }
63
+ if (opportunity.action === OpportunityAction.BORROW) {
64
+ const borrowAToken = opportunity.explorerAddress.toLowerCase();
65
+ if (!acc[borrowAToken])
66
+ acc[borrowAToken] = {};
67
+ acc[borrowAToken].borrow = {
68
+ apr: opportunity.apr,
69
+ rewardToken: rewardToken.address,
70
+ rewardTokenSymbol: (0, exports.getAaveUnderlyingSymbol)(rewardToken.symbol),
71
+ description: `Eligible for incentives through Merkl. \n${opportunity.description}`,
72
+ };
73
+ }
74
+ return acc;
75
+ }, {});
76
+ }
77
+ catch (e) {
78
+ console.error('Failed to fetch Merkle campaigns', e);
79
+ return {};
80
+ }
81
+ });
82
+ exports.getMerkleCampaigns = getMerkleCampaigns;
@@ -10,7 +10,7 @@ exports.aaveV1AssetsDefaultMarket = [
10
10
  exports.aaveV2AssetsDefaultMarket = ['USDT', 'WBTC', 'ETH', 'YFI', 'ZRX', 'UNI', 'AAVE', 'BAT', 'BUSD', 'DAI', 'ENJ', 'KNCL', 'LINK', 'MANA', 'MKR', 'REN', 'SNX', 'SUSD', 'TUSD', 'USDC', 'CRV', 'GUSD', 'BAL', 'xSUSHI', 'RENFIL', 'RAI', 'AMPL', 'USDP', 'DPI', 'FRAX', 'FEI', 'stETH', 'ENS', 'UST', 'CVX', '1INCH', 'LUSD'];
11
11
  exports.aaveV3AssetsDefaultMarketEth = [
12
12
  'ETH', 'wstETH', 'WBTC', 'USDC', 'DAI', 'LINK', 'AAVE', 'cbETH', 'USDT', 'rETH', 'LUSD', 'CRV', 'MKR', 'SNX', 'BAL', 'UNI', 'LDO', 'ENS', '1INCH', 'FRAX', 'GHO', 'RPL', 'sDAI', 'STG', 'KNC', 'FXS', 'crvUSD', 'PYUSD', 'weETH', 'osETH', 'USDe', 'ETHx', 'sUSDe', 'tBTC', 'cbBTC', 'USDS', 'rsETH', 'LBTC', 'eBTC', 'RLUSD', 'PT eUSDe May', 'PT sUSDe July', 'USDtb',
13
- 'eUSDe', 'PT USDe July', 'PT eUSDe Aug', 'EURC', 'FBTC', 'PT sUSDe Sep', 'PT USDe Sep', 'tETH', 'ezETH', 'XAUt', 'PT sUSDe Nov',
13
+ 'eUSDe', 'PT USDe July', 'PT eUSDe Aug', 'EURC', 'FBTC', 'PT sUSDe Sep', 'PT USDe Sep', 'tETH', 'ezETH', 'XAUt', 'PT sUSDe Nov', 'PT USDe Nov',
14
14
  ];
15
15
  exports.aaveV3AssetsDefaultMarketOpt = [
16
16
  'DAI', 'USDC.e', 'USDT', 'SUSD', 'AAVE', 'LINK', 'WBTC', 'ETH', 'OP', 'wstETH', 'LUSD', 'MAI', 'rETH', 'USDC',
@@ -65,7 +65,7 @@ const getApyFromDfsApi = (asset) => __awaiter(void 0, void 0, void 0, function*
65
65
  return '0';
66
66
  }
67
67
  });
68
- exports.STAKING_ASSETS = ['cbETH', 'wstETH', 'cbETH', 'rETH', 'sDAI', 'weETH', 'sUSDe', 'osETH', 'ezETH', 'ETHx', 'rsETH', 'pufETH', 'wrsETH', 'wsuperOETHb', 'sUSDS', 'tETH', 'PT sUSDe Sep', 'PT USDe Sep', 'PT sUSDe Nov'];
68
+ exports.STAKING_ASSETS = ['cbETH', 'wstETH', 'cbETH', 'rETH', 'sDAI', 'weETH', 'sUSDe', 'osETH', 'ezETH', 'ETHx', 'rsETH', 'pufETH', 'wrsETH', 'wsuperOETHb', 'sUSDS', 'tETH', 'PT sUSDe Sep', 'PT USDe Sep', 'PT sUSDe Nov', 'PT USDe Nov'];
69
69
  exports.getStakingApy = (0, memoizee_1.default)((asset) => __awaiter(void 0, void 0, void 0, function* () {
70
70
  try {
71
71
  if (asset === 'stETH' || asset === 'wstETH')
@@ -112,6 +112,8 @@ exports.getStakingApy = (0, memoizee_1.default)((asset) => __awaiter(void 0, voi
112
112
  return yield getApyFromDfsApi('USDe');
113
113
  if (asset === 'PT sUSDe Nov')
114
114
  return yield getApyFromDfsApi('PT sUSDe Nov');
115
+ if (asset === 'PT USDe Nov')
116
+ return yield getApyFromDfsApi('PT USDe Nov');
115
117
  }
116
118
  catch (e) {
117
119
  console.error(`Failed to fetch APY for ${asset}`);
@@ -66,6 +66,7 @@ export interface IncentiveData {
66
66
  token: string;
67
67
  apy: string;
68
68
  incentiveKind?: 'staking' | 'reward';
69
+ description?: string;
69
70
  }
70
71
  export interface AaveV3AssetData extends AaveAssetData {
71
72
  isIsolated: boolean;
@@ -80,8 +81,8 @@ export interface AaveV3AssetData extends AaveAssetData {
80
81
  isFlashLoanEnabled: boolean;
81
82
  assetId: string | number | null;
82
83
  liquidationBonus: string;
83
- supplyIncentives?: IncentiveData[];
84
- borrowIncentives?: IncentiveData[];
84
+ supplyIncentives: IncentiveData[];
85
+ borrowIncentives: IncentiveData[];
85
86
  }
86
87
  export type EModeCategoriesData = Record<number, EModeCategoryData>;
87
88
  export type AaveAssetsData<T> = {
@@ -17,6 +17,7 @@ import { ethToWeth, isEnabledOnBitmap, isLayer2Network, wethToEth, wethToEthByAd
17
17
  import { getStakingApy, STAKING_ASSETS } from '../staking';
18
18
  import { NetworkNumber, } from '../types/common';
19
19
  import { getViemProvider, setViemBlockNumber } from '../services/viem';
20
+ import { getAaveUnderlyingSymbol, getMerkleCampaigns } from './rewards';
20
21
  export const aaveV3EmodeCategoriesMapping = (extractedState, usedAssets) => {
21
22
  const { eModeCategoriesData } = extractedState;
22
23
  const usedAssetsValues = Object.values(usedAssets);
@@ -51,11 +52,12 @@ export function _getAaveV3MarketData(provider_1, network_1, market_1) {
51
52
  const marketAddress = market.providerAddress;
52
53
  const networksWithIncentives = [NetworkNumber.Eth, NetworkNumber.Arb, NetworkNumber.Opt, NetworkNumber.Linea];
53
54
  // eslint-disable-next-line prefer-const
54
- let [loanInfo, eModesInfo, isBorrowAllowed, rewardInfo] = yield Promise.all([
55
+ let [loanInfo, eModesInfo, isBorrowAllowed, rewardInfo, merkleRewardsMap] = yield Promise.all([
55
56
  loanInfoContract.read.getFullTokensInfo([marketAddress, _addresses], setViemBlockNumber(blockNumber)),
56
57
  loanInfoContract.read.getAllEmodes([marketAddress], setViemBlockNumber(blockNumber)),
57
58
  loanInfoContract.read.isBorrowAllowed([marketAddress], setViemBlockNumber(blockNumber)), // Used on L2s check for PriceOracleSentinel (mainnet will always return true)
58
59
  networksWithIncentives.includes(network) ? aaveIncentivesContract.read.getReservesIncentivesData([marketAddress], setViemBlockNumber(blockNumber)) : null,
60
+ getMerkleCampaigns(network),
59
61
  ]);
60
62
  isBorrowAllowed = isLayer2Network(network) ? isBorrowAllowed : true;
61
63
  const eModeCategoriesData = {};
@@ -137,10 +139,13 @@ export function _getAaveV3MarketData(provider_1, network_1, market_1) {
137
139
  isolationModeBorrowingEnabled: tokenMarket.isolationModeBorrowingEnabled,
138
140
  isFlashLoanEnabled: tokenMarket.isFlashLoanEnabled,
139
141
  aTokenAddress: tokenMarket.aTokenAddress,
142
+ supplyIncentives: [],
143
+ borrowIncentives: [],
140
144
  });
141
145
  })));
142
146
  // Get incentives data
143
- yield Promise.all(assetsData.map((_market) => __awaiter(this, void 0, void 0, function* () {
147
+ yield Promise.all(assetsData.map((_market, index) => __awaiter(this, void 0, void 0, function* () {
148
+ var _a;
144
149
  /* eslint-disable no-param-reassign */
145
150
  // @ts-ignore
146
151
  const rewardForMarket = rewardInfo === null || rewardInfo === void 0 ? void 0 : rewardInfo[_market.underlyingTokenAddress];
@@ -148,38 +153,44 @@ export function _getAaveV3MarketData(provider_1, network_1, market_1) {
148
153
  if (isStakingAsset) {
149
154
  _market.incentiveSupplyApy = yield getStakingApy(_market.symbol);
150
155
  _market.incentiveSupplyToken = _market.symbol;
151
- if (!_market.supplyIncentives) {
152
- _market.supplyIncentives = [];
153
- }
154
156
  _market.supplyIncentives.push({
155
157
  apy: _market.incentiveSupplyApy || '0',
156
158
  token: _market.symbol,
157
159
  incentiveKind: 'staking',
160
+ description: `Native ${_market.symbol} yield.`,
158
161
  });
159
- }
160
- if (_market.canBeBorrowed && _market.incentiveSupplyApy) {
161
- _market.incentiveBorrowApy = _market.incentiveSupplyApy;
162
- _market.incentiveBorrowToken = _market.incentiveSupplyToken;
163
- if (!_market.borrowIncentives) {
164
- _market.borrowIncentives = [];
162
+ if (_market.canBeBorrowed) {
163
+ // when borrowing assets whose value increases over time
164
+ _market.incentiveBorrowApy = new Dec(_market.incentiveSupplyApy).mul(-1).toString();
165
+ _market.incentiveBorrowToken = _market.symbol;
166
+ _market.borrowIncentives.push({
167
+ apy: _market.incentiveBorrowApy,
168
+ token: _market.incentiveBorrowToken,
169
+ incentiveKind: 'reward',
170
+ description: `Due to the native yield of ${_market.symbol}, the value of the debt would increase over time.`,
171
+ });
165
172
  }
166
- _market.borrowIncentives.push({
167
- apy: _market.incentiveBorrowApy,
168
- token: _market.incentiveBorrowToken,
169
- incentiveKind: 'reward',
170
- });
171
173
  }
172
- if (_market.symbol === 'USDe') {
173
- const merklApy = yield getStakingApy(_market.symbol);
174
- if (!_market.supplyIncentives) {
175
- _market.supplyIncentives = [];
176
- }
174
+ const aTokenAddress = _market.aTokenAddress.toLowerCase(); // DEV: Should aTokenAddress be in AaveV3AssetData type?
175
+ if ((_a = merkleRewardsMap[aTokenAddress]) === null || _a === void 0 ? void 0 : _a.supply) {
176
+ const { apr, rewardTokenSymbol, description } = merkleRewardsMap[aTokenAddress].supply;
177
177
  _market.supplyIncentives.push({
178
- apy: merklApy || '0',
179
- token: _market.symbol,
178
+ apy: aprToApy(apr),
179
+ token: rewardTokenSymbol,
180
180
  incentiveKind: 'reward',
181
+ description,
181
182
  });
182
183
  }
184
+ // const aTokenDebtAddress = '0xTODO';
185
+ // if (merkleRewardsMap[aTokenDebtAddress]?.supply) {
186
+ // const { apr, rewardTokenSymbol, description } = merkleRewardsMap[aTokenDebtAddress].supply;
187
+ // _market.borrowIncentives.push({
188
+ // apy: aprToApy(apr),
189
+ // token: rewardTokenSymbol,
190
+ // incentiveKind: 'reward',
191
+ // description,
192
+ // });
193
+ // }
183
194
  if (!rewardForMarket)
184
195
  return;
185
196
  // @ts-ignore
@@ -202,13 +213,11 @@ export function _getAaveV3MarketData(provider_1, network_1, market_1) {
202
213
  .toString();
203
214
  _market.incentiveSupplyApy = new Dec(_market.incentiveSupplyApy || '0').add(rewardApy)
204
215
  .toString();
205
- if (!_market.supplyIncentives) {
206
- _market.supplyIncentives = [];
207
- }
208
216
  _market.supplyIncentives.push({
209
- token: supplyRewardData.rewardTokenSymbol,
217
+ token: getAaveUnderlyingSymbol(supplyRewardData.rewardTokenSymbol),
210
218
  apy: rewardApy,
211
219
  incentiveKind: 'reward',
220
+ description: 'Eligible for protocol-level incentives.',
212
221
  });
213
222
  }
214
223
  });
@@ -231,13 +240,11 @@ export function _getAaveV3MarketData(provider_1, network_1, market_1) {
231
240
  .toString();
232
241
  _market.incentiveBorrowApy = new Dec(_market.incentiveBorrowApy || '0').add(rewardApy)
233
242
  .toString();
234
- if (!_market.borrowIncentives) {
235
- _market.borrowIncentives = [];
236
- }
237
243
  _market.borrowIncentives.push({
238
- token: borrowRewardData.rewardTokenSymbol,
244
+ token: getAaveUnderlyingSymbol(borrowRewardData.rewardTokenSymbol),
239
245
  apy: rewardApy,
240
246
  incentiveKind: 'reward',
247
+ description: 'Eligible for protocol-level incentives.',
241
248
  });
242
249
  }
243
250
  });
@@ -0,0 +1,14 @@
1
+ import { EthAddress, NetworkNumber } from '../types/common';
2
+ type RewardInfo = {
3
+ apr: number;
4
+ rewardToken: EthAddress;
5
+ rewardTokenSymbol: string;
6
+ description: string;
7
+ };
8
+ type MerkleRewardMap = Record<EthAddress, {
9
+ supply?: RewardInfo;
10
+ borrow?: RewardInfo;
11
+ }>;
12
+ export declare const getAaveUnderlyingSymbol: (_symbol?: string) => any;
13
+ export declare const getMerkleCampaigns: (chainId: NetworkNumber) => Promise<MerkleRewardMap>;
14
+ export {};
@@ -0,0 +1,77 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { DEFAULT_TIMEOUT, wethToEth } from '../services/utils';
11
+ var OpportunityAction;
12
+ (function (OpportunityAction) {
13
+ OpportunityAction["LEND"] = "LEND";
14
+ OpportunityAction["BORROW"] = "BORROW";
15
+ })(OpportunityAction || (OpportunityAction = {}));
16
+ var OpportunityStatus;
17
+ (function (OpportunityStatus) {
18
+ OpportunityStatus["LIVE"] = "LIVE";
19
+ OpportunityStatus["PAST"] = "PAST";
20
+ OpportunityStatus["UPCOMING"] = "UPCOMING";
21
+ })(OpportunityStatus || (OpportunityStatus = {}));
22
+ export const getAaveUnderlyingSymbol = (_symbol = '') => {
23
+ let symbol = _symbol
24
+ .replace(/^aEthLido/, '')
25
+ .replace(/^aEthEtherFi/, '')
26
+ .replace(/^aEth/, '')
27
+ .replace(/^aArb/, '')
28
+ .replace(/^aOpt/, '')
29
+ .replace(/^aBas/, '')
30
+ .replace(/^aLin/, '');
31
+ if (symbol.startsWith('a'))
32
+ symbol = symbol.slice(1);
33
+ return wethToEth(symbol);
34
+ };
35
+ export const getMerkleCampaigns = (chainId) => __awaiter(void 0, void 0, void 0, function* () {
36
+ try {
37
+ const res = yield fetch('https://api.merkl.xyz/v4/opportunities?mainProtocolId=aave', {
38
+ signal: AbortSignal.timeout(DEFAULT_TIMEOUT),
39
+ });
40
+ if (!res.ok)
41
+ throw new Error('Failed to fetch Merkle campaigns');
42
+ const opportunities = yield res.json();
43
+ const relevantOpportunities = opportunities
44
+ .filter((o) => o.chainId === chainId)
45
+ .filter((o) => o.liveCampaigns > 0);
46
+ return relevantOpportunities.reduce((acc, opportunity) => {
47
+ const rewardToken = opportunity.rewardsRecord.breakdowns[0].token;
48
+ if (opportunity.action === OpportunityAction.LEND) {
49
+ const supplyAToken = opportunity.explorerAddress.toLowerCase();
50
+ if (!acc[supplyAToken])
51
+ acc[supplyAToken] = {};
52
+ acc[supplyAToken].supply = {
53
+ apr: opportunity.apr,
54
+ rewardToken: rewardToken.address,
55
+ rewardTokenSymbol: getAaveUnderlyingSymbol(rewardToken.symbol),
56
+ description: `Eligible for incentives through Merkl. \n${opportunity.description}`,
57
+ };
58
+ }
59
+ if (opportunity.action === OpportunityAction.BORROW) {
60
+ const borrowAToken = opportunity.explorerAddress.toLowerCase();
61
+ if (!acc[borrowAToken])
62
+ acc[borrowAToken] = {};
63
+ acc[borrowAToken].borrow = {
64
+ apr: opportunity.apr,
65
+ rewardToken: rewardToken.address,
66
+ rewardTokenSymbol: getAaveUnderlyingSymbol(rewardToken.symbol),
67
+ description: `Eligible for incentives through Merkl. \n${opportunity.description}`,
68
+ };
69
+ }
70
+ return acc;
71
+ }, {});
72
+ }
73
+ catch (e) {
74
+ console.error('Failed to fetch Merkle campaigns', e);
75
+ return {};
76
+ }
77
+ });
@@ -7,7 +7,7 @@ export const aaveV1AssetsDefaultMarket = [
7
7
  export const aaveV2AssetsDefaultMarket = ['USDT', 'WBTC', 'ETH', 'YFI', 'ZRX', 'UNI', 'AAVE', 'BAT', 'BUSD', 'DAI', 'ENJ', 'KNCL', 'LINK', 'MANA', 'MKR', 'REN', 'SNX', 'SUSD', 'TUSD', 'USDC', 'CRV', 'GUSD', 'BAL', 'xSUSHI', 'RENFIL', 'RAI', 'AMPL', 'USDP', 'DPI', 'FRAX', 'FEI', 'stETH', 'ENS', 'UST', 'CVX', '1INCH', 'LUSD'];
8
8
  export const aaveV3AssetsDefaultMarketEth = [
9
9
  'ETH', 'wstETH', 'WBTC', 'USDC', 'DAI', 'LINK', 'AAVE', 'cbETH', 'USDT', 'rETH', 'LUSD', 'CRV', 'MKR', 'SNX', 'BAL', 'UNI', 'LDO', 'ENS', '1INCH', 'FRAX', 'GHO', 'RPL', 'sDAI', 'STG', 'KNC', 'FXS', 'crvUSD', 'PYUSD', 'weETH', 'osETH', 'USDe', 'ETHx', 'sUSDe', 'tBTC', 'cbBTC', 'USDS', 'rsETH', 'LBTC', 'eBTC', 'RLUSD', 'PT eUSDe May', 'PT sUSDe July', 'USDtb',
10
- 'eUSDe', 'PT USDe July', 'PT eUSDe Aug', 'EURC', 'FBTC', 'PT sUSDe Sep', 'PT USDe Sep', 'tETH', 'ezETH', 'XAUt', 'PT sUSDe Nov',
10
+ 'eUSDe', 'PT USDe July', 'PT eUSDe Aug', 'EURC', 'FBTC', 'PT sUSDe Sep', 'PT USDe Sep', 'tETH', 'ezETH', 'XAUt', 'PT sUSDe Nov', 'PT USDe Nov',
11
11
  ];
12
12
  export const aaveV3AssetsDefaultMarketOpt = [
13
13
  'DAI', 'USDC.e', 'USDT', 'SUSD', 'AAVE', 'LINK', 'WBTC', 'ETH', 'OP', 'wstETH', 'LUSD', 'MAI', 'rETH', 'USDC',
@@ -59,7 +59,7 @@ const getApyFromDfsApi = (asset) => __awaiter(void 0, void 0, void 0, function*
59
59
  return '0';
60
60
  }
61
61
  });
62
- export const STAKING_ASSETS = ['cbETH', 'wstETH', 'cbETH', 'rETH', 'sDAI', 'weETH', 'sUSDe', 'osETH', 'ezETH', 'ETHx', 'rsETH', 'pufETH', 'wrsETH', 'wsuperOETHb', 'sUSDS', 'tETH', 'PT sUSDe Sep', 'PT USDe Sep', 'PT sUSDe Nov'];
62
+ export const STAKING_ASSETS = ['cbETH', 'wstETH', 'cbETH', 'rETH', 'sDAI', 'weETH', 'sUSDe', 'osETH', 'ezETH', 'ETHx', 'rsETH', 'pufETH', 'wrsETH', 'wsuperOETHb', 'sUSDS', 'tETH', 'PT sUSDe Sep', 'PT USDe Sep', 'PT sUSDe Nov', 'PT USDe Nov'];
63
63
  export const getStakingApy = memoize((asset) => __awaiter(void 0, void 0, void 0, function* () {
64
64
  try {
65
65
  if (asset === 'stETH' || asset === 'wstETH')
@@ -106,6 +106,8 @@ export const getStakingApy = memoize((asset) => __awaiter(void 0, void 0, void 0
106
106
  return yield getApyFromDfsApi('USDe');
107
107
  if (asset === 'PT sUSDe Nov')
108
108
  return yield getApyFromDfsApi('PT sUSDe Nov');
109
+ if (asset === 'PT USDe Nov')
110
+ return yield getApyFromDfsApi('PT USDe Nov');
109
111
  }
110
112
  catch (e) {
111
113
  console.error(`Failed to fetch APY for ${asset}`);
@@ -66,6 +66,7 @@ export interface IncentiveData {
66
66
  token: string;
67
67
  apy: string;
68
68
  incentiveKind?: 'staking' | 'reward';
69
+ description?: string;
69
70
  }
70
71
  export interface AaveV3AssetData extends AaveAssetData {
71
72
  isIsolated: boolean;
@@ -80,8 +81,8 @@ export interface AaveV3AssetData extends AaveAssetData {
80
81
  isFlashLoanEnabled: boolean;
81
82
  assetId: string | number | null;
82
83
  liquidationBonus: string;
83
- supplyIncentives?: IncentiveData[];
84
- borrowIncentives?: IncentiveData[];
84
+ supplyIncentives: IncentiveData[];
85
+ borrowIncentives: IncentiveData[];
85
86
  }
86
87
  export type EModeCategoriesData = Record<number, EModeCategoryData>;
87
88
  export type AaveAssetsData<T> = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defisaver/positions-sdk",
3
- "version": "2.0.13",
3
+ "version": "2.0.15-dev",
4
4
  "description": "",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./esm/index.js",
@@ -21,7 +21,7 @@
21
21
  "author": "",
22
22
  "license": "ISC",
23
23
  "dependencies": {
24
- "@defisaver/tokens": "^1.7.0",
24
+ "@defisaver/tokens": "^1.7.1",
25
25
  "@types/lodash": "^4.17.15",
26
26
  "@types/memoizee": "^0.4.12",
27
27
  "decimal.js": "^10.6.0",
@@ -29,6 +29,7 @@ import {
29
29
  Blockish, EthAddress, EthereumProvider, NetworkNumber, PositionBalances,
30
30
  } from '../types/common';
31
31
  import { getViemProvider, setViemBlockNumber } from '../services/viem';
32
+ import { getAaveUnderlyingSymbol, getMerkleCampaigns } from './rewards';
32
33
 
33
34
  export const aaveV3EmodeCategoriesMapping = (extractedState: any, usedAssets: AaveV3UsedAssets) => {
34
35
  const { eModeCategoriesData }: { assetsData: AaveV3AssetsData, eModeCategoriesData: EModeCategoriesData } = extractedState;
@@ -70,11 +71,12 @@ export async function _getAaveV3MarketData(provider: Client, network: NetworkNum
70
71
  const networksWithIncentives = [NetworkNumber.Eth, NetworkNumber.Arb, NetworkNumber.Opt, NetworkNumber.Linea];
71
72
 
72
73
  // eslint-disable-next-line prefer-const
73
- let [loanInfo, eModesInfo, isBorrowAllowed, rewardInfo] = await Promise.all([
74
+ let [loanInfo, eModesInfo, isBorrowAllowed, rewardInfo, merkleRewardsMap] = await Promise.all([
74
75
  loanInfoContract.read.getFullTokensInfo([marketAddress, _addresses as EthAddress[]], setViemBlockNumber(blockNumber)),
75
76
  loanInfoContract.read.getAllEmodes([marketAddress], setViemBlockNumber(blockNumber)),
76
77
  loanInfoContract.read.isBorrowAllowed([marketAddress], setViemBlockNumber(blockNumber)), // Used on L2s check for PriceOracleSentinel (mainnet will always return true)
77
78
  networksWithIncentives.includes(network) ? aaveIncentivesContract.read.getReservesIncentivesData([marketAddress], setViemBlockNumber(blockNumber)) : null,
79
+ getMerkleCampaigns(network),
78
80
  ]);
79
81
  isBorrowAllowed = isLayer2Network(network) ? isBorrowAllowed : true;
80
82
 
@@ -160,54 +162,63 @@ export async function _getAaveV3MarketData(provider: Client, network: NetworkNum
160
162
  isolationModeBorrowingEnabled: tokenMarket.isolationModeBorrowingEnabled,
161
163
  isFlashLoanEnabled: tokenMarket.isFlashLoanEnabled,
162
164
  aTokenAddress: tokenMarket.aTokenAddress,
165
+ supplyIncentives: [],
166
+ borrowIncentives: [],
163
167
  });
164
- }));
165
-
168
+ }),
169
+ );
166
170
 
167
171
  // Get incentives data
168
- await Promise.all(assetsData.map(async (_market: AaveV3AssetData) => {
172
+ await Promise.all(assetsData.map(async (_market: AaveV3AssetData, index) => {
169
173
  /* eslint-disable no-param-reassign */
170
174
  // @ts-ignore
171
175
  const rewardForMarket = rewardInfo?.[_market.underlyingTokenAddress];
172
176
  const isStakingAsset = STAKING_ASSETS.includes(_market.symbol);
177
+
173
178
  if (isStakingAsset) {
174
179
  _market.incentiveSupplyApy = await getStakingApy(_market.symbol);
175
180
  _market.incentiveSupplyToken = _market.symbol;
176
- if (!_market.supplyIncentives) {
177
- _market.supplyIncentives = [];
178
- }
179
181
  _market.supplyIncentives.push({
180
182
  apy: _market.incentiveSupplyApy || '0',
181
183
  token: _market.symbol,
182
184
  incentiveKind: 'staking',
185
+ description: `Native ${_market.symbol} yield.`,
183
186
  });
184
- }
185
-
186
- if (_market.canBeBorrowed && _market.incentiveSupplyApy) {
187
- _market.incentiveBorrowApy = _market.incentiveSupplyApy;
188
- _market.incentiveBorrowToken = _market.incentiveSupplyToken;
189
- if (!_market.borrowIncentives) {
190
- _market.borrowIncentives = [];
187
+ if (_market.canBeBorrowed) {
188
+ // when borrowing assets whose value increases over time
189
+ _market.incentiveBorrowApy = new Dec(_market.incentiveSupplyApy).mul(-1).toString();
190
+ _market.incentiveBorrowToken = _market.symbol;
191
+ _market.borrowIncentives.push({
192
+ apy: _market.incentiveBorrowApy,
193
+ token: _market.incentiveBorrowToken,
194
+ incentiveKind: 'reward',
195
+ description: `Due to the native yield of ${_market.symbol}, the value of the debt would increase over time.`,
196
+ });
191
197
  }
192
- _market.borrowIncentives.push({
193
- apy: _market.incentiveBorrowApy,
194
- token: _market.incentiveBorrowToken!!,
195
- incentiveKind: 'reward',
196
- });
197
198
  }
198
199
 
199
- if (_market.symbol === 'USDe') {
200
- const merklApy = await getStakingApy(_market.symbol);
201
- if (!_market.supplyIncentives) {
202
- _market.supplyIncentives = [];
203
- }
200
+ const aTokenAddress = (_market as any).aTokenAddress.toLowerCase(); // DEV: Should aTokenAddress be in AaveV3AssetData type?
201
+ if (merkleRewardsMap[aTokenAddress]?.supply) {
202
+ const { apr, rewardTokenSymbol, description } = merkleRewardsMap[aTokenAddress].supply;
204
203
  _market.supplyIncentives.push({
205
- apy: merklApy || '0',
206
- token: _market.symbol,
204
+ apy: aprToApy(apr),
205
+ token: rewardTokenSymbol,
207
206
  incentiveKind: 'reward',
207
+ description,
208
208
  });
209
209
  }
210
210
 
211
+ // const aTokenDebtAddress = '0xTODO'; // variableDebtTokenAddress is not in loanInfo ATM
212
+ // if (merkleRewardsMap[aTokenDebtAddress]?.supply) {
213
+ // const { apr, rewardTokenSymbol, description } = merkleRewardsMap[aTokenDebtAddress].supply;
214
+ // _market.borrowIncentives.push({
215
+ // apy: aprToApy(apr),
216
+ // token: rewardTokenSymbol,
217
+ // incentiveKind: 'reward',
218
+ // description,
219
+ // });
220
+ // }
221
+
211
222
  if (!rewardForMarket) return;
212
223
  // @ts-ignore
213
224
  rewardForMarket.aIncentiveData.rewardsTokenInformation.forEach(supplyRewardData => {
@@ -227,14 +238,11 @@ export async function _getAaveV3MarketData(provider: Client, network: NetworkNum
227
238
  .toString();
228
239
  _market.incentiveSupplyApy = new Dec(_market.incentiveSupplyApy || '0').add(rewardApy)
229
240
  .toString();
230
-
231
- if (!_market.supplyIncentives) {
232
- _market.supplyIncentives = [];
233
- }
234
241
  _market.supplyIncentives.push({
235
- token: supplyRewardData.rewardTokenSymbol,
242
+ token: getAaveUnderlyingSymbol(supplyRewardData.rewardTokenSymbol),
236
243
  apy: rewardApy,
237
244
  incentiveKind: 'reward',
245
+ description: 'Eligible for protocol-level incentives.',
238
246
  });
239
247
  }
240
248
  });
@@ -255,14 +263,11 @@ export async function _getAaveV3MarketData(provider: Client, network: NetworkNum
255
263
  .toString();
256
264
  _market.incentiveBorrowApy = new Dec(_market.incentiveBorrowApy || '0').add(rewardApy)
257
265
  .toString();
258
-
259
- if (!_market.borrowIncentives) {
260
- _market.borrowIncentives = [];
261
- }
262
266
  _market.borrowIncentives.push({
263
- token: borrowRewardData.rewardTokenSymbol,
267
+ token: getAaveUnderlyingSymbol(borrowRewardData.rewardTokenSymbol),
264
268
  apy: rewardApy,
265
269
  incentiveKind: 'reward',
270
+ description: 'Eligible for protocol-level incentives.',
266
271
  });
267
272
  }
268
273
  });
@@ -0,0 +1,125 @@
1
+ import { DEFAULT_TIMEOUT, wethToEth } from '../services/utils';
2
+ import { EthAddress, NetworkNumber } from '../types/common';
3
+
4
+ enum OpportunityAction {
5
+ LEND = 'LEND',
6
+ BORROW = 'BORROW',
7
+ }
8
+
9
+ enum OpportunityStatus {
10
+ LIVE = 'LIVE',
11
+ PAST = 'PAST',
12
+ UPCOMING = 'UPCOMING',
13
+ }
14
+
15
+ type MerklOpportunity = {
16
+ chainId: number;
17
+ type: string;
18
+ identifier: EthAddress;
19
+ name: string;
20
+ status: OpportunityStatus;
21
+ action: OpportunityAction;
22
+ tvl: number;
23
+ apr: number;
24
+ dailyRewards: number;
25
+ tags: [];
26
+ id: string;
27
+ explorerAddress?: EthAddress;
28
+ tokens: {
29
+ id: string;
30
+ name: string;
31
+ chainId: number;
32
+ address: EthAddress;
33
+ decimals: number;
34
+ icon: string;
35
+ verified: boolean;
36
+ isTest: boolean;
37
+ price: number;
38
+ symbol: string;
39
+ }[];
40
+ rewardsRecord: {
41
+ id: string;
42
+ total: number;
43
+ timestamp: string;
44
+ breakdowns: {
45
+ token: {
46
+ id: string;
47
+ name: string;
48
+ chainId: number;
49
+ address: string;
50
+ decimals: number;
51
+ symbol: string;
52
+ displaySymbol: string;
53
+ icon: string;
54
+ verified: boolean;
55
+ isTest: boolean;
56
+ type: string;
57
+ isNative: boolean;
58
+ price: number;
59
+ };
60
+ amount: string;
61
+ value: number;
62
+ distributionType: string;
63
+ id: string;
64
+ campaignId: string;
65
+ dailyRewardsRecordId: string;
66
+ }[];
67
+ };
68
+ };
69
+
70
+ type RewardInfo = { apr: number; rewardToken: EthAddress; rewardTokenSymbol: string, description: string };
71
+ type MerkleRewardMap = Record<EthAddress, { supply?: RewardInfo; borrow?: RewardInfo }>;
72
+
73
+ export const getAaveUnderlyingSymbol = (_symbol = '') => {
74
+ let symbol = _symbol
75
+ .replace(/^aEthLido/, '')
76
+ .replace(/^aEthEtherFi/, '')
77
+ .replace(/^aEth/, '')
78
+ .replace(/^aArb/, '')
79
+ .replace(/^aOpt/, '')
80
+ .replace(/^aBas/, '')
81
+ .replace(/^aLin/, '');
82
+ if (symbol.startsWith('a')) symbol = symbol.slice(1);
83
+ return wethToEth(symbol);
84
+ };
85
+
86
+ export const getMerkleCampaigns = async (chainId: NetworkNumber): Promise<MerkleRewardMap> => {
87
+ try {
88
+ const res = await fetch('https://api.merkl.xyz/v4/opportunities?mainProtocolId=aave', {
89
+ signal: AbortSignal.timeout(DEFAULT_TIMEOUT),
90
+ });
91
+ if (!res.ok) throw new Error('Failed to fetch Merkle campaigns');
92
+ const opportunities = await res.json() as MerklOpportunity[];
93
+ const relevantOpportunities = opportunities
94
+ .filter((o: any) => o.chainId === chainId)
95
+ .filter((o: any) => o.liveCampaigns > 0);
96
+ return relevantOpportunities.reduce((acc: any, opportunity: any) => {
97
+ const rewardToken = opportunity.rewardsRecord.breakdowns[0].token;
98
+ if (opportunity.action === OpportunityAction.LEND) {
99
+ const supplyAToken = opportunity.explorerAddress.toLowerCase() as EthAddress;
100
+ if (!acc[supplyAToken]) acc[supplyAToken] = {};
101
+ acc[supplyAToken].supply = {
102
+ apr: opportunity.apr,
103
+ rewardToken: rewardToken.address,
104
+ rewardTokenSymbol: getAaveUnderlyingSymbol(rewardToken.symbol),
105
+ description: `Eligible for incentives through Merkl. \n${opportunity.description}`,
106
+ };
107
+ }
108
+ if (opportunity.action === OpportunityAction.BORROW) {
109
+ const borrowAToken = opportunity.explorerAddress.toLowerCase() as EthAddress;
110
+ if (!acc[borrowAToken]) acc[borrowAToken] = {};
111
+ acc[borrowAToken].borrow = {
112
+ apr: opportunity.apr,
113
+ rewardToken: rewardToken.address,
114
+ rewardTokenSymbol: getAaveUnderlyingSymbol(rewardToken.symbol),
115
+ description: `Eligible for incentives through Merkl. \n${opportunity.description}`,
116
+ };
117
+ }
118
+ return acc;
119
+ }, {} as MerkleRewardMap);
120
+ } catch (e) {
121
+ console.error('Failed to fetch Merkle campaigns', e);
122
+ return {};
123
+ }
124
+ };
125
+
@@ -10,7 +10,7 @@ export const aaveV2AssetsDefaultMarket = ['USDT', 'WBTC', 'ETH', 'YFI', 'ZRX', '
10
10
 
11
11
  export const aaveV3AssetsDefaultMarketEth = [
12
12
  'ETH', 'wstETH', 'WBTC', 'USDC', 'DAI', 'LINK', 'AAVE', 'cbETH', 'USDT', 'rETH', 'LUSD', 'CRV', 'MKR', 'SNX', 'BAL', 'UNI', 'LDO', 'ENS', '1INCH', 'FRAX', 'GHO', 'RPL', 'sDAI', 'STG', 'KNC', 'FXS', 'crvUSD', 'PYUSD', 'weETH', 'osETH', 'USDe', 'ETHx', 'sUSDe', 'tBTC', 'cbBTC', 'USDS', 'rsETH', 'LBTC', 'eBTC', 'RLUSD', 'PT eUSDe May', 'PT sUSDe July', 'USDtb',
13
- 'eUSDe', 'PT USDe July', 'PT eUSDe Aug', 'EURC', 'FBTC', 'PT sUSDe Sep', 'PT USDe Sep', 'tETH', 'ezETH', 'XAUt', 'PT sUSDe Nov',
13
+ 'eUSDe', 'PT USDe July', 'PT eUSDe Aug', 'EURC', 'FBTC', 'PT sUSDe Sep', 'PT USDe Sep', 'tETH', 'ezETH', 'XAUt', 'PT sUSDe Nov', 'PT USDe Nov',
14
14
  ];
15
15
  export const aaveV3AssetsDefaultMarketOpt = [
16
16
  'DAI', 'USDC.e', 'USDT', 'SUSD', 'AAVE', 'LINK', 'WBTC', 'ETH', 'OP', 'wstETH', 'LUSD', 'MAI', 'rETH', 'USDC',
@@ -54,7 +54,7 @@ const getApyFromDfsApi = async (asset: string) => {
54
54
  }
55
55
  };
56
56
 
57
- export const STAKING_ASSETS = ['cbETH', 'wstETH', 'cbETH', 'rETH', 'sDAI', 'weETH', 'sUSDe', 'osETH', 'ezETH', 'ETHx', 'rsETH', 'pufETH', 'wrsETH', 'wsuperOETHb', 'sUSDS', 'tETH', 'PT sUSDe Sep', 'PT USDe Sep', 'PT sUSDe Nov'];
57
+ export const STAKING_ASSETS = ['cbETH', 'wstETH', 'cbETH', 'rETH', 'sDAI', 'weETH', 'sUSDe', 'osETH', 'ezETH', 'ETHx', 'rsETH', 'pufETH', 'wrsETH', 'wsuperOETHb', 'sUSDS', 'tETH', 'PT sUSDe Sep', 'PT USDe Sep', 'PT sUSDe Nov', 'PT USDe Nov'];
58
58
 
59
59
  export const getStakingApy = memoize(async (asset: string) => {
60
60
  try {
@@ -80,6 +80,7 @@ export const getStakingApy = memoize(async (asset: string) => {
80
80
  if (asset === 'tETH') return await getApyFromDfsApi('tETH');
81
81
  if (asset === 'USDe') return await getApyFromDfsApi('USDe');
82
82
  if (asset === 'PT sUSDe Nov') return await getApyFromDfsApi('PT sUSDe Nov');
83
+ if (asset === 'PT USDe Nov') return await getApyFromDfsApi('PT USDe Nov');
83
84
  } catch (e) {
84
85
  console.error(`Failed to fetch APY for ${asset}`);
85
86
  }
package/src/types/aave.ts CHANGED
@@ -74,6 +74,7 @@ export interface IncentiveData {
74
74
  token: string,
75
75
  apy: string,
76
76
  incentiveKind?: 'staking' | 'reward';
77
+ description?: string;
77
78
  }
78
79
 
79
80
  export interface AaveV3AssetData extends AaveAssetData {
@@ -89,8 +90,8 @@ export interface AaveV3AssetData extends AaveAssetData {
89
90
  isFlashLoanEnabled: boolean,
90
91
  assetId: string | number | null,
91
92
  liquidationBonus: string,
92
- supplyIncentives?: IncentiveData[];
93
- borrowIncentives?: IncentiveData[];
93
+ supplyIncentives: IncentiveData[];
94
+ borrowIncentives: IncentiveData[];
94
95
  }
95
96
 
96
97
  export type EModeCategoriesData = Record<number, EModeCategoryData>;