curvance 4.1.2 → 5.1.0
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/README.md +65 -10
- package/dist/abis/OptimizerReader.json +43 -45
- package/dist/abis/ProtocolReader.json +279 -55
- package/dist/chains/arbitrum.js +3 -3
- package/dist/chains/arbitrum.js.map +1 -1
- package/dist/classes/Api.d.ts +2 -2
- package/dist/classes/Api.d.ts.map +1 -1
- package/dist/classes/Api.js +87 -14
- package/dist/classes/Api.js.map +1 -1
- package/dist/classes/BorrowableCToken.d.ts +9 -1
- package/dist/classes/BorrowableCToken.d.ts.map +1 -1
- package/dist/classes/BorrowableCToken.js +67 -12
- package/dist/classes/BorrowableCToken.js.map +1 -1
- package/dist/classes/CToken.d.ts +210 -21
- package/dist/classes/CToken.d.ts.map +1 -1
- package/dist/classes/CToken.js +692 -284
- package/dist/classes/CToken.js.map +1 -1
- package/dist/classes/Calldata.d.ts +2 -2
- package/dist/classes/Calldata.d.ts.map +1 -1
- package/dist/classes/Calldata.js +6 -2
- package/dist/classes/Calldata.js.map +1 -1
- package/dist/classes/DexAggregators/IDexAgg.d.ts +1 -1
- package/dist/classes/DexAggregators/Kuru.js +1 -1
- package/dist/classes/DexAggregators/Kuru.js.map +1 -1
- package/dist/classes/DexAggregators/KyberSwap.d.ts.map +1 -1
- package/dist/classes/DexAggregators/KyberSwap.js +112 -61
- package/dist/classes/DexAggregators/KyberSwap.js.map +1 -1
- package/dist/classes/DexAggregators/MultiDexAgg.d.ts +2 -2
- package/dist/classes/DexAggregators/MultiDexAgg.d.ts.map +1 -1
- package/dist/classes/DexAggregators/MultiDexAgg.js +30 -18
- package/dist/classes/DexAggregators/MultiDexAgg.js.map +1 -1
- package/dist/classes/DexAggregators/UnsupportedDexAgg.d.ts +19 -0
- package/dist/classes/DexAggregators/UnsupportedDexAgg.d.ts.map +1 -0
- package/dist/classes/DexAggregators/UnsupportedDexAgg.js +29 -0
- package/dist/classes/DexAggregators/UnsupportedDexAgg.js.map +1 -0
- package/dist/classes/DexAggregators/helpers.d.ts +30 -0
- package/dist/classes/DexAggregators/helpers.d.ts.map +1 -0
- package/dist/classes/DexAggregators/helpers.js +57 -0
- package/dist/classes/DexAggregators/helpers.js.map +1 -0
- package/dist/classes/DexAggregators/index.d.ts +2 -0
- package/dist/classes/DexAggregators/index.d.ts.map +1 -1
- package/dist/classes/DexAggregators/index.js +1 -0
- package/dist/classes/DexAggregators/index.js.map +1 -1
- package/dist/classes/ERC20.d.ts +3 -3
- package/dist/classes/ERC20.d.ts.map +1 -1
- package/dist/classes/ERC20.js +26 -10
- package/dist/classes/ERC20.js.map +1 -1
- package/dist/classes/FormatConverter.d.ts.map +1 -1
- package/dist/classes/FormatConverter.js +4 -1
- package/dist/classes/FormatConverter.js.map +1 -1
- package/dist/classes/Market.d.ts +46 -8
- package/dist/classes/Market.d.ts.map +1 -1
- package/dist/classes/Market.js +342 -111
- package/dist/classes/Market.js.map +1 -1
- package/dist/classes/NativeToken.d.ts +2 -2
- package/dist/classes/NativeToken.d.ts.map +1 -1
- package/dist/classes/NativeToken.js +21 -7
- package/dist/classes/NativeToken.js.map +1 -1
- package/dist/classes/OptimizerReader.d.ts +15 -7
- package/dist/classes/OptimizerReader.d.ts.map +1 -1
- package/dist/classes/OptimizerReader.js +108 -30
- package/dist/classes/OptimizerReader.js.map +1 -1
- package/dist/classes/OracleManager.d.ts.map +1 -1
- package/dist/classes/OracleManager.js +11 -4
- package/dist/classes/OracleManager.js.map +1 -1
- package/dist/classes/PositionManager.d.ts.map +1 -1
- package/dist/classes/PositionManager.js +1 -3
- package/dist/classes/PositionManager.js.map +1 -1
- package/dist/classes/ProtocolReader.d.ts +30 -9
- package/dist/classes/ProtocolReader.d.ts.map +1 -1
- package/dist/classes/ProtocolReader.js +158 -138
- package/dist/classes/ProtocolReader.js.map +1 -1
- package/dist/classes/Zapper.d.ts +5 -5
- package/dist/classes/Zapper.d.ts.map +1 -1
- package/dist/classes/Zapper.js +21 -18
- package/dist/classes/Zapper.js.map +1 -1
- package/dist/contracts/monad-mainnet.json +1 -1
- package/dist/feePolicy.d.ts +2 -0
- package/dist/feePolicy.d.ts.map +1 -1
- package/dist/feePolicy.js +19 -0
- package/dist/feePolicy.js.map +1 -1
- package/dist/format/borrow.d.ts.map +1 -1
- package/dist/format/borrow.js +7 -1
- package/dist/format/borrow.js.map +1 -1
- package/dist/format/health.d.ts +3 -2
- package/dist/format/health.d.ts.map +1 -1
- package/dist/format/health.js +10 -9
- package/dist/format/health.js.map +1 -1
- package/dist/format/leverage.js +5 -4
- package/dist/format/leverage.js.map +1 -1
- package/dist/helpers.d.ts +14 -11
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +171 -52
- package/dist/helpers.js.map +1 -1
- package/dist/integrations/merkl.d.ts +2 -1
- package/dist/integrations/merkl.d.ts.map +1 -1
- package/dist/integrations/merkl.js +199 -4
- package/dist/integrations/merkl.js.map +1 -1
- package/dist/integrations/snapshot.d.ts +28 -24
- package/dist/integrations/snapshot.d.ts.map +1 -1
- package/dist/integrations/snapshot.js +106 -42
- package/dist/integrations/snapshot.js.map +1 -1
- package/dist/retry-provider.d.ts +6 -0
- package/dist/retry-provider.d.ts.map +1 -1
- package/dist/retry-provider.js +103 -11
- package/dist/retry-provider.js.map +1 -1
- package/dist/setup.d.ts +8 -6
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +125 -45
- package/dist/setup.js.map +1 -1
- package/dist/validation.d.ts +1 -1
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +13 -7
- package/dist/validation.js.map +1 -1
- package/package.json +6 -3
package/dist/classes/Market.js
CHANGED
|
@@ -8,11 +8,19 @@ const helpers_1 = require("../helpers");
|
|
|
8
8
|
const CToken_1 = require("./CToken");
|
|
9
9
|
const MarketManagerIsolated_json_1 = __importDefault(require("../abis/MarketManagerIsolated.json"));
|
|
10
10
|
const decimal_js_1 = require("decimal.js");
|
|
11
|
-
const setup_1 = require("../setup");
|
|
12
11
|
const merkl_1 = require("../integrations/merkl");
|
|
13
12
|
const BorrowableCToken_1 = require("./BorrowableCToken");
|
|
14
13
|
const FormatConverter_1 = __importDefault(require("./FormatConverter"));
|
|
15
14
|
const Api_1 = require("./Api");
|
|
15
|
+
const chains_1 = require("../chains");
|
|
16
|
+
function resolveDefaultSetupConfig(context) {
|
|
17
|
+
const config = require("../setup").setup_config;
|
|
18
|
+
if (config == undefined) {
|
|
19
|
+
throw new Error(`Setup config is not configured for ${context}. ` +
|
|
20
|
+
`Pass setup/provider context explicitly or initialize setupChain() first.`);
|
|
21
|
+
}
|
|
22
|
+
return config;
|
|
23
|
+
}
|
|
16
24
|
class Market {
|
|
17
25
|
provider;
|
|
18
26
|
signer;
|
|
@@ -26,6 +34,7 @@ class Market {
|
|
|
26
34
|
cache;
|
|
27
35
|
milestone = null;
|
|
28
36
|
incentives = [];
|
|
37
|
+
_userDataScope;
|
|
29
38
|
constructor(provider, signer, account, static_data, dynamic_data, user_data, deploy_data, oracle_manager, reader, setup) {
|
|
30
39
|
this.provider = provider;
|
|
31
40
|
this.signer = signer;
|
|
@@ -36,14 +45,10 @@ class Market {
|
|
|
36
45
|
this.setup = setup;
|
|
37
46
|
this.contract = (0, helpers_1.contractSetup)(provider, this.address, MarketManagerIsolated_json_1.default);
|
|
38
47
|
this.cache = { static: static_data, dynamic: dynamic_data, user: user_data, deploy: deploy_data };
|
|
39
|
-
|
|
48
|
+
this._userDataScope = "full";
|
|
49
|
+
for (const tokenData of Market.mergeTokenPayloads(static_data, dynamic_data, user_data)) {
|
|
40
50
|
// @NOTE: Merged fields from the 3 types, so you wanna make sure there is no collisions
|
|
41
51
|
// Otherwise we will have some dataloss
|
|
42
|
-
const tokenData = {
|
|
43
|
-
...static_data.tokens[i],
|
|
44
|
-
...dynamic_data.tokens[i],
|
|
45
|
-
...user_data.tokens[i]
|
|
46
|
-
};
|
|
47
52
|
if (tokenData.isBorrowable) {
|
|
48
53
|
const ctoken = new BorrowableCToken_1.BorrowableCToken(provider, tokenData.address, tokenData, this);
|
|
49
54
|
this.tokens.push(ctoken);
|
|
@@ -57,6 +62,44 @@ class Market {
|
|
|
57
62
|
getAccountOrThrow() {
|
|
58
63
|
return (0, helpers_1.requireAccount)(this.account, this.signer);
|
|
59
64
|
}
|
|
65
|
+
assertRefreshAccountCompatible(account, allowSignerMismatch = false) {
|
|
66
|
+
if (allowSignerMismatch) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const signerAddress = this.signer?.address;
|
|
70
|
+
if (signerAddress == null || signerAddress.toLowerCase() === account.toLowerCase()) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
throw new Error(`Cannot refresh signer-backed market ${this.address} for ${account}; ` +
|
|
74
|
+
`the active signer is ${signerAddress}.`);
|
|
75
|
+
}
|
|
76
|
+
bindRefreshedAccount(account, allowSignerMismatch = false) {
|
|
77
|
+
this.assertRefreshAccountCompatible(account, allowSignerMismatch);
|
|
78
|
+
this.account = account;
|
|
79
|
+
}
|
|
80
|
+
requireFullUserTokenData(accessLabel) {
|
|
81
|
+
if (this.userDataScope !== "summary") {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
throw new Error(`Market-level token-derived user data is stale for ${this.address} after a summary-only refresh. ` +
|
|
85
|
+
`Call market.reloadUserData(account) or Market.reloadUserMarkets(...) before ${accessLabel}.`);
|
|
86
|
+
}
|
|
87
|
+
requireValidCachedUserHealth(accessLabel) {
|
|
88
|
+
if (this.cache.user.errorCodeHit || this.cache.user.priceStale) {
|
|
89
|
+
throw new Error(`Cached market user data for ${this.address} is not reliable for ${accessLabel} because ` +
|
|
90
|
+
`the reader reported an oracle error or stale price.`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
cooldownDateFromUnlockTime(unlockTime, cooldownLength = this.cooldownLength) {
|
|
94
|
+
if (unlockTime === cooldownLength) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
98
|
+
if (unlockTime <= now) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
return new Date(Number(unlockTime * 1000n));
|
|
102
|
+
}
|
|
60
103
|
/** @returns {string} - The name of the market at deployment. */
|
|
61
104
|
get name() { return this.cache.deploy.name; }
|
|
62
105
|
/** @returns {Plugins} - The address of the market's plugins by deploy name. */
|
|
@@ -66,15 +109,27 @@ class Market {
|
|
|
66
109
|
/** @returns {bigint[]} - A list of oracle identifiers which can be mapped to AdaptorTypes enum */
|
|
67
110
|
get adapters() { return this.cache.static.adapters; }
|
|
68
111
|
/** @returns {Date | null} - Market cooldown, activated by Collateralization or Borrowing. Lasts as long as {this.cooldownLength} which is currently 20mins */
|
|
69
|
-
get cooldown() { return this.
|
|
112
|
+
get cooldown() { return this.cooldownDateFromUnlockTime(this.cache.user.cooldown); }
|
|
113
|
+
/** @returns The scope of the latest whole-market user refresh. */
|
|
114
|
+
get userDataScope() { return this._userDataScope ?? "full"; }
|
|
70
115
|
/** @returns {Decimal} - The user's collateral in Shares. */
|
|
71
|
-
get userCollateral() {
|
|
116
|
+
get userCollateral() {
|
|
117
|
+
this.requireValidCachedUserHealth("reading userCollateral");
|
|
118
|
+
return (0, helpers_1.toDecimal)(this.cache.user.collateral, 18n);
|
|
119
|
+
}
|
|
72
120
|
/** @returns {USD} - The user's debt in USD. */
|
|
73
|
-
get userDebt() {
|
|
121
|
+
get userDebt() {
|
|
122
|
+
this.requireValidCachedUserHealth("reading userDebt");
|
|
123
|
+
return (0, helpers_1.toDecimal)(this.cache.user.debt, 18n);
|
|
124
|
+
}
|
|
74
125
|
/** @returns {USD} - The user's maximum debt in USD. */
|
|
75
|
-
get userMaxDebt() {
|
|
126
|
+
get userMaxDebt() {
|
|
127
|
+
this.requireValidCachedUserHealth("reading userMaxDebt");
|
|
128
|
+
return (0, helpers_1.toDecimal)(this.cache.user.maxDebt, 18n);
|
|
129
|
+
}
|
|
76
130
|
/** @returns {USD} - The user's remaining credit with a .1% buffer in USD */
|
|
77
131
|
get userRemainingCredit() {
|
|
132
|
+
this.requireValidCachedUserHealth("reading userRemainingCredit");
|
|
78
133
|
const remaining = this.cache.user.maxDebt - this.cache.user.debt;
|
|
79
134
|
return (0, helpers_1.toDecimal)(remaining, 18n).mul(.999);
|
|
80
135
|
}
|
|
@@ -83,6 +138,7 @@ class Market {
|
|
|
83
138
|
* @returns {Percentage | null} - The user's position health Percentage or null if infinity
|
|
84
139
|
*/
|
|
85
140
|
get positionHealth() {
|
|
141
|
+
this.requireValidCachedUserHealth("reading positionHealth");
|
|
86
142
|
if (this.cache.user.positionHealth == helpers_1.UINT256_MAX) {
|
|
87
143
|
return null;
|
|
88
144
|
}
|
|
@@ -93,6 +149,7 @@ class Market {
|
|
|
93
149
|
* @returns {USD} - The total user deposits in USD.
|
|
94
150
|
*/
|
|
95
151
|
get userDeposits() {
|
|
152
|
+
this.requireFullUserTokenData("reading userDeposits");
|
|
96
153
|
let total_deposits = (0, decimal_js_1.Decimal)(0);
|
|
97
154
|
for (const token of this.tokens) {
|
|
98
155
|
total_deposits = total_deposits.add(token.getUserAssetBalance(true));
|
|
@@ -104,6 +161,7 @@ class Market {
|
|
|
104
161
|
* @returns {USD} - The user's net position in USD.
|
|
105
162
|
*/
|
|
106
163
|
get userNet() {
|
|
164
|
+
this.requireFullUserTokenData("reading userNet");
|
|
107
165
|
return this.userDeposits.sub(this.userDebt);
|
|
108
166
|
}
|
|
109
167
|
/** @returns Market LTV */
|
|
@@ -127,13 +185,17 @@ class Market {
|
|
|
127
185
|
}
|
|
128
186
|
return `${min.mul(100)}% - ${max.mul(100)}%`;
|
|
129
187
|
}
|
|
130
|
-
/** @returns Total market deposits
|
|
131
|
-
|
|
132
|
-
|
|
188
|
+
/** @returns Total market deposits in USD, summed across the market's tokens.
|
|
189
|
+
* Renamed from `tvl` to match the sibling getter naming
|
|
190
|
+
* (`totalDebt`, `totalCollateral`). Backed by the per-token
|
|
191
|
+
* `getDeposits` (which now values via `totalAssets`, not `totalSupply`,
|
|
192
|
+
* so the liquidity ≤ deposits invariant holds). */
|
|
193
|
+
get totalDeposits() {
|
|
194
|
+
let total = new decimal_js_1.Decimal(0);
|
|
133
195
|
for (const token of this.tokens) {
|
|
134
|
-
|
|
196
|
+
total = total.add(token.getDeposits(true));
|
|
135
197
|
}
|
|
136
|
-
return
|
|
198
|
+
return total;
|
|
137
199
|
}
|
|
138
200
|
/** @returns Total market debt */
|
|
139
201
|
get totalDebt() {
|
|
@@ -158,6 +220,7 @@ class Market {
|
|
|
158
220
|
* @returns What tokens can and cannot be borrowed from
|
|
159
221
|
*/
|
|
160
222
|
getBorrowableCTokens() {
|
|
223
|
+
this.requireFullUserTokenData("reading borrowable token eligibility");
|
|
161
224
|
const result = {
|
|
162
225
|
eligible: [],
|
|
163
226
|
ineligible: []
|
|
@@ -181,6 +244,7 @@ class Market {
|
|
|
181
244
|
* @returns The total user deposits change (ex: 50, which would be $50/day)
|
|
182
245
|
*/
|
|
183
246
|
getUserDepositsChange(rate) {
|
|
247
|
+
this.requireFullUserTokenData(`reading user deposit change for rate ${rate}`);
|
|
184
248
|
let total_change = (0, decimal_js_1.Decimal)(0);
|
|
185
249
|
for (const token of this.tokens) {
|
|
186
250
|
const amount = token.getUserAssetBalance(true);
|
|
@@ -194,6 +258,7 @@ class Market {
|
|
|
194
258
|
* @returns The total user debt change (ex: 50, which would be $50/day)
|
|
195
259
|
*/
|
|
196
260
|
getUserDebtChange(rate) {
|
|
261
|
+
this.requireFullUserTokenData(`reading user debt change for rate ${rate}`);
|
|
197
262
|
let total_change = (0, decimal_js_1.Decimal)(0);
|
|
198
263
|
for (const token of this.tokens) {
|
|
199
264
|
if (!token.isBorrowable) {
|
|
@@ -210,6 +275,7 @@ class Market {
|
|
|
210
275
|
* @returns The total user net change (ex: 50, which would be $50/day)
|
|
211
276
|
*/
|
|
212
277
|
getUserNetChange(rate) {
|
|
278
|
+
this.requireFullUserTokenData(`reading user net change for rate ${rate}`);
|
|
213
279
|
const earn = this.getUserDepositsChange(rate);
|
|
214
280
|
const debt = this.getUserDebtChange(rate);
|
|
215
281
|
return earn.sub(debt);
|
|
@@ -253,24 +319,82 @@ class Market {
|
|
|
253
319
|
return Promise.all(this.tokens.map((token) => token.getSnapshot(account)));
|
|
254
320
|
}
|
|
255
321
|
hasUserActivity() {
|
|
322
|
+
this.requireFullUserTokenData("determining user activity");
|
|
256
323
|
return this.tokens.some((token) => token.cache.userAssetBalance > 0n ||
|
|
257
324
|
token.cache.userShareBalance > 0n ||
|
|
258
325
|
token.cache.userCollateral > 0n ||
|
|
259
326
|
token.cache.userDebt > 0n);
|
|
260
327
|
}
|
|
328
|
+
requireRefreshTokenRows(rows, label) {
|
|
329
|
+
if (rows.length !== this.tokens.length) {
|
|
330
|
+
throw new Error(`Token row count mismatch for market ${this.address} during refresh: ` +
|
|
331
|
+
`expected=${this.tokens.length} ${label}=${rows.length}.`);
|
|
332
|
+
}
|
|
333
|
+
const rowsByAddress = new Map(rows.map((row) => [row.address.toLowerCase(), row]));
|
|
334
|
+
for (const token of this.tokens) {
|
|
335
|
+
if (!rowsByAddress.has(token.address.toLowerCase())) {
|
|
336
|
+
throw new Error(`Missing ${label} token data for ${token.address} in market ${this.address} during refresh.`);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return rowsByAddress;
|
|
340
|
+
}
|
|
341
|
+
requireRefreshMarketAddress(row, label) {
|
|
342
|
+
if (row.address.toLowerCase() !== this.address.toLowerCase()) {
|
|
343
|
+
throw new Error(`Mismatched ${label} market data during refresh: expected=${this.address} received=${row.address}.`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
validateStateRows(dynamicData, userData) {
|
|
347
|
+
this.requireRefreshMarketAddress(dynamicData, "dynamic");
|
|
348
|
+
if (userData != undefined) {
|
|
349
|
+
this.requireRefreshMarketAddress(userData, "user");
|
|
350
|
+
}
|
|
351
|
+
this.requireRefreshTokenRows(dynamicData.tokens, "dynamic");
|
|
352
|
+
if (userData != undefined) {
|
|
353
|
+
this.requireRefreshTokenRows(userData.tokens, "user");
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
validateRefreshState(dynamicData, userData) {
|
|
357
|
+
this.validateStateRows(dynamicData, userData);
|
|
358
|
+
}
|
|
359
|
+
static requireMarketRow(rows, market, label) {
|
|
360
|
+
const row = new Map(rows.map((entry) => [entry.address.toLowerCase(), entry])).get(market.address.toLowerCase());
|
|
361
|
+
if (row == undefined) {
|
|
362
|
+
throw new Error(`Could not reload ${label} data for market ${market.address}.`);
|
|
363
|
+
}
|
|
364
|
+
return row;
|
|
365
|
+
}
|
|
261
366
|
applyState(dynamicData, userData) {
|
|
367
|
+
this.validateStateRows(dynamicData, userData);
|
|
368
|
+
const dynamicRowsByAddress = this.requireRefreshTokenRows(dynamicData.tokens, "dynamic");
|
|
369
|
+
const userRowsByAddress = userData != undefined
|
|
370
|
+
? this.requireRefreshTokenRows(userData.tokens, "user")
|
|
371
|
+
: undefined;
|
|
262
372
|
this.cache.dynamic = dynamicData;
|
|
263
373
|
if (userData != undefined) {
|
|
264
374
|
this.cache.user = userData;
|
|
375
|
+
this._userDataScope = "full";
|
|
265
376
|
}
|
|
266
377
|
for (const token of this.tokens) {
|
|
267
|
-
const nextDynamic =
|
|
268
|
-
const nextUser =
|
|
378
|
+
const nextDynamic = dynamicRowsByAddress.get(token.address.toLowerCase());
|
|
379
|
+
const nextUser = userRowsByAddress?.get(token.address.toLowerCase());
|
|
269
380
|
token.cache = {
|
|
270
381
|
...token.cache,
|
|
271
|
-
...
|
|
382
|
+
...nextDynamic,
|
|
272
383
|
...(nextUser ?? {}),
|
|
273
384
|
};
|
|
385
|
+
if (nextUser != undefined) {
|
|
386
|
+
token.markUserCacheFresh?.();
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
applyUserSummary(userData) {
|
|
391
|
+
this.cache.user = {
|
|
392
|
+
...this.cache.user,
|
|
393
|
+
...userData,
|
|
394
|
+
};
|
|
395
|
+
this._userDataScope = "summary";
|
|
396
|
+
for (const token of this.tokens) {
|
|
397
|
+
token.invalidateUserCache?.();
|
|
274
398
|
}
|
|
275
399
|
}
|
|
276
400
|
async reloadMarketData() {
|
|
@@ -281,48 +405,149 @@ class Market {
|
|
|
281
405
|
}
|
|
282
406
|
this.applyState(dynamic);
|
|
283
407
|
}
|
|
284
|
-
async reloadUserData(account) {
|
|
408
|
+
async reloadUserData(account, options = {}) {
|
|
409
|
+
const allowSignerMismatch = options.allowSignerMismatch ?? false;
|
|
410
|
+
this.assertRefreshAccountCompatible(account, allowSignerMismatch);
|
|
285
411
|
const { dynamicMarkets, userMarkets } = await this.reader.getMarketStates([this.address], account);
|
|
286
|
-
const dynamic = dynamicMarkets
|
|
287
|
-
const user = userMarkets
|
|
288
|
-
if (dynamic == undefined || user == undefined) {
|
|
289
|
-
throw new Error(`Could not reload market state for ${this.address}.`);
|
|
290
|
-
}
|
|
412
|
+
const dynamic = Market.requireMarketRow(dynamicMarkets, this, "dynamic");
|
|
413
|
+
const user = Market.requireMarketRow(userMarkets, this, "user");
|
|
291
414
|
this.applyState(dynamic, user);
|
|
415
|
+
this.bindRefreshedAccount(account, allowSignerMismatch);
|
|
416
|
+
}
|
|
417
|
+
async reloadUserSummary(account) {
|
|
418
|
+
this.assertRefreshAccountCompatible(account);
|
|
419
|
+
const userMarkets = await this.reader.getMarketSummaries([this.address], account);
|
|
420
|
+
const user = Market.requireMarketRow(userMarkets, this, "user summary");
|
|
421
|
+
this.applyUserSummary(user);
|
|
422
|
+
this.bindRefreshedAccount(account);
|
|
292
423
|
}
|
|
293
424
|
static getActiveUserMarkets(markets) {
|
|
294
425
|
return markets.filter((market) => market.hasUserActivity());
|
|
295
426
|
}
|
|
296
|
-
static
|
|
297
|
-
if (markets.length === 0) {
|
|
298
|
-
return [];
|
|
299
|
-
}
|
|
427
|
+
static groupByReaderDeployment(markets) {
|
|
300
428
|
const groups = new Map();
|
|
301
429
|
for (const market of markets) {
|
|
302
|
-
const
|
|
430
|
+
const groupKey = market.reader.batchKey ?? market.reader;
|
|
431
|
+
const existing = groups.get(groupKey);
|
|
303
432
|
if (existing) {
|
|
304
|
-
existing.push(market);
|
|
433
|
+
existing.markets.push(market);
|
|
305
434
|
}
|
|
306
435
|
else {
|
|
307
|
-
groups.set(
|
|
436
|
+
groups.set(groupKey, {
|
|
437
|
+
reader: market.reader,
|
|
438
|
+
markets: [market],
|
|
439
|
+
});
|
|
308
440
|
}
|
|
309
441
|
}
|
|
310
|
-
|
|
442
|
+
return groups.values();
|
|
443
|
+
}
|
|
444
|
+
static async reloadUserMarkets(markets, account) {
|
|
445
|
+
if (markets.length === 0) {
|
|
446
|
+
return [];
|
|
447
|
+
}
|
|
448
|
+
for (const market of markets) {
|
|
449
|
+
market.assertRefreshAccountCompatible(account);
|
|
450
|
+
}
|
|
451
|
+
const plans = [];
|
|
452
|
+
for (const { reader, markets: groupedMarkets } of this.groupByReaderDeployment(markets)) {
|
|
311
453
|
const addresses = groupedMarkets.map((market) => market.address);
|
|
312
454
|
const { dynamicMarkets, userMarkets } = await reader.getMarketStates(addresses, account);
|
|
313
|
-
const dynamicByAddress = new Map(dynamicMarkets.map((market) => [market.address, market]));
|
|
314
|
-
const userByAddress = new Map(userMarkets.map((market) => [market.address, market]));
|
|
455
|
+
const dynamicByAddress = new Map(dynamicMarkets.map((market) => [market.address.toLowerCase(), market]));
|
|
456
|
+
const userByAddress = new Map(userMarkets.map((market) => [market.address.toLowerCase(), market]));
|
|
315
457
|
for (const market of groupedMarkets) {
|
|
316
|
-
const dynamic = dynamicByAddress.get(market.address);
|
|
317
|
-
const user = userByAddress.get(market.address);
|
|
458
|
+
const dynamic = dynamicByAddress.get(market.address.toLowerCase());
|
|
459
|
+
const user = userByAddress.get(market.address.toLowerCase());
|
|
318
460
|
if (dynamic == undefined || user == undefined) {
|
|
319
461
|
throw new Error(`Could not reload market state for ${market.address}.`);
|
|
320
462
|
}
|
|
321
|
-
market.
|
|
463
|
+
market.validateStateRows(dynamic, user);
|
|
464
|
+
plans.push({ market, dynamic, user });
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
for (const { market, dynamic, user } of plans) {
|
|
468
|
+
market.applyState(dynamic, user);
|
|
469
|
+
market.bindRefreshedAccount(account);
|
|
470
|
+
}
|
|
471
|
+
return markets;
|
|
472
|
+
}
|
|
473
|
+
static async reloadUserMarketSummaries(markets, account) {
|
|
474
|
+
if (markets.length === 0) {
|
|
475
|
+
return [];
|
|
476
|
+
}
|
|
477
|
+
for (const market of markets) {
|
|
478
|
+
market.assertRefreshAccountCompatible(account);
|
|
479
|
+
}
|
|
480
|
+
const plans = [];
|
|
481
|
+
for (const { reader, markets: groupedMarkets } of this.groupByReaderDeployment(markets)) {
|
|
482
|
+
const addresses = groupedMarkets.map((market) => market.address);
|
|
483
|
+
const userMarkets = await reader.getMarketSummaries(addresses, account);
|
|
484
|
+
const userByAddress = new Map(userMarkets.map((market) => [market.address.toLowerCase(), market]));
|
|
485
|
+
for (const market of groupedMarkets) {
|
|
486
|
+
const user = userByAddress.get(market.address.toLowerCase());
|
|
487
|
+
if (user == undefined) {
|
|
488
|
+
throw new Error(`Could not reload market user summary for ${market.address}.`);
|
|
489
|
+
}
|
|
490
|
+
market.requireRefreshMarketAddress(user, "user summary");
|
|
491
|
+
plans.push({ market, user });
|
|
322
492
|
}
|
|
323
493
|
}
|
|
494
|
+
for (const { market, user } of plans) {
|
|
495
|
+
market.applyUserSummary(user);
|
|
496
|
+
market.bindRefreshedAccount(account);
|
|
497
|
+
}
|
|
324
498
|
return markets;
|
|
325
499
|
}
|
|
500
|
+
static buildDeployDataIndex(setup) {
|
|
501
|
+
const index = new Map();
|
|
502
|
+
const deployments = setup.contracts.markets;
|
|
503
|
+
for (const [name, data] of Object.entries(deployments)) {
|
|
504
|
+
if (typeof data !== 'object' || data == null || typeof data.address !== 'string') {
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
const key = data.address.toLowerCase();
|
|
508
|
+
if (!index.has(key)) {
|
|
509
|
+
index.set(key, {
|
|
510
|
+
name,
|
|
511
|
+
plugins: 'plugins' in data ? data.plugins : {},
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return index;
|
|
516
|
+
}
|
|
517
|
+
static buildYieldIndex(yields) {
|
|
518
|
+
const index = new Map();
|
|
519
|
+
for (const yieldEntry of yields) {
|
|
520
|
+
const key = yieldEntry.symbol.toUpperCase();
|
|
521
|
+
if (!index.has(key)) {
|
|
522
|
+
index.set(key, yieldEntry);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
return index;
|
|
526
|
+
}
|
|
527
|
+
static buildMarketPayloadIndex(entries) {
|
|
528
|
+
return new Map(entries.map((entry) => [entry.address.toLowerCase(), entry]));
|
|
529
|
+
}
|
|
530
|
+
static requireTokenRow(rowsByAddress, tokenAddress, marketAddress, label) {
|
|
531
|
+
const row = rowsByAddress.get(tokenAddress.toLowerCase());
|
|
532
|
+
if (row == undefined) {
|
|
533
|
+
throw new Error(`Missing ${label} token data for ${tokenAddress} in market ${marketAddress} during Market boot.`);
|
|
534
|
+
}
|
|
535
|
+
return row;
|
|
536
|
+
}
|
|
537
|
+
static mergeTokenPayloads(staticData, dynamicData, userData) {
|
|
538
|
+
if (staticData.tokens.length !== dynamicData.tokens.length ||
|
|
539
|
+
staticData.tokens.length !== userData.tokens.length) {
|
|
540
|
+
throw new Error(`Token row count mismatch for market ${staticData.address} during Market boot: ` +
|
|
541
|
+
`static=${staticData.tokens.length} dynamic=${dynamicData.tokens.length} user=${userData.tokens.length}.`);
|
|
542
|
+
}
|
|
543
|
+
const dynamicByAddress = this.buildMarketPayloadIndex(dynamicData.tokens);
|
|
544
|
+
const userByAddress = this.buildMarketPayloadIndex(userData.tokens);
|
|
545
|
+
return staticData.tokens.map((staticToken) => ({
|
|
546
|
+
...staticToken,
|
|
547
|
+
...this.requireTokenRow(dynamicByAddress, staticToken.address, staticData.address, "dynamic"),
|
|
548
|
+
...this.requireTokenRow(userByAddress, staticToken.address, staticData.address, "user"),
|
|
549
|
+
}));
|
|
550
|
+
}
|
|
326
551
|
/**
|
|
327
552
|
* Preview the impact of the user descision for their deposit/borrow/leverage
|
|
328
553
|
* @param user - Wallet address
|
|
@@ -335,7 +560,14 @@ class Market {
|
|
|
335
560
|
async previewAssetImpact(user, collateral_ctoken, debt_ctoken, deposit_amount, borrow_amount, rate_change) {
|
|
336
561
|
const amount_in = (0, helpers_1.toBigInt)(deposit_amount, collateral_ctoken.asset.decimals);
|
|
337
562
|
const amount_out = (0, helpers_1.toBigInt)(borrow_amount, debt_ctoken.asset.decimals);
|
|
338
|
-
|
|
563
|
+
let { supply, borrow } = await this.reader.previewAssetImpact(user, collateral_ctoken.address, debt_ctoken.address, amount_in, amount_out);
|
|
564
|
+
if (amount_out > 0n) {
|
|
565
|
+
const irm = await debt_ctoken.dynamicIRM();
|
|
566
|
+
const currentAssetsHeld = await debt_ctoken.contract.assetsHeld();
|
|
567
|
+
const currentDebt = await debt_ctoken.contract.marketOutstandingDebt();
|
|
568
|
+
const projectedAssetsHeld = currentAssetsHeld > amount_out ? currentAssetsHeld - amount_out : 0n;
|
|
569
|
+
borrow = await irm.borrowRate(projectedAssetsHeld, currentDebt + amount_out);
|
|
570
|
+
}
|
|
339
571
|
const supply_apy = (0, decimal_js_1.Decimal)(supply * (0, helpers_1.getRateSeconds)('year')).div(helpers_1.WAD);
|
|
340
572
|
const borrow_apy = (0, decimal_js_1.Decimal)(borrow * (0, helpers_1.getRateSeconds)('year')).div(helpers_1.WAD);
|
|
341
573
|
const supply_percent = (0, decimal_js_1.Decimal)(supply * (0, helpers_1.getRateSeconds)(rate_change)).div(helpers_1.WAD);
|
|
@@ -371,27 +603,26 @@ class Market {
|
|
|
371
603
|
if (newLeverage.equals(1)) {
|
|
372
604
|
return null;
|
|
373
605
|
}
|
|
374
|
-
const
|
|
375
|
-
const
|
|
606
|
+
const preview = deposit_ctoken.previewLeverageDown(newLeverage, currentLeverage, borrow_ctoken);
|
|
607
|
+
const repayCollateralAssets = preview.collateralAssetReduction;
|
|
608
|
+
let { collateralAssetReduction } = preview;
|
|
609
|
+
if (preview.feeBps > 0n) {
|
|
610
|
+
collateralAssetReduction = collateralAssetReduction * 10000n / (10000n - preview.feeBps);
|
|
611
|
+
}
|
|
612
|
+
const repayUsd = deposit_ctoken.convertTokensToUsd(repayCollateralAssets, true);
|
|
376
613
|
const repayTokens = borrow_ctoken.convertUsdToTokens(repayUsd, true);
|
|
377
614
|
return this.previewPositionHealth(deposit_ctoken, borrow_ctoken, false, FormatConverter_1.default.bigIntToDecimal(collateralAssetReduction, deposit_ctoken.asset.decimals), true, repayTokens);
|
|
378
615
|
}
|
|
379
|
-
async previewPositionHealthLeverageUp(deposit_ctoken, borrow_ctoken, newLeverage, depositAssets) {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
// must be included or the preview will undercount collateral (showing ~0% health).
|
|
390
|
-
const depositInTokens = depositAssets
|
|
391
|
-
? FormatConverter_1.default.bigIntToDecimal(depositAssets, deposit_ctoken.asset.decimals)
|
|
392
|
-
: (0, decimal_js_1.Decimal)(0);
|
|
393
|
-
const collateralIncrease = collateralFromBorrow.add(depositInTokens);
|
|
394
|
-
return this.previewPositionHealth(deposit_ctoken, borrow_ctoken, true, collateralIncrease, false, borrowAmount);
|
|
616
|
+
async previewPositionHealthLeverageUp(deposit_ctoken, borrow_ctoken, newLeverage, depositAssets, positionManagerType) {
|
|
617
|
+
if ((depositAssets ?? 0n) > 0n) {
|
|
618
|
+
return this.previewPositionHealthDepositAndLeverage(deposit_ctoken, borrow_ctoken, newLeverage, depositAssets, positionManagerType);
|
|
619
|
+
}
|
|
620
|
+
const preview = deposit_ctoken.previewLeverageUp(newLeverage, borrow_ctoken, undefined, positionManagerType);
|
|
621
|
+
return this.previewPositionHealth(deposit_ctoken, borrow_ctoken, true, preview.collateralIncreaseInAssets, false, preview.debtIncreaseInAssets);
|
|
622
|
+
}
|
|
623
|
+
async previewPositionHealthDepositAndLeverage(deposit_ctoken, borrow_ctoken, newLeverage, depositAssets, positionManagerType) {
|
|
624
|
+
const preview = deposit_ctoken.previewDepositAndLeverage(newLeverage, borrow_ctoken, depositAssets, positionManagerType);
|
|
625
|
+
return this.previewPositionHealth(deposit_ctoken, borrow_ctoken, true, preview.collateralIncreaseInAssets, false, preview.debtIncreaseInAssets);
|
|
395
626
|
}
|
|
396
627
|
/**
|
|
397
628
|
* A dynamic position health previewer for any action
|
|
@@ -434,12 +665,13 @@ class Market {
|
|
|
434
665
|
*/
|
|
435
666
|
async previewPositionHealthRedeem(ctoken, amount) {
|
|
436
667
|
const user = this.getAccountOrThrow();
|
|
437
|
-
const
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
|
|
668
|
+
const redeemShares = ctoken.convertTokenInputToShares(amount);
|
|
669
|
+
const redeemAssets = FormatConverter_1.default.decimalToBigInt(amount, ctoken.asset.decimals);
|
|
670
|
+
const existing_collateral = ctoken.getUserCollateralShares();
|
|
671
|
+
if (redeemShares > existing_collateral) {
|
|
672
|
+
throw new Error(`Insufficient collateral: Existing (${existing_collateral}) < Redeem amount (${redeemShares})`);
|
|
441
673
|
}
|
|
442
|
-
const data = await this.reader.getPositionHealth(this.address, user, ctoken.address, helpers_1.EMPTY_ADDRESS, false,
|
|
674
|
+
const data = await this.reader.getPositionHealth(this.address, user, ctoken.address, helpers_1.EMPTY_ADDRESS, false, redeemAssets, false, 0n, 0n);
|
|
443
675
|
if (data.errorCodeHit) {
|
|
444
676
|
throw new Error(`Error code hit when calculating position health preview. This usually means price is stale so we couldn't get a valid health value.`);
|
|
445
677
|
}
|
|
@@ -476,7 +708,10 @@ class Market {
|
|
|
476
708
|
*/
|
|
477
709
|
async previewPositionHealthRepay(token, amount) {
|
|
478
710
|
const user = this.getAccountOrThrow();
|
|
479
|
-
const
|
|
711
|
+
const repayAssets = amount.eq(0)
|
|
712
|
+
? helpers_1.UINT256_MAX
|
|
713
|
+
: FormatConverter_1.default.decimalToBigInt(amount, token.decimals);
|
|
714
|
+
const data = await this.reader.getPositionHealth(this.address, user, helpers_1.EMPTY_ADDRESS, token.address, false, 0n, true, repayAssets, 0n);
|
|
480
715
|
if (data.errorCodeHit) {
|
|
481
716
|
throw new Error(`Error code hit when calculating position health preview. This usually means price is stale so we couldn't get a valid health value.`);
|
|
482
717
|
}
|
|
@@ -490,8 +725,8 @@ class Market {
|
|
|
490
725
|
* @param borrowAssets - Amount of assets being borrowed
|
|
491
726
|
* @returns An object containing the hypothetical liquidity values
|
|
492
727
|
*/
|
|
493
|
-
async hypotheticalLiquidityOf(account, cTokenModified = helpers_1.EMPTY_ADDRESS, redemptionShares = 0n, borrowAssets = 0n) {
|
|
494
|
-
return this.
|
|
728
|
+
async hypotheticalLiquidityOf(account, cTokenModified = helpers_1.EMPTY_ADDRESS, redemptionShares = 0n, borrowAssets = 0n, bufferTime = 0n) {
|
|
729
|
+
return this.reader.hypotheticalLiquidityOf(this.address, account, cTokenModified, redemptionShares, borrowAssets, bufferTime);
|
|
495
730
|
}
|
|
496
731
|
/**
|
|
497
732
|
* Fetch the expiration date of a user's cooldown period
|
|
@@ -503,7 +738,7 @@ class Market {
|
|
|
503
738
|
const cooldownTimestamp = await this.contract.accountAssets(account);
|
|
504
739
|
const cooldownLength = fetch || this.cooldownLength == 0n ? await this.contract.MIN_HOLD_PERIOD() : this.cooldownLength;
|
|
505
740
|
const unlockTime = cooldownTimestamp + cooldownLength;
|
|
506
|
-
return unlockTime
|
|
741
|
+
return this.cooldownDateFromUnlockTime(unlockTime, cooldownLength);
|
|
507
742
|
}
|
|
508
743
|
/**
|
|
509
744
|
* Fetch multiple market cooldown expirations
|
|
@@ -522,7 +757,7 @@ class Market {
|
|
|
522
757
|
const market = markets[i];
|
|
523
758
|
const cooldownTimestamp = cooldownTimestamps[i];
|
|
524
759
|
const cooldownLength = market.cooldownLength;
|
|
525
|
-
cooldowns[market.address] = cooldownTimestamp
|
|
760
|
+
cooldowns[market.address] = market.cooldownDateFromUnlockTime(cooldownTimestamp, cooldownLength);
|
|
526
761
|
}
|
|
527
762
|
return cooldowns;
|
|
528
763
|
}
|
|
@@ -533,68 +768,64 @@ class Market {
|
|
|
533
768
|
* @param provider - The RPC provider
|
|
534
769
|
* @returns An array of Market instances setup with protocol reader data
|
|
535
770
|
*/
|
|
536
|
-
static async getAll(reader, oracle_manager, provider
|
|
537
|
-
const
|
|
538
|
-
const
|
|
771
|
+
static async getAll(reader, oracle_manager, provider, signer, account, milestones = {}, incentives = {}, setup) {
|
|
772
|
+
const resolvedSetup = setup ?? resolveDefaultSetupConfig("Market.getAll");
|
|
773
|
+
const resolvedProvider = provider ?? resolvedSetup.readProvider;
|
|
774
|
+
const resolvedSigner = signer === undefined ? resolvedSetup.signer : signer;
|
|
775
|
+
const resolvedAccount = account === undefined ? resolvedSetup.account : account;
|
|
776
|
+
const chainId = chains_1.chain_config[resolvedSetup.chain]?.chainId;
|
|
777
|
+
const all_data = await reader.getAllMarketData(resolvedAccount);
|
|
539
778
|
// Filter out USDC — DeFiLlama incorrectly returns YZM vault yield labeled as USDC
|
|
540
779
|
const [yields, merklLendOpps, merklBorrowOpps] = await Promise.all([
|
|
541
|
-
Api_1.Api.fetchNativeYields(
|
|
542
|
-
(0, merkl_1.fetchMerklOpportunities)({ action: 'LEND' }).catch(() => []),
|
|
543
|
-
(0, merkl_1.fetchMerklOpportunities)({ action: 'BORROW' }).catch(() => []),
|
|
780
|
+
Api_1.Api.fetchNativeYields(resolvedSetup).then(y => y.filter(y => y.symbol.toUpperCase() !== 'USDC')),
|
|
781
|
+
(0, merkl_1.fetchMerklOpportunities)({ action: 'LEND', chainId }).catch(() => []),
|
|
782
|
+
(0, merkl_1.fetchMerklOpportunities)({ action: 'BORROW', chainId }).catch(() => []),
|
|
544
783
|
]);
|
|
784
|
+
const deployIndex = this.buildDeployDataIndex(resolvedSetup);
|
|
785
|
+
const milestonesByAddress = new Map(Object.entries(milestones).map(([market, milestone]) => [market.toLowerCase(), milestone]));
|
|
786
|
+
const incentivesByAddress = new Map(Object.entries(incentives).map(([market, marketIncentives]) => [market.toLowerCase(), marketIncentives]));
|
|
787
|
+
const lendOppApyByToken = (0, helpers_1.aggregateMerklAprByToken)(merklLendOpps, "deposit");
|
|
788
|
+
const borrowOppApyByToken = (0, helpers_1.aggregateMerklAprByToken)(merklBorrowOpps, "borrow");
|
|
789
|
+
const yieldIndex = this.buildYieldIndex(yields);
|
|
790
|
+
const dynamicByAddress = this.buildMarketPayloadIndex(all_data.dynamicMarket);
|
|
791
|
+
const userByAddress = this.buildMarketPayloadIndex(all_data.userData.markets);
|
|
545
792
|
let markets = [];
|
|
546
|
-
for (
|
|
547
|
-
const staticData = all_data.staticMarket[i];
|
|
548
|
-
const dynamicData = all_data.dynamicMarket[i];
|
|
549
|
-
const userData = all_data.userData.markets[i];
|
|
793
|
+
for (const staticData of all_data.staticMarket) {
|
|
550
794
|
const market_address = staticData.address;
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
if (typeof data != 'object') {
|
|
555
|
-
continue;
|
|
556
|
-
}
|
|
557
|
-
if (market_address == data.address) {
|
|
558
|
-
deploy_data = {
|
|
559
|
-
name: obj_key,
|
|
560
|
-
plugins: 'plugins' in data ? data.plugins : {}
|
|
561
|
-
};
|
|
562
|
-
break;
|
|
563
|
-
}
|
|
564
|
-
}
|
|
795
|
+
const deploy_data = deployIndex.get(market_address.toLowerCase());
|
|
796
|
+
const dynamicData = dynamicByAddress.get(market_address.toLowerCase());
|
|
797
|
+
const userData = userByAddress.get(market_address.toLowerCase());
|
|
565
798
|
if (deploy_data == undefined) {
|
|
566
799
|
console.warn(`Could not find deploy data for market: ${market_address}, skipping...`);
|
|
567
800
|
continue;
|
|
568
801
|
}
|
|
569
|
-
if (staticData == undefined) {
|
|
570
|
-
console.warn(`Could not find static market data for index: ${i}`);
|
|
571
|
-
continue;
|
|
572
|
-
}
|
|
573
802
|
if (dynamicData == undefined) {
|
|
574
|
-
|
|
575
|
-
continue;
|
|
803
|
+
throw new Error(`Missing dynamic market data for ${market_address} during Market.getAll boot.`);
|
|
576
804
|
}
|
|
577
805
|
if (userData == undefined) {
|
|
578
|
-
|
|
579
|
-
continue;
|
|
806
|
+
throw new Error(`Missing user market data for ${market_address} during Market.getAll boot.`);
|
|
580
807
|
}
|
|
581
|
-
const market = new Market(
|
|
582
|
-
|
|
583
|
-
|
|
808
|
+
const market = new Market(resolvedProvider, resolvedSigner, resolvedAccount, staticData, dynamicData, userData, deploy_data, oracle_manager, reader, resolvedSetup);
|
|
809
|
+
const rewardKey = market.address.toLowerCase();
|
|
810
|
+
const milestone = milestonesByAddress.get(rewardKey);
|
|
811
|
+
if (milestone != undefined) {
|
|
812
|
+
market.milestone = milestone;
|
|
584
813
|
}
|
|
585
|
-
|
|
586
|
-
|
|
814
|
+
const marketIncentives = incentivesByAddress.get(rewardKey);
|
|
815
|
+
if (marketIncentives != undefined) {
|
|
816
|
+
market.incentives = marketIncentives;
|
|
587
817
|
}
|
|
588
818
|
for (const token of market.tokens) {
|
|
589
|
-
const
|
|
590
|
-
|
|
591
|
-
|
|
819
|
+
const tokenKey = token.address.toLowerCase();
|
|
820
|
+
const lendApy = lendOppApyByToken.get(tokenKey);
|
|
821
|
+
if (lendApy != undefined) {
|
|
822
|
+
token.incentiveSupplyApy = lendApy;
|
|
592
823
|
}
|
|
593
|
-
const
|
|
594
|
-
if (
|
|
595
|
-
token.incentiveBorrowApy =
|
|
824
|
+
const borrowApy = borrowOppApyByToken.get(tokenKey);
|
|
825
|
+
if (borrowApy != undefined) {
|
|
826
|
+
token.incentiveBorrowApy = borrowApy;
|
|
596
827
|
}
|
|
597
|
-
const api_yield =
|
|
828
|
+
const api_yield = yieldIndex.get(token.asset.symbol.toUpperCase());
|
|
598
829
|
if (api_yield != undefined) {
|
|
599
830
|
token.nativeApy = new decimal_js_1.Decimal(api_yield.apy / 100);
|
|
600
831
|
}
|