@defisaver/positions-sdk 2.1.168-stable-pair-dev → 2.1.169-portfolio-api-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.d.ts +2 -12
- package/cjs/aaveV3/sgho.d.ts +2 -16
- package/cjs/aaveV4/lend.d.ts +2 -43
- package/cjs/claiming/aaveV3.d.ts +2 -2
- package/cjs/claiming/ethena.d.ts +2 -1
- package/cjs/claiming/king.d.ts +2 -1
- package/cjs/claiming/spark.d.ts +2 -2
- package/cjs/fluid/index.d.ts +5 -49
- package/cjs/helpers/aaveV4Helpers/index.js +1 -11
- package/cjs/liquity/index.d.ts +2 -12
- package/cjs/liquityV2/index.d.ts +8 -23
- package/cjs/liquityV2/index.js +37 -19
- package/cjs/moneymarket/moneymarketCommonService.js +2 -12
- package/cjs/portfolio/index.d.ts +16 -8
- package/cjs/portfolio/index.js +458 -520
- package/cjs/portfolio/lendingProtocols.d.ts +184 -0
- package/cjs/portfolio/lendingProtocols.js +196 -0
- package/cjs/savings/index.d.ts +8 -2
- package/cjs/savings/index.js +33 -4
- package/cjs/types/aave.d.ts +98 -2
- package/cjs/types/aaveV4.d.ts +44 -0
- package/cjs/types/common.d.ts +0 -1
- package/cjs/types/common.js +0 -1
- package/cjs/types/compound.d.ts +26 -2
- package/cjs/types/curveUsd.d.ts +9 -1
- package/cjs/types/fluid.d.ts +13 -0
- package/cjs/types/index.d.ts +1 -0
- package/cjs/types/index.js +1 -0
- package/cjs/types/liquity.d.ts +12 -0
- package/cjs/types/liquityV2.d.ts +24 -0
- package/cjs/types/llamaLend.d.ts +12 -1
- package/cjs/types/morphoBlue.d.ts +2 -0
- package/cjs/types/portfolio.d.ts +125 -5
- package/cjs/types/savings/index.d.ts +9 -1
- package/cjs/types/spark.d.ts +21 -1
- package/cjs/umbrella/index.d.ts +2 -3
- package/esm/aaveV3/index.d.ts +2 -12
- package/esm/aaveV3/sgho.d.ts +2 -16
- package/esm/aaveV4/lend.d.ts +2 -43
- package/esm/claiming/aaveV3.d.ts +2 -2
- package/esm/claiming/aaveV3.js +1 -1
- package/esm/claiming/ethena.d.ts +2 -1
- package/esm/claiming/king.d.ts +2 -1
- package/esm/claiming/spark.d.ts +2 -2
- package/esm/claiming/spark.js +1 -1
- package/esm/fluid/index.d.ts +5 -49
- package/esm/helpers/aaveV4Helpers/index.js +1 -11
- package/esm/liquity/index.d.ts +2 -12
- package/esm/liquityV2/index.d.ts +8 -23
- package/esm/liquityV2/index.js +35 -18
- package/esm/moneymarket/moneymarketCommonService.js +2 -12
- package/esm/portfolio/index.d.ts +16 -8
- package/esm/portfolio/index.js +458 -522
- package/esm/portfolio/lendingProtocols.d.ts +184 -0
- package/esm/portfolio/lendingProtocols.js +189 -0
- package/esm/savings/index.d.ts +8 -2
- package/esm/savings/index.js +31 -3
- package/esm/types/aave.d.ts +98 -2
- package/esm/types/aaveV4.d.ts +44 -0
- package/esm/types/common.d.ts +0 -1
- package/esm/types/common.js +0 -1
- package/esm/types/compound.d.ts +26 -2
- package/esm/types/curveUsd.d.ts +9 -1
- package/esm/types/fluid.d.ts +13 -0
- package/esm/types/index.d.ts +1 -0
- package/esm/types/index.js +1 -0
- package/esm/types/liquity.d.ts +12 -0
- package/esm/types/liquityV2.d.ts +24 -0
- package/esm/types/llamaLend.d.ts +12 -1
- package/esm/types/morphoBlue.d.ts +2 -0
- package/esm/types/portfolio.d.ts +125 -5
- package/esm/types/savings/index.d.ts +9 -1
- package/esm/types/spark.d.ts +21 -1
- package/esm/umbrella/index.d.ts +2 -3
- package/package.json +1 -1
- package/src/aaveV3/index.ts +2 -1
- package/src/aaveV3/sgho.ts +2 -17
- package/src/aaveV4/lend.ts +2 -48
- package/src/claiming/aaveV3.ts +4 -2
- package/src/claiming/ethena.ts +5 -5
- package/src/claiming/king.ts +3 -3
- package/src/claiming/spark.ts +6 -4
- package/src/fluid/index.ts +4 -3
- package/src/helpers/aaveV4Helpers/index.ts +1 -12
- package/src/liquity/index.ts +2 -2
- package/src/liquityV2/index.ts +48 -22
- package/src/moneymarket/moneymarketCommonService.ts +2 -13
- package/src/portfolio/index.ts +306 -331
- package/src/portfolio/lendingProtocols.ts +281 -0
- package/src/savings/index.ts +41 -4
- package/src/types/aave.ts +104 -1
- package/src/types/aaveV4.ts +49 -0
- package/src/types/common.ts +0 -1
- package/src/types/compound.ts +38 -2
- package/src/types/curveUsd.ts +17 -1
- package/src/types/fluid.ts +14 -0
- package/src/types/index.ts +1 -0
- package/src/types/liquity.ts +13 -1
- package/src/types/liquityV2.ts +26 -1
- package/src/types/llamaLend.ts +19 -1
- package/src/types/morphoBlue.ts +3 -0
- package/src/types/portfolio.ts +151 -5
- package/src/types/savings/index.ts +12 -1
- package/src/types/spark.ts +25 -1
- package/src/umbrella/index.ts +2 -1
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import Dec from 'decimal.js';
|
|
2
|
+
import { Client } from 'viem';
|
|
3
|
+
import { EthAddress, NetworkNumber } from '../types/common';
|
|
4
|
+
import {
|
|
5
|
+
AaveMarkets,
|
|
6
|
+
AaveV4Spokes,
|
|
7
|
+
CompoundMarkets,
|
|
8
|
+
CrvUsdMarkets,
|
|
9
|
+
LlamaLendMarkets,
|
|
10
|
+
MorphoBlueMarkets,
|
|
11
|
+
MorphoMidnightMarkets,
|
|
12
|
+
SparkMarkets,
|
|
13
|
+
} from '../markets';
|
|
14
|
+
import {
|
|
15
|
+
AaveMarketInfo,
|
|
16
|
+
AaveV4SpokeInfo,
|
|
17
|
+
AaveVersions,
|
|
18
|
+
CompoundMarketData,
|
|
19
|
+
CompoundVersions,
|
|
20
|
+
CrvUSDMarketData,
|
|
21
|
+
LlamaLendMarketData,
|
|
22
|
+
MorphoBlueMarketData,
|
|
23
|
+
MorphoMidnightMarketData,
|
|
24
|
+
PortfolioMarketsData,
|
|
25
|
+
PortfolioPositionsData,
|
|
26
|
+
PortfolioPositionsDataForAddress,
|
|
27
|
+
PortfolioProtocolData,
|
|
28
|
+
SparkMarketData,
|
|
29
|
+
} from '../types';
|
|
30
|
+
import { _getAaveV3AccountData, _getAaveV3MarketData } from '../aaveV3';
|
|
31
|
+
import { _getAaveV4AccountData, _getAaveV4SpokeData } from '../aaveV4';
|
|
32
|
+
import { _getAaveV2AccountData, _getAaveV2MarketsData } from '../aaveV2';
|
|
33
|
+
import { _getCompoundV2AccountData, _getCompoundV2MarketsData } from '../compoundV2';
|
|
34
|
+
import { _getCompoundV3AccountData, _getCompoundV3MarketsData } from '../compoundV3';
|
|
35
|
+
import { _getCurveUsdGlobalData, _getCurveUsdUserData } from '../curveUsd';
|
|
36
|
+
import { _getLlamaLendGlobalData, _getLlamaLendUserData } from '../llamaLend';
|
|
37
|
+
import { _getMorphoBlueAccountData, _getMorphoBluePortfolioMarketData } from '../morphoBlue';
|
|
38
|
+
import { _getMorphoMidnightAccountData, _getMorphoMidnightMarketData } from '../morphoMidnight';
|
|
39
|
+
import { _getSparkAccountData, _getSparkMarketsData } from '../spark';
|
|
40
|
+
import { ZERO_ADDRESS } from '../constants';
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The lending protocols the portfolio reads the same way — a market's data, then each address's position on it — one
|
|
44
|
+
* entry each. Adding such a protocol is its types (its key in PortfolioPositionsDataForAddress and in
|
|
45
|
+
* PortfolioMarketsData) and its entry in LENDING_PROTOCOLS; the portfolio reads, errors and options follow. Maker,
|
|
46
|
+
* Liquity, Fluid and Liquity V2 have shapes of their own and are read by their own code in ./index.ts.
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
/** What a position read gets. */
|
|
50
|
+
export interface PortfolioReadContext {
|
|
51
|
+
client: Client;
|
|
52
|
+
network: NetworkNumber;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** What a market read gets: also the default client, on Ethereum (Compound V3 reads its prices there). */
|
|
56
|
+
export interface PortfolioMarketsReadContext extends PortfolioReadContext {
|
|
57
|
+
defaultClient: Client;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
type PositionKey = keyof PortfolioPositionsDataForAddress;
|
|
61
|
+
type MarketsKey = keyof PortfolioMarketsData;
|
|
62
|
+
type PositionsOf<K extends PositionKey> = NonNullable<PortfolioPositionsDataForAddress[K]>;
|
|
63
|
+
|
|
64
|
+
/** The data of one of a protocol's positions: what positions[address][K][market] holds as `{ error, data }`. */
|
|
65
|
+
export type LendingPositionData<K extends PositionKey> =
|
|
66
|
+
NonNullable<PositionsOf<K>[keyof PositionsOf<K>]> extends PortfolioProtocolData<infer D> ? D : never;
|
|
67
|
+
|
|
68
|
+
export interface LendingProtocol<K extends PositionKey, M extends MarketsKey, Market extends { value: string }> {
|
|
69
|
+
/** Its key in PortfolioMarketsData. */
|
|
70
|
+
marketsKey: M;
|
|
71
|
+
/** Its name in error messages. */
|
|
72
|
+
label: string;
|
|
73
|
+
/** Its markets on a network; none where it is not deployed. */
|
|
74
|
+
markets: (network: NetworkNumber) => Market[];
|
|
75
|
+
readMarket: (context: PortfolioMarketsReadContext, market: Market) => Promise<PortfolioMarketsData[M][string]>;
|
|
76
|
+
/** An address's position on a market; undefined when the market can hold none. */
|
|
77
|
+
readPosition: (
|
|
78
|
+
context: PortfolioReadContext,
|
|
79
|
+
address: EthAddress,
|
|
80
|
+
market: Market,
|
|
81
|
+
marketData: PortfolioMarketsData[M][string],
|
|
82
|
+
) => Promise<LendingPositionData<K> | undefined>;
|
|
83
|
+
/** Whether there is a position to list: an address without one gets no entry for that market. */
|
|
84
|
+
holds: (position: LendingPositionData<K>) => boolean;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* A market's data, or a throw that the caller's catch turns into the position's error entry: read against a missing
|
|
89
|
+
* market, a position would otherwise come back empty and read as "no position".
|
|
90
|
+
*/
|
|
91
|
+
export const requireMarket = <T>(marketsData: Record<string, T>, market: string): T => {
|
|
92
|
+
const marketData = marketsData[market];
|
|
93
|
+
if (!marketData) throw new Error(`Market data for ${market} is not available`);
|
|
94
|
+
return marketData;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/** requireMarket for one protocol's key, typed by that key's market data. */
|
|
98
|
+
const requireMarketOf = <M extends MarketsKey>(marketsData: PortfolioMarketsData, key: M, market: string): PortfolioMarketsData[M][string] => {
|
|
99
|
+
// TypeScript reads marketsData[key][market] as any protocol's market data; the key's own is what is stored there.
|
|
100
|
+
const marketData = (marketsData[key] as Record<string, PortfolioMarketsData[M][string] | undefined>)[market];
|
|
101
|
+
if (!marketData) throw new Error(`Market data for ${market} is not available`);
|
|
102
|
+
return marketData;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/** A protocol's entry with its reads, typed by its own market and position types. */
|
|
106
|
+
const lendingProtocol = <K extends PositionKey, M extends MarketsKey, Market extends { value: string }>(
|
|
107
|
+
key: K,
|
|
108
|
+
protocol: LendingProtocol<K, M, Market>,
|
|
109
|
+
) => {
|
|
110
|
+
/** Every market of the protocol into `markets`; resolves to the ones that failed (left out), with their errors. */
|
|
111
|
+
const readMarkets = async (context: PortfolioMarketsReadContext, markets: PortfolioMarketsData): Promise<Record<string, string>> => {
|
|
112
|
+
const protocolMarkets = markets[protocol.marketsKey];
|
|
113
|
+
const failed: Record<string, string> = {};
|
|
114
|
+
await Promise.all(protocol.markets(context.network).map(async (market) => {
|
|
115
|
+
try {
|
|
116
|
+
protocolMarkets[market.value] = await protocol.readMarket(context, market);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
console.error(`Error fetching ${protocol.marketsKey} for market ${market.value}:`, error);
|
|
119
|
+
failed[market.value] = `Error fetching ${protocol.marketsKey} for market ${market.value}`;
|
|
120
|
+
}
|
|
121
|
+
}));
|
|
122
|
+
return failed;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Every address's position on every market into `positions`, each read once its market is in: an entry with the data
|
|
127
|
+
* where the address holds a position, an entry with an error where the read or its market failed, none otherwise.
|
|
128
|
+
*/
|
|
129
|
+
const readPositions = (
|
|
130
|
+
context: PortfolioReadContext,
|
|
131
|
+
addresses: EthAddress[],
|
|
132
|
+
marketsData: Promise<PortfolioMarketsData>,
|
|
133
|
+
positions: PortfolioPositionsData,
|
|
134
|
+
): Promise<void>[] => protocol.markets(context.network).flatMap((market) => addresses.map(async (address) => {
|
|
135
|
+
// Keyed by the protocol's market type in PortfolioPositionsDataForAddress; written here by market.value.
|
|
136
|
+
const byMarket = positions[address.toLowerCase() as EthAddress][key] as Record<string, PortfolioProtocolData<LendingPositionData<K>>>;
|
|
137
|
+
try {
|
|
138
|
+
const marketData = requireMarketOf(await marketsData, protocol.marketsKey, market.value);
|
|
139
|
+
const position = await protocol.readPosition(context, address, market, marketData);
|
|
140
|
+
if (position && protocol.holds(position)) byMarket[market.value] = { error: '', data: position };
|
|
141
|
+
} catch (error) {
|
|
142
|
+
console.error(`Error fetching ${protocol.label} account data for address ${address} on market ${market.value}:`, error);
|
|
143
|
+
byMarket[market.value] = { error: `Error fetching ${protocol.label} account data for address ${address} on market ${market.value}`, data: null };
|
|
144
|
+
}
|
|
145
|
+
}));
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
key, marketsKey: protocol.marketsKey, markets: protocol.markets, readMarkets, readPositions,
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const onNetwork = <Market extends { chainIds: NetworkNumber[] }>(network: NetworkNumber, markets: Market[]) => markets.filter((market) => market.chainIds.includes(network));
|
|
153
|
+
|
|
154
|
+
const suppliesAnything = (position: { suppliedUsd: string }) => new Dec(position.suppliedUsd).gt(0);
|
|
155
|
+
const suppliesOrBorrowsAnything = (position: { suppliedUsd: string, borrowedUsd: string }) => new Dec(position.suppliedUsd).gt(0) || new Dec(position.borrowedUsd).gt(0);
|
|
156
|
+
|
|
157
|
+
export const aaveV3Lending = lendingProtocol('aaveV3', {
|
|
158
|
+
marketsKey: 'aaveV3MarketsData',
|
|
159
|
+
label: 'AaveV3',
|
|
160
|
+
markets: (network): AaveMarketInfo[] => onNetwork(network, [AaveVersions.AaveV3, AaveVersions.AaveV3Lido, AaveVersions.AaveV3Etherfi].map((version) => AaveMarkets(network)[version])),
|
|
161
|
+
readMarket: ({ client, network }, market) => _getAaveV3MarketData(client, network, market),
|
|
162
|
+
readPosition: ({ client, network }, address, market, marketData) => _getAaveV3AccountData(client, network, address, { selectedMarket: market, ...marketData }),
|
|
163
|
+
holds: suppliesAnything,
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
export const aaveV4Lending = lendingProtocol('aaveV4', {
|
|
167
|
+
marketsKey: 'aaveV4SpokesData',
|
|
168
|
+
label: 'AaveV4',
|
|
169
|
+
markets: (network): AaveV4SpokeInfo[] => onNetwork(network, Object.values(AaveV4Spokes(network))),
|
|
170
|
+
readMarket: ({ client, network }, spoke) => _getAaveV4SpokeData(client, network, spoke),
|
|
171
|
+
readPosition: ({ client, network }, address, _spoke, spokeData) => _getAaveV4AccountData(client, network, spokeData, address),
|
|
172
|
+
holds: suppliesAnything,
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
export const morphoBlueLending = lendingProtocol('morphoBlue', {
|
|
176
|
+
marketsKey: 'morphoMarketsData',
|
|
177
|
+
label: 'MorphoBlue',
|
|
178
|
+
markets: (network): MorphoBlueMarketData[] => onNetwork(network, Object.values(MorphoBlueMarkets(network))),
|
|
179
|
+
readMarket: ({ client, network }, market) => _getMorphoBluePortfolioMarketData(client, network, market),
|
|
180
|
+
readPosition: ({ client, network }, address, market, marketData) => _getMorphoBlueAccountData(client, network, address, market, marketData),
|
|
181
|
+
holds: suppliesAnything,
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
export const morphoMidnightLending = lendingProtocol('morphoMidnight', {
|
|
185
|
+
marketsKey: 'morphoMidnightMarketsData',
|
|
186
|
+
label: 'MorphoMidnight',
|
|
187
|
+
markets: (network): MorphoMidnightMarketData[] => onNetwork(network, Object.values(MorphoMidnightMarkets(network))),
|
|
188
|
+
readMarket: ({ client, network }, market) => _getMorphoMidnightMarketData(client, network, market),
|
|
189
|
+
// Markets are created lazily on the first position, so an uncreated one can hold no position.
|
|
190
|
+
readPosition: async ({ client, network }, address, market, marketData) => (marketData.isCreated
|
|
191
|
+
? _getMorphoMidnightAccountData(client, network, address, market, marketData)
|
|
192
|
+
: undefined),
|
|
193
|
+
holds: suppliesAnything,
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
export const compoundV3Lending = lendingProtocol('compoundV3', {
|
|
197
|
+
marketsKey: 'compoundV3MarketsData',
|
|
198
|
+
label: 'CompoundV3',
|
|
199
|
+
markets: (network): CompoundMarketData[] => onNetwork(network, Object.values(CompoundMarkets(network)).filter((market) => market.value !== CompoundVersions.CompoundV2)),
|
|
200
|
+
readMarket: ({ client, defaultClient, network }, market) => _getCompoundV3MarketsData(client, network, market, defaultClient),
|
|
201
|
+
readPosition: ({ client, network }, address, market, marketData) => _getCompoundV3AccountData(client, network, address, ZERO_ADDRESS, { selectedMarket: market, assetsData: marketData.assetsData }),
|
|
202
|
+
holds: suppliesAnything,
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
export const sparkLending = lendingProtocol('spark', {
|
|
206
|
+
marketsKey: 'sparkMarketsData',
|
|
207
|
+
label: 'Spark',
|
|
208
|
+
markets: (network): SparkMarketData[] => onNetwork(network, Object.values(SparkMarkets(network))),
|
|
209
|
+
readMarket: ({ client, network }, market) => _getSparkMarketsData(client, network, market),
|
|
210
|
+
readPosition: ({ client, network }, address, market, marketData) => _getSparkAccountData(client, network, address, {
|
|
211
|
+
selectedMarket: market, assetsData: marketData.assetsData, eModeCategoriesData: marketData.eModeCategoriesData,
|
|
212
|
+
}),
|
|
213
|
+
holds: suppliesAnything,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
export const aaveV2Lending = lendingProtocol('aaveV2', {
|
|
217
|
+
marketsKey: 'aaveV2MarketsData',
|
|
218
|
+
label: 'AaveV2',
|
|
219
|
+
markets: (network): AaveMarketInfo[] => onNetwork(network, [AaveMarkets(network)[AaveVersions.AaveV2]]),
|
|
220
|
+
readMarket: ({ client, network }, market) => _getAaveV2MarketsData(client, network, market),
|
|
221
|
+
readPosition: ({ client, network }, address, market, marketData) => _getAaveV2AccountData(client, network, address, marketData.assetsData, market),
|
|
222
|
+
holds: suppliesAnything,
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
export const compoundV2Lending = lendingProtocol('compoundV2', {
|
|
226
|
+
marketsKey: 'compoundV2MarketsData',
|
|
227
|
+
label: 'CompoundV2',
|
|
228
|
+
markets: (network): CompoundMarketData[] => onNetwork(network, [CompoundMarkets(network)[CompoundVersions.CompoundV2]]),
|
|
229
|
+
readMarket: ({ client, network }) => _getCompoundV2MarketsData(client, network),
|
|
230
|
+
readPosition: ({ client, network }, address, _market, marketData) => _getCompoundV2AccountData(client, network, address, marketData.assetsData),
|
|
231
|
+
holds: suppliesAnything,
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
export const crvUsdLending = lendingProtocol('crvUsd', {
|
|
235
|
+
marketsKey: 'crvUsdMarketsData',
|
|
236
|
+
label: 'Curve USD',
|
|
237
|
+
markets: (network): CrvUSDMarketData[] => onNetwork(network, Object.values(CrvUsdMarkets(network))),
|
|
238
|
+
readMarket: ({ client, network }, market) => _getCurveUsdGlobalData(client, network, market),
|
|
239
|
+
// The market's borrow rate is passed in, so the read does not fetch it again.
|
|
240
|
+
readPosition: ({ client, network }, address, market, marketData) => _getCurveUsdUserData(client, network, address, market, marketData.activeBand, marketData.borrowRate),
|
|
241
|
+
holds: suppliesOrBorrowsAnything,
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
export const llamaLendLending = lendingProtocol('llamaLend', {
|
|
245
|
+
marketsKey: 'llamaLendMarketsData',
|
|
246
|
+
label: 'LlamaLend',
|
|
247
|
+
markets: (network): LlamaLendMarketData[] => ([NetworkNumber.Eth, NetworkNumber.Arb].includes(network) ? onNetwork(network, Object.values(LlamaLendMarkets(network))) : []),
|
|
248
|
+
readMarket: ({ client, network }, market) => _getLlamaLendGlobalData(client, network, market),
|
|
249
|
+
readPosition: async ({ client, network }, address, market, marketData) => ({
|
|
250
|
+
...await _getLlamaLendUserData(client, network, address, market, marketData),
|
|
251
|
+
borrowRate: marketData.borrowRate,
|
|
252
|
+
}),
|
|
253
|
+
holds: suppliesOrBorrowsAnything,
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
/** Every lending protocol read through its entry, in the order positions list them. */
|
|
257
|
+
export const LENDING_PROTOCOLS = [
|
|
258
|
+
aaveV3Lending,
|
|
259
|
+
aaveV4Lending,
|
|
260
|
+
morphoBlueLending,
|
|
261
|
+
morphoMidnightLending,
|
|
262
|
+
compoundV3Lending,
|
|
263
|
+
sparkLending,
|
|
264
|
+
aaveV2Lending,
|
|
265
|
+
compoundV2Lending,
|
|
266
|
+
crvUsdLending,
|
|
267
|
+
llamaLendLending,
|
|
268
|
+
] as const;
|
|
269
|
+
|
|
270
|
+
export type LendingKey = typeof LENDING_PROTOCOLS[number]['key'];
|
|
271
|
+
|
|
272
|
+
/** The keys ./index.ts reads with code of its own. */
|
|
273
|
+
export type SpecialPositionKey = 'maker' | 'liquity' | 'fluid' | 'liquityV2';
|
|
274
|
+
type SpecialMarketsKey = 'liquityV2MarketsData';
|
|
275
|
+
|
|
276
|
+
// Every position key and every markets key is read by an entry here or by its own code in ./index.ts: one added to
|
|
277
|
+
// PortfolioPositionsDataForAddress or PortfolioMarketsData with neither is a compile error on these lines, naming it.
|
|
278
|
+
type UnreadPositionKey = Exclude<PositionKey, LendingKey | SpecialPositionKey>;
|
|
279
|
+
type UnreadMarketsKey = Exclude<MarketsKey, typeof LENDING_PROTOCOLS[number]['marketsKey'] | SpecialMarketsKey>;
|
|
280
|
+
export const EVERY_POSITION_KEY_IS_READ: [UnreadPositionKey] extends [never] ? true : UnreadPositionKey = true;
|
|
281
|
+
export const EVERY_MARKETS_KEY_IS_READ: [UnreadMarketsKey] extends [never] ? true : UnreadMarketsKey = true;
|
package/src/savings/index.ts
CHANGED
|
@@ -2,6 +2,9 @@ import {
|
|
|
2
2
|
MakerDsrType,
|
|
3
3
|
MorphoVaultType,
|
|
4
4
|
SavingsData,
|
|
5
|
+
SavingsDataWithErrors,
|
|
6
|
+
SavingsErrors,
|
|
7
|
+
SavingsVaultKey,
|
|
5
8
|
SkySavingsType,
|
|
6
9
|
SparkSavingsVaultType,
|
|
7
10
|
SummerVaultType,
|
|
@@ -27,11 +30,16 @@ export {
|
|
|
27
30
|
yearnV3Vaults,
|
|
28
31
|
};
|
|
29
32
|
|
|
30
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Every savings vault of a network for the given accounts, and, for each vault that came back without data, why — so
|
|
35
|
+
* a vault that failed is never mistaken for one the accounts have nothing in.
|
|
36
|
+
*/
|
|
37
|
+
export const getSavingsDataWithErrors = async (
|
|
31
38
|
provider: EthereumProvider,
|
|
32
39
|
network: NetworkNumber,
|
|
33
40
|
accounts: EthAddress[],
|
|
34
|
-
) => {
|
|
41
|
+
): Promise<SavingsDataWithErrors> => {
|
|
42
|
+
const isMainnet = network === NetworkNumber.Eth;
|
|
35
43
|
const morphoVaultsList = (Object.keys(morphoVaults.morphoVaultsOptions.MORPHO_VAULTS) as MorphoVaultType[])
|
|
36
44
|
.filter((key) => morphoVaults.morphoVaultsOptions.getMorphoVault(key).network === network);
|
|
37
45
|
const yearnVaultsList = Object.keys(yearnVaults.yearnVaultsOptions.YEARN_VAULTS) as YearnVaultType[];
|
|
@@ -40,7 +48,17 @@ export const getSavingsData = async (
|
|
|
40
48
|
const summerVaultsList = (Object.keys(summerVaults.summerVaultsOptions.SUMMER_VAULTS) as SummerVaultType[])
|
|
41
49
|
.filter((key) => summerVaults.summerVaultsOptions.getSummerVault(key).network === network);
|
|
42
50
|
|
|
51
|
+
// Every vault read on this network, so one left without data or an error can still be reported.
|
|
52
|
+
const vaultKeys: SavingsVaultKey[] = [
|
|
53
|
+
...morphoVaultsList,
|
|
54
|
+
...(isMainnet ? [
|
|
55
|
+
...yearnVaultsList, ...sparkSavingsVaultsList, ...yearnV3VaultsList, MakerDsrType.MakerDsrVault, SkySavingsType.SkySavings,
|
|
56
|
+
] : []),
|
|
57
|
+
...summerVaultsList,
|
|
58
|
+
];
|
|
59
|
+
|
|
43
60
|
const savingsData: SavingsData = {};
|
|
61
|
+
const errors: SavingsErrors = {};
|
|
44
62
|
|
|
45
63
|
await Promise.all([
|
|
46
64
|
...(morphoVaultsList.length ? [
|
|
@@ -51,10 +69,11 @@ export const getSavingsData = async (
|
|
|
51
69
|
Object.assign(savingsData, data);
|
|
52
70
|
} catch (err) {
|
|
53
71
|
console.error('[getSavingsData] Error fetching morpho vaults:', err);
|
|
72
|
+
morphoVaultsList.forEach((vaultKey) => { errors[vaultKey] = `Error fetching morpho vault ${vaultKey}`; });
|
|
54
73
|
}
|
|
55
74
|
})(),
|
|
56
75
|
] : []),
|
|
57
|
-
...(
|
|
76
|
+
...(isMainnet ? [
|
|
58
77
|
...yearnVaultsList.map(async (vaultKey) => {
|
|
59
78
|
try {
|
|
60
79
|
const vault = yearnVaults.yearnVaultsOptions.getYearnVault(vaultKey);
|
|
@@ -62,6 +81,7 @@ export const getSavingsData = async (
|
|
|
62
81
|
savingsData[vaultKey] = data;
|
|
63
82
|
} catch (err) {
|
|
64
83
|
console.error(`[getSavingsData] Error fetching yearn vault ${vaultKey}:`, err);
|
|
84
|
+
errors[vaultKey] = `Error fetching yearn vault ${vaultKey}`;
|
|
65
85
|
}
|
|
66
86
|
}),
|
|
67
87
|
...sparkSavingsVaultsList.map(async (vaultKey) => {
|
|
@@ -71,6 +91,7 @@ export const getSavingsData = async (
|
|
|
71
91
|
savingsData[vaultKey] = data;
|
|
72
92
|
} catch (err) {
|
|
73
93
|
console.error(`[getSavingsData] Error fetching spark savings vault ${vaultKey}:`, err);
|
|
94
|
+
errors[vaultKey] = `Error fetching spark savings vault ${vaultKey}`;
|
|
74
95
|
}
|
|
75
96
|
}),
|
|
76
97
|
...yearnV3VaultsList.map(async (vaultKey) => {
|
|
@@ -80,6 +101,7 @@ export const getSavingsData = async (
|
|
|
80
101
|
savingsData[vaultKey] = data;
|
|
81
102
|
} catch (err) {
|
|
82
103
|
console.error(`[getSavingsData] Error fetching yearn v3 vault ${vaultKey}:`, err);
|
|
104
|
+
errors[vaultKey] = `Error fetching yearn v3 vault ${vaultKey}`;
|
|
83
105
|
}
|
|
84
106
|
}),
|
|
85
107
|
(async () => {
|
|
@@ -88,6 +110,7 @@ export const getSavingsData = async (
|
|
|
88
110
|
savingsData[MakerDsrType.MakerDsrVault] = data;
|
|
89
111
|
} catch (err) {
|
|
90
112
|
console.error('[getSavingsData] Error fetching maker DSR data:', err);
|
|
113
|
+
errors[MakerDsrType.MakerDsrVault] = 'Error fetching maker DSR data';
|
|
91
114
|
}
|
|
92
115
|
})(),
|
|
93
116
|
(async () => {
|
|
@@ -96,6 +119,7 @@ export const getSavingsData = async (
|
|
|
96
119
|
savingsData[SkySavingsType.SkySavings] = data;
|
|
97
120
|
} catch (err) {
|
|
98
121
|
console.error('[getSavingsData] Error fetching Sky savings data:', err);
|
|
122
|
+
errors[SkySavingsType.SkySavings] = 'Error fetching Sky savings data';
|
|
99
123
|
}
|
|
100
124
|
})(),
|
|
101
125
|
] : []),
|
|
@@ -106,9 +130,22 @@ export const getSavingsData = async (
|
|
|
106
130
|
savingsData[vaultKey] = data;
|
|
107
131
|
} catch (err) {
|
|
108
132
|
console.error(`[getSavingsData] Error fetching summer vault ${vaultKey}:`, err);
|
|
133
|
+
errors[vaultKey] = `Error fetching summer vault ${vaultKey}`;
|
|
109
134
|
}
|
|
110
135
|
}),
|
|
111
136
|
]);
|
|
112
137
|
|
|
113
|
-
return
|
|
138
|
+
// getMorphoVaultsData leaves out, without throwing, a vault whose on-chain reads failed or that the Morpho API did not return.
|
|
139
|
+
vaultKeys.forEach((vaultKey) => {
|
|
140
|
+
if (!savingsData[vaultKey] && !errors[vaultKey]) errors[vaultKey] = `No data returned for savings vault ${vaultKey}`;
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
return { data: savingsData, errors };
|
|
114
144
|
};
|
|
145
|
+
|
|
146
|
+
/** Every savings vault of a network for the given accounts. A vault that failed is left out: use getSavingsDataWithErrors to tell why. */
|
|
147
|
+
export const getSavingsData = async (
|
|
148
|
+
provider: EthereumProvider,
|
|
149
|
+
network: NetworkNumber,
|
|
150
|
+
accounts: EthAddress[],
|
|
151
|
+
): Promise<SavingsData> => (await getSavingsDataWithErrors(provider, network, accounts)).data;
|
package/src/types/aave.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
EthAddress,
|
|
2
3
|
IncentiveData,
|
|
3
4
|
LeverageType,
|
|
4
5
|
MMAssetData, MMPositionData, MMUsedAsset, NetworkNumber,
|
|
@@ -97,6 +98,9 @@ export interface AaveV3AssetData extends AaveAssetData {
|
|
|
97
98
|
liquidationBonus: string,
|
|
98
99
|
supplyIncentives: IncentiveData[];
|
|
99
100
|
borrowIncentives: IncentiveData[];
|
|
101
|
+
// Set by _getAaveV3MarketData. Optional, so objects built by hand still type-check.
|
|
102
|
+
aTokenAddress?: EthAddress,
|
|
103
|
+
vTokenAddress?: EthAddress,
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
export type EModeCategoriesData = Record<number, EModeCategoryData>;
|
|
@@ -138,7 +142,15 @@ export type AaveV2UsedAssets = AaveUsedAssets<AaveV2UsedAsset>;
|
|
|
138
142
|
|
|
139
143
|
export type AaveV3UsedAssets = AaveUsedAssets<AaveV3UsedAsset>;
|
|
140
144
|
|
|
141
|
-
|
|
145
|
+
/**
|
|
146
|
+
* Fields aaveAnyGetAggregatedPositionData adds to every Aave V2/V3 position at runtime, on top of those declared
|
|
147
|
+
* below. Optional, so code that builds a position by hand keeps compiling.
|
|
148
|
+
*/
|
|
149
|
+
export type AavePositionAggregatedFields = Partial<Omit<AaveV3AggregatedPositionData,
|
|
150
|
+
| keyof MMPositionData | 'ratio' | 'collRatio' | 'safetyRatioWithLtvZeroFallback' | 'suppliedUsd' | 'borrowedUsd'
|
|
151
|
+
| 'borrowLimitUsd' | 'suppliedCollateralUsd' | 'incentiveUsd' | 'totalInterestUsd'>>;
|
|
152
|
+
|
|
153
|
+
export interface AavePositionData extends MMPositionData, AavePositionAggregatedFields {
|
|
142
154
|
ratio: string,
|
|
143
155
|
minRatio: string,
|
|
144
156
|
collRatio: string,
|
|
@@ -159,6 +171,11 @@ export interface AavePositionData extends MMPositionData {
|
|
|
159
171
|
|
|
160
172
|
export interface AaveV2PositionData extends AavePositionData {
|
|
161
173
|
usedAssets: AaveV2UsedAssets,
|
|
174
|
+
// Always their empty values: _getAaveV2AccountData starts from Aave V3's EMPTY_AAVE_DATA, which carries them.
|
|
175
|
+
eModeCategory?: number,
|
|
176
|
+
isInIsolationMode?: boolean,
|
|
177
|
+
isInSiloedMode?: boolean,
|
|
178
|
+
eModeCategories?: { [key: number]: EModeCategoryDataMapping },
|
|
162
179
|
}
|
|
163
180
|
|
|
164
181
|
export interface AaveV3PositionData extends AavePositionData {
|
|
@@ -206,3 +223,89 @@ export interface AaveHelperCommon {
|
|
|
206
223
|
selectedMarket: Partial<AaveMarketInfo>,
|
|
207
224
|
network?: NetworkNumber,
|
|
208
225
|
}
|
|
226
|
+
|
|
227
|
+
export interface SghoUserData {
|
|
228
|
+
shares: string;
|
|
229
|
+
balance: string;
|
|
230
|
+
maxDeposit: string;
|
|
231
|
+
maxWithdraw: string;
|
|
232
|
+
underlyingBalance: string;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export interface SghoData {
|
|
236
|
+
totalAssets: string;
|
|
237
|
+
totalSupply: string;
|
|
238
|
+
supplyCap: string;
|
|
239
|
+
/** Target savings rate as an APY percent (e.g. "4.25" for 4.25%). */
|
|
240
|
+
targetRate: string;
|
|
241
|
+
paused: boolean;
|
|
242
|
+
user: SghoUserData;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** stkAAVE, stkGHO and sGHO of an address, from getStakeAaveData. */
|
|
246
|
+
export interface StakeAaveData {
|
|
247
|
+
activatedCooldown: string,
|
|
248
|
+
activatedCooldownAmount: string,
|
|
249
|
+
stkAaveRewardsBalance: string,
|
|
250
|
+
aaveRewardsBalance: string,
|
|
251
|
+
stkAaveBalance: string,
|
|
252
|
+
stkGhoBalance: string,
|
|
253
|
+
ghoMeritApy: string,
|
|
254
|
+
stkAaveApy: string,
|
|
255
|
+
sgho: SghoData,
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export interface UmbrellaTokenInfo {
|
|
259
|
+
token: EthAddress,
|
|
260
|
+
/** USD, converted from the oracle's 8 decimals. */
|
|
261
|
+
price: string,
|
|
262
|
+
name: string,
|
|
263
|
+
symbol: string,
|
|
264
|
+
decimals: number,
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export interface UmbrellaRewardTokenData {
|
|
268
|
+
rewardTokenData: UmbrellaTokenInfo,
|
|
269
|
+
maxEmissionPerSecond: bigint,
|
|
270
|
+
distributionEnd: bigint,
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export interface UmbrellaStakingAccountData {
|
|
274
|
+
stakeUserBalance: string,
|
|
275
|
+
rewardsTokenUserData: { reward: EthAddress, currentReward: string }[],
|
|
276
|
+
userCooldownAmount: string,
|
|
277
|
+
// Passed through unconverted: the view's bigint, or '0' when the view returns none.
|
|
278
|
+
userEndOfCooldown: bigint | string,
|
|
279
|
+
userWithdrawalWindow: bigint | string,
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* One Umbrella stake token of an address, from getUmbrellaData: the view contracts' structs merged, with the amounts
|
|
284
|
+
* the app reads converted to decimal strings. The bigint fields are the views' raw values, as the SDK passes them.
|
|
285
|
+
*/
|
|
286
|
+
export interface UmbrellaStakingTokenData {
|
|
287
|
+
stakeTokenData: UmbrellaTokenInfo,
|
|
288
|
+
totalAssets: string,
|
|
289
|
+
targetLiquidity: string,
|
|
290
|
+
isStakeConfigured: boolean,
|
|
291
|
+
rewardsTokenData: UmbrellaRewardTokenData[],
|
|
292
|
+
stakeToken: EthAddress,
|
|
293
|
+
stakeUserBalance: bigint,
|
|
294
|
+
rewardsTokenUserData: { reward: EthAddress, currentReward: bigint }[],
|
|
295
|
+
stkToken: EthAddress,
|
|
296
|
+
totalShares: string,
|
|
297
|
+
stkUnderlyingToken: EthAddress,
|
|
298
|
+
aToken: EthAddress,
|
|
299
|
+
cooldownPeriod: bigint,
|
|
300
|
+
unstakeWindow: bigint,
|
|
301
|
+
stkTokenToWaTokenRate: string,
|
|
302
|
+
waTokenToATokenRate: string,
|
|
303
|
+
rewardsEmissionRates: string[],
|
|
304
|
+
userCooldownAmount: bigint,
|
|
305
|
+
userEndOfCooldown: bigint,
|
|
306
|
+
userWithdrawalWindow: bigint,
|
|
307
|
+
account: UmbrellaStakingAccountData,
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/** Keyed by Umbrella stake (UmbrellaGHO, UmbrellaUSDC, UmbrellaUSDT, UmbrellaETH). */
|
|
311
|
+
export type UmbrellaStakingData = Record<string, UmbrellaStakingTokenData>;
|
package/src/types/aaveV4.ts
CHANGED
|
@@ -207,3 +207,52 @@ export interface AaveV4AccountData extends AaveV4AggregatedPositionData {
|
|
|
207
207
|
healthFactor: string,
|
|
208
208
|
riskPremiumBps: number,
|
|
209
209
|
}
|
|
210
|
+
|
|
211
|
+
/** One Aave V4 tokenized spoke (Lend vault) as the view contract returns it for a user. */
|
|
212
|
+
export interface AaveV4TokenizationSpokeData {
|
|
213
|
+
underlyingAsset: EthAddress;
|
|
214
|
+
assetId: string;
|
|
215
|
+
decimals: number;
|
|
216
|
+
spoke: EthAddress;
|
|
217
|
+
spokeActive: boolean;
|
|
218
|
+
spokeHalted: boolean;
|
|
219
|
+
spokeDepositCap: string;
|
|
220
|
+
spokeTotalAssets: string;
|
|
221
|
+
spokeTotalShares: string;
|
|
222
|
+
hub: EthAddress;
|
|
223
|
+
hubLiquidity: string;
|
|
224
|
+
hubDrawnRate: string;
|
|
225
|
+
convertToShares: string;
|
|
226
|
+
convertToAssets: string;
|
|
227
|
+
user: EthAddress;
|
|
228
|
+
userSuppliedAssets: string;
|
|
229
|
+
userSuppliedShares: string;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/** Parsed tokenization spoke data with human-readable supplied amounts for display */
|
|
233
|
+
export interface AaveV4TokenizationSpokeDataParsed {
|
|
234
|
+
vaultAddress: EthAddress;
|
|
235
|
+
key: string | null;
|
|
236
|
+
symbol: string;
|
|
237
|
+
hubKey: string;
|
|
238
|
+
// ---- Spoke ----
|
|
239
|
+
spokeActive: boolean;
|
|
240
|
+
spokeHalted: boolean;
|
|
241
|
+
/** Deposit cap in asset units (wei string) */
|
|
242
|
+
spokeDepositCap: string;
|
|
243
|
+
/** Total assets currently in spoke in asset units (wei string) */
|
|
244
|
+
spokeTotalAssets: string;
|
|
245
|
+
// ---- Hub ----
|
|
246
|
+
/** Available hub liquidity in asset units (wei string) */
|
|
247
|
+
hubLiquidity: string;
|
|
248
|
+
/** The conversion rate from assets to shares expressed in asset units. */
|
|
249
|
+
convertToShares: string;
|
|
250
|
+
// ---- User ----
|
|
251
|
+
userSuppliedAssetsEth: string;
|
|
252
|
+
userSuppliedSharesEth: string;
|
|
253
|
+
userSuppliedAssets: string;
|
|
254
|
+
userSuppliedShares: string;
|
|
255
|
+
underlyingAsset: EthAddress;
|
|
256
|
+
spoke: EthAddress;
|
|
257
|
+
decimals: number;
|
|
258
|
+
}
|
package/src/types/common.ts
CHANGED
package/src/types/compound.ts
CHANGED
|
@@ -70,6 +70,8 @@ export interface CompoundAssetData extends MMAssetData {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
export interface CompoundV2AssetData extends CompoundAssetData {
|
|
73
|
+
// Set by _getCompoundV2MarketsData. Optional, so objects built by hand still type-check.
|
|
74
|
+
exchangeRate?: string,
|
|
73
75
|
}
|
|
74
76
|
export interface CompoundV3AssetData extends CompoundAssetData {
|
|
75
77
|
borrowCollateralFactor: string,
|
|
@@ -81,6 +83,20 @@ export interface CompoundV3AssetData extends CompoundAssetData {
|
|
|
81
83
|
supplyCap: string,
|
|
82
84
|
priceInBaseAsset: string,
|
|
83
85
|
canBeWithdrawn: boolean,
|
|
86
|
+
// The rest are set by formatMarketData and formatBaseData, which also spread in the view contract's raw asset
|
|
87
|
+
// data. Optional, so objects built by hand still type-check.
|
|
88
|
+
tokenAddr?: EthAddress,
|
|
89
|
+
// The base asset's only.
|
|
90
|
+
isBase?: boolean,
|
|
91
|
+
baseBorrowMin?: string,
|
|
92
|
+
baseTrackingBorrowRewardsSpeed?: string,
|
|
93
|
+
baseTrackingSupplyRewardsSpeed?: string,
|
|
94
|
+
borrowIndex?: string,
|
|
95
|
+
supplyIndex?: string,
|
|
96
|
+
trackingBorrowIndex?: string,
|
|
97
|
+
trackingSupplyIndex?: string,
|
|
98
|
+
rewardSupplySpeed?: string,
|
|
99
|
+
rewardBorrowSpeed?: string,
|
|
84
100
|
}
|
|
85
101
|
|
|
86
102
|
export interface CompoundAssetsData<T> {
|
|
@@ -143,10 +159,30 @@ export interface CompoundPositionData extends MMPositionData {
|
|
|
143
159
|
automationResubscribeRequired?: boolean,
|
|
144
160
|
}
|
|
145
161
|
|
|
146
|
-
|
|
162
|
+
/**
|
|
163
|
+
* Fields getCompoundV2AggregatedData adds to every Compound V2 position at runtime — a subset of
|
|
164
|
+
* CompoundAggregatedPositionData. Optional, so code that builds a position by hand keeps compiling.
|
|
165
|
+
*/
|
|
166
|
+
export type CompoundV2PositionAggregatedFields = Partial<Pick<CompoundAggregatedPositionData,
|
|
167
|
+
| 'suppliedCollateralUsd' | 'liquidationLimitUsd' | 'leftToBorrowUsd' | 'collRatio' | 'leveragedType'
|
|
168
|
+
| 'leveragedAsset' | 'liquidationPrice'>>;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Fields getCompoundV3AggregatedData adds to every Compound V3 position at runtime, on top of those declared in
|
|
172
|
+
* CompoundPositionData. Optional, so code that builds a position by hand keeps compiling.
|
|
173
|
+
*/
|
|
174
|
+
export type CompoundV3PositionAggregatedFields = Partial<Omit<CompoundAggregatedPositionData,
|
|
175
|
+
| keyof MMPositionData | 'ratio' | 'minRatio' | 'suppliedUsd' | 'borrowedUsd' | 'borrowLimitUsd' | 'incentiveUsd'
|
|
176
|
+
| 'totalInterestUsd'>>;
|
|
177
|
+
|
|
178
|
+
export interface CompoundV2PositionData extends CompoundPositionData, CompoundV2PositionAggregatedFields {
|
|
147
179
|
usedAssets: CompoundV2UsedAssets,
|
|
180
|
+
// Always false: _getCompoundV2AccountData starts from EMPTY_COMPOUND_DATA, which carries it.
|
|
181
|
+
borrowStableSupplyUnstable?: boolean,
|
|
148
182
|
}
|
|
149
183
|
|
|
150
|
-
export interface CompoundV3PositionData extends CompoundPositionData {
|
|
184
|
+
export interface CompoundV3PositionData extends CompoundPositionData, CompoundV3PositionAggregatedFields {
|
|
151
185
|
usedAssets: CompoundV3UsedAssets,
|
|
186
|
+
// Whether the user's smart wallet is allowed to manage the account on Comet (Comet.isAllowed).
|
|
187
|
+
isAllowed?: boolean,
|
|
152
188
|
}
|