@defisaver/positions-sdk 0.0.186 → 0.0.188-dev-markets
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.
- package/cjs/compoundV3/index.js +14 -9
- package/cjs/config/contracts.d.ts +670 -228
- package/cjs/config/contracts.js +41 -5
- package/cjs/contracts.d.ts +2 -0
- package/cjs/contracts.js +3 -1
- package/cjs/helpers/morphoBlueHelpers/index.d.ts +42 -1
- package/cjs/helpers/morphoBlueHelpers/index.js +203 -20
- package/cjs/markets/compound/index.d.ts +4 -0
- package/cjs/markets/compound/index.js +41 -1
- package/cjs/markets/compound/marketsAssets.d.ts +14 -0
- package/cjs/markets/compound/marketsAssets.js +17 -3
- package/cjs/markets/morphoBlue/index.d.ts +8 -0
- package/cjs/markets/morphoBlue/index.js +71 -2
- package/cjs/morphoBlue/index.js +27 -10
- package/cjs/services/priceService.d.ts +3 -0
- package/cjs/services/priceService.js +33 -1
- package/cjs/types/compound.d.ts +3 -1
- package/cjs/types/compound.js +2 -0
- package/cjs/types/contracts/generated/CUSDSv3.d.ts +441 -0
- package/cjs/types/contracts/generated/CUSDSv3.js +5 -0
- package/cjs/types/contracts/generated/CWstETHv3.d.ts +441 -0
- package/cjs/types/contracts/generated/CWstETHv3.js +5 -0
- package/cjs/types/contracts/generated/DFSFeedRegistry.d.ts +40 -0
- package/cjs/types/contracts/generated/DFSFeedRegistry.js +5 -0
- package/cjs/types/contracts/generated/MorphoBlueView.d.ts +5 -5
- package/cjs/types/contracts/generated/WstETHPriceFeed.d.ts +39 -0
- package/cjs/types/contracts/generated/WstETHPriceFeed.js +5 -0
- package/cjs/types/contracts/generated/index.d.ts +4 -0
- package/cjs/types/morphoBlue.d.ts +37 -1
- package/cjs/types/morphoBlue.js +4 -0
- package/esm/compoundV3/index.js +15 -10
- package/esm/config/contracts.d.ts +670 -228
- package/esm/config/contracts.js +41 -5
- package/esm/contracts.d.ts +2 -0
- package/esm/contracts.js +2 -0
- package/esm/helpers/morphoBlueHelpers/index.d.ts +42 -1
- package/esm/helpers/morphoBlueHelpers/index.js +200 -20
- package/esm/markets/compound/index.d.ts +4 -0
- package/esm/markets/compound/index.js +39 -1
- package/esm/markets/compound/marketsAssets.d.ts +14 -0
- package/esm/markets/compound/marketsAssets.js +16 -2
- package/esm/markets/morphoBlue/index.d.ts +8 -0
- package/esm/markets/morphoBlue/index.js +65 -1
- package/esm/morphoBlue/index.js +30 -13
- package/esm/services/priceService.d.ts +3 -0
- package/esm/services/priceService.js +31 -1
- package/esm/types/compound.d.ts +3 -1
- package/esm/types/compound.js +2 -0
- package/esm/types/contracts/generated/CUSDSv3.d.ts +441 -0
- package/esm/types/contracts/generated/CUSDSv3.js +4 -0
- package/esm/types/contracts/generated/CWstETHv3.d.ts +441 -0
- package/esm/types/contracts/generated/CWstETHv3.js +4 -0
- package/esm/types/contracts/generated/DFSFeedRegistry.d.ts +40 -0
- package/esm/types/contracts/generated/DFSFeedRegistry.js +4 -0
- package/esm/types/contracts/generated/MorphoBlueView.d.ts +5 -5
- package/esm/types/contracts/generated/WstETHPriceFeed.d.ts +39 -0
- package/esm/types/contracts/generated/WstETHPriceFeed.js +4 -0
- package/esm/types/contracts/generated/index.d.ts +4 -0
- package/esm/types/morphoBlue.d.ts +37 -1
- package/esm/types/morphoBlue.js +4 -0
- package/package.json +2 -2
- package/src/compoundV3/index.ts +20 -11
- package/src/config/contracts.js +41 -5
- package/src/contracts.ts +2 -0
- package/src/helpers/morphoBlueHelpers/index.ts +228 -19
- package/src/markets/compound/index.ts +42 -2
- package/src/markets/compound/marketsAssets.ts +20 -2
- package/src/markets/morphoBlue/index.ts +70 -1
- package/src/morphoBlue/index.ts +33 -16
- package/src/services/priceService.ts +41 -2
- package/src/types/compound.ts +2 -0
- package/src/types/contracts/generated/CUSDSv3.ts +685 -0
- package/src/types/contracts/generated/CWstETHv3.ts +685 -0
- package/src/types/contracts/generated/DFSFeedRegistry.ts +77 -0
- package/src/types/contracts/generated/MorphoBlueView.ts +9 -5
- package/src/types/contracts/generated/WstETHPriceFeed.ts +59 -0
- package/src/types/contracts/generated/index.ts +4 -0
- package/src/types/morphoBlue.ts +35 -0
|
@@ -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;
|
|
@@ -89,28 +92,234 @@ export const getBorrowRate = (borrowRate: string, totalBorrowShares: string) =>
|
|
|
89
92
|
return new Dec(compound(borrowRate)).div(1e18).mul(100).toString();
|
|
90
93
|
};
|
|
91
94
|
|
|
92
|
-
export const getApyAfterValuesEstimation = async (selectedMarket: MorphoBlueMarketData, action: string, amount: string, asset: string, web3: Web3, network: NetworkNumber) => {
|
|
95
|
+
export const getApyAfterValuesEstimation = async (selectedMarket: MorphoBlueMarketData, actions: { action: string, amount: string, asset: string }[], web3: Web3, network: NetworkNumber) => {
|
|
93
96
|
const morphoBlueViewContract = MorphoBlueViewContract(web3, network);
|
|
94
97
|
const lltvInWei = assetAmountInWei(selectedMarket.lltv, 'ETH');
|
|
95
98
|
const marketData: MarketParamsStruct = [selectedMarket.loanToken, selectedMarket.collateralToken, selectedMarket.oracle, selectedMarket.irm, lltvInWei];
|
|
96
|
-
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
99
|
+
|
|
100
|
+
const params = actions.map(({ action, asset, amount }) => {
|
|
101
|
+
const isBorrowOperation = borrowOperations.includes(action);
|
|
102
|
+
const amountInWei = assetAmountInWei(amount, asset);
|
|
103
|
+
let liquidityAdded;
|
|
104
|
+
let liquidityRemoved;
|
|
105
|
+
if (isBorrowOperation) {
|
|
106
|
+
liquidityAdded = action === 'payback' ? amountInWei : '0';
|
|
107
|
+
liquidityRemoved = action === 'borrow' ? amountInWei : '0';
|
|
108
|
+
} else {
|
|
109
|
+
liquidityAdded = action === 'collateral' ? amountInWei : '0';
|
|
110
|
+
liquidityRemoved = action === 'withdraw' ? amountInWei : '0';
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
liquidityAdded,
|
|
114
|
+
liquidityRemoved,
|
|
115
|
+
isBorrowOperation,
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
const data = await morphoBlueViewContract.methods.getApyAfterValuesEstimation(
|
|
108
119
|
marketData,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
liquidityRemoved,
|
|
112
|
-
]).call();
|
|
120
|
+
params,
|
|
121
|
+
).call();
|
|
113
122
|
const borrowRate = getBorrowRate(data.borrowRate, data.market.totalBorrowShares);
|
|
114
123
|
const supplyRate = getSupplyRate(data.market.totalSupplyAssets, data.market.totalBorrowAssets, data.borrowRate, data.market.fee);
|
|
115
124
|
return { borrowRate, supplyRate };
|
|
116
|
-
};
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const API_URL = 'https://blue-api.morpho.org/graphql';
|
|
128
|
+
const MARKET_QUERY = `
|
|
129
|
+
query MarketByUniqueKey($uniqueKey: String!, $chainId: Int!) {
|
|
130
|
+
marketByUniqueKey(uniqueKey: $uniqueKey, chainId: $chainId) {
|
|
131
|
+
reallocatableLiquidityAssets
|
|
132
|
+
targetBorrowUtilization
|
|
133
|
+
loanAsset {
|
|
134
|
+
address
|
|
135
|
+
decimals
|
|
136
|
+
priceUsd
|
|
137
|
+
}
|
|
138
|
+
state {
|
|
139
|
+
liquidityAssets
|
|
140
|
+
borrowAssets
|
|
141
|
+
supplyAssets
|
|
142
|
+
}
|
|
143
|
+
publicAllocatorSharedLiquidity {
|
|
144
|
+
assets
|
|
145
|
+
vault {
|
|
146
|
+
address
|
|
147
|
+
name
|
|
148
|
+
}
|
|
149
|
+
allocationMarket {
|
|
150
|
+
uniqueKey
|
|
151
|
+
loanAsset {
|
|
152
|
+
address
|
|
153
|
+
}
|
|
154
|
+
collateralAsset {
|
|
155
|
+
address
|
|
156
|
+
}
|
|
157
|
+
irmAddress
|
|
158
|
+
oracle {
|
|
159
|
+
address
|
|
160
|
+
}
|
|
161
|
+
lltv
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
loanAsset {
|
|
165
|
+
address
|
|
166
|
+
}
|
|
167
|
+
collateralAsset {
|
|
168
|
+
address
|
|
169
|
+
}
|
|
170
|
+
oracle {
|
|
171
|
+
address
|
|
172
|
+
}
|
|
173
|
+
irmAddress
|
|
174
|
+
lltv
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
`;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Get reallocatable liquidity to a given market and target borrow utilization
|
|
181
|
+
* @param marketId - Unique key of the market liquidity is reallocated to
|
|
182
|
+
* @param network - The network number
|
|
183
|
+
* @returns The reallocatable liquidity and target borrow utilization
|
|
184
|
+
*/
|
|
185
|
+
export const getReallocatableLiquidity = async (marketId: string, network: NetworkNumber = NetworkNumber.Eth): Promise<{ reallocatableLiquidity: string, targetBorrowUtilization: string }> => {
|
|
186
|
+
const response = await fetch(API_URL, {
|
|
187
|
+
method: 'POST',
|
|
188
|
+
headers: { 'Content-Type': 'application/json' },
|
|
189
|
+
body: JSON.stringify({
|
|
190
|
+
query: MARKET_QUERY,
|
|
191
|
+
variables: { uniqueKey: marketId, chainId: network },
|
|
192
|
+
}),
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const data: { data: { marketByUniqueKey: MorphoBlueRealloactionMarketData } } = await response.json();
|
|
196
|
+
const marketData: MorphoBlueRealloactionMarketData = data?.data?.marketByUniqueKey;
|
|
197
|
+
|
|
198
|
+
if (!marketData) throw new Error('Market data not found');
|
|
199
|
+
|
|
200
|
+
return { reallocatableLiquidity: marketData.reallocatableLiquidityAssets, targetBorrowUtilization: marketData.targetBorrowUtilization };
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Get liquidity to allocate for a given amount to borrow.
|
|
205
|
+
* First, the function will try to calculate the amount of liquidity to allocate to be able to
|
|
206
|
+
* hit the target utilization. If it is not possible to allocate enough liquidity to hit the
|
|
207
|
+
* target utilization, the function will allocate the amount of liquidity needed to be able to
|
|
208
|
+
* borrow the selected amount.
|
|
209
|
+
* @param amountToBorrow - The amount to borrow
|
|
210
|
+
* @param totalBorrow - The total amount borrowed from market
|
|
211
|
+
* @param totalSupply - The total amount supplied to market
|
|
212
|
+
* @param targetBorrowUtilization - The target borrow utilization of market
|
|
213
|
+
* @param reallocatableLiquidityAssets - The amount of liquidity that can be reallocated from other markets
|
|
214
|
+
* @returns The amount of liquidity to allocate
|
|
215
|
+
*/
|
|
216
|
+
export const getLiquidityToAllocate = (amountToBorrow: string, totalBorrow: string, totalSupply: string, targetBorrowUtilization: string, reallocatableLiquidityAssets: string) => {
|
|
217
|
+
const newTotalBorrowAssets = new Dec(totalBorrow).add(amountToBorrow).toString();
|
|
218
|
+
const leftToBorrow = new Dec(totalSupply).sub(totalBorrow).toString();
|
|
219
|
+
let liquidityToAllocate = new Dec(newTotalBorrowAssets).div(targetBorrowUtilization).mul(1e18).sub(totalSupply)
|
|
220
|
+
.toFixed(0)
|
|
221
|
+
.toString();
|
|
222
|
+
|
|
223
|
+
if (new Dec(reallocatableLiquidityAssets).lt(liquidityToAllocate) || new Dec(liquidityToAllocate).lt('0')) {
|
|
224
|
+
liquidityToAllocate = new Dec(amountToBorrow).lt(leftToBorrow) ? '0' : new Dec(amountToBorrow).sub(leftToBorrow).toString();
|
|
225
|
+
if (new Dec(reallocatableLiquidityAssets).lt(liquidityToAllocate)) throw new Error('Not enough liquidity available to allocate');
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return liquidityToAllocate;
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Get the vaults and withdrawals needed to reallocate liquidity for a given amount to borrow.
|
|
233
|
+
* Amount to be reallocated is calculated in `getLiquidityToAllocate`
|
|
234
|
+
* @param market - The market data
|
|
235
|
+
* @param assetsData - The assets data
|
|
236
|
+
* @param amountToBorrow - Amount being borrowed (not the amount being reallocated)
|
|
237
|
+
* @param network - The network number
|
|
238
|
+
* @returns The vaults and withdrawals needed to reallocate liquidity
|
|
239
|
+
*/
|
|
240
|
+
export const getReallocation = async (market: MorphoBlueMarketData, assetsData: MorphoBlueAssetsData, amountToBorrow: string, network: NetworkNumber = NetworkNumber.Eth): Promise<{ vaults: string[], withdrawals: (string | string[])[][][] }> => {
|
|
241
|
+
const { marketId, loanToken } = market;
|
|
242
|
+
const response = await fetch(API_URL, {
|
|
243
|
+
method: 'POST',
|
|
244
|
+
headers: { 'Content-Type': 'application/json' },
|
|
245
|
+
body: JSON.stringify({
|
|
246
|
+
query: MARKET_QUERY,
|
|
247
|
+
variables: { uniqueKey: marketId, chainId: network },
|
|
248
|
+
}),
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
const data: { data: { marketByUniqueKey: MorphoBlueRealloactionMarketData } } = await response.json();
|
|
252
|
+
const marketData: MorphoBlueRealloactionMarketData = data?.data?.marketByUniqueKey;
|
|
253
|
+
|
|
254
|
+
if (!marketData) throw new Error('Market data not found');
|
|
255
|
+
|
|
256
|
+
const loanAssetInfo = getAssetInfoByAddress(loanToken, network);
|
|
257
|
+
const { totalBorrow, totalSupply } = assetsData[loanAssetInfo.symbol] || { totalBorrow: '0', totalSupply: '0' };
|
|
258
|
+
const totalBorrowWei = assetAmountInWei(totalBorrow!, loanAssetInfo.symbol);
|
|
259
|
+
const totalSupplyWei = assetAmountInWei(totalSupply!, loanAssetInfo.symbol);
|
|
260
|
+
|
|
261
|
+
const newTotalBorrowAssets = new Dec(totalBorrowWei).add(amountToBorrow).toString();
|
|
262
|
+
|
|
263
|
+
const newUtil = new Dec(newTotalBorrowAssets).div(totalSupplyWei).toString();
|
|
264
|
+
const newUtilScaled = new Dec(newUtil).mul(1e18).toString();
|
|
265
|
+
|
|
266
|
+
if (new Dec(newUtilScaled).lt(marketData.targetBorrowUtilization)) return { vaults: [], withdrawals: [] };
|
|
267
|
+
|
|
268
|
+
const liquidityToAllocate = getLiquidityToAllocate(amountToBorrow, totalBorrowWei, totalSupplyWei, marketData.targetBorrowUtilization, marketData.reallocatableLiquidityAssets);
|
|
269
|
+
|
|
270
|
+
const vaultTotalAssets = marketData.publicAllocatorSharedLiquidity.reduce(
|
|
271
|
+
(acc: Record<string, string>, item: MorphoBluePublicAllocatorItem) => {
|
|
272
|
+
const vaultAddress = item.vault.address;
|
|
273
|
+
acc[vaultAddress] = new Dec(acc[vaultAddress] || '0').add(item.assets).toString();
|
|
274
|
+
return acc;
|
|
275
|
+
},
|
|
276
|
+
{},
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
const sortedVaults = Object.entries(vaultTotalAssets).sort(
|
|
280
|
+
([, a]: [string, string], [, b]: [string, string]) => new Dec(b || '0').sub(a || '0').toNumber(),
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
const withdrawalsPerVault: Record<string, [string[], string, string][]> = {};
|
|
284
|
+
let totalReallocated = '0';
|
|
285
|
+
for (const [vaultAddress] of sortedVaults) {
|
|
286
|
+
if (new Dec(totalReallocated).gte(liquidityToAllocate)) break;
|
|
287
|
+
|
|
288
|
+
const vaultAllocations = marketData.publicAllocatorSharedLiquidity.filter(
|
|
289
|
+
(item: MorphoBluePublicAllocatorItem) => compareAddresses(item.vault.address, vaultAddress),
|
|
290
|
+
);
|
|
291
|
+
for (const item of vaultAllocations) {
|
|
292
|
+
if (new Dec(totalReallocated).gte(liquidityToAllocate)) break;
|
|
293
|
+
const itemAmount = item.assets;
|
|
294
|
+
const leftToAllocate = new Dec(liquidityToAllocate).sub(totalReallocated).toString();
|
|
295
|
+
const amountToTake = new Dec(itemAmount).lt(leftToAllocate) ? itemAmount : leftToAllocate;
|
|
296
|
+
totalReallocated = new Dec(totalReallocated).add(amountToTake).toString();
|
|
297
|
+
const withdrawal: [string[], string, string] = [
|
|
298
|
+
[
|
|
299
|
+
item.allocationMarket.loanAsset.address,
|
|
300
|
+
item.allocationMarket.collateralAsset?.address,
|
|
301
|
+
item.allocationMarket.oracle?.address,
|
|
302
|
+
item.allocationMarket.irmAddress,
|
|
303
|
+
item.allocationMarket.lltv,
|
|
304
|
+
],
|
|
305
|
+
amountToTake.toString(),
|
|
306
|
+
item.allocationMarket.uniqueKey,
|
|
307
|
+
];
|
|
308
|
+
if (!withdrawalsPerVault[vaultAddress]) {
|
|
309
|
+
withdrawalsPerVault[vaultAddress] = [];
|
|
310
|
+
}
|
|
311
|
+
withdrawalsPerVault[vaultAddress].push(withdrawal);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const vaults = Object.keys(withdrawalsPerVault);
|
|
316
|
+
const withdrawals = vaults.map(
|
|
317
|
+
(vaultAddress) => withdrawalsPerVault[vaultAddress].sort(
|
|
318
|
+
(a, b) => a[2].localeCompare(b[2]),
|
|
319
|
+
).map(w => [w[0], w[1]]),
|
|
320
|
+
);
|
|
321
|
+
return {
|
|
322
|
+
vaults,
|
|
323
|
+
withdrawals,
|
|
324
|
+
};
|
|
325
|
+
};
|
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
v3ETHCollAssets,
|
|
7
7
|
v3USDbCCollAssets,
|
|
8
8
|
v3USDCCollAssets,
|
|
9
|
-
v3USDCeCollAssets,
|
|
10
|
-
v3USDTCollAssets,
|
|
9
|
+
v3USDCeCollAssets, v3USDSCollAssets,
|
|
10
|
+
v3USDTCollAssets, v3wstETHCollAssets,
|
|
11
11
|
} from './marketsAssets';
|
|
12
12
|
|
|
13
13
|
export {
|
|
@@ -31,6 +31,8 @@ const BULKER_OPTIONS: Record<NetworkNumber, Record<CompoundVersions, CompoundBul
|
|
|
31
31
|
[CompoundVersions.CompoundV3USDC]: { supply: 2, withdraw: 5 },
|
|
32
32
|
[CompoundVersions.CompoundV3ETH]: STANDARD_BULKER_OPTIONS,
|
|
33
33
|
[CompoundVersions.CompoundV3USDT]: STANDARD_BULKER_OPTIONS,
|
|
34
|
+
[CompoundVersions.CompoundV3wstETH]: STANDARD_BULKER_OPTIONS,
|
|
35
|
+
[CompoundVersions.CompoundV3USDS]: STANDARD_BULKER_OPTIONS,
|
|
34
36
|
|
|
35
37
|
// Non-existing markets, keeping it because of typescript
|
|
36
38
|
[CompoundVersions.CompoundV2]: EMPTY_BULKER_OPTIONS,
|
|
@@ -46,6 +48,8 @@ const BULKER_OPTIONS: Record<NetworkNumber, Record<CompoundVersions, CompoundBul
|
|
|
46
48
|
// Non-existing markets, keeping it because of typescript
|
|
47
49
|
[CompoundVersions.CompoundV2]: EMPTY_BULKER_OPTIONS,
|
|
48
50
|
[CompoundVersions.CompoundV3USDbC]: EMPTY_BULKER_OPTIONS,
|
|
51
|
+
[CompoundVersions.CompoundV3wstETH]: EMPTY_BULKER_OPTIONS,
|
|
52
|
+
[CompoundVersions.CompoundV3USDS]: EMPTY_BULKER_OPTIONS,
|
|
49
53
|
},
|
|
50
54
|
[NetworkNumber.Base]: {
|
|
51
55
|
[CompoundVersions.CompoundV3ETH]: STANDARD_BULKER_OPTIONS,
|
|
@@ -56,6 +60,8 @@ const BULKER_OPTIONS: Record<NetworkNumber, Record<CompoundVersions, CompoundBul
|
|
|
56
60
|
[CompoundVersions.CompoundV2]: EMPTY_BULKER_OPTIONS,
|
|
57
61
|
[CompoundVersions.CompoundV3USDCe]: EMPTY_BULKER_OPTIONS,
|
|
58
62
|
[CompoundVersions.CompoundV3USDT]: EMPTY_BULKER_OPTIONS,
|
|
63
|
+
[CompoundVersions.CompoundV3wstETH]: EMPTY_BULKER_OPTIONS,
|
|
64
|
+
[CompoundVersions.CompoundV3USDS]: EMPTY_BULKER_OPTIONS,
|
|
59
65
|
},
|
|
60
66
|
[NetworkNumber.Opt]: {
|
|
61
67
|
[CompoundVersions.CompoundV3USDC]: STANDARD_BULKER_OPTIONS,
|
|
@@ -65,6 +71,8 @@ const BULKER_OPTIONS: Record<NetworkNumber, Record<CompoundVersions, CompoundBul
|
|
|
65
71
|
[CompoundVersions.CompoundV3USDbC]: EMPTY_BULKER_OPTIONS,
|
|
66
72
|
[CompoundVersions.CompoundV2]: EMPTY_BULKER_OPTIONS,
|
|
67
73
|
[CompoundVersions.CompoundV3USDCe]: EMPTY_BULKER_OPTIONS,
|
|
74
|
+
[CompoundVersions.CompoundV3wstETH]: EMPTY_BULKER_OPTIONS,
|
|
75
|
+
[CompoundVersions.CompoundV3USDS]: EMPTY_BULKER_OPTIONS,
|
|
68
76
|
},
|
|
69
77
|
};
|
|
70
78
|
|
|
@@ -164,6 +172,36 @@ export const COMPOUND_V3_USDT = (networkId: NetworkNumber): CompoundMarketData =
|
|
|
164
172
|
// icon: SvgAdapter(protocolIcons.compoundv3),
|
|
165
173
|
});
|
|
166
174
|
|
|
175
|
+
export const COMPOUND_V3_WSTETH = (networkId: NetworkNumber): CompoundMarketData => ({
|
|
176
|
+
chainIds: [NetworkNumber.Eth],
|
|
177
|
+
label: 'Compound V3 - wstETH',
|
|
178
|
+
shortLabel: 'v3',
|
|
179
|
+
value: CompoundVersions.CompoundV3wstETH,
|
|
180
|
+
baseAsset: 'wstETH',
|
|
181
|
+
collAssets: networkId ? v3wstETHCollAssets[networkId] : [],
|
|
182
|
+
baseMarket: 'cWstETHv3',
|
|
183
|
+
baseMarketAddress: getConfigContractAddress('cWstETHv3', networkId),
|
|
184
|
+
secondLabel: 'Market',
|
|
185
|
+
bulkerName: networkId === NetworkNumber.Eth ? 'CompV3BulkerMainnetETH' : 'CompV3BulkerL2',
|
|
186
|
+
bulkerAddress: getConfigContractAddress(networkId === NetworkNumber.Eth ? 'CompV3BulkerMainnetETH' : 'CompV3BulkerL2', networkId),
|
|
187
|
+
bulkerOptions: BULKER_OPTIONS[networkId][CompoundVersions.CompoundV3wstETH],
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
export const COMPOUND_V3_USDS = (networkId: NetworkNumber): CompoundMarketData => ({
|
|
191
|
+
chainIds: [NetworkNumber.Eth],
|
|
192
|
+
label: 'Compound V3 - USDS',
|
|
193
|
+
shortLabel: 'v3',
|
|
194
|
+
value: CompoundVersions.CompoundV3USDS,
|
|
195
|
+
baseAsset: 'USDS',
|
|
196
|
+
collAssets: networkId ? v3USDSCollAssets[networkId] : [],
|
|
197
|
+
baseMarket: 'cUSDSv3',
|
|
198
|
+
baseMarketAddress: getConfigContractAddress('cUSDSv3', networkId),
|
|
199
|
+
secondLabel: 'Market',
|
|
200
|
+
bulkerName: networkId === NetworkNumber.Eth ? 'CompV3BulkerMainnetETH' : 'CompV3BulkerL2',
|
|
201
|
+
bulkerAddress: getConfigContractAddress(networkId === NetworkNumber.Eth ? 'CompV3BulkerMainnetETH' : 'CompV3BulkerL2', networkId),
|
|
202
|
+
bulkerOptions: BULKER_OPTIONS[networkId][CompoundVersions.CompoundV3USDS],
|
|
203
|
+
});
|
|
204
|
+
|
|
167
205
|
export const CompoundMarkets = (networkId: NetworkNumber) => ({
|
|
168
206
|
[CompoundVersions.CompoundV2]: COMPOUND_V2,
|
|
169
207
|
[CompoundVersions.CompoundV3ETH]: COMPOUND_V3_ETH(networkId),
|
|
@@ -171,4 +209,6 @@ export const CompoundMarkets = (networkId: NetworkNumber) => ({
|
|
|
171
209
|
[CompoundVersions.CompoundV3USDbC]: COMPOUND_V3_USDBC(networkId),
|
|
172
210
|
[CompoundVersions.CompoundV3USDCe]: COMPOUND_V3_USDCe(networkId),
|
|
173
211
|
[CompoundVersions.CompoundV3USDT]: COMPOUND_V3_USDT(networkId),
|
|
212
|
+
[CompoundVersions.CompoundV3wstETH]: COMPOUND_V3_WSTETH(networkId),
|
|
213
|
+
[CompoundVersions.CompoundV3USDS]: COMPOUND_V3_USDS(networkId),
|
|
174
214
|
}) as const;
|
|
@@ -7,7 +7,7 @@ export const compoundV2CollateralAssets = [
|
|
|
7
7
|
].map((symbol) => getAssetInfo(symbol));
|
|
8
8
|
|
|
9
9
|
export const v3USDCCollAssetsEth = ['COMP', 'WBTC', 'ETH', 'UNI', 'LINK', 'wstETH', 'cbBTC', 'tBTC'];
|
|
10
|
-
export const v3USDCCollAssetsArb = ['ARB', 'ETH', 'GMX', 'WBTC', 'wstETH', 'ezETH'];
|
|
10
|
+
export const v3USDCCollAssetsArb = ['ARB', 'ETH', 'GMX', 'WBTC', 'wstETH', 'ezETH', 'wUSDM'];
|
|
11
11
|
export const v3USDCCollAssetsBase = ['ETH', 'cbETH', 'wstETH', 'cbBTC'];
|
|
12
12
|
export const v3USDCCollAssetsOpt = ['ETH', 'OP', 'WBTC', 'wstETH'];
|
|
13
13
|
|
|
@@ -52,7 +52,7 @@ export const v3USDbCCollAssets = {
|
|
|
52
52
|
[NetworkNumber.Base]: v3USDbCCollAssetsBase,
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
-
export const v3USDTCollAssetsEth = ['COMP', 'ETH', 'WBTC', 'UNI', 'LINK', 'wstETH', 'cbBTC', 'tBTC', 'wUSDM', 'sFRAX'];
|
|
55
|
+
export const v3USDTCollAssetsEth = ['COMP', 'ETH', 'WBTC', 'UNI', 'LINK', 'wstETH', 'cbBTC', 'tBTC', 'wUSDM', 'sFRAX', 'mETH'];
|
|
56
56
|
export const v3USDTCollAssetsArb = ['ETH', 'WBTC', 'wstETH', 'ARB', 'GMX'];
|
|
57
57
|
export const v3USDTCollAssetsOpt = ['ETH', 'WBTC', 'OP', 'wstETH'];
|
|
58
58
|
|
|
@@ -62,4 +62,22 @@ export const v3USDTCollAssets = {
|
|
|
62
62
|
[NetworkNumber.Opt]: v3USDTCollAssetsOpt,
|
|
63
63
|
[NetworkNumber.Arb]: v3USDTCollAssetsArb,
|
|
64
64
|
[NetworkNumber.Base]: [],
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const v3USDSCollAssetsEth = ['wstETH', 'ETH', 'sUSDS', 'cbETH', 'tBTC', 'USDe'];
|
|
68
|
+
|
|
69
|
+
export const v3USDSCollAssets = {
|
|
70
|
+
[NetworkNumber.Eth]: v3USDSCollAssetsEth,
|
|
71
|
+
[NetworkNumber.Opt]: [],
|
|
72
|
+
[NetworkNumber.Arb]: [],
|
|
73
|
+
[NetworkNumber.Base]: [],
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const v3wstETHCollAssetsEth = ['rsETH', 'ezETH'];
|
|
77
|
+
|
|
78
|
+
export const v3wstETHCollAssets = {
|
|
79
|
+
[NetworkNumber.Eth]: v3wstETHCollAssetsEth,
|
|
80
|
+
[NetworkNumber.Opt]: [],
|
|
81
|
+
[NetworkNumber.Arb]: [],
|
|
82
|
+
[NetworkNumber.Base]: [],
|
|
65
83
|
};
|
|
@@ -723,7 +723,7 @@ export const MORPHO_BLUE_CBBTC_USDC_860_BASE = (networkId: NetworkNumber = Netwo
|
|
|
723
723
|
export const MORPHO_BLUE_WSUPEROETHB_WETH_915_BASE = (networkId: NetworkNumber = NetworkNumber.Eth): MorphoBlueMarketData => ({
|
|
724
724
|
chainIds: [NetworkNumber.Base],
|
|
725
725
|
label: 'Morpho',
|
|
726
|
-
shortLabel: 'wsuperOETHb/
|
|
726
|
+
shortLabel: 'wsuperOETHb/ETH',
|
|
727
727
|
value: MorphoBlueVersions.MorphoBlueWsuperOETHbWETH_915_Base,
|
|
728
728
|
url: 'wsuperoethbweth-144bf18d',
|
|
729
729
|
loanToken: '0x4200000000000000000000000000000000000006',
|
|
@@ -736,6 +736,70 @@ export const MORPHO_BLUE_WSUPEROETHB_WETH_915_BASE = (networkId: NetworkNumber =
|
|
|
736
736
|
protocolName: 'morpho-blue',
|
|
737
737
|
});
|
|
738
738
|
|
|
739
|
+
export const MORPHO_BLUE_LBTC_WBTC_945 = (networkId: NetworkNumber = NetworkNumber.Eth): MorphoBlueMarketData => ({
|
|
740
|
+
chainIds: [NetworkNumber.Eth],
|
|
741
|
+
label: 'Morpho',
|
|
742
|
+
shortLabel: 'LBTC/WBTC',
|
|
743
|
+
value: MorphoBlueVersions.MorphoBlueLBTCWBTC_945,
|
|
744
|
+
url: 'lbtcwbtc-f6a05662',
|
|
745
|
+
loanToken: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599',
|
|
746
|
+
collateralToken: '0x8236a87084f8B84306f72007F36F2618A5634494',
|
|
747
|
+
oracle: '0xa98105B8227E0f2157816Feb7A331364A9B74F80',
|
|
748
|
+
oracleType: MorphoBlueOracleType.MARKET_RATE,
|
|
749
|
+
irm: '0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC',
|
|
750
|
+
lltv: 0.945,
|
|
751
|
+
marketId: '0xf6a056627a51e511ec7f48332421432ea6971fc148d8f3c451e14ea108026549',
|
|
752
|
+
protocolName: 'morpho-blue',
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
export const MORPHO_BLUE_LBTC_CBBTC_945_BASE = (networkId: NetworkNumber = NetworkNumber.Eth): MorphoBlueMarketData => ({
|
|
756
|
+
chainIds: [NetworkNumber.Base],
|
|
757
|
+
label: 'Morpho',
|
|
758
|
+
shortLabel: 'LBTC/cbBTC',
|
|
759
|
+
value: MorphoBlueVersions.MorphoBlueLBTCCbBTC_945_Base,
|
|
760
|
+
url: 'lbtccbbtc-30767836',
|
|
761
|
+
loanToken: '0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf',
|
|
762
|
+
collateralToken: '0xecAc9C5F704e954931349Da37F60E39f515c11c1',
|
|
763
|
+
oracle: '0x9Ae0E86e88AEE94B700240eBE0BD17D969BAD0EA',
|
|
764
|
+
oracleType: MorphoBlueOracleType.MARKET_RATE,
|
|
765
|
+
irm: '0x46415998764C29aB2a25CbeA6254146D50D22687',
|
|
766
|
+
lltv: 0.945,
|
|
767
|
+
marketId: '0x30767836635facec1282e6ef4a5981406ed4e72727b3a63a3a72c74e8279a8d7',
|
|
768
|
+
protocolName: 'morpho-blue',
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
export const MORPHO_BLUE_WSTETH_EURC_860_BASE = (networkId: NetworkNumber = NetworkNumber.Eth): MorphoBlueMarketData => ({
|
|
772
|
+
chainIds: [NetworkNumber.Base],
|
|
773
|
+
label: 'Morpho',
|
|
774
|
+
shortLabel: 'wstETH/EURC',
|
|
775
|
+
value: MorphoBlueVersions.MorphoBlueWstEthEURC_860_Base,
|
|
776
|
+
url: 'wstetheurc-f7e40290',
|
|
777
|
+
loanToken: '0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42',
|
|
778
|
+
collateralToken: '0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452',
|
|
779
|
+
oracle: '0xa54122f0E0766258377Ffe732e454A3248f454F4',
|
|
780
|
+
oracleType: MorphoBlueOracleType.MARKET_RATE,
|
|
781
|
+
irm: '0x46415998764C29aB2a25CbeA6254146D50D22687',
|
|
782
|
+
lltv: 0.86,
|
|
783
|
+
marketId: '0xf7e40290f8ca1d5848b3c129502599aa0f0602eb5f5235218797a34242719561',
|
|
784
|
+
protocolName: 'morpho-blue',
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
export const MORPHO_BLUE_CBBTC_EURC_860_BASE = (networkId: NetworkNumber = NetworkNumber.Eth): MorphoBlueMarketData => ({
|
|
788
|
+
chainIds: [NetworkNumber.Base],
|
|
789
|
+
label: 'Morpho',
|
|
790
|
+
shortLabel: 'cbBTC/EURC',
|
|
791
|
+
value: MorphoBlueVersions.MorphoBlueCbBTCEURC_860_Base,
|
|
792
|
+
url: 'cbbtceurc-67ebd84b',
|
|
793
|
+
loanToken: '0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42',
|
|
794
|
+
collateralToken: '0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf',
|
|
795
|
+
oracle: '0xA857411CB2231a6A87a3bEF987a4cED8A067d799',
|
|
796
|
+
oracleType: MorphoBlueOracleType.MARKET_RATE,
|
|
797
|
+
irm: '0x46415998764C29aB2a25CbeA6254146D50D22687',
|
|
798
|
+
lltv: 0.86,
|
|
799
|
+
marketId: '0x67ebd84b2fb39e3bc5a13d97e4c07abe1ea617e40654826e9abce252e95f049e',
|
|
800
|
+
protocolName: 'morpho-blue',
|
|
801
|
+
});
|
|
802
|
+
|
|
739
803
|
export const MorphoBlueMarkets = (networkId: NetworkNumber) => ({
|
|
740
804
|
[MorphoBlueVersions.MorphoBlueWstEthUSDC]: MORPHO_BLUE_WSTETH_USDC(networkId),
|
|
741
805
|
[MorphoBlueVersions.MorphoBlueSDAIUSDC]: MORPHO_BLUE_SDAI_USDC(networkId),
|
|
@@ -760,6 +824,7 @@ export const MorphoBlueMarkets = (networkId: NetworkNumber) => ({
|
|
|
760
824
|
[MorphoBlueVersions.MorphoBlueCbBTCUSDC_860]: MORPHO_BLUE_CBBTC_USDC_860(networkId),
|
|
761
825
|
[MorphoBlueVersions.MorphoBlueREthEth_945]: MORPHO_BLUE_RETH_ETH_945(networkId),
|
|
762
826
|
[MorphoBlueVersions.MorphoBlueSUSDeUSDC_915]: MORPHO_BLUE_SUSDE_USDC_915(networkId),
|
|
827
|
+
[MorphoBlueVersions.MorphoBlueLBTCWBTC_945]: MORPHO_BLUE_LBTC_WBTC_945(networkId),
|
|
763
828
|
|
|
764
829
|
// wstETH/WETH
|
|
765
830
|
[MorphoBlueVersions.MorphoBlueWstEthEth_945]: MORPHO_BLUE_WSTETH_ETH_945(networkId),
|
|
@@ -786,6 +851,10 @@ export const MorphoBlueMarkets = (networkId: NetworkNumber) => ({
|
|
|
786
851
|
[MorphoBlueVersions.MorphoBlueREthEth_945_Base]: MORPHO_BLUE_RETH_ETH_945_BASE(networkId),
|
|
787
852
|
[MorphoBlueVersions.MorphoBlueCbBTCEth_915_Base]: MORPHO_BLUE_CBBTC_ETH_915_BASE(networkId),
|
|
788
853
|
[MorphoBlueVersions.MorphoBlueCbBTCUSDC_860_Base]: MORPHO_BLUE_CBBTC_USDC_860_BASE(networkId),
|
|
854
|
+
[MorphoBlueVersions.MorphoBlueCbBTCEURC_860_Base]: MORPHO_BLUE_CBBTC_EURC_860_BASE(networkId),
|
|
855
|
+
[MorphoBlueVersions.MorphoBlueWstEthEURC_860_Base]: MORPHO_BLUE_WSTETH_EURC_860_BASE(networkId),
|
|
856
|
+
[MorphoBlueVersions.MorphoBlueLBTCCbBTC_945_Base]: MORPHO_BLUE_LBTC_CBBTC_945_BASE(networkId),
|
|
857
|
+
|
|
789
858
|
|
|
790
859
|
// wsuperOETHb/WETH Base
|
|
791
860
|
[MorphoBlueVersions.MorphoBlueWsuperOETHbWETH_915_Base]: MORPHO_BLUE_WSUPEROETHB_WETH_915_BASE(networkId),
|
package/src/morphoBlue/index.ts
CHANGED
|
@@ -1,41 +1,58 @@
|
|
|
1
1
|
import Web3 from 'web3';
|
|
2
2
|
import Dec from 'decimal.js';
|
|
3
|
-
import { assetAmountInEth,
|
|
3
|
+
import { assetAmountInEth, getAssetInfoByAddress } from '@defisaver/tokens';
|
|
4
4
|
import {
|
|
5
5
|
Blockish, EthAddress, MMUsedAssets, NetworkNumber, PositionBalances,
|
|
6
6
|
} from '../types/common';
|
|
7
|
-
import {
|
|
8
|
-
FeedRegistryContract,
|
|
9
|
-
MorphoBlueViewContract,
|
|
10
|
-
} from '../contracts';
|
|
7
|
+
import { DFSFeedRegistryContract, FeedRegistryContract, MorphoBlueViewContract } from '../contracts';
|
|
11
8
|
import {
|
|
12
9
|
MorphoBlueAssetsData, MorphoBlueMarketData, MorphoBlueMarketInfo, MorphoBluePositionData,
|
|
13
10
|
} from '../types';
|
|
14
|
-
import {
|
|
11
|
+
import { USD_QUOTE, WAD } from '../constants';
|
|
15
12
|
import { getStakingApy, STAKING_ASSETS } from '../staking';
|
|
16
13
|
import { wethToEth } from '../services/utils';
|
|
17
14
|
import { getBorrowRate, getMorphoBlueAggregatedPositionData, getSupplyRate } from '../helpers/morphoBlueHelpers';
|
|
15
|
+
import { getChainlinkAssetAddress } from '../services/priceService';
|
|
16
|
+
|
|
17
|
+
const isMainnetNetwork = (network: NetworkNumber) => network === NetworkNumber.Eth;
|
|
18
18
|
|
|
19
19
|
export async function getMorphoBlueMarketData(web3: Web3, network: NetworkNumber, selectedMarket: MorphoBlueMarketData, mainnetWeb3: Web3): Promise<MorphoBlueMarketInfo> {
|
|
20
20
|
const {
|
|
21
21
|
loanToken, collateralToken, oracle, irm, lltv, oracleType,
|
|
22
22
|
} = selectedMarket;
|
|
23
|
+
|
|
23
24
|
const lltvInWei = new Dec(lltv).mul(WAD).toString();
|
|
24
25
|
const loanTokenInfo = getAssetInfoByAddress(loanToken, network);
|
|
25
26
|
const collateralTokenInfo = getAssetInfoByAddress(collateralToken, network);
|
|
26
|
-
let loanTokenFeedAddress = loanTokenInfo.addresses[NetworkNumber.Eth];
|
|
27
|
-
if (loanTokenInfo.symbol === 'WETH') {
|
|
28
|
-
const ethAddress = getAssetInfo('ETH').address;
|
|
29
|
-
loanTokenFeedAddress = ethAddress;
|
|
30
|
-
}
|
|
31
27
|
|
|
32
|
-
const
|
|
28
|
+
const loanTokenFeedAddress = getChainlinkAssetAddress(loanTokenInfo.symbol, network);
|
|
29
|
+
|
|
33
30
|
const morphoBlueViewContract = MorphoBlueViewContract(web3, network);
|
|
34
31
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
let marketInfo;
|
|
33
|
+
let loanTokenPrice;
|
|
34
|
+
const isTokenUSDA = loanTokenInfo.symbol === 'USDA';
|
|
35
|
+
const isMainnet = isMainnetNetwork(network);
|
|
36
|
+
if (isMainnet) {
|
|
37
|
+
const feedRegistryContract = FeedRegistryContract(mainnetWeb3, NetworkNumber.Eth);
|
|
38
|
+
const [_loanTokenPrice, _marketInfo] = await Promise.all([
|
|
39
|
+
isTokenUSDA ? Promise.resolve('100000000') : feedRegistryContract.methods.latestAnswer(loanTokenFeedAddress, USD_QUOTE).call(),
|
|
40
|
+
morphoBlueViewContract.methods.getMarketInfoNotTuple(loanToken, collateralToken, oracle, irm, lltvInWei).call(),
|
|
41
|
+
]);
|
|
42
|
+
marketInfo = _marketInfo;
|
|
43
|
+
loanTokenPrice = _loanTokenPrice;
|
|
44
|
+
} else {
|
|
45
|
+
// Currently only base network is supported
|
|
46
|
+
const feedRegistryContract = DFSFeedRegistryContract(web3, network);
|
|
47
|
+
|
|
48
|
+
const [loanTokenPriceRound, _marketInfo] = await Promise.all([
|
|
49
|
+
isTokenUSDA ? Promise.resolve({ answer: '100000000' }) // Normalize to match the expected object structure
|
|
50
|
+
: feedRegistryContract.methods.latestRoundData(loanTokenFeedAddress, USD_QUOTE).call(),
|
|
51
|
+
morphoBlueViewContract.methods.getMarketInfoNotTuple(loanToken, collateralToken, oracle, irm, lltvInWei).call(),
|
|
52
|
+
]);
|
|
53
|
+
marketInfo = _marketInfo;
|
|
54
|
+
loanTokenPrice = loanTokenPriceRound.answer;
|
|
55
|
+
}
|
|
39
56
|
|
|
40
57
|
const supplyRate = getSupplyRate(marketInfo.totalSupplyAssets, marketInfo.totalBorrowAssets, marketInfo.borrowRate, marketInfo.fee);
|
|
41
58
|
const compoundedBorrowRate = getBorrowRate(marketInfo.borrowRate, marketInfo.totalBorrowShares);
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import Web3 from 'web3';
|
|
2
2
|
import Dec from 'decimal.js';
|
|
3
|
-
import {
|
|
3
|
+
import { getAssetInfo } from '@defisaver/tokens';
|
|
4
|
+
import {
|
|
5
|
+
COMPPriceFeedContract,
|
|
6
|
+
ETHPriceFeedContract,
|
|
7
|
+
USDCPriceFeedContract,
|
|
8
|
+
WstETHPriceFeedContract,
|
|
9
|
+
} from '../contracts';
|
|
4
10
|
import { NetworkNumber } from '../types/common';
|
|
11
|
+
import { multicall } from '../multicall';
|
|
5
12
|
|
|
6
13
|
export const getEthPrice = async (web3: Web3) => {
|
|
7
14
|
const contract = ETHPriceFeedContract(web3, NetworkNumber.Eth);
|
|
@@ -19,4 +26,36 @@ export const getCompPrice = async (web3: Web3) => {
|
|
|
19
26
|
const contract = COMPPriceFeedContract(web3, NetworkNumber.Eth);
|
|
20
27
|
const price = await contract.methods.latestAnswer().call();
|
|
21
28
|
return new Dec(price).div(1e8).toString();
|
|
22
|
-
};
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const getWstETHPrice = async (web3: Web3) => {
|
|
32
|
+
const wstETHFeedContract = WstETHPriceFeedContract(web3, NetworkNumber.Eth);
|
|
33
|
+
const ethFeedContract = ETHPriceFeedContract(web3, NetworkNumber.Eth);
|
|
34
|
+
const calls = [
|
|
35
|
+
{
|
|
36
|
+
target: ethFeedContract.options.address,
|
|
37
|
+
abiItem: ethFeedContract.options.jsonInterface.find(({ name }) => name === 'latestAnswer'),
|
|
38
|
+
params: [],
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
target: wstETHFeedContract.options.address,
|
|
42
|
+
abiItem: wstETHFeedContract.options.jsonInterface.find(({ name }) => name === 'latestRoundData'),
|
|
43
|
+
params: [],
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
const multicallRes = await multicall(calls, web3);
|
|
48
|
+
|
|
49
|
+
const ethPrice = new Dec(multicallRes[0][0]).div(1e8);
|
|
50
|
+
|
|
51
|
+
const wstETHRate = new Dec(multicallRes[1].answer).div(1e8);
|
|
52
|
+
|
|
53
|
+
return new Dec(ethPrice).mul(wstETHRate).toString();
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// chainlink price feed available only on mainnet
|
|
57
|
+
export const getChainlinkAssetAddress = (symbol: string, network: NetworkNumber) => {
|
|
58
|
+
if (['WBTC', 'RENBTC'].includes(symbol?.toUpperCase())) return '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB';
|
|
59
|
+
if (symbol?.toUpperCase() === 'WETH') return getAssetInfo('ETH').addresses[network];
|
|
60
|
+
return getAssetInfo(symbol).addresses[network];
|
|
61
|
+
};
|
package/src/types/compound.ts
CHANGED