@defisaver/positions-sdk 0.0.181 → 0.0.183-dev-allocator

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.
@@ -104,7 +104,7 @@ function getAaveV3MarketData(web3, network, market, defaultWeb3) {
104
104
  params: [],
105
105
  },
106
106
  {
107
- target: (0, tokens_1.getAssetInfo)('GHO').address,
107
+ target: (0, tokens_1.getAssetInfo)('GHO', network).address,
108
108
  abiItem: (0, utils_1.getAbiItem)(GhoTokenAbi, 'getFacilitatorsList'),
109
109
  params: [],
110
110
  },
@@ -148,7 +148,7 @@ function getAaveV3MarketData(web3, network, market, defaultWeb3) {
148
148
  const assetsData = yield Promise.all(loanInfo
149
149
  .map((tokenMarket, i) => __awaiter(this, void 0, void 0, function* () {
150
150
  const symbol = market.assets[i];
151
- const nativeAsset = symbol === 'GHO';
151
+ const nativeAsset = symbol === 'GHO' && network === common_1.NetworkNumber.Eth;
152
152
  // eslint-disable-next-line guard-for-in
153
153
  for (const eModeIndex in eModeCategoriesData) {
154
154
  if ((0, utils_1.isEnabledOnBitmap)(Number(eModeCategoriesData[eModeIndex].collateralBitmap), Number(tokenMarket.assetId)))
@@ -198,6 +198,7 @@ function getAaveV3MarketData(web3, network, market, defaultWeb3) {
198
198
  _market.supplyIncentives.push({
199
199
  apy: _market.incentiveSupplyApy || '0',
200
200
  token: _market.symbol,
201
+ incentiveKind: 'staking',
201
202
  });
202
203
  }
203
204
  if (_market.canBeBorrowed && _market.incentiveSupplyApy) {
@@ -209,6 +210,7 @@ function getAaveV3MarketData(web3, network, market, defaultWeb3) {
209
210
  _market.borrowIncentives.push({
210
211
  apy: _market.incentiveBorrowApy,
211
212
  token: _market.incentiveBorrowToken,
213
+ incentiveKind: 'reward',
212
214
  });
213
215
  }
214
216
  if (!rewardForMarket)
@@ -238,6 +240,7 @@ function getAaveV3MarketData(web3, network, market, defaultWeb3) {
238
240
  _market.supplyIncentives.push({
239
241
  token: supplyRewardData.rewardTokenSymbol,
240
242
  apy: rewardApy,
243
+ incentiveKind: 'reward',
241
244
  });
242
245
  }
243
246
  });
@@ -265,6 +268,7 @@ function getAaveV3MarketData(web3, network, market, defaultWeb3) {
265
268
  _market.borrowIncentives.push({
266
269
  token: borrowRewardData.rewardTokenSymbol,
267
270
  apy: rewardApy,
271
+ incentiveKind: 'reward',
268
272
  });
269
273
  }
270
274
  });
@@ -419,7 +423,7 @@ const getAaveV3AccountData = (web3, network, address, extractedState) => __await
419
423
  }
420
424
  if (!usedAssets[asset])
421
425
  usedAssets[asset] = {};
422
- const nativeAsset = asset === 'GHO';
426
+ const nativeAsset = asset === 'GHO' && network === common_1.NetworkNumber.Eth;
423
427
  let discountRateOnBorrow = '0';
424
428
  const borrowed = new decimal_js_1.default(borrowedStable).add(borrowedVariable).toString();
425
429
  if (nativeAsset && new decimal_js_1.default(borrowed).gt(0) && new decimal_js_1.default(stkAaveBalance).gt(0)) {
@@ -2280,6 +2280,9 @@ export namespace GHO {
2280
2280
  "1": {
2281
2281
  address: string;
2282
2282
  };
2283
+ "42161": {
2284
+ address: string;
2285
+ };
2283
2286
  };
2284
2287
  export { networks_15 as networks };
2285
2288
  }
@@ -312,6 +312,9 @@ module.exports = {
312
312
  "networks": {
313
313
  "1": {
314
314
  "address": "0x40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f"
315
+ },
316
+ "42161": {
317
+ "address": "0x7dfF72693f6A4149b17e7C6314655f6A9F7c8B33"
315
318
  }
316
319
  }
317
320
  },
@@ -115,7 +115,6 @@ const aaveAnyGetAggregatedPositionData = (_a) => {
115
115
  usedAssets,
116
116
  assetsData,
117
117
  isMorpho: (0, exports.isMorphoAave)({ selectedMarket }),
118
- network,
119
118
  });
120
119
  payload.netApy = netApy;
121
120
  payload.incentiveUsd = incentiveUsd;
@@ -12,3 +12,8 @@ export declare const getApyAfterValuesEstimation: (selectedMarket: MorphoBlueMar
12
12
  borrowRate: string;
13
13
  supplyRate: string;
14
14
  }>;
15
+ export declare const getReallocatableLiquidity: (marketId: string, network?: NetworkNumber) => Promise<string>;
16
+ export declare const getReallocation: (marketId: string, liquidityToAllocate: string, network?: NetworkNumber) => Promise<{
17
+ vaults: string[];
18
+ withdrawals: [string[], string][][];
19
+ }>;
@@ -12,13 +12,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.getApyAfterValuesEstimation = exports.getBorrowRate = exports.getSupplyRate = exports.getMorphoBlueAggregatedPositionData = void 0;
15
+ exports.getReallocation = exports.getReallocatableLiquidity = exports.getApyAfterValuesEstimation = exports.getBorrowRate = exports.getSupplyRate = exports.getMorphoBlueAggregatedPositionData = void 0;
16
16
  const decimal_js_1 = __importDefault(require("decimal.js"));
17
17
  const tokens_1 = require("@defisaver/tokens");
18
18
  const moneymarket_1 = require("../../moneymarket");
19
19
  const staking_1 = require("../../staking");
20
+ const common_1 = require("../../types/common");
20
21
  const constants_1 = require("../../constants");
21
22
  const contracts_1 = require("../../contracts");
23
+ const utils_1 = require("../../services/utils");
22
24
  const getMorphoBlueAggregatedPositionData = ({ usedAssets, assetsData, marketInfo }) => {
23
25
  var _a, _b, _c, _d, _e, _f;
24
26
  const payload = {};
@@ -110,3 +112,127 @@ const getApyAfterValuesEstimation = (selectedMarket, action, amount, asset, web3
110
112
  return { borrowRate, supplyRate };
111
113
  });
112
114
  exports.getApyAfterValuesEstimation = getApyAfterValuesEstimation;
115
+ const API_URL = 'https://blue-api.morpho.org/graphql';
116
+ const MARKET_QUERY = `
117
+ query MarketByUniqueKey($uniqueKey: String!, $chainId: Int!) {
118
+ marketByUniqueKey(uniqueKey: $uniqueKey, chainId: $chainId) {
119
+ reallocatableLiquidityAssets
120
+ loanAsset {
121
+ address
122
+ decimals
123
+ priceUsd
124
+ }
125
+ state {
126
+ liquidityAssets
127
+ }
128
+ publicAllocatorSharedLiquidity {
129
+ assets
130
+ vault {
131
+ address
132
+ name
133
+ }
134
+ allocationMarket {
135
+ uniqueKey
136
+ loanAsset {
137
+ address
138
+ }
139
+ collateralAsset {
140
+ address
141
+ }
142
+ irmAddress
143
+ oracle {
144
+ address
145
+ }
146
+ lltv
147
+ }
148
+ }
149
+ loanAsset {
150
+ address
151
+ }
152
+ collateralAsset {
153
+ address
154
+ }
155
+ oracle {
156
+ address
157
+ }
158
+ irmAddress
159
+ lltv
160
+ }
161
+ }
162
+ `;
163
+ const getReallocatableLiquidity = (marketId, network = common_1.NetworkNumber.Eth) => __awaiter(void 0, void 0, void 0, function* () {
164
+ var _a;
165
+ const response = yield fetch(API_URL, {
166
+ method: 'POST',
167
+ headers: { 'Content-Type': 'application/json' },
168
+ body: JSON.stringify({
169
+ query: MARKET_QUERY,
170
+ variables: { uniqueKey: marketId, chainId: network },
171
+ }),
172
+ });
173
+ const data = yield response.json();
174
+ const marketData = (_a = data === null || data === void 0 ? void 0 : data.data) === null || _a === void 0 ? void 0 : _a.marketByUniqueKey;
175
+ if (!marketData)
176
+ throw new Error('Market data not found');
177
+ return marketData.reallocatableLiquidityAssets;
178
+ });
179
+ exports.getReallocatableLiquidity = getReallocatableLiquidity;
180
+ const getReallocation = (marketId, liquidityToAllocate, network = common_1.NetworkNumber.Eth) => __awaiter(void 0, void 0, void 0, function* () {
181
+ var _b, _c, _d;
182
+ const response = yield fetch(API_URL, {
183
+ method: 'POST',
184
+ headers: { 'Content-Type': 'application/json' },
185
+ body: JSON.stringify({
186
+ query: MARKET_QUERY,
187
+ variables: { uniqueKey: marketId, chainId: network },
188
+ }),
189
+ });
190
+ const data = yield response.json();
191
+ const marketData = (_b = data === null || data === void 0 ? void 0 : data.data) === null || _b === void 0 ? void 0 : _b.marketByUniqueKey;
192
+ if (!marketData)
193
+ throw new Error('Market data not found');
194
+ if (new decimal_js_1.default(marketData.reallocatableLiquidityAssets).lt(liquidityToAllocate))
195
+ throw new Error('Not enough liquidity available to allocate');
196
+ const vaultTotalAssets = marketData.publicAllocatorSharedLiquidity.reduce((acc, item) => {
197
+ const vaultAddress = item.vault.address;
198
+ acc[vaultAddress] = new decimal_js_1.default(acc[vaultAddress] || '0').add(item.assets).toString();
199
+ return acc;
200
+ }, {});
201
+ const sortedVaults = Object.entries(vaultTotalAssets).sort(([, a], [, b]) => new decimal_js_1.default(b || '0').sub(a || '0').toNumber());
202
+ const withdrawalsPerVault = {};
203
+ let totalReallocated = '0';
204
+ for (const [vaultAddress] of sortedVaults) {
205
+ if (new decimal_js_1.default(totalReallocated).gte(liquidityToAllocate))
206
+ break;
207
+ const vaultAllocations = marketData.publicAllocatorSharedLiquidity.filter((item) => (0, utils_1.compareAddresses)(item.vault.address, vaultAddress));
208
+ for (const item of vaultAllocations) {
209
+ if (new decimal_js_1.default(totalReallocated).gte(liquidityToAllocate))
210
+ break;
211
+ const itemAmount = item.assets;
212
+ const leftToAllocate = new decimal_js_1.default(liquidityToAllocate).sub(totalReallocated).toString();
213
+ const amountToTake = new decimal_js_1.default(itemAmount).lt(leftToAllocate) ? itemAmount : leftToAllocate;
214
+ totalReallocated = new decimal_js_1.default(totalReallocated).add(amountToTake).toString();
215
+ const withdrawal = [
216
+ [
217
+ item.allocationMarket.loanAsset.address,
218
+ (_c = item.allocationMarket.collateralAsset) === null || _c === void 0 ? void 0 : _c.address,
219
+ (_d = item.allocationMarket.oracle) === null || _d === void 0 ? void 0 : _d.address,
220
+ item.allocationMarket.irmAddress,
221
+ item.allocationMarket.lltv,
222
+ ],
223
+ amountToTake.toString(),
224
+ ];
225
+ if (!withdrawalsPerVault[vaultAddress]) {
226
+ withdrawalsPerVault[vaultAddress] = [];
227
+ }
228
+ withdrawalsPerVault[vaultAddress].push(withdrawal);
229
+ }
230
+ }
231
+ const vaults = Object.keys(withdrawalsPerVault);
232
+ const withdrawals = vaults.map((vaultAddress) => withdrawalsPerVault[vaultAddress]);
233
+ return {
234
+ vaults,
235
+ withdrawals,
236
+ };
237
+ });
238
+ exports.getReallocation = getReallocation;
@@ -1,5 +1,5 @@
1
1
  import Web3 from 'web3';
2
- import { MMAssetsData, MMUsedAssets, NetworkNumber } from '../types/common';
2
+ import { MMAssetsData, MMUsedAssets } from '../types/common';
3
3
  export declare const getStETHApy: (web3: Web3, fromBlock?: number, blockNumber?: 'latest' | number) => Promise<string>;
4
4
  export declare const getCbETHApy: (web3: Web3, blockNumber?: 'latest' | number) => Promise<string>;
5
5
  export declare const getREthApy: (web3: Web3, blockNumber?: 'latest' | number) => Promise<string>;
@@ -8,11 +8,10 @@ export declare const getSsrApy: () => Promise<string>;
8
8
  export declare const STAKING_ASSETS: string[];
9
9
  export declare const getStakingApy: (asset: string, web3: Web3, blockNumber?: 'latest' | number, fromBlock?: number | undefined) => "0" | Promise<any> | undefined;
10
10
  export declare const calculateInterestEarned: (principal: string, interest: string, type: string, apy?: boolean) => number;
11
- export declare const calculateNetApy: ({ usedAssets, assetsData, isMorpho, network, }: {
11
+ export declare const calculateNetApy: ({ usedAssets, assetsData, isMorpho }: {
12
12
  usedAssets: MMUsedAssets;
13
13
  assetsData: MMAssetsData;
14
14
  isMorpho?: boolean | undefined;
15
- network?: NetworkNumber | undefined;
16
15
  }) => {
17
16
  netApy: string;
18
17
  totalInterestUsd: string;
@@ -170,7 +170,7 @@ const calculateInterestEarned = (principal, interest, type, apy = false) => {
170
170
  return (+principal * (Math.pow(((1 + (+interest / 100) / constants_1.BLOCKS_IN_A_YEAR)), (constants_1.BLOCKS_IN_A_YEAR * interval)))) - +principal; // eslint-disable-line
171
171
  };
172
172
  exports.calculateInterestEarned = calculateInterestEarned;
173
- const calculateNetApy = ({ usedAssets, assetsData, isMorpho = false, network = 1, }) => {
173
+ const calculateNetApy = ({ usedAssets, assetsData, isMorpho = false }) => {
174
174
  const sumValues = Object.values(usedAssets).reduce((_acc, usedAsset) => {
175
175
  const acc = Object.assign({}, _acc);
176
176
  const assetData = assetsData[usedAsset.symbol];
@@ -193,7 +193,7 @@ const calculateNetApy = ({ usedAssets, assetsData, isMorpho = false, network = 1
193
193
  acc.borrowedUsd = new decimal_js_1.default(acc.borrowedUsd).add(amount).toString();
194
194
  const rate = isMorpho
195
195
  ? usedAsset.borrowRate === '0' ? assetData.borrowRateP2P : usedAsset.borrowRate
196
- : (usedAsset.symbol === 'GHO' && network === common_1.NetworkNumber.Eth)
196
+ : (usedAsset.symbol === 'GHO' && assetsData.nativeAsset)
197
197
  ? usedAsset.discountedBorrowRate
198
198
  : ((usedAsset === null || usedAsset === void 0 ? void 0 : usedAsset.interestMode) === '1' ? usedAsset.stableBorrowRate : assetData.borrowRate);
199
199
  const borrowInterest = (0, exports.calculateInterestEarned)(amount, rate, 'year', true);
@@ -76,6 +76,7 @@ export interface MorphoAaveV2AssetData extends AaveV2AssetData {
76
76
  export interface IncentiveData {
77
77
  token: string;
78
78
  apy: string;
79
+ incentiveKind?: 'staking' | 'reward';
79
80
  }
80
81
  export interface AaveV3AssetData extends AaveAssetData {
81
82
  isIsolated: boolean;
@@ -137,3 +137,28 @@ export interface MorphoBluePositionData {
137
137
  supplyShares: string;
138
138
  borrowShares: string;
139
139
  }
140
+ export interface MorphoBlueVault {
141
+ address: string;
142
+ }
143
+ export interface MorphoBlueAllocationMarket {
144
+ loanAsset: {
145
+ address: string;
146
+ };
147
+ collateralAsset: {
148
+ address: string;
149
+ };
150
+ oracle: {
151
+ address: string;
152
+ };
153
+ irmAddress: string;
154
+ lltv: string;
155
+ }
156
+ export interface MorphoBluePublicAllocatorItem {
157
+ vault: MorphoBlueVault;
158
+ assets: string;
159
+ allocationMarket: MorphoBlueAllocationMarket;
160
+ }
161
+ export interface MorphoBlueRealloactionMarketData {
162
+ reallocatableLiquidityAssets: string;
163
+ publicAllocatorSharedLiquidity: MorphoBluePublicAllocatorItem[];
164
+ }
@@ -16,7 +16,7 @@ import { getStakingApy, STAKING_ASSETS } from '../staking';
16
16
  import { multicall } from '../multicall';
17
17
  import { getAssetsBalances } from '../assets';
18
18
  import { aprToApy, calculateBorrowingAssetLimit } from '../moneymarket';
19
- import { aaveAnyGetAggregatedPositionData, aaveV3IsInIsolationMode, aaveV3IsInSiloedMode, } from '../helpers/aaveHelpers';
19
+ import { aaveAnyGetAggregatedPositionData, aaveV3IsInIsolationMode, aaveV3IsInSiloedMode } from '../helpers/aaveHelpers';
20
20
  import { AAVE_V3 } from '../markets/aave';
21
21
  export const test = (web3, network) => {
22
22
  const contract = AaveV3ViewContract(web3, 1);
@@ -95,7 +95,7 @@ export function getAaveV3MarketData(web3, network, market, defaultWeb3) {
95
95
  params: [],
96
96
  },
97
97
  {
98
- target: getAssetInfo('GHO').address,
98
+ target: getAssetInfo('GHO', network).address,
99
99
  abiItem: getAbiItem(GhoTokenAbi, 'getFacilitatorsList'),
100
100
  params: [],
101
101
  },
@@ -139,7 +139,7 @@ export function getAaveV3MarketData(web3, network, market, defaultWeb3) {
139
139
  const assetsData = yield Promise.all(loanInfo
140
140
  .map((tokenMarket, i) => __awaiter(this, void 0, void 0, function* () {
141
141
  const symbol = market.assets[i];
142
- const nativeAsset = symbol === 'GHO';
142
+ const nativeAsset = symbol === 'GHO' && network === NetworkNumber.Eth;
143
143
  // eslint-disable-next-line guard-for-in
144
144
  for (const eModeIndex in eModeCategoriesData) {
145
145
  if (isEnabledOnBitmap(Number(eModeCategoriesData[eModeIndex].collateralBitmap), Number(tokenMarket.assetId)))
@@ -189,6 +189,7 @@ export function getAaveV3MarketData(web3, network, market, defaultWeb3) {
189
189
  _market.supplyIncentives.push({
190
190
  apy: _market.incentiveSupplyApy || '0',
191
191
  token: _market.symbol,
192
+ incentiveKind: 'staking',
192
193
  });
193
194
  }
194
195
  if (_market.canBeBorrowed && _market.incentiveSupplyApy) {
@@ -200,6 +201,7 @@ export function getAaveV3MarketData(web3, network, market, defaultWeb3) {
200
201
  _market.borrowIncentives.push({
201
202
  apy: _market.incentiveBorrowApy,
202
203
  token: _market.incentiveBorrowToken,
204
+ incentiveKind: 'reward',
203
205
  });
204
206
  }
205
207
  if (!rewardForMarket)
@@ -229,6 +231,7 @@ export function getAaveV3MarketData(web3, network, market, defaultWeb3) {
229
231
  _market.supplyIncentives.push({
230
232
  token: supplyRewardData.rewardTokenSymbol,
231
233
  apy: rewardApy,
234
+ incentiveKind: 'reward',
232
235
  });
233
236
  }
234
237
  });
@@ -256,6 +259,7 @@ export function getAaveV3MarketData(web3, network, market, defaultWeb3) {
256
259
  _market.borrowIncentives.push({
257
260
  token: borrowRewardData.rewardTokenSymbol,
258
261
  apy: rewardApy,
262
+ incentiveKind: 'reward',
259
263
  });
260
264
  }
261
265
  });
@@ -408,7 +412,7 @@ export const getAaveV3AccountData = (web3, network, address, extractedState) =>
408
412
  }
409
413
  if (!usedAssets[asset])
410
414
  usedAssets[asset] = {};
411
- const nativeAsset = asset === 'GHO';
415
+ const nativeAsset = asset === 'GHO' && network === NetworkNumber.Eth;
412
416
  let discountRateOnBorrow = '0';
413
417
  const borrowed = new Dec(borrowedStable).add(borrowedVariable).toString();
414
418
  if (nativeAsset && new Dec(borrowed).gt(0) && new Dec(stkAaveBalance).gt(0)) {
@@ -2280,6 +2280,9 @@ export namespace GHO {
2280
2280
  "1": {
2281
2281
  address: string;
2282
2282
  };
2283
+ "42161": {
2284
+ address: string;
2285
+ };
2283
2286
  };
2284
2287
  export { networks_15 as networks };
2285
2288
  }
@@ -311,6 +311,9 @@ module.exports = {
311
311
  "networks": {
312
312
  "1": {
313
313
  "address": "0x40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f"
314
+ },
315
+ "42161": {
316
+ "address": "0x7dfF72693f6A4149b17e7C6314655f6A9F7c8B33"
314
317
  }
315
318
  }
316
319
  },
@@ -98,7 +98,6 @@ export const aaveAnyGetAggregatedPositionData = (_a) => {
98
98
  usedAssets,
99
99
  assetsData,
100
100
  isMorpho: isMorphoAave({ selectedMarket }),
101
- network,
102
101
  });
103
102
  payload.netApy = netApy;
104
103
  payload.incentiveUsd = incentiveUsd;
@@ -12,3 +12,8 @@ export declare const getApyAfterValuesEstimation: (selectedMarket: MorphoBlueMar
12
12
  borrowRate: string;
13
13
  supplyRate: string;
14
14
  }>;
15
+ export declare const getReallocatableLiquidity: (marketId: string, network?: NetworkNumber) => Promise<string>;
16
+ export declare const getReallocation: (marketId: string, liquidityToAllocate: string, network?: NetworkNumber) => Promise<{
17
+ vaults: string[];
18
+ withdrawals: [string[], string][][];
19
+ }>;
@@ -11,8 +11,10 @@ import Dec from 'decimal.js';
11
11
  import { assetAmountInWei } from '@defisaver/tokens';
12
12
  import { calcLeverageLiqPrice, getAssetsTotal, isLeveragedPos } from '../../moneymarket';
13
13
  import { calculateNetApy } from '../../staking';
14
+ import { NetworkNumber } from '../../types/common';
14
15
  import { borrowOperations, SECONDS_PER_YEAR, WAD } from '../../constants';
15
16
  import { MorphoBlueViewContract } from '../../contracts';
17
+ import { compareAddresses } from '../../services/utils';
16
18
  export const getMorphoBlueAggregatedPositionData = ({ usedAssets, assetsData, marketInfo }) => {
17
19
  var _a, _b, _c, _d, _e, _f;
18
20
  const payload = {};
@@ -100,3 +102,125 @@ export const getApyAfterValuesEstimation = (selectedMarket, action, amount, asse
100
102
  const supplyRate = getSupplyRate(data.market.totalSupplyAssets, data.market.totalBorrowAssets, data.borrowRate, data.market.fee);
101
103
  return { borrowRate, supplyRate };
102
104
  });
105
+ const API_URL = 'https://blue-api.morpho.org/graphql';
106
+ const MARKET_QUERY = `
107
+ query MarketByUniqueKey($uniqueKey: String!, $chainId: Int!) {
108
+ marketByUniqueKey(uniqueKey: $uniqueKey, chainId: $chainId) {
109
+ reallocatableLiquidityAssets
110
+ loanAsset {
111
+ address
112
+ decimals
113
+ priceUsd
114
+ }
115
+ state {
116
+ liquidityAssets
117
+ }
118
+ publicAllocatorSharedLiquidity {
119
+ assets
120
+ vault {
121
+ address
122
+ name
123
+ }
124
+ allocationMarket {
125
+ uniqueKey
126
+ loanAsset {
127
+ address
128
+ }
129
+ collateralAsset {
130
+ address
131
+ }
132
+ irmAddress
133
+ oracle {
134
+ address
135
+ }
136
+ lltv
137
+ }
138
+ }
139
+ loanAsset {
140
+ address
141
+ }
142
+ collateralAsset {
143
+ address
144
+ }
145
+ oracle {
146
+ address
147
+ }
148
+ irmAddress
149
+ lltv
150
+ }
151
+ }
152
+ `;
153
+ export const getReallocatableLiquidity = (marketId, network = NetworkNumber.Eth) => __awaiter(void 0, void 0, void 0, function* () {
154
+ var _a;
155
+ const response = yield fetch(API_URL, {
156
+ method: 'POST',
157
+ headers: { 'Content-Type': 'application/json' },
158
+ body: JSON.stringify({
159
+ query: MARKET_QUERY,
160
+ variables: { uniqueKey: marketId, chainId: network },
161
+ }),
162
+ });
163
+ const data = yield response.json();
164
+ const marketData = (_a = data === null || data === void 0 ? void 0 : data.data) === null || _a === void 0 ? void 0 : _a.marketByUniqueKey;
165
+ if (!marketData)
166
+ throw new Error('Market data not found');
167
+ return marketData.reallocatableLiquidityAssets;
168
+ });
169
+ export const getReallocation = (marketId, liquidityToAllocate, network = NetworkNumber.Eth) => __awaiter(void 0, void 0, void 0, function* () {
170
+ var _b, _c, _d;
171
+ const response = yield fetch(API_URL, {
172
+ method: 'POST',
173
+ headers: { 'Content-Type': 'application/json' },
174
+ body: JSON.stringify({
175
+ query: MARKET_QUERY,
176
+ variables: { uniqueKey: marketId, chainId: network },
177
+ }),
178
+ });
179
+ const data = yield response.json();
180
+ const marketData = (_b = data === null || data === void 0 ? void 0 : data.data) === null || _b === void 0 ? void 0 : _b.marketByUniqueKey;
181
+ if (!marketData)
182
+ throw new Error('Market data not found');
183
+ if (new Dec(marketData.reallocatableLiquidityAssets).lt(liquidityToAllocate))
184
+ throw new Error('Not enough liquidity available to allocate');
185
+ const vaultTotalAssets = marketData.publicAllocatorSharedLiquidity.reduce((acc, item) => {
186
+ const vaultAddress = item.vault.address;
187
+ acc[vaultAddress] = new Dec(acc[vaultAddress] || '0').add(item.assets).toString();
188
+ return acc;
189
+ }, {});
190
+ const sortedVaults = Object.entries(vaultTotalAssets).sort(([, a], [, b]) => new Dec(b || '0').sub(a || '0').toNumber());
191
+ const withdrawalsPerVault = {};
192
+ let totalReallocated = '0';
193
+ for (const [vaultAddress] of sortedVaults) {
194
+ if (new Dec(totalReallocated).gte(liquidityToAllocate))
195
+ break;
196
+ const vaultAllocations = marketData.publicAllocatorSharedLiquidity.filter((item) => compareAddresses(item.vault.address, vaultAddress));
197
+ for (const item of vaultAllocations) {
198
+ if (new Dec(totalReallocated).gte(liquidityToAllocate))
199
+ break;
200
+ const itemAmount = item.assets;
201
+ const leftToAllocate = new Dec(liquidityToAllocate).sub(totalReallocated).toString();
202
+ const amountToTake = new Dec(itemAmount).lt(leftToAllocate) ? itemAmount : leftToAllocate;
203
+ totalReallocated = new Dec(totalReallocated).add(amountToTake).toString();
204
+ const withdrawal = [
205
+ [
206
+ item.allocationMarket.loanAsset.address,
207
+ (_c = item.allocationMarket.collateralAsset) === null || _c === void 0 ? void 0 : _c.address,
208
+ (_d = item.allocationMarket.oracle) === null || _d === void 0 ? void 0 : _d.address,
209
+ item.allocationMarket.irmAddress,
210
+ item.allocationMarket.lltv,
211
+ ],
212
+ amountToTake.toString(),
213
+ ];
214
+ if (!withdrawalsPerVault[vaultAddress]) {
215
+ withdrawalsPerVault[vaultAddress] = [];
216
+ }
217
+ withdrawalsPerVault[vaultAddress].push(withdrawal);
218
+ }
219
+ }
220
+ const vaults = Object.keys(withdrawalsPerVault);
221
+ const withdrawals = vaults.map((vaultAddress) => withdrawalsPerVault[vaultAddress]);
222
+ return {
223
+ vaults,
224
+ withdrawals,
225
+ };
226
+ });
@@ -1,5 +1,5 @@
1
1
  import Web3 from 'web3';
2
- import { MMAssetsData, MMUsedAssets, NetworkNumber } from '../types/common';
2
+ import { MMAssetsData, MMUsedAssets } from '../types/common';
3
3
  export declare const getStETHApy: (web3: Web3, fromBlock?: number, blockNumber?: 'latest' | number) => Promise<string>;
4
4
  export declare const getCbETHApy: (web3: Web3, blockNumber?: 'latest' | number) => Promise<string>;
5
5
  export declare const getREthApy: (web3: Web3, blockNumber?: 'latest' | number) => Promise<string>;
@@ -8,11 +8,10 @@ export declare const getSsrApy: () => Promise<string>;
8
8
  export declare const STAKING_ASSETS: string[];
9
9
  export declare const getStakingApy: (asset: string, web3: Web3, blockNumber?: 'latest' | number, fromBlock?: number | undefined) => "0" | Promise<any> | undefined;
10
10
  export declare const calculateInterestEarned: (principal: string, interest: string, type: string, apy?: boolean) => number;
11
- export declare const calculateNetApy: ({ usedAssets, assetsData, isMorpho, network, }: {
11
+ export declare const calculateNetApy: ({ usedAssets, assetsData, isMorpho }: {
12
12
  usedAssets: MMUsedAssets;
13
13
  assetsData: MMAssetsData;
14
14
  isMorpho?: boolean | undefined;
15
- network?: NetworkNumber | undefined;
16
15
  }) => {
17
16
  netApy: string;
18
17
  totalInterestUsd: string;
@@ -157,7 +157,7 @@ export const calculateInterestEarned = (principal, interest, type, apy = false)
157
157
  }
158
158
  return (+principal * (Math.pow(((1 + (+interest / 100) / BLOCKS_IN_A_YEAR)), (BLOCKS_IN_A_YEAR * interval)))) - +principal; // eslint-disable-line
159
159
  };
160
- export const calculateNetApy = ({ usedAssets, assetsData, isMorpho = false, network = 1, }) => {
160
+ export const calculateNetApy = ({ usedAssets, assetsData, isMorpho = false }) => {
161
161
  const sumValues = Object.values(usedAssets).reduce((_acc, usedAsset) => {
162
162
  const acc = Object.assign({}, _acc);
163
163
  const assetData = assetsData[usedAsset.symbol];
@@ -180,7 +180,7 @@ export const calculateNetApy = ({ usedAssets, assetsData, isMorpho = false, netw
180
180
  acc.borrowedUsd = new Dec(acc.borrowedUsd).add(amount).toString();
181
181
  const rate = isMorpho
182
182
  ? usedAsset.borrowRate === '0' ? assetData.borrowRateP2P : usedAsset.borrowRate
183
- : (usedAsset.symbol === 'GHO' && network === NetworkNumber.Eth)
183
+ : (usedAsset.symbol === 'GHO' && assetsData.nativeAsset)
184
184
  ? usedAsset.discountedBorrowRate
185
185
  : ((usedAsset === null || usedAsset === void 0 ? void 0 : usedAsset.interestMode) === '1' ? usedAsset.stableBorrowRate : assetData.borrowRate);
186
186
  const borrowInterest = calculateInterestEarned(amount, rate, 'year', true);
@@ -76,6 +76,7 @@ export interface MorphoAaveV2AssetData extends AaveV2AssetData {
76
76
  export interface IncentiveData {
77
77
  token: string;
78
78
  apy: string;
79
+ incentiveKind?: 'staking' | 'reward';
79
80
  }
80
81
  export interface AaveV3AssetData extends AaveAssetData {
81
82
  isIsolated: boolean;
@@ -137,3 +137,28 @@ export interface MorphoBluePositionData {
137
137
  supplyShares: string;
138
138
  borrowShares: string;
139
139
  }
140
+ export interface MorphoBlueVault {
141
+ address: string;
142
+ }
143
+ export interface MorphoBlueAllocationMarket {
144
+ loanAsset: {
145
+ address: string;
146
+ };
147
+ collateralAsset: {
148
+ address: string;
149
+ };
150
+ oracle: {
151
+ address: string;
152
+ };
153
+ irmAddress: string;
154
+ lltv: string;
155
+ }
156
+ export interface MorphoBluePublicAllocatorItem {
157
+ vault: MorphoBlueVault;
158
+ assets: string;
159
+ allocationMarket: MorphoBlueAllocationMarket;
160
+ }
161
+ export interface MorphoBlueRealloactionMarketData {
162
+ reallocatableLiquidityAssets: string;
163
+ publicAllocatorSharedLiquidity: MorphoBluePublicAllocatorItem[];
164
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defisaver/positions-sdk",
3
- "version": "0.0.181",
3
+ "version": "0.0.183-dev-allocator",
4
4
  "description": "",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./esm/index.js",
@@ -34,11 +34,7 @@ import { multicall } from '../multicall';
34
34
  import { IUiIncentiveDataProviderV3 } from '../types/contracts/generated/AaveUiIncentiveDataProviderV3';
35
35
  import { getAssetsBalances } from '../assets';
36
36
  import { aprToApy, calculateBorrowingAssetLimit } from '../moneymarket';
37
- import {
38
- aaveAnyGetAggregatedPositionData,
39
- aaveV3IsInIsolationMode,
40
- aaveV3IsInSiloedMode,
41
- } from '../helpers/aaveHelpers';
37
+ import { aaveAnyGetAggregatedPositionData, aaveV3IsInIsolationMode, aaveV3IsInSiloedMode } from '../helpers/aaveHelpers';
42
38
  import { AAVE_V3 } from '../markets/aave';
43
39
 
44
40
  export const test = (web3: Web3, network: NetworkNumber) => {
@@ -137,7 +133,7 @@ export async function getAaveV3MarketData(web3: Web3, network: NetworkNumber, ma
137
133
  params: [],
138
134
  },
139
135
  {
140
- target: getAssetInfo('GHO').address,
136
+ target: getAssetInfo('GHO', network).address,
141
137
  abiItem: getAbiItem(GhoTokenAbi, 'getFacilitatorsList'),
142
138
  params: [],
143
139
  },
@@ -191,7 +187,7 @@ export async function getAaveV3MarketData(web3: Web3, network: NetworkNumber, ma
191
187
  const assetsData: AaveV3AssetData[] = await Promise.all(loanInfo
192
188
  .map(async (tokenMarket, i) => {
193
189
  const symbol = market.assets[i];
194
- const nativeAsset = symbol === 'GHO';
190
+ const nativeAsset = symbol === 'GHO' && network === NetworkNumber.Eth;
195
191
 
196
192
  // eslint-disable-next-line guard-for-in
197
193
  for (const eModeIndex in eModeCategoriesData) {
@@ -290,6 +286,7 @@ export async function getAaveV3MarketData(web3: Web3, network: NetworkNumber, ma
290
286
  _market.supplyIncentives.push({
291
287
  apy: _market.incentiveSupplyApy || '0',
292
288
  token: _market.symbol,
289
+ incentiveKind: 'staking',
293
290
  });
294
291
  }
295
292
 
@@ -302,6 +299,7 @@ export async function getAaveV3MarketData(web3: Web3, network: NetworkNumber, ma
302
299
  _market.borrowIncentives.push({
303
300
  apy: _market.incentiveBorrowApy,
304
301
  token: _market.incentiveBorrowToken!!,
302
+ incentiveKind: 'reward',
305
303
  });
306
304
  }
307
305
 
@@ -330,6 +328,7 @@ export async function getAaveV3MarketData(web3: Web3, network: NetworkNumber, ma
330
328
  _market.supplyIncentives.push({
331
329
  token: supplyRewardData.rewardTokenSymbol,
332
330
  apy: rewardApy,
331
+ incentiveKind: 'reward',
333
332
  });
334
333
  }
335
334
  });
@@ -356,6 +355,7 @@ export async function getAaveV3MarketData(web3: Web3, network: NetworkNumber, ma
356
355
  _market.borrowIncentives.push({
357
356
  token: borrowRewardData.rewardTokenSymbol,
358
357
  apy: rewardApy,
358
+ incentiveKind: 'reward',
359
359
  });
360
360
  }
361
361
  });
@@ -543,7 +543,7 @@ export const getAaveV3AccountData = async (web3: Web3, network: NetworkNumber, a
543
543
  interestMode = 'both';
544
544
  }
545
545
  if (!usedAssets[asset]) usedAssets[asset] = {} as AaveV3UsedAsset;
546
- const nativeAsset = asset === 'GHO';
546
+ const nativeAsset = asset === 'GHO' && network === NetworkNumber.Eth;
547
547
 
548
548
  let discountRateOnBorrow = '0';
549
549
  const borrowed = new Dec(borrowedStable).add(borrowedVariable).toString();
@@ -312,6 +312,9 @@ module.exports = {
312
312
  "networks": {
313
313
  "1": {
314
314
  "address": "0x40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f"
315
+ },
316
+ "42161": {
317
+ "address": "0x7dfF72693f6A4149b17e7C6314655f6A9F7c8B33"
315
318
  }
316
319
  }
317
320
  },
@@ -129,7 +129,6 @@ export const aaveAnyGetAggregatedPositionData = ({
129
129
  usedAssets,
130
130
  assetsData,
131
131
  isMorpho: isMorphoAave({ selectedMarket }),
132
- network,
133
132
  });
134
133
  payload.netApy = netApy;
135
134
  payload.incentiveUsd = incentiveUsd;
@@ -1,15 +1,18 @@
1
1
  import Dec from 'decimal.js';
2
- import { assetAmountInWei } from '@defisaver/tokens';
2
+ import { assetAmountInWei, getAssetInfoByAddress } from '@defisaver/tokens';
3
3
  import Web3 from 'web3';
4
4
  import { calcLeverageLiqPrice, getAssetsTotal, isLeveragedPos } from '../../moneymarket';
5
5
  import { calculateNetApy } from '../../staking';
6
6
  import { MMAssetsData, MMUsedAssets, NetworkNumber } from '../../types/common';
7
7
  import {
8
8
  MorphoBlueAggregatedPositionData, MorphoBlueAssetsData, MorphoBlueMarketData, MorphoBlueMarketInfo,
9
+ MorphoBluePublicAllocatorItem,
10
+ MorphoBlueRealloactionMarketData,
9
11
  } from '../../types';
10
12
  import { borrowOperations, SECONDS_PER_YEAR, WAD } from '../../constants';
11
13
  import { MorphoBlueViewContract } from '../../contracts';
12
14
  import { MarketParamsStruct } from '../../types/contracts/generated/MorphoBlueView';
15
+ import { compareAddresses } from '../../services/utils';
13
16
 
14
17
  export const getMorphoBlueAggregatedPositionData = ({ usedAssets, assetsData, marketInfo }: { usedAssets: MMUsedAssets, assetsData: MorphoBlueAssetsData, marketInfo: MorphoBlueMarketInfo }): MorphoBlueAggregatedPositionData => {
15
18
  const payload = {} as MorphoBlueAggregatedPositionData;
@@ -113,4 +116,142 @@ export const getApyAfterValuesEstimation = async (selectedMarket: MorphoBlueMark
113
116
  const borrowRate = getBorrowRate(data.borrowRate, data.market.totalBorrowShares);
114
117
  const supplyRate = getSupplyRate(data.market.totalSupplyAssets, data.market.totalBorrowAssets, data.borrowRate, data.market.fee);
115
118
  return { borrowRate, supplyRate };
119
+ };
120
+
121
+ const API_URL = 'https://blue-api.morpho.org/graphql';
122
+ const MARKET_QUERY = `
123
+ query MarketByUniqueKey($uniqueKey: String!, $chainId: Int!) {
124
+ marketByUniqueKey(uniqueKey: $uniqueKey, chainId: $chainId) {
125
+ reallocatableLiquidityAssets
126
+ loanAsset {
127
+ address
128
+ decimals
129
+ priceUsd
130
+ }
131
+ state {
132
+ liquidityAssets
133
+ }
134
+ publicAllocatorSharedLiquidity {
135
+ assets
136
+ vault {
137
+ address
138
+ name
139
+ }
140
+ allocationMarket {
141
+ uniqueKey
142
+ loanAsset {
143
+ address
144
+ }
145
+ collateralAsset {
146
+ address
147
+ }
148
+ irmAddress
149
+ oracle {
150
+ address
151
+ }
152
+ lltv
153
+ }
154
+ }
155
+ loanAsset {
156
+ address
157
+ }
158
+ collateralAsset {
159
+ address
160
+ }
161
+ oracle {
162
+ address
163
+ }
164
+ irmAddress
165
+ lltv
166
+ }
167
+ }
168
+ `;
169
+
170
+ export const getReallocatableLiquidity = async (marketId: string, network: NetworkNumber = NetworkNumber.Eth): Promise<string> => {
171
+ const response = await fetch(API_URL, {
172
+ method: 'POST',
173
+ headers: { 'Content-Type': 'application/json' },
174
+ body: JSON.stringify({
175
+ query: MARKET_QUERY,
176
+ variables: { uniqueKey: marketId, chainId: network },
177
+ }),
178
+ });
179
+
180
+ const data: { data: { marketByUniqueKey: MorphoBlueRealloactionMarketData } } = await response.json();
181
+ const marketData: MorphoBlueRealloactionMarketData = data?.data?.marketByUniqueKey;
182
+
183
+ if (!marketData) throw new Error('Market data not found');
184
+
185
+ return marketData.reallocatableLiquidityAssets;
186
+ };
187
+
188
+ export const getReallocation = async (marketId: string, liquidityToAllocate: string, network: NetworkNumber = NetworkNumber.Eth) => {
189
+ const response = await fetch(API_URL, {
190
+ method: 'POST',
191
+ headers: { 'Content-Type': 'application/json' },
192
+ body: JSON.stringify({
193
+ query: MARKET_QUERY,
194
+ variables: { uniqueKey: marketId, chainId: network },
195
+ }),
196
+ });
197
+
198
+ const data: { data: { marketByUniqueKey: MorphoBlueRealloactionMarketData } } = await response.json();
199
+ const marketData: MorphoBlueRealloactionMarketData = data?.data?.marketByUniqueKey;
200
+
201
+ if (!marketData) throw new Error('Market data not found');
202
+
203
+ if (new Dec(marketData.reallocatableLiquidityAssets).lt(liquidityToAllocate)) throw new Error('Not enough liquidity available to allocate');
204
+
205
+ const vaultTotalAssets = marketData.publicAllocatorSharedLiquidity.reduce(
206
+ (acc: Record<string, string>, item: MorphoBluePublicAllocatorItem) => {
207
+ const vaultAddress = item.vault.address;
208
+ acc[vaultAddress] = new Dec(acc[vaultAddress] || '0').add(item.assets).toString();
209
+ return acc;
210
+ },
211
+ {},
212
+ );
213
+
214
+ const sortedVaults = Object.entries(vaultTotalAssets).sort(
215
+ ([, a]: [string, string], [, b]: [string, string]) => new Dec(b || '0').sub(a || '0').toNumber(),
216
+ );
217
+
218
+ const withdrawalsPerVault: Record<string, [string[], string][]> = {};
219
+ let totalReallocated = '0';
220
+ for (const [vaultAddress] of sortedVaults) {
221
+ if (new Dec(totalReallocated).gte(liquidityToAllocate)) break;
222
+
223
+ const vaultAllocations = marketData.publicAllocatorSharedLiquidity.filter(
224
+ (item: MorphoBluePublicAllocatorItem) => compareAddresses(item.vault.address, vaultAddress),
225
+ );
226
+ for (const item of vaultAllocations) {
227
+ if (new Dec(totalReallocated).gte(liquidityToAllocate)) break;
228
+ const itemAmount = item.assets;
229
+ const leftToAllocate = new Dec(liquidityToAllocate).sub(totalReallocated).toString();
230
+ const amountToTake = new Dec(itemAmount).lt(leftToAllocate) ? itemAmount : leftToAllocate;
231
+ totalReallocated = new Dec(totalReallocated).add(amountToTake).toString();
232
+ const withdrawal: [string[], string] = [
233
+ [
234
+ item.allocationMarket.loanAsset.address,
235
+ item.allocationMarket.collateralAsset?.address,
236
+ item.allocationMarket.oracle?.address,
237
+ item.allocationMarket.irmAddress,
238
+ item.allocationMarket.lltv,
239
+ ],
240
+ amountToTake.toString(),
241
+ ];
242
+ if (!withdrawalsPerVault[vaultAddress]) {
243
+ withdrawalsPerVault[vaultAddress] = [];
244
+ }
245
+ withdrawalsPerVault[vaultAddress].push(withdrawal);
246
+ }
247
+ }
248
+
249
+ const vaults = Object.keys(withdrawalsPerVault);
250
+ const withdrawals = vaults.map(
251
+ (vaultAddress) => withdrawalsPerVault[vaultAddress],
252
+ );
253
+ return {
254
+ vaults,
255
+ withdrawals,
256
+ };
116
257
  };
@@ -151,9 +151,7 @@ export const calculateInterestEarned = (principal: string, interest: string, typ
151
151
  return (+principal * (((1 + (+interest / 100) / BLOCKS_IN_A_YEAR)) ** (BLOCKS_IN_A_YEAR * interval))) - +principal; // eslint-disable-line
152
152
  };
153
153
 
154
- export const calculateNetApy = ({
155
- usedAssets, assetsData, isMorpho = false, network = 1,
156
- }: { usedAssets: MMUsedAssets, assetsData: MMAssetsData, isMorpho?: boolean, network?: NetworkNumber }) => {
154
+ export const calculateNetApy = ({ usedAssets, assetsData, isMorpho = false }: { usedAssets: MMUsedAssets, assetsData: MMAssetsData, isMorpho?: boolean }) => {
157
155
  const sumValues = Object.values(usedAssets).reduce((_acc, usedAsset) => {
158
156
  const acc = { ..._acc };
159
157
  const assetData = assetsData[usedAsset.symbol];
@@ -178,7 +176,7 @@ export const calculateNetApy = ({
178
176
  acc.borrowedUsd = new Dec(acc.borrowedUsd).add(amount).toString();
179
177
  const rate = isMorpho
180
178
  ? usedAsset.borrowRate === '0' ? assetData.borrowRateP2P : usedAsset.borrowRate
181
- : (usedAsset.symbol === 'GHO' && network === NetworkNumber.Eth)
179
+ : (usedAsset.symbol === 'GHO' && assetsData.nativeAsset)
182
180
  ? usedAsset.discountedBorrowRate
183
181
  : (usedAsset?.interestMode === '1' ? usedAsset.stableBorrowRate : assetData.borrowRate);
184
182
  const borrowInterest = calculateInterestEarned(amount, rate as string, 'year', true);
package/src/types/aave.ts CHANGED
@@ -87,6 +87,7 @@ export interface MorphoAaveV2AssetData extends AaveV2AssetData {
87
87
  export interface IncentiveData {
88
88
  token: string,
89
89
  apy: string,
90
+ incentiveKind?: 'staking' | 'reward';
90
91
  }
91
92
 
92
93
  export interface AaveV3AssetData extends AaveAssetData {
@@ -152,3 +152,26 @@ export interface MorphoBluePositionData {
152
152
  supplyShares: string,
153
153
  borrowShares: string,
154
154
  }
155
+
156
+ export interface MorphoBlueVault {
157
+ address: string,
158
+ }
159
+
160
+ export interface MorphoBlueAllocationMarket {
161
+ loanAsset: { address: string },
162
+ collateralAsset: { address: string },
163
+ oracle: { address: string },
164
+ irmAddress: string,
165
+ lltv: string,
166
+ }
167
+
168
+ export interface MorphoBluePublicAllocatorItem {
169
+ vault: MorphoBlueVault,
170
+ assets: string,
171
+ allocationMarket: MorphoBlueAllocationMarket,
172
+ }
173
+
174
+ export interface MorphoBlueRealloactionMarketData {
175
+ reallocatableLiquidityAssets: string,
176
+ publicAllocatorSharedLiquidity: MorphoBluePublicAllocatorItem[],
177
+ }