@defisaver/positions-sdk 2.1.127-midnight-dev → 2.1.127-midnight-2-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.
- package/cjs/aaveV3/index.js +7 -1
- package/cjs/aaveV4/lend.js +3 -3
- package/cjs/claiming/index.d.ts +2 -1
- package/cjs/claiming/index.js +3 -1
- package/cjs/claiming/uniswap.d.ts +5 -0
- package/cjs/claiming/uniswap.js +75 -0
- package/cjs/config/contracts.d.ts +22 -0
- package/cjs/config/contracts.js +9 -1
- package/cjs/contracts.d.ts +35 -0
- package/cjs/contracts.js +2 -1
- package/cjs/curveUsd/index.js +1 -1
- package/cjs/helpers/morphoBlueHelpers/index.js +1 -0
- package/cjs/helpers/morphoMidnightHelpers/index.d.ts +62 -0
- package/cjs/helpers/morphoMidnightHelpers/index.js +156 -1
- package/cjs/llamaLend/index.js +1 -1
- package/cjs/markets/aaveV4/index.d.ts +2 -0
- package/cjs/markets/aaveV4/index.js +14 -1
- package/cjs/morphoBlue/index.d.ts +8 -6
- package/cjs/morphoBlue/index.js +69 -40
- package/cjs/morphoMidnight/index.js +25 -1
- package/cjs/portfolio/index.js +31 -2
- package/cjs/savings/summerVaults/options.js +10 -10
- package/cjs/staking/staking.js +3 -0
- package/cjs/types/aaveV4.d.ts +2 -1
- package/cjs/types/aaveV4.js +1 -0
- package/cjs/types/claiming.d.ts +10 -0
- package/cjs/types/claiming.js +2 -0
- package/cjs/types/morphoBlue.d.ts +9 -0
- package/cjs/types/morphoMidnight.d.ts +3 -0
- package/esm/aaveV3/index.js +7 -1
- package/esm/aaveV4/lend.js +3 -3
- package/esm/claiming/index.d.ts +2 -1
- package/esm/claiming/index.js +2 -1
- package/esm/claiming/uniswap.d.ts +5 -0
- package/esm/claiming/uniswap.js +67 -0
- package/esm/config/contracts.d.ts +22 -0
- package/esm/config/contracts.js +8 -0
- package/esm/contracts.d.ts +35 -0
- package/esm/contracts.js +1 -0
- package/esm/curveUsd/index.js +1 -1
- package/esm/helpers/morphoBlueHelpers/index.js +1 -0
- package/esm/helpers/morphoMidnightHelpers/index.d.ts +62 -0
- package/esm/helpers/morphoMidnightHelpers/index.js +149 -0
- package/esm/llamaLend/index.js +1 -1
- package/esm/markets/aaveV4/index.d.ts +2 -0
- package/esm/markets/aaveV4/index.js +12 -0
- package/esm/morphoBlue/index.d.ts +8 -6
- package/esm/morphoBlue/index.js +62 -39
- package/esm/morphoMidnight/index.js +26 -2
- package/esm/portfolio/index.js +32 -3
- package/esm/savings/summerVaults/options.js +10 -10
- package/esm/staking/staking.js +3 -0
- package/esm/types/aaveV4.d.ts +2 -1
- package/esm/types/aaveV4.js +1 -0
- package/esm/types/claiming.d.ts +10 -0
- package/esm/types/claiming.js +2 -0
- package/esm/types/morphoBlue.d.ts +9 -0
- package/esm/types/morphoMidnight.d.ts +3 -0
- package/package.json +2 -2
- package/src/aaveV3/index.ts +13 -1
- package/src/aaveV4/lend.ts +3 -3
- package/src/claiming/index.ts +2 -0
- package/src/claiming/uniswap.ts +70 -0
- package/src/config/contracts.ts +9 -0
- package/src/contracts.ts +2 -0
- package/src/curveUsd/index.ts +1 -1
- package/src/helpers/morphoBlueHelpers/index.ts +1 -0
- package/src/helpers/morphoMidnightHelpers/index.ts +206 -0
- package/src/llamaLend/index.ts +1 -1
- package/src/markets/aaveV4/index.ts +13 -0
- package/src/morphoBlue/index.ts +101 -44
- package/src/morphoMidnight/index.ts +29 -2
- package/src/portfolio/index.ts +32 -3
- package/src/savings/summerVaults/options.ts +10 -10
- package/src/staking/staking.ts +2 -0
- package/src/types/aaveV4.ts +1 -0
- package/src/types/claiming.ts +11 -0
- package/src/types/morphoBlue.ts +11 -0
- package/src/types/morphoMidnight.ts +6 -0
package/src/llamaLend/index.ts
CHANGED
|
@@ -24,7 +24,7 @@ const getAndFormatBands = async (provider: Client, network: NetworkNumber, selec
|
|
|
24
24
|
// getBandsData uses a lot of gas to get all of the bands at once, so we use pagination and fetch 200 bands at a time
|
|
25
25
|
let i = minBand;
|
|
26
26
|
while (i < maxBand) {
|
|
27
|
-
i +=
|
|
27
|
+
i += 20;
|
|
28
28
|
if (i > maxBand) {
|
|
29
29
|
pivots.push(maxBand);
|
|
30
30
|
} else {
|
|
@@ -193,6 +193,18 @@ export const AAVE_V4_USDG_PENDLE_SPOKE = (networkId: NetworkNumber): AaveV4Spoke
|
|
|
193
193
|
],
|
|
194
194
|
});
|
|
195
195
|
|
|
196
|
+
export const AAVE_V4_USDG_MAPLE_SPOKE = (networkId: NetworkNumber): AaveV4SpokeInfo => ({
|
|
197
|
+
chainIds: [NetworkNumber.Eth],
|
|
198
|
+
label: 'USDG Maple',
|
|
199
|
+
value: AaveV4SpokesType.AaveV4USDGMapleSpoke,
|
|
200
|
+
url: 'usdg-maple',
|
|
201
|
+
address: '0x774b9655413c34809c1f1b16b654465A89EBE989',
|
|
202
|
+
hubs: [
|
|
203
|
+
AAVE_V4_PAXOS_HUB(NetworkNumber.Eth).address,
|
|
204
|
+
AAVE_V4_CORE_HUB(NetworkNumber.Eth).address,
|
|
205
|
+
],
|
|
206
|
+
});
|
|
207
|
+
|
|
196
208
|
export const AaveV4Spokes = (networkId: NetworkNumber) => ({
|
|
197
209
|
[AaveV4SpokesType.AaveV4BluechipSpoke]: AAVE_V4_BLUECHIP_SPOKE(networkId),
|
|
198
210
|
[AaveV4SpokesType.AaveV4EthenaCorrelatedSpoke]: AAVE_V4_ETHENA_CORRELATED_SPOKE(networkId),
|
|
@@ -205,6 +217,7 @@ export const AaveV4Spokes = (networkId: NetworkNumber) => ({
|
|
|
205
217
|
[AaveV4SpokesType.AaveV4LombardBtcSpoke]: AAVE_V4_LOMBARD_BTC_SPOKE(networkId),
|
|
206
218
|
[AaveV4SpokesType.AaveV4MainSpoke]: AAVE_V4_MAIN_SPOKE(networkId),
|
|
207
219
|
[AaveV4SpokesType.AaveV4USDGPendleSpoke]: AAVE_V4_USDG_PENDLE_SPOKE(networkId),
|
|
220
|
+
[AaveV4SpokesType.AaveV4USDGMapleSpoke]: AAVE_V4_USDG_MAPLE_SPOKE(networkId),
|
|
208
221
|
}) as const;
|
|
209
222
|
|
|
210
223
|
export const getAaveV4SpokeTypeInfo = (type: AaveV4SpokesType, network?: NetworkNumber) => ({ ...AaveV4Spokes(network ?? NetworkNumber.Eth) }[type]);
|
package/src/morphoBlue/index.ts
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
DFSFeedRegistryContractViem, FeedRegistryContractViem, MorphoBlueViewContractViem,
|
|
9
9
|
} from '../contracts';
|
|
10
10
|
import {
|
|
11
|
-
MorphoBlueAssetsData, MorphoBlueMarketData, MorphoBlueMarketInfo, MorphoBluePositionData,
|
|
11
|
+
MorphoBlueAssetsData, MorphoBlueEarnData, MorphoBlueMarketData, MorphoBlueMarketInfo, MorphoBlueMarketRewards, MorphoBluePositionData,
|
|
12
12
|
} from '../types';
|
|
13
13
|
import { USD_QUOTE, WAD } from '../constants';
|
|
14
14
|
import { calculateNetApy, getStakingApy, STAKING_ASSETS } from '../staking';
|
|
@@ -21,7 +21,39 @@ import { getViemProvider, setViemBlockNumber } from '../services/viem';
|
|
|
21
21
|
|
|
22
22
|
const HARDCODED_USD_STABLE_PRICE = '100000000'; // $1 with 8 decimals
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
const getMorphoRewardIncentives = (apy: string) => [{
|
|
25
|
+
token: 'MORPHO',
|
|
26
|
+
apy,
|
|
27
|
+
incentiveKind: IncentiveKind.Reward,
|
|
28
|
+
description: 'Eligible for protocol-level MORPHO incentives.',
|
|
29
|
+
}];
|
|
30
|
+
|
|
31
|
+
export const addMorphoBlueRewardsToMarketInfo = (
|
|
32
|
+
marketInfo: MorphoBlueMarketInfo,
|
|
33
|
+
rewards: MorphoBlueMarketRewards,
|
|
34
|
+
): MorphoBlueMarketInfo => ({
|
|
35
|
+
...marketInfo,
|
|
36
|
+
assetsData: {
|
|
37
|
+
...marketInfo.assetsData,
|
|
38
|
+
[marketInfo.loanToken]: {
|
|
39
|
+
...marketInfo.assetsData[marketInfo.loanToken],
|
|
40
|
+
supplyIncentives: [
|
|
41
|
+
...marketInfo.assetsData[marketInfo.loanToken].supplyIncentives.filter(({ token }) => token !== 'MORPHO'),
|
|
42
|
+
...getMorphoRewardIncentives(rewards.supplyApy),
|
|
43
|
+
],
|
|
44
|
+
borrowIncentives: [
|
|
45
|
+
...marketInfo.assetsData[marketInfo.loanToken].borrowIncentives.filter(({ token }) => token !== 'MORPHO'),
|
|
46
|
+
...getMorphoRewardIncentives(rewards.borrowApy),
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
async function getMorphoBlueMarketDataInternal(
|
|
53
|
+
provider: Client,
|
|
54
|
+
network: NetworkNumber,
|
|
55
|
+
selectedMarket: MorphoBlueMarketData,
|
|
56
|
+
): Promise<MorphoBlueMarketInfo> {
|
|
25
57
|
const {
|
|
26
58
|
loanToken, collateralToken, oracle, irm, lltv, oracleType,
|
|
27
59
|
} = selectedMarket;
|
|
@@ -59,16 +91,6 @@ export async function _getMorphoBlueMarketData(provider: Client, network: Networ
|
|
|
59
91
|
loanTokenPrice = loanTokenPriceRound[1].toString();
|
|
60
92
|
}
|
|
61
93
|
|
|
62
|
-
let morphoSupplyApy = '0';
|
|
63
|
-
let morphoBorrowApy = '0';
|
|
64
|
-
try {
|
|
65
|
-
const { supplyApy: _morphoSupplyApy, borrowApy: _morphoBorrowApy } = await getRewardsForMarket(selectedMarket.marketId, network);
|
|
66
|
-
morphoSupplyApy = _morphoSupplyApy;
|
|
67
|
-
morphoBorrowApy = _morphoBorrowApy;
|
|
68
|
-
} catch (e) {
|
|
69
|
-
console.error(e);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
94
|
const supplyRate = getSupplyRate(marketInfo.totalSupplyAssets.toString(), marketInfo.totalBorrowAssets.toString(), marketInfo.borrowRate.toString(), marketInfo.fee.toString());
|
|
73
95
|
const compoundedBorrowRate = getBorrowRate(marketInfo.borrowRate.toString(), marketInfo.totalBorrowShares.toString());
|
|
74
96
|
const utillization = new Dec(marketInfo.totalBorrowAssets.toString()).div(marketInfo.totalSupplyAssets.toString()).mul(100).toString();
|
|
@@ -90,18 +112,8 @@ export async function _getMorphoBlueMarketData(provider: Client, network: Networ
|
|
|
90
112
|
totalBorrow: new Dec(marketInfo.totalBorrowAssets.toString()).div(scale).toString(),
|
|
91
113
|
canBeSupplied: true,
|
|
92
114
|
canBeBorrowed: true,
|
|
93
|
-
supplyIncentives: [
|
|
94
|
-
|
|
95
|
-
apy: morphoSupplyApy,
|
|
96
|
-
incentiveKind: IncentiveKind.Reward,
|
|
97
|
-
description: 'Eligible for protocol-level MORPHO incentives.',
|
|
98
|
-
}],
|
|
99
|
-
borrowIncentives: [{
|
|
100
|
-
token: 'MORPHO',
|
|
101
|
-
apy: morphoBorrowApy,
|
|
102
|
-
incentiveKind: IncentiveKind.Reward,
|
|
103
|
-
description: 'Eligible for protocol-level MORPHO incentives.',
|
|
104
|
-
}],
|
|
115
|
+
supplyIncentives: [],
|
|
116
|
+
borrowIncentives: [],
|
|
105
117
|
};
|
|
106
118
|
|
|
107
119
|
assetsData[wethToEth(collateralTokenInfo.symbol)] = {
|
|
@@ -138,10 +150,70 @@ export async function _getMorphoBlueMarketData(provider: Client, network: Networ
|
|
|
138
150
|
};
|
|
139
151
|
}
|
|
140
152
|
|
|
153
|
+
export async function _getMorphoBlueMarketData(provider: Client, network: NetworkNumber, selectedMarket: MorphoBlueMarketData): Promise<MorphoBlueMarketInfo> {
|
|
154
|
+
const marketInfo = await getMorphoBlueMarketDataInternal(provider, network, selectedMarket);
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
const rewards = await getRewardsForMarket(selectedMarket.marketId, network);
|
|
158
|
+
return addMorphoBlueRewardsToMarketInfo(marketInfo, rewards);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
console.error(error);
|
|
161
|
+
return addMorphoBlueRewardsToMarketInfo(marketInfo, { supplyApy: '0', borrowApy: '0' });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function _getMorphoBluePortfolioMarketData(provider: Client, network: NetworkNumber, selectedMarket: MorphoBlueMarketData): Promise<MorphoBlueMarketInfo> {
|
|
166
|
+
return getMorphoBlueMarketDataInternal(provider, network, selectedMarket);
|
|
167
|
+
}
|
|
168
|
+
|
|
141
169
|
export async function getMorphoBlueMarketData(provider: EthereumProvider, network: NetworkNumber, selectedMarket: MorphoBlueMarketData): Promise<MorphoBlueMarketInfo> {
|
|
142
170
|
return _getMorphoBlueMarketData(getViemProvider(provider, network), network, selectedMarket);
|
|
143
171
|
}
|
|
144
172
|
|
|
173
|
+
export function getMorphoBluePortfolioMarketData(provider: EthereumProvider, network: NetworkNumber, selectedMarket: MorphoBlueMarketData): Promise<MorphoBlueMarketInfo> {
|
|
174
|
+
return _getMorphoBluePortfolioMarketData(getViemProvider(provider, network), network, selectedMarket);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export const getMorphoBluePositionDataWithMarketInfo = (
|
|
178
|
+
data: MorphoBluePositionData,
|
|
179
|
+
marketInfo: MorphoBlueMarketInfo,
|
|
180
|
+
): MorphoBluePositionData => ({
|
|
181
|
+
...data,
|
|
182
|
+
...getMorphoBlueAggregatedPositionData({
|
|
183
|
+
usedAssets: data.usedAssets,
|
|
184
|
+
assetsData: marketInfo.assetsData,
|
|
185
|
+
marketInfo,
|
|
186
|
+
}),
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
export const getMorphoEarnDataWithMarketInfo = (data: MorphoBlueEarnData, marketInfo: MorphoBlueMarketInfo): MorphoBlueEarnData => {
|
|
190
|
+
const loanTokenInfo = marketInfo.assetsData[marketInfo.loanToken];
|
|
191
|
+
const usedAssets: MMUsedAssets = {
|
|
192
|
+
[marketInfo.loanToken]: {
|
|
193
|
+
symbol: loanTokenInfo.symbol,
|
|
194
|
+
supplied: data.amount,
|
|
195
|
+
borrowed: '0',
|
|
196
|
+
isSupplied: new Dec(data.amount).gt(0),
|
|
197
|
+
isBorrowed: false,
|
|
198
|
+
collateral: false,
|
|
199
|
+
suppliedUsd: data.amountUsd,
|
|
200
|
+
borrowedUsd: '0',
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
...data,
|
|
206
|
+
apy: calculateNetApy({ usedAssets, assetsData: marketInfo.assetsData as unknown as MMAssetsData }).netApy,
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
export function getMorphoBlueMarketRewards(
|
|
211
|
+
network: NetworkNumber,
|
|
212
|
+
selectedMarket: MorphoBlueMarketData,
|
|
213
|
+
): Promise<MorphoBlueMarketRewards> {
|
|
214
|
+
return getRewardsForMarket(selectedMarket.marketId, network);
|
|
215
|
+
}
|
|
216
|
+
|
|
145
217
|
export const _getMorphoBlueAccountBalances = async (provider: Client, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress, selectedMarket: MorphoBlueMarketData): Promise<PositionBalances> => {
|
|
146
218
|
let balances: PositionBalances = {
|
|
147
219
|
collateral: {},
|
|
@@ -238,7 +310,7 @@ export async function getMorphoBlueAccountData(provider: EthereumProvider, netwo
|
|
|
238
310
|
return _getMorphoBlueAccountData(getViemProvider(provider, network), network, account, selectedMarket, marketInfo);
|
|
239
311
|
}
|
|
240
312
|
|
|
241
|
-
export async function getMorphoEarn(provider: Client, network: NetworkNumber, account: EthAddress, selectedMarket: MorphoBlueMarketData, marketInfo: MorphoBlueMarketInfo): Promise<
|
|
313
|
+
export async function getMorphoEarn(provider: Client, network: NetworkNumber, account: EthAddress, selectedMarket: MorphoBlueMarketData, marketInfo: MorphoBlueMarketInfo): Promise<MorphoBlueEarnData> {
|
|
242
314
|
const {
|
|
243
315
|
loanToken, collateralToken, oracle, irm, lltv,
|
|
244
316
|
} = selectedMarket;
|
|
@@ -254,24 +326,9 @@ export async function getMorphoEarn(provider: Client, network: NetworkNumber, ac
|
|
|
254
326
|
const loanTokenInfo = marketInfo.assetsData[marketInfo.loanToken];
|
|
255
327
|
const loanTokenSupplied = assetAmountInEth(loanInfo.suppliedInAssets.toString(), marketInfo.loanToken);
|
|
256
328
|
const loanTokenSuppliedUsd = new Dec(loanTokenSupplied).mul(loanTokenInfo.price).toString();
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
symbol: loanTokenInfo.symbol,
|
|
260
|
-
supplied: loanTokenSupplied,
|
|
261
|
-
borrowed: '0',
|
|
262
|
-
isSupplied: new Dec(loanInfo.suppliedInAssets.toString()).gt(0),
|
|
263
|
-
isBorrowed: false,
|
|
264
|
-
collateral: false,
|
|
265
|
-
suppliedUsd: loanTokenSuppliedUsd,
|
|
266
|
-
borrowedUsd: '0',
|
|
267
|
-
},
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
const { netApy } = calculateNetApy({ usedAssets, assetsData: marketInfo.assetsData as unknown as MMAssetsData });
|
|
271
|
-
|
|
272
|
-
return {
|
|
273
|
-
apy: netApy,
|
|
329
|
+
return getMorphoEarnDataWithMarketInfo({
|
|
330
|
+
apy: '0',
|
|
274
331
|
amount: loanTokenSupplied,
|
|
275
332
|
amountUsd: loanTokenSuppliedUsd,
|
|
276
|
-
};
|
|
277
|
-
}
|
|
333
|
+
}, marketInfo);
|
|
334
|
+
}
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import { USD_QUOTE } from '../constants';
|
|
14
14
|
import { calculateNetApy } from '../staking';
|
|
15
15
|
import { isMainnetNetwork, wethToEth } from '../services/utils';
|
|
16
|
-
import { getMorphoMidnightAggregatedPositionData } from '../helpers/morphoMidnightHelpers';
|
|
16
|
+
import { getMorphoMidnightAggregatedPositionData, getMorphoMidnightUserBorrowInfo } from '../helpers/morphoMidnightHelpers';
|
|
17
17
|
import { getChainlinkAssetAddress } from '../services/priceService';
|
|
18
18
|
import { getViemProvider, setViemBlockNumber } from '../services/viem';
|
|
19
19
|
|
|
@@ -157,13 +157,40 @@ export async function _getMorphoMidnightAccountData(provider: Client, network: N
|
|
|
157
157
|
};
|
|
158
158
|
});
|
|
159
159
|
|
|
160
|
+
// Enrich borrower positions with the orderbook-derived rate + principal/interest split (off-chain).
|
|
161
|
+
// MidnightView only stores `debt` (= face value at maturity), so we default to full-debt-as-principal and
|
|
162
|
+
// override from the transactions API when available. Never throw here — the position must still render.
|
|
163
|
+
let borrowRate = '0';
|
|
164
|
+
let debtBase = debt; // fallback: treat the full on-chain debt as principal until fill history is known
|
|
165
|
+
let debtInterest = '0';
|
|
166
|
+
let assetsDataForApy = marketInfo.assetsData;
|
|
167
|
+
if (new Dec(positionInfo.debt.toString()).gt(0)) {
|
|
168
|
+
try {
|
|
169
|
+
const borrowInfo = await getMorphoMidnightUserBorrowInfo(account, marketId, marketInfo.maturity, marketInfo.loanToken);
|
|
170
|
+
borrowRate = borrowInfo.borrowRate;
|
|
171
|
+
debtBase = borrowInfo.debtBase;
|
|
172
|
+
debtInterest = borrowInfo.debtInterest;
|
|
173
|
+
usedAssets[marketInfo.loanToken].borrowRate = borrowRate;
|
|
174
|
+
// Reflect the real borrow cost in netApy without mutating the shared marketInfo.assetsData.
|
|
175
|
+
assetsDataForApy = {
|
|
176
|
+
...marketInfo.assetsData,
|
|
177
|
+
[marketInfo.loanToken]: { ...loanTokenData, borrowRate },
|
|
178
|
+
};
|
|
179
|
+
} catch (err) {
|
|
180
|
+
// Orderbook API unavailable — keep the on-chain-only fallback above.
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
160
184
|
return {
|
|
161
185
|
usedAssets,
|
|
162
186
|
credit,
|
|
163
187
|
debt,
|
|
188
|
+
borrowRate,
|
|
189
|
+
debtBase,
|
|
190
|
+
debtInterest,
|
|
164
191
|
maturity: marketInfo.maturity,
|
|
165
192
|
isMatured: marketInfo.isMatured,
|
|
166
|
-
...getMorphoMidnightAggregatedPositionData({ usedAssets, assetsData:
|
|
193
|
+
...getMorphoMidnightAggregatedPositionData({ usedAssets, assetsData: assetsDataForApy, marketInfo }),
|
|
167
194
|
};
|
|
168
195
|
}
|
|
169
196
|
|
package/src/portfolio/index.ts
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
MorphoMidnightMarkets,
|
|
13
13
|
SparkMarkets,
|
|
14
14
|
} from '../markets';
|
|
15
|
-
import { _getMorphoBlueAccountData,
|
|
15
|
+
import { _getMorphoBlueAccountData, _getMorphoBluePortfolioMarketData, getMorphoEarn } from '../morphoBlue';
|
|
16
16
|
import { _getMorphoMidnightAccountData, _getMorphoMidnightMarketData, getMorphoMidnightEarn } from '../morphoMidnight';
|
|
17
17
|
import {
|
|
18
18
|
AaveV2MarketData,
|
|
@@ -54,6 +54,7 @@ import { fetchSparkAirdropRewards, fetchSparkRewards } from '../claiming/spark';
|
|
|
54
54
|
import { getKingRewards } from '../claiming/king';
|
|
55
55
|
import { fetchEthenaAirdropRewards } from '../claiming/ethena';
|
|
56
56
|
import { _getAaveV4AccountData, _getAaveV4SpokeData } from '../aaveV4';
|
|
57
|
+
import { getUniswapRewards } from '../claiming/uniswap';
|
|
57
58
|
|
|
58
59
|
export async function getPortfolioData(provider: EthereumProvider, network: NetworkNumber, defaultProvider: EthereumProvider, addresses: EthAddress[], isSim = false): Promise<{
|
|
59
60
|
positions: PortfolioPositionsData;
|
|
@@ -78,7 +79,8 @@ export async function getPortfolioData(provider: EthereumProvider, network: Netw
|
|
|
78
79
|
const liquityV2MarketsStaking = [NetworkNumber.Eth].includes(network) ? Object.values(LiquityV2Markets(network)).filter(market => !market.isLegacy) : [];
|
|
79
80
|
const aaveV4Spokes = Object.values(AaveV4Spokes(network)).filter((market) => market.chainIds.includes(network));
|
|
80
81
|
|
|
81
|
-
|
|
82
|
+
|
|
83
|
+
const args: [NetworkNumber, any?] = [network, { batch: { multicall: { batchSize: isSim ? 2_000 : 2_500_000 } } }];
|
|
82
84
|
const client = getViemProvider(provider, ...args);
|
|
83
85
|
const defaultClient = getViemProvider(defaultProvider, ...args);
|
|
84
86
|
|
|
@@ -170,7 +172,7 @@ export async function getPortfolioData(provider: EthereumProvider, network: Netw
|
|
|
170
172
|
await Promise.allSettled([
|
|
171
173
|
// === MARKET DATA (needs to be fetched first) ===
|
|
172
174
|
...morphoMarkets.map(async (market) => {
|
|
173
|
-
const marketData = await
|
|
175
|
+
const marketData = await _getMorphoBluePortfolioMarketData(client, network, market);
|
|
174
176
|
morphoMarketsData[market.value] = marketData;
|
|
175
177
|
}),
|
|
176
178
|
...morphoMidnightMarkets.map(async (market) => {
|
|
@@ -322,6 +324,33 @@ export async function getPortfolioData(provider: EthereumProvider, network: Netw
|
|
|
322
324
|
}
|
|
323
325
|
}
|
|
324
326
|
})(),
|
|
327
|
+
// Batch UNI rewards
|
|
328
|
+
(async () => {
|
|
329
|
+
try {
|
|
330
|
+
if (!isMainnet) {
|
|
331
|
+
for (const address of addresses) {
|
|
332
|
+
rewardsData[address.toLowerCase()].uniswap = { error: '', data: [] };
|
|
333
|
+
}
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
const uniswapRewards = await getUniswapRewards(client, network, addresses);
|
|
337
|
+
for (const address of addresses) {
|
|
338
|
+
const lowerAddress = address.toLowerCase() as EthAddress;
|
|
339
|
+
rewardsData[lowerAddress].uniswap = {
|
|
340
|
+
error: '',
|
|
341
|
+
data: uniswapRewards[lowerAddress] || [],
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
} catch (error) {
|
|
345
|
+
console.error('Error fetching Uniswap rewards data in batch:', error);
|
|
346
|
+
for (const address of addresses) {
|
|
347
|
+
rewardsData[address.toLowerCase() as EthAddress].uniswap = {
|
|
348
|
+
error: 'Error fetching Uniswap rewards data in batch',
|
|
349
|
+
data: null,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
})(),
|
|
325
354
|
...sparkMarkets.map((market) => addresses.map(async address => {
|
|
326
355
|
try {
|
|
327
356
|
if (!isMainnet) {
|
|
@@ -8,7 +8,7 @@ export const SUMMER_VAULT_USDC_MAINNET_LR: SummerVault = {
|
|
|
8
8
|
asset: 'USDC',
|
|
9
9
|
network: NetworkNumber.Eth,
|
|
10
10
|
deploymentBlock: 21795049,
|
|
11
|
-
isLegacy:
|
|
11
|
+
isLegacy: true,
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
export const SUMMER_VAULT_USDC_MAINNET_HR: SummerVault = {
|
|
@@ -18,7 +18,7 @@ export const SUMMER_VAULT_USDC_MAINNET_HR: SummerVault = {
|
|
|
18
18
|
asset: 'USDC',
|
|
19
19
|
network: NetworkNumber.Eth,
|
|
20
20
|
deploymentBlock: 22488041,
|
|
21
|
-
isLegacy:
|
|
21
|
+
isLegacy: true,
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
export const SUMMER_VAULT_USDT_MAINNET_LR: SummerVault = {
|
|
@@ -28,7 +28,7 @@ export const SUMMER_VAULT_USDT_MAINNET_LR: SummerVault = {
|
|
|
28
28
|
asset: 'USDT',
|
|
29
29
|
network: NetworkNumber.Eth,
|
|
30
30
|
deploymentBlock: 21795276,
|
|
31
|
-
isLegacy:
|
|
31
|
+
isLegacy: true,
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
export const SUMMER_VAULT_ETH_MAINNET_LR: SummerVault = {
|
|
@@ -38,7 +38,7 @@ export const SUMMER_VAULT_ETH_MAINNET_LR: SummerVault = {
|
|
|
38
38
|
asset: 'WETH',
|
|
39
39
|
network: NetworkNumber.Eth,
|
|
40
40
|
deploymentBlock: 21795390,
|
|
41
|
-
isLegacy:
|
|
41
|
+
isLegacy: true,
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
export const SUMMER_VAULT_ETH_MAINNET_HR: SummerVault = {
|
|
@@ -48,7 +48,7 @@ export const SUMMER_VAULT_ETH_MAINNET_HR: SummerVault = {
|
|
|
48
48
|
asset: 'WETH',
|
|
49
49
|
network: NetworkNumber.Eth,
|
|
50
50
|
deploymentBlock: 22291252,
|
|
51
|
-
isLegacy:
|
|
51
|
+
isLegacy: true,
|
|
52
52
|
};
|
|
53
53
|
|
|
54
54
|
export const SUMMER_VAULT_USDC_ARBITRUM_LR: SummerVault = {
|
|
@@ -58,7 +58,7 @@ export const SUMMER_VAULT_USDC_ARBITRUM_LR: SummerVault = {
|
|
|
58
58
|
asset: 'USDC',
|
|
59
59
|
network: NetworkNumber.Arb,
|
|
60
60
|
deploymentBlock: 404339289,
|
|
61
|
-
isLegacy:
|
|
61
|
+
isLegacy: true,
|
|
62
62
|
};
|
|
63
63
|
|
|
64
64
|
export const SUMMER_VAULT_USDT_ARBITRUM_LR: SummerVault = {
|
|
@@ -68,7 +68,7 @@ export const SUMMER_VAULT_USDT_ARBITRUM_LR: SummerVault = {
|
|
|
68
68
|
asset: 'USDT',
|
|
69
69
|
network: NetworkNumber.Arb,
|
|
70
70
|
deploymentBlock: 303594065,
|
|
71
|
-
isLegacy:
|
|
71
|
+
isLegacy: true,
|
|
72
72
|
};
|
|
73
73
|
|
|
74
74
|
export const SUMMER_VAULT_USDC_BASE_LR: SummerVault = {
|
|
@@ -78,7 +78,7 @@ export const SUMMER_VAULT_USDC_BASE_LR: SummerVault = {
|
|
|
78
78
|
asset: 'USDC',
|
|
79
79
|
network: NetworkNumber.Base,
|
|
80
80
|
deploymentBlock: 303594065,
|
|
81
|
-
isLegacy:
|
|
81
|
+
isLegacy: true,
|
|
82
82
|
};
|
|
83
83
|
|
|
84
84
|
export const SUMMER_VAULT_EURC_BASE_LR: SummerVault = {
|
|
@@ -88,7 +88,7 @@ export const SUMMER_VAULT_EURC_BASE_LR: SummerVault = {
|
|
|
88
88
|
asset: 'EURC',
|
|
89
89
|
network: NetworkNumber.Base,
|
|
90
90
|
deploymentBlock: 27544064,
|
|
91
|
-
isLegacy:
|
|
91
|
+
isLegacy: true,
|
|
92
92
|
};
|
|
93
93
|
|
|
94
94
|
export const SUMMER_VAULT_ETH_BASE_LR: SummerVault = {
|
|
@@ -98,7 +98,7 @@ export const SUMMER_VAULT_ETH_BASE_LR: SummerVault = {
|
|
|
98
98
|
asset: 'WETH',
|
|
99
99
|
network: NetworkNumber.Base,
|
|
100
100
|
deploymentBlock: 29066887,
|
|
101
|
-
isLegacy:
|
|
101
|
+
isLegacy: true,
|
|
102
102
|
};
|
|
103
103
|
|
|
104
104
|
export const SUMMER_VAULTS: Record<SummerVaultType, SummerVault> = {
|
package/src/staking/staking.ts
CHANGED
|
@@ -66,6 +66,7 @@ export const STAKING_ASSETS = [
|
|
|
66
66
|
'PT sUSDe Nov', 'PT USDe Nov', 'PT USDe Jan', 'PT sUSDe Jan', 'wrsETH', 'wstETH', 'syrupUSDT', 'syrupUSDC', 'wstUSR',
|
|
67
67
|
'PT sUSDe Feb', 'PT USDe Feb', 'PT sUSDe Apr', 'PT USDe Apr', 'PT sUSDe May', 'PT USDe May', 'PT srUSDe Apr', 'GHO',
|
|
68
68
|
'PT sUSDe June', 'PT USDe June', 'PT srUSDe Jun', 'PT srUSDe Oct', 'PT USDG May', 'PT sUSDS Nov', 'PT sUSDe Oct', 'PT USDG Sep',
|
|
69
|
+
'syrupUSDG',
|
|
69
70
|
];
|
|
70
71
|
|
|
71
72
|
export const getStakingApy = memoize(async (asset: string, network: number = NetworkNumber.Eth) => {
|
|
@@ -97,6 +98,7 @@ export const getStakingApy = memoize(async (asset: string, network: number = Net
|
|
|
97
98
|
if (asset === 'PT sUSDe Jan') return await getApyFromDfsApi('PT sUSDe Jan', network);
|
|
98
99
|
if (asset === 'syrupUSDT') return await getApyFromDfsApi('syrupUSDT');
|
|
99
100
|
if (asset === 'syrupUSDC') return await getApyFromDfsApi('syrupUSDC');
|
|
101
|
+
if (asset === 'syrupUSDG') return await getApyFromDfsApi('syrupUSDG');
|
|
100
102
|
if (asset === 'wstUSR') return await getApyFromDfsApi('wstUSR');
|
|
101
103
|
if (asset === 'PT sUSDe Feb') return await getApyFromDfsApi('PT sUSDe Feb', network);
|
|
102
104
|
if (asset === 'PT USDe Feb') return await getApyFromDfsApi('PT USDe Feb', network);
|
package/src/types/aaveV4.ts
CHANGED
|
@@ -21,6 +21,7 @@ export enum AaveV4SpokesType {
|
|
|
21
21
|
AaveV4LombardBtcSpoke = 'aave_v4_lombard_btc_spoke',
|
|
22
22
|
AaveV4MainSpoke = 'aave_v4_main_spoke',
|
|
23
23
|
AaveV4USDGPendleSpoke = 'aave_v4_usdg_pendle_spoke',
|
|
24
|
+
AaveV4USDGMapleSpoke = 'aave_v4_usdg_maple_spoke',
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export interface AaveV4HubInfo {
|
package/src/types/claiming.ts
CHANGED
|
@@ -15,6 +15,8 @@ export enum ClaimType {
|
|
|
15
15
|
SPARK_AIRDROP = 'SPARK_AIRDROP',
|
|
16
16
|
/** Spark Airdrop */
|
|
17
17
|
SPARK_WST_ETH_REWARDS = 'SPARK_WST_ETH_REWARDS', // TODO: This will be removed once we fully refactor spark rewards
|
|
18
|
+
/** UNI Airdrop */
|
|
19
|
+
UNI_REWARDS = 'UNI_REWARDS',
|
|
18
20
|
|
|
19
21
|
ETHENA_AIRDROP = 'ETHENA_AIRDROP',
|
|
20
22
|
}
|
|
@@ -88,6 +90,15 @@ export type SparkWstEthRewardsClaimableToken = _ClaimableTokenPartial & { claimT
|
|
|
88
90
|
|
|
89
91
|
export type EthenaAirdropClaimableToken = _ClaimableTokenPartial & { claimType: ClaimType.ETHENA_AIRDROP };
|
|
90
92
|
|
|
93
|
+
export type UniswapAirdropClaimableToken = _ClaimableTokenPartial & {
|
|
94
|
+
claimType: ClaimType.UNI_REWARDS,
|
|
95
|
+
additionalClaimFields: {
|
|
96
|
+
index: number;
|
|
97
|
+
isClaimed: boolean;
|
|
98
|
+
proof: string[];
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
|
|
91
102
|
export type ClaimableToken =
|
|
92
103
|
AaveRewardsClaimableToken
|
|
93
104
|
| AaveMeritRewardsClaimableToken
|
package/src/types/morphoBlue.ts
CHANGED
|
@@ -235,6 +235,17 @@ export interface MorphoBluePositionData {
|
|
|
235
235
|
exposure: string,
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
+
export interface MorphoBlueEarnData {
|
|
239
|
+
apy: string,
|
|
240
|
+
amount: string,
|
|
241
|
+
amountUsd: string,
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export interface MorphoBlueMarketRewards {
|
|
245
|
+
supplyApy: string,
|
|
246
|
+
borrowApy: string,
|
|
247
|
+
}
|
|
248
|
+
|
|
238
249
|
export interface MorphoBlueVault {
|
|
239
250
|
address: string,
|
|
240
251
|
}
|
|
@@ -99,6 +99,12 @@ export interface MorphoMidnightPositionData extends MorphoMidnightAggregatedPosi
|
|
|
99
99
|
usedAssets: MMUsedAssets,
|
|
100
100
|
credit: string, // lender credit units, face value at maturity (with interest); 0 for borrowers
|
|
101
101
|
debt: string, // borrower debt, face value at maturity (with interest); 0 for lenders
|
|
102
|
+
// Borrow rate + base/interest split are orderbook-derived off-chain (from the Midnight transactions API):
|
|
103
|
+
// MidnightView only stores `debt` (= face value at maturity), so principal-vs-interest and the effective
|
|
104
|
+
// rate are computed from the fill history. Default to '0'/`debt`/'0' for lenders or when the API is unavailable.
|
|
105
|
+
borrowRate: string, // weighted-average borrow APY as a percent
|
|
106
|
+
debtBase: string, // base borrowed (principal), loan-token units
|
|
107
|
+
debtInterest: string, // debt − debtBase (fixed interest owed at maturity), loan-token units
|
|
102
108
|
maturity: number,
|
|
103
109
|
isMatured: boolean,
|
|
104
110
|
}
|