@moonwell-fi/moonwell-sdk 0.11.0 → 0.12.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/CHANGELOG.md +6 -0
- package/_cjs/actions/core/markets/common.js +26 -12
- package/_cjs/actions/core/markets/common.js.map +1 -1
- package/_cjs/actions/core/markets/getMarketSnapshots.js +173 -321
- package/_cjs/actions/core/markets/getMarketSnapshots.js.map +1 -1
- package/_cjs/actions/core/user-positions/getUserPositionSnapshots.js +31 -26
- package/_cjs/actions/core/user-positions/getUserPositionSnapshots.js.map +1 -1
- package/_cjs/actions/governance/getCirculatingSupplySnapshots.js +35 -29
- package/_cjs/actions/governance/getCirculatingSupplySnapshots.js.map +1 -1
- package/_cjs/actions/governance/getStakingSnapshots.js +16 -12
- package/_cjs/actions/governance/getStakingSnapshots.js.map +1 -1
- package/_cjs/actions/governance/proposals/common.js +247 -211
- package/_cjs/actions/governance/proposals/common.js.map +1 -1
- package/_cjs/actions/morpho/markets/common.js +26 -29
- package/_cjs/actions/morpho/markets/common.js.map +1 -1
- package/_cjs/actions/morpho/user-positions/getMorphoVaultUserPositionSnapshots.js +12 -69
- package/_cjs/actions/morpho/user-positions/getMorphoVaultUserPositionSnapshots.js.map +1 -1
- package/_cjs/actions/morpho/vaults/common.js +7 -4
- package/_cjs/actions/morpho/vaults/common.js.map +1 -1
- package/_cjs/actions/morpho/vaults/getMorphoVaultSnapshots.js +21 -78
- package/_cjs/actions/morpho/vaults/getMorphoVaultSnapshots.js.map +1 -1
- package/_cjs/actions/morpho/vaults/getMorphoVaultStakingSnapshots.js +13 -66
- package/_cjs/actions/morpho/vaults/getMorphoVaultStakingSnapshots.js.map +1 -1
- package/_cjs/client/createMoonwellClient.js +9 -3
- package/_cjs/client/createMoonwellClient.js.map +1 -1
- package/_cjs/environments/definitions/arbitrum/environment.js +1 -2
- package/_cjs/environments/definitions/arbitrum/environment.js.map +1 -1
- package/_cjs/environments/definitions/avalanche/environment.js +1 -2
- package/_cjs/environments/definitions/avalanche/environment.js.map +1 -1
- package/_cjs/environments/definitions/base/custom.js +0 -1
- package/_cjs/environments/definitions/base/custom.js.map +1 -1
- package/_cjs/environments/definitions/base/environment.js +1 -2
- package/_cjs/environments/definitions/base/environment.js.map +1 -1
- package/_cjs/environments/definitions/ethereum/environment.js +1 -2
- package/_cjs/environments/definitions/ethereum/environment.js.map +1 -1
- package/_cjs/environments/definitions/moonbeam/environment.js +1 -2
- package/_cjs/environments/definitions/moonbeam/environment.js.map +1 -1
- package/_cjs/environments/definitions/optimism/custom.js +0 -1
- package/_cjs/environments/definitions/optimism/custom.js.map +1 -1
- package/_cjs/environments/definitions/optimism/environment.js +1 -2
- package/_cjs/environments/definitions/optimism/environment.js.map +1 -1
- package/_cjs/environments/definitions/polygon/environment.js +1 -2
- package/_cjs/environments/definitions/polygon/environment.js.map +1 -1
- package/_cjs/environments/index.js +8 -8
- package/_cjs/environments/index.js.map +1 -1
- package/_cjs/environments/types/config.js +1 -0
- package/_cjs/environments/types/config.js.map +1 -1
- package/_cjs/errors/version.js +1 -1
- package/_esm/actions/core/markets/common.js +26 -13
- package/_esm/actions/core/markets/common.js.map +1 -1
- package/_esm/actions/core/markets/getMarketSnapshots.js +194 -346
- package/_esm/actions/core/markets/getMarketSnapshots.js.map +1 -1
- package/_esm/actions/core/user-positions/getUserPositionSnapshots.js +32 -29
- package/_esm/actions/core/user-positions/getUserPositionSnapshots.js.map +1 -1
- package/_esm/actions/governance/getCirculatingSupplySnapshots.js +35 -30
- package/_esm/actions/governance/getCirculatingSupplySnapshots.js.map +1 -1
- package/_esm/actions/governance/getStakingSnapshots.js +17 -13
- package/_esm/actions/governance/getStakingSnapshots.js.map +1 -1
- package/_esm/actions/governance/proposals/common.js +246 -216
- package/_esm/actions/governance/proposals/common.js.map +1 -1
- package/_esm/actions/morpho/markets/common.js +27 -34
- package/_esm/actions/morpho/markets/common.js.map +1 -1
- package/_esm/actions/morpho/user-positions/getMorphoVaultUserPositionSnapshots.js +14 -68
- package/_esm/actions/morpho/user-positions/getMorphoVaultUserPositionSnapshots.js.map +1 -1
- package/_esm/actions/morpho/vaults/common.js +7 -4
- package/_esm/actions/morpho/vaults/common.js.map +1 -1
- package/_esm/actions/morpho/vaults/getMorphoVaultSnapshots.js +24 -78
- package/_esm/actions/morpho/vaults/getMorphoVaultSnapshots.js.map +1 -1
- package/_esm/actions/morpho/vaults/getMorphoVaultStakingSnapshots.js +15 -65
- package/_esm/actions/morpho/vaults/getMorphoVaultStakingSnapshots.js.map +1 -1
- package/_esm/client/createMoonwellClient.js +9 -3
- package/_esm/client/createMoonwellClient.js.map +1 -1
- package/_esm/environments/definitions/arbitrum/environment.js +1 -2
- package/_esm/environments/definitions/arbitrum/environment.js.map +1 -1
- package/_esm/environments/definitions/avalanche/environment.js +1 -2
- package/_esm/environments/definitions/avalanche/environment.js.map +1 -1
- package/_esm/environments/definitions/base/custom.js +0 -1
- package/_esm/environments/definitions/base/custom.js.map +1 -1
- package/_esm/environments/definitions/base/environment.js +1 -2
- package/_esm/environments/definitions/base/environment.js.map +1 -1
- package/_esm/environments/definitions/ethereum/environment.js +1 -2
- package/_esm/environments/definitions/ethereum/environment.js.map +1 -1
- package/_esm/environments/definitions/moonbeam/environment.js +1 -2
- package/_esm/environments/definitions/moonbeam/environment.js.map +1 -1
- package/_esm/environments/definitions/optimism/custom.js +0 -1
- package/_esm/environments/definitions/optimism/custom.js.map +1 -1
- package/_esm/environments/definitions/optimism/environment.js +1 -2
- package/_esm/environments/definitions/optimism/environment.js.map +1 -1
- package/_esm/environments/definitions/polygon/environment.js +1 -2
- package/_esm/environments/definitions/polygon/environment.js.map +1 -1
- package/_esm/environments/index.js +8 -8
- package/_esm/environments/index.js.map +1 -1
- package/_esm/environments/types/config.js +1 -0
- package/_esm/environments/types/config.js.map +1 -1
- package/_esm/errors/version.js +1 -1
- package/_types/actions/core/markets/common.d.ts.map +1 -1
- package/_types/actions/core/markets/getMarketSnapshots.d.ts.map +1 -1
- package/_types/actions/core/user-positions/getUserPositionSnapshots.d.ts +0 -1
- package/_types/actions/core/user-positions/getUserPositionSnapshots.d.ts.map +1 -1
- package/_types/actions/governance/getCirculatingSupplySnapshots.d.ts.map +1 -1
- package/_types/actions/governance/getStakingSnapshots.d.ts.map +1 -1
- package/_types/actions/governance/proposals/common.d.ts +2 -8
- package/_types/actions/governance/proposals/common.d.ts.map +1 -1
- package/_types/actions/morpho/markets/common.d.ts.map +1 -1
- package/_types/actions/morpho/user-positions/getMorphoVaultUserPositionSnapshots.d.ts.map +1 -1
- package/_types/actions/morpho/vaults/common.d.ts.map +1 -1
- package/_types/actions/morpho/vaults/getMorphoVaultSnapshots.d.ts.map +1 -1
- package/_types/actions/morpho/vaults/getMorphoVaultStakingSnapshots.d.ts.map +1 -1
- package/_types/client/createMoonwellClient.d.ts +4 -4
- package/_types/client/createMoonwellClient.d.ts.map +1 -1
- package/_types/environments/definitions/arbitrum/environment.d.ts +1 -1
- package/_types/environments/definitions/arbitrum/environment.d.ts.map +1 -1
- package/_types/environments/definitions/avalanche/environment.d.ts +1 -1
- package/_types/environments/definitions/avalanche/environment.d.ts.map +1 -1
- package/_types/environments/definitions/base/custom.d.ts +0 -1
- package/_types/environments/definitions/base/custom.d.ts.map +1 -1
- package/_types/environments/definitions/base/environment.d.ts +1 -1
- package/_types/environments/definitions/base/environment.d.ts.map +1 -1
- package/_types/environments/definitions/ethereum/environment.d.ts +1 -1
- package/_types/environments/definitions/ethereum/environment.d.ts.map +1 -1
- package/_types/environments/definitions/moonbeam/environment.d.ts +1 -1
- package/_types/environments/definitions/moonbeam/environment.d.ts.map +1 -1
- package/_types/environments/definitions/optimism/custom.d.ts +0 -1
- package/_types/environments/definitions/optimism/custom.d.ts.map +1 -1
- package/_types/environments/definitions/optimism/environment.d.ts +1 -2
- package/_types/environments/definitions/optimism/environment.d.ts.map +1 -1
- package/_types/environments/definitions/polygon/environment.d.ts +1 -1
- package/_types/environments/definitions/polygon/environment.d.ts.map +1 -1
- package/_types/environments/index.d.ts +0 -3
- package/_types/environments/index.d.ts.map +1 -1
- package/_types/environments/types/config.d.ts +10 -3
- package/_types/environments/types/config.d.ts.map +1 -1
- package/_types/errors/version.d.ts +1 -1
- package/actions/core/markets/common.ts +33 -18
- package/actions/core/markets/getMarketSnapshots.ts +261 -511
- package/actions/core/user-positions/getUserPositionSnapshots.ts +44 -46
- package/actions/governance/getCirculatingSupplySnapshots.ts +43 -35
- package/actions/governance/getStakingSnapshots.ts +32 -29
- package/actions/governance/proposals/common.ts +369 -330
- package/actions/morpho/markets/common.ts +32 -43
- package/actions/morpho/user-positions/getMorphoVaultUserPositionSnapshots.ts +20 -109
- package/actions/morpho/vaults/common.ts +7 -6
- package/actions/morpho/vaults/getMorphoVaultSnapshots.ts +36 -120
- package/actions/morpho/vaults/getMorphoVaultStakingSnapshots.ts +24 -111
- package/client/createMoonwellClient.ts +17 -5
- package/environments/definitions/arbitrum/environment.ts +0 -2
- package/environments/definitions/avalanche/environment.ts +0 -2
- package/environments/definitions/base/custom.ts +0 -1
- package/environments/definitions/base/environment.ts +0 -2
- package/environments/definitions/ethereum/environment.ts +0 -2
- package/environments/definitions/moonbeam/environment.ts +0 -2
- package/environments/definitions/optimism/custom.ts +0 -1
- package/environments/definitions/optimism/environment.ts +0 -2
- package/environments/definitions/polygon/environment.ts +0 -2
- package/environments/index.ts +6 -27
- package/environments/types/config.ts +11 -3
- package/errors/version.ts +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
2
|
import type { MoonwellClient } from "../../../client/createMoonwellClient.js";
|
|
3
3
|
import {
|
|
4
|
-
Amount,
|
|
5
4
|
type SnapshotPeriod,
|
|
6
5
|
applyGranularity,
|
|
7
6
|
calculateTimeRange,
|
|
@@ -16,7 +15,6 @@ import type { MarketSnapshot } from "../../../types/market.js";
|
|
|
16
15
|
import {
|
|
17
16
|
DEFAULT_LUNAR_TIMEOUT_MS,
|
|
18
17
|
createLunarIndexerClient,
|
|
19
|
-
shouldFallback,
|
|
20
18
|
} from "../../lunar-indexer-client.js";
|
|
21
19
|
import { transformMarketSnapshots } from "../../lunar-indexer-transformers.js";
|
|
22
20
|
import {
|
|
@@ -93,9 +91,7 @@ export async function getMarketSnapshots<
|
|
|
93
91
|
args.endTime,
|
|
94
92
|
);
|
|
95
93
|
|
|
96
|
-
//
|
|
97
|
-
// Morpho Blue API, subgraph, or a mix). Apply a final sanity check to ensure
|
|
98
|
-
// totalSupply is always in loan token units.
|
|
94
|
+
// Apply a final sanity check to ensure totalSupply is always in loan token units.
|
|
99
95
|
//
|
|
100
96
|
// Some markets (e.g. USDC/ETH where collateral=USDC, loan=WETH) normalize
|
|
101
97
|
// totalSupply to collateral units — skip the check for those because
|
|
@@ -144,103 +140,51 @@ async function fetchCoreMarketSnapshots(
|
|
|
144
140
|
startTime?: number,
|
|
145
141
|
endTime?: number,
|
|
146
142
|
): Promise<MarketSnapshot[]> {
|
|
147
|
-
if (environment.lunarIndexerUrl) {
|
|
143
|
+
if (!environment.lunarIndexerUrl) {
|
|
144
|
+
if (!environment.indexerUrl) return [];
|
|
148
145
|
try {
|
|
149
|
-
|
|
146
|
+
return await fetchCoreMarketSnapshotsFromPonder(
|
|
150
147
|
marketAddress,
|
|
151
148
|
environment,
|
|
152
|
-
period,
|
|
153
|
-
startTime,
|
|
154
|
-
endTime,
|
|
155
149
|
);
|
|
156
|
-
return result;
|
|
157
150
|
} catch (error) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
console.debug(
|
|
162
|
-
"[Lunar fallback] Falling back to Ponder for snapshots:",
|
|
151
|
+
console.warn(
|
|
152
|
+
`[getMarketSnapshots] Ponder failed for chain ${environment.chainId}:`,
|
|
163
153
|
error,
|
|
164
154
|
);
|
|
155
|
+
environment.onError?.(error, {
|
|
156
|
+
source: "market-snapshots-ponder",
|
|
157
|
+
chainId: environment.chainId,
|
|
158
|
+
});
|
|
159
|
+
return [];
|
|
165
160
|
}
|
|
166
161
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
return result;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
async function fetchCoreMarketSnapshotsFromLunar(
|
|
176
|
-
marketAddress: string,
|
|
177
|
-
environment: Environment,
|
|
178
|
-
period?: "1M" | "3M" | "1Y" | "ALL",
|
|
179
|
-
customStartTime?: number,
|
|
180
|
-
customEndTime?: number,
|
|
181
|
-
): Promise<MarketSnapshot[]> {
|
|
182
|
-
if (!environment.lunarIndexerUrl) {
|
|
183
|
-
throw new Error("Lunar Indexer URL not configured");
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const client = createLunarIndexerClient({
|
|
187
|
-
baseUrl: environment.lunarIndexerUrl,
|
|
188
|
-
timeout: DEFAULT_LUNAR_TIMEOUT_MS,
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
const marketId = buildMarketId(environment.chainId, marketAddress);
|
|
192
|
-
const { startTime, endTime, granularity } = calculateTimeRange(
|
|
193
|
-
period,
|
|
194
|
-
customStartTime,
|
|
195
|
-
customEndTime,
|
|
196
|
-
);
|
|
197
|
-
|
|
198
|
-
const allSnapshots: MarketSnapshot[] = [];
|
|
199
|
-
let cursor: string | null = null;
|
|
200
|
-
const MAX_PAGES = 100;
|
|
201
|
-
let page = 0;
|
|
202
|
-
|
|
203
|
-
do {
|
|
204
|
-
const response = await client.getMarketSnapshots(marketId, {
|
|
205
|
-
limit: 1000,
|
|
206
|
-
...(cursor && { cursor }),
|
|
207
|
-
granularity: toApiGranularity(granularity),
|
|
162
|
+
try {
|
|
163
|
+
return await fetchCoreMarketSnapshotsFromLunar(
|
|
164
|
+
marketAddress,
|
|
165
|
+
environment,
|
|
166
|
+
period,
|
|
208
167
|
startTime,
|
|
209
168
|
endTime,
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
const transformed = transformMarketSnapshots(
|
|
213
|
-
response.results,
|
|
214
|
-
environment.chainId,
|
|
215
169
|
);
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
const price = supplied > 0 ? suppliedUsd / supplied : 0;
|
|
228
|
-
|
|
229
|
-
return {
|
|
230
|
-
...snapshot,
|
|
231
|
-
collateralTokenPrice: price,
|
|
232
|
-
loanTokenPrice: price,
|
|
233
|
-
};
|
|
234
|
-
});
|
|
170
|
+
} catch (error) {
|
|
171
|
+
console.warn(
|
|
172
|
+
`[getMarketSnapshots] Lunar Indexer failed for chain ${environment.chainId}:`,
|
|
173
|
+
error,
|
|
174
|
+
);
|
|
175
|
+
environment.onError?.(error, {
|
|
176
|
+
source: "market-snapshots",
|
|
177
|
+
chainId: environment.chainId,
|
|
178
|
+
});
|
|
179
|
+
return [];
|
|
180
|
+
}
|
|
235
181
|
}
|
|
236
182
|
|
|
237
183
|
async function fetchCoreMarketSnapshotsFromPonder(
|
|
238
184
|
marketAddress: string,
|
|
239
185
|
environment: Environment,
|
|
240
186
|
): Promise<MarketSnapshot[]> {
|
|
241
|
-
|
|
242
|
-
let hasNextPage = true;
|
|
243
|
-
let endCursor: string | undefined;
|
|
187
|
+
if (!environment.indexerUrl) return [];
|
|
244
188
|
|
|
245
189
|
interface MarketDailyData {
|
|
246
190
|
totalBorrows: number;
|
|
@@ -254,15 +198,16 @@ async function fetchCoreMarketSnapshotsFromPonder(
|
|
|
254
198
|
timestamp: number;
|
|
255
199
|
}
|
|
256
200
|
|
|
201
|
+
const dailyData: MarketDailyData[] = [];
|
|
202
|
+
let hasNextPage = true;
|
|
203
|
+
let endCursor: string | undefined;
|
|
204
|
+
|
|
257
205
|
while (hasNextPage) {
|
|
258
206
|
const result = await axios.post<{
|
|
259
207
|
data: {
|
|
260
208
|
marketDailySnapshots: {
|
|
261
209
|
items: MarketDailyData[];
|
|
262
|
-
pageInfo: {
|
|
263
|
-
hasNextPage: boolean;
|
|
264
|
-
endCursor: string;
|
|
265
|
-
};
|
|
210
|
+
pageInfo: { hasNextPage: boolean; endCursor: string };
|
|
266
211
|
};
|
|
267
212
|
};
|
|
268
213
|
}>(environment.indexerUrl, {
|
|
@@ -304,78 +249,97 @@ async function fetchCoreMarketSnapshotsFromPonder(
|
|
|
304
249
|
endCursor = result.data.data.marketDailySnapshots.pageInfo.endCursor;
|
|
305
250
|
}
|
|
306
251
|
|
|
307
|
-
if (dailyData.length
|
|
308
|
-
return dailyData.map((point: any) => {
|
|
309
|
-
const supplied = Number(point.totalSupplies);
|
|
310
|
-
const borrow = Number(point.totalBorrows);
|
|
252
|
+
if (dailyData.length === 0) return [];
|
|
311
253
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
254
|
+
return dailyData.map((point) => {
|
|
255
|
+
const supplied = Number(point.totalSupplies);
|
|
256
|
+
const borrow = Number(point.totalBorrows);
|
|
257
|
+
const borrowUsd = Number(point.totalBorrowsUSD);
|
|
258
|
+
const suppliedUsd = Number(point.totalSuppliesUSD);
|
|
259
|
+
const liquidity = Math.max(point.totalLiquidity, 0);
|
|
260
|
+
const liquidityUsd = Math.max(point.totalLiquidityUSD, 0);
|
|
261
|
+
const price = suppliedUsd / supplied;
|
|
316
262
|
|
|
317
|
-
|
|
263
|
+
return {
|
|
264
|
+
marketId: marketAddress.toLowerCase(),
|
|
265
|
+
chainId: environment.chainId,
|
|
266
|
+
timestamp: point.timestamp * 1000,
|
|
267
|
+
totalSupply: supplied,
|
|
268
|
+
totalSupplyUsd: suppliedUsd,
|
|
269
|
+
totalBorrows: borrow,
|
|
270
|
+
totalBorrowsUsd: borrowUsd,
|
|
271
|
+
totalLiquidity: liquidity,
|
|
272
|
+
totalLiquidityUsd: liquidityUsd,
|
|
273
|
+
totalReallocatableLiquidity: 0,
|
|
274
|
+
totalReallocatableLiquidityUsd: 0,
|
|
275
|
+
baseSupplyApy: point.baseSupplyApy,
|
|
276
|
+
baseBorrowApy: point.baseBorrowApy,
|
|
277
|
+
collateralTokenPrice: price,
|
|
278
|
+
loanTokenPrice: price,
|
|
279
|
+
};
|
|
280
|
+
});
|
|
281
|
+
}
|
|
318
282
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
totalReallocatableLiquidity: 0,
|
|
330
|
-
totalReallocatableLiquidityUsd: 0,
|
|
331
|
-
baseSupplyApy: point.baseSupplyApy,
|
|
332
|
-
baseBorrowApy: point.baseBorrowApy,
|
|
333
|
-
collateralTokenPrice: price,
|
|
334
|
-
loanTokenPrice: price,
|
|
335
|
-
};
|
|
283
|
+
async function fetchCoreMarketSnapshotsFromLunar(
|
|
284
|
+
marketAddress: string,
|
|
285
|
+
environment: Environment,
|
|
286
|
+
period?: "1M" | "3M" | "1Y" | "ALL",
|
|
287
|
+
customStartTime?: number,
|
|
288
|
+
customEndTime?: number,
|
|
289
|
+
): Promise<MarketSnapshot[]> {
|
|
290
|
+
if (!environment.lunarIndexerUrl) {
|
|
291
|
+
throw new Error("Lunar Indexer URL not configured");
|
|
292
|
+
}
|
|
336
293
|
|
|
337
|
-
|
|
294
|
+
const client = createLunarIndexerClient({
|
|
295
|
+
baseUrl: environment.lunarIndexerUrl,
|
|
296
|
+
timeout: DEFAULT_LUNAR_TIMEOUT_MS,
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
const marketId = buildMarketId(environment.chainId, marketAddress);
|
|
300
|
+
const { startTime, endTime, granularity } = calculateTimeRange(
|
|
301
|
+
period,
|
|
302
|
+
customStartTime,
|
|
303
|
+
customEndTime,
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
const allSnapshots: MarketSnapshot[] = [];
|
|
307
|
+
let cursor: string | null = null;
|
|
308
|
+
const MAX_PAGES = 100;
|
|
309
|
+
let page = 0;
|
|
310
|
+
|
|
311
|
+
do {
|
|
312
|
+
const response = await client.getMarketSnapshots(marketId, {
|
|
313
|
+
limit: 1000,
|
|
314
|
+
...(cursor && { cursor }),
|
|
315
|
+
granularity: toApiGranularity(granularity),
|
|
316
|
+
startTime,
|
|
317
|
+
endTime,
|
|
338
318
|
});
|
|
339
|
-
} else {
|
|
340
|
-
return [];
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
319
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
operationName?: string,
|
|
348
|
-
variables?: any,
|
|
349
|
-
) {
|
|
350
|
-
try {
|
|
351
|
-
const url =
|
|
352
|
-
environment.custom.morpho?.apiUrl || "https://api.morpho.org/graphql";
|
|
353
|
-
const response = await axios.post(
|
|
354
|
-
url,
|
|
355
|
-
{ query: query, operationName, variables },
|
|
356
|
-
{ timeout: 5000 },
|
|
320
|
+
const transformed = transformMarketSnapshots(
|
|
321
|
+
response.results,
|
|
322
|
+
environment.chainId,
|
|
357
323
|
);
|
|
358
324
|
|
|
359
|
-
|
|
360
|
-
if (typeof window !== "undefined") {
|
|
361
|
-
console.debug(
|
|
362
|
-
`[Morpho GraphQL Market Snapshots] Non-200 (${response.statusText}) or errors:`,
|
|
363
|
-
response.data.errors,
|
|
364
|
-
);
|
|
365
|
-
}
|
|
366
|
-
return undefined;
|
|
367
|
-
}
|
|
325
|
+
allSnapshots.push(...transformed);
|
|
368
326
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
327
|
+
cursor = response.nextCursor;
|
|
328
|
+
page++;
|
|
329
|
+
} while (cursor !== null && page < MAX_PAGES);
|
|
330
|
+
|
|
331
|
+
allSnapshots.sort((a, b) => a.timestamp - b.timestamp);
|
|
332
|
+
return applyGranularity(allSnapshots, granularity).map((snapshot) => {
|
|
333
|
+
const supplied = snapshot.totalSupply;
|
|
334
|
+
const suppliedUsd = snapshot.totalSupplyUsd;
|
|
335
|
+
const price = supplied > 0 ? suppliedUsd / supplied : 0;
|
|
336
|
+
|
|
337
|
+
return {
|
|
338
|
+
...snapshot,
|
|
339
|
+
collateralTokenPrice: price,
|
|
340
|
+
loanTokenPrice: price,
|
|
341
|
+
};
|
|
342
|
+
});
|
|
379
343
|
}
|
|
380
344
|
|
|
381
345
|
// Fetches a timestamp-ms → WELL price map from the WELL market in the indexer.
|
|
@@ -432,386 +396,172 @@ export async function fetchIsolatedMarketSnapshots(
|
|
|
432
396
|
): Promise<MarketSnapshot[]> {
|
|
433
397
|
const lunarIndexerUrl = environment.lunarIndexerUrl;
|
|
434
398
|
|
|
435
|
-
if (lunarIndexerUrl) {
|
|
436
|
-
|
|
437
|
-
const { startTime } = calculateTimeRange(
|
|
438
|
-
period,
|
|
439
|
-
customStartTime,
|
|
440
|
-
customEndTime,
|
|
441
|
-
);
|
|
442
|
-
|
|
443
|
-
// The USDC/ETH market (collateral = USDC, loan = WETH) needs normalization:
|
|
444
|
-
// the indexer returns totalSupplyAssets in WETH units but the chart needs
|
|
445
|
-
// USDC-equivalent units (totalSupplyAssetsUsd / collateralTokenPrice).
|
|
446
|
-
const marketConfig = Object.values(environment.config.morphoMarkets).find(
|
|
447
|
-
(m) => m.id.toLowerCase() === marketAddress.toLowerCase(),
|
|
448
|
-
);
|
|
449
|
-
const loanSymbol = marketConfig
|
|
450
|
-
? environment.config.tokens[marketConfig.loanToken]?.symbol
|
|
451
|
-
: undefined;
|
|
452
|
-
const collateralSymbol = marketConfig
|
|
453
|
-
? environment.config.tokens[marketConfig.collateralToken]?.symbol
|
|
454
|
-
: undefined;
|
|
455
|
-
const normalizeToCollateral =
|
|
456
|
-
loanSymbol === "ETH" && collateralSymbol === "USDC";
|
|
457
|
-
|
|
458
|
-
// stkWELL is not priced by the indexer (same oracle as WELL but unrecognized).
|
|
459
|
-
// Fetch the WELL market snapshots concurrently and use their prices to correct
|
|
460
|
-
// any stkWELL snapshots where collateralTokenPrice is 0.
|
|
461
|
-
const isStkWellMarket = collateralSymbol === "stkWELL";
|
|
462
|
-
const wellMarketConfig = isStkWellMarket
|
|
463
|
-
? Object.values(environment.config.morphoMarkets).find(
|
|
464
|
-
(m) => m.collateralToken === "WELL" || m.loanToken === "WELL",
|
|
465
|
-
)
|
|
466
|
-
: undefined;
|
|
467
|
-
|
|
468
|
-
const wellPricesPromise = wellMarketConfig
|
|
469
|
-
? fetchWellPricesByTimestamp(
|
|
470
|
-
lunarIndexerUrl,
|
|
471
|
-
environment.chainId,
|
|
472
|
-
wellMarketConfig,
|
|
473
|
-
startTime,
|
|
474
|
-
)
|
|
475
|
-
: Promise.resolve(new Map<number, number>());
|
|
476
|
-
|
|
477
|
-
const allSnapshots: MarketSnapshot[] = [];
|
|
478
|
-
let cursor: string | undefined;
|
|
479
|
-
const MAX_PAGES = 100;
|
|
480
|
-
let page = 0;
|
|
481
|
-
|
|
482
|
-
do {
|
|
483
|
-
const response = await fetchMarketSnapshotsFromIndexer(
|
|
484
|
-
lunarIndexerUrl,
|
|
485
|
-
environment.chainId,
|
|
486
|
-
marketAddress,
|
|
487
|
-
{
|
|
488
|
-
startTime,
|
|
489
|
-
granularity: "1d",
|
|
490
|
-
limit: 1000,
|
|
491
|
-
...(cursor && { cursor }),
|
|
492
|
-
},
|
|
493
|
-
);
|
|
494
|
-
|
|
495
|
-
allSnapshots.push(
|
|
496
|
-
...response.results
|
|
497
|
-
.filter((s) => isStartOfDay(s.timestamp))
|
|
498
|
-
.map((s) =>
|
|
499
|
-
transformIsolatedMarketSnapshotFromIndexer(s, {
|
|
500
|
-
normalizeToCollateral,
|
|
501
|
-
}),
|
|
502
|
-
),
|
|
503
|
-
);
|
|
504
|
-
|
|
505
|
-
cursor = response.nextCursor ?? undefined;
|
|
506
|
-
page++;
|
|
507
|
-
} while (cursor !== undefined && page < MAX_PAGES);
|
|
508
|
-
|
|
509
|
-
// Sanity check for non-normalized markets: detect when totalSupplyAssets was
|
|
510
|
-
// stored in collateral units instead of loan token units (an indexer bug seen on
|
|
511
|
-
// the stkWELL/USDC market). When this happens, totalSupplyUsd / totalSupply is
|
|
512
|
-
// close to collateralTokenPrice rather than loanTokenPrice. Recover the correct
|
|
513
|
-
// loan-token amount from the USD value instead of discarding the data point.
|
|
514
|
-
// We skip normalized markets (e.g. USDC/ETH where totalSupply is already in
|
|
515
|
-
// collateral units after normalization) to avoid false corrections.
|
|
516
|
-
const sanitizedSnapshots = normalizeToCollateral
|
|
517
|
-
? allSnapshots
|
|
518
|
-
: allSnapshots.map((snapshot) => {
|
|
519
|
-
if (snapshot.totalSupply === 0 || snapshot.loanTokenPrice === 0)
|
|
520
|
-
return snapshot;
|
|
521
|
-
const impliedLoanPrice =
|
|
522
|
-
snapshot.totalSupplyUsd / snapshot.totalSupply;
|
|
523
|
-
if (impliedLoanPrice < snapshot.loanTokenPrice * 0.1) {
|
|
524
|
-
return {
|
|
525
|
-
...snapshot,
|
|
526
|
-
totalSupply: snapshot.totalSupplyUsd / snapshot.loanTokenPrice,
|
|
527
|
-
totalLiquidity:
|
|
528
|
-
snapshot.totalLiquidityUsd / snapshot.loanTokenPrice,
|
|
529
|
-
};
|
|
530
|
-
}
|
|
531
|
-
return snapshot;
|
|
532
|
-
});
|
|
533
|
-
|
|
534
|
-
if (isStkWellMarket) {
|
|
535
|
-
const wellPriceByTimestampMs = await wellPricesPromise;
|
|
536
|
-
return sanitizedSnapshots.map((snapshot) => {
|
|
537
|
-
// Resolve the collateral (stkWELL) price: use indexed price when available,
|
|
538
|
-
// fall back to the WELL market price fetched concurrently.
|
|
539
|
-
let collateralTokenPrice = snapshot.collateralTokenPrice;
|
|
540
|
-
if (collateralTokenPrice === 0) {
|
|
541
|
-
const wellPrice = wellPriceByTimestampMs.get(snapshot.timestamp);
|
|
542
|
-
if (wellPrice) collateralTokenPrice = wellPrice;
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
// The lunar indexer stores totalSupplyAssets in loan-token (USDC) units.
|
|
546
|
-
// All fallback paths (BlueAPI, subgraph) convert to collateral (stkWELL) units:
|
|
547
|
-
// totalSupply = totalSupplyUsd / collateralTokenPrice
|
|
548
|
-
// Apply the same conversion here so the chart axis is consistent.
|
|
549
|
-
const totalSupply =
|
|
550
|
-
collateralTokenPrice > 0
|
|
551
|
-
? snapshot.totalSupplyUsd / collateralTokenPrice
|
|
552
|
-
: snapshot.totalSupply;
|
|
553
|
-
const totalLiquidity =
|
|
554
|
-
collateralTokenPrice > 0
|
|
555
|
-
? snapshot.totalLiquidityUsd / collateralTokenPrice
|
|
556
|
-
: snapshot.totalLiquidity;
|
|
557
|
-
const totalReallocatableLiquidity =
|
|
558
|
-
collateralTokenPrice > 0
|
|
559
|
-
? snapshot.totalReallocatableLiquidityUsd / collateralTokenPrice
|
|
560
|
-
: snapshot.totalReallocatableLiquidity;
|
|
561
|
-
|
|
562
|
-
return {
|
|
563
|
-
...snapshot,
|
|
564
|
-
collateralTokenPrice,
|
|
565
|
-
totalSupply,
|
|
566
|
-
totalLiquidity,
|
|
567
|
-
totalReallocatableLiquidity,
|
|
568
|
-
};
|
|
569
|
-
});
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
return sanitizedSnapshots;
|
|
573
|
-
} catch (error) {
|
|
574
|
-
if (!shouldFallback(error)) {
|
|
575
|
-
throw error;
|
|
576
|
-
}
|
|
577
|
-
console.debug(
|
|
578
|
-
"[Lunar fallback] Falling back for isolated market snapshots:",
|
|
579
|
-
error,
|
|
580
|
-
);
|
|
581
|
-
}
|
|
399
|
+
if (!lunarIndexerUrl) {
|
|
400
|
+
return [];
|
|
582
401
|
}
|
|
583
402
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
403
|
+
try {
|
|
404
|
+
return await fetchIsolatedMarketSnapshotsFromLunar(
|
|
405
|
+
marketAddress,
|
|
406
|
+
environment,
|
|
407
|
+
lunarIndexerUrl,
|
|
408
|
+
period,
|
|
409
|
+
customStartTime,
|
|
410
|
+
customEndTime,
|
|
411
|
+
);
|
|
412
|
+
} catch (error) {
|
|
413
|
+
console.warn(
|
|
414
|
+
`[getMarketSnapshots] Lunar Indexer failed for chain ${environment.chainId}:`,
|
|
415
|
+
error,
|
|
416
|
+
);
|
|
417
|
+
environment.onError?.(error, {
|
|
418
|
+
source: "market-snapshots",
|
|
419
|
+
chainId: environment.chainId,
|
|
420
|
+
});
|
|
421
|
+
return [];
|
|
422
|
+
}
|
|
591
423
|
}
|
|
592
424
|
|
|
593
|
-
async function
|
|
425
|
+
async function fetchIsolatedMarketSnapshotsFromLunar(
|
|
594
426
|
marketAddress: string,
|
|
595
427
|
environment: Environment,
|
|
428
|
+
lunarIndexerUrl: string,
|
|
596
429
|
period?: "1M" | "3M" | "1Y" | "ALL",
|
|
597
430
|
customStartTime?: number,
|
|
598
431
|
customEndTime?: number,
|
|
599
432
|
): Promise<MarketSnapshot[]> {
|
|
433
|
+
const { startTime } = calculateTimeRange(
|
|
434
|
+
period,
|
|
435
|
+
customStartTime,
|
|
436
|
+
customEndTime,
|
|
437
|
+
);
|
|
438
|
+
|
|
439
|
+
// The USDC/ETH market (collateral = USDC, loan = WETH) needs normalization:
|
|
440
|
+
// the indexer returns totalSupplyAssets in WETH units but the chart needs
|
|
441
|
+
// USDC-equivalent units (totalSupplyAssetsUsd / collateralTokenPrice).
|
|
600
442
|
const marketConfig = Object.values(environment.config.morphoMarkets).find(
|
|
601
|
-
(
|
|
443
|
+
(m) => m.id.toLowerCase() === marketAddress.toLowerCase(),
|
|
602
444
|
);
|
|
445
|
+
const loanSymbol = marketConfig
|
|
446
|
+
? environment.config.tokens[marketConfig.loanToken]?.symbol
|
|
447
|
+
: undefined;
|
|
448
|
+
const collateralSymbol = marketConfig
|
|
449
|
+
? environment.config.tokens[marketConfig.collateralToken]?.symbol
|
|
450
|
+
: undefined;
|
|
451
|
+
const normalizeToCollateral =
|
|
452
|
+
loanSymbol === "ETH" && collateralSymbol === "USDC";
|
|
453
|
+
|
|
454
|
+
// stkWELL is not priced by the indexer (same oracle as WELL but unrecognized).
|
|
455
|
+
// Fetch the WELL market snapshots concurrently and use their prices to correct
|
|
456
|
+
// any stkWELL snapshots where collateralTokenPrice is 0.
|
|
457
|
+
const isStkWellMarket = collateralSymbol === "stkWELL";
|
|
458
|
+
const wellMarketConfig = isStkWellMarket
|
|
459
|
+
? Object.values(environment.config.morphoMarkets).find(
|
|
460
|
+
(m) => m.collateralToken === "WELL" || m.loanToken === "WELL",
|
|
461
|
+
)
|
|
462
|
+
: undefined;
|
|
603
463
|
|
|
604
|
-
const
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
464
|
+
const wellPricesPromise = wellMarketConfig
|
|
465
|
+
? fetchWellPricesByTimestamp(
|
|
466
|
+
lunarIndexerUrl,
|
|
467
|
+
environment.chainId,
|
|
468
|
+
wellMarketConfig,
|
|
469
|
+
startTime,
|
|
470
|
+
)
|
|
471
|
+
: Promise.resolve(new Map<number, number>());
|
|
608
472
|
|
|
609
|
-
|
|
610
|
-
let
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
environment.config.morphoMarkets,
|
|
614
|
-
).find(
|
|
615
|
-
(market) =>
|
|
616
|
-
market.collateralToken === "WELL" || market.loanToken === "WELL",
|
|
617
|
-
);
|
|
473
|
+
const allSnapshots: MarketSnapshot[] = [];
|
|
474
|
+
let cursor: string | undefined;
|
|
475
|
+
const MAX_PAGES = 100;
|
|
476
|
+
let page = 0;
|
|
618
477
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
}`;
|
|
478
|
+
do {
|
|
479
|
+
const response = await fetchMarketSnapshotsFromIndexer(
|
|
480
|
+
lunarIndexerUrl,
|
|
481
|
+
environment.chainId,
|
|
482
|
+
marketAddress,
|
|
483
|
+
{
|
|
484
|
+
startTime,
|
|
485
|
+
granularity: "1d",
|
|
486
|
+
limit: 1000,
|
|
487
|
+
...(cursor && { cursor }),
|
|
488
|
+
},
|
|
489
|
+
);
|
|
634
490
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
: wellResult.wellMarket.loanAsset.priceUsd;
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
}
|
|
491
|
+
allSnapshots.push(
|
|
492
|
+
...response.results
|
|
493
|
+
.filter((s) => isStartOfDay(s.timestamp))
|
|
494
|
+
.map((s) =>
|
|
495
|
+
transformIsolatedMarketSnapshotFromIndexer(s, {
|
|
496
|
+
normalizeToCollateral,
|
|
497
|
+
}),
|
|
498
|
+
),
|
|
499
|
+
);
|
|
648
500
|
|
|
649
|
-
|
|
501
|
+
cursor = response.nextCursor ?? undefined;
|
|
502
|
+
page++;
|
|
503
|
+
} while (cursor !== undefined && page < MAX_PAGES);
|
|
650
504
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
priceUsd
|
|
672
|
-
decimals
|
|
673
|
-
}
|
|
674
|
-
collateralAsset {
|
|
675
|
-
priceUsd
|
|
676
|
-
decimals
|
|
677
|
-
}
|
|
678
|
-
historicalState {
|
|
679
|
-
supplyApy(options: $options) {
|
|
680
|
-
x
|
|
681
|
-
y
|
|
682
|
-
}
|
|
683
|
-
borrowApy(options: $options) {
|
|
684
|
-
x
|
|
685
|
-
y
|
|
686
|
-
}
|
|
687
|
-
borrowAssets(options: $options) {
|
|
688
|
-
x
|
|
689
|
-
y
|
|
690
|
-
}
|
|
691
|
-
borrowAssetsUsd(options: $options) {
|
|
692
|
-
x
|
|
693
|
-
y
|
|
694
|
-
}
|
|
695
|
-
supplyAssets(options: $options) {
|
|
696
|
-
x
|
|
697
|
-
y
|
|
698
|
-
}
|
|
699
|
-
supplyAssetsUsd(options: $options) {
|
|
700
|
-
x
|
|
701
|
-
y
|
|
702
|
-
}
|
|
703
|
-
liquidityAssets(options: $options) {
|
|
704
|
-
x
|
|
705
|
-
y
|
|
706
|
-
}
|
|
707
|
-
liquidityAssetsUsd(options: $options) {
|
|
708
|
-
x
|
|
709
|
-
y
|
|
710
|
-
}
|
|
505
|
+
// Sanity check for non-normalized markets: detect when totalSupplyAssets was
|
|
506
|
+
// stored in collateral units instead of loan token units (an indexer bug seen on
|
|
507
|
+
// the stkWELL/USDC market). When this happens, totalSupplyUsd / totalSupply is
|
|
508
|
+
// close to collateralTokenPrice rather than loanTokenPrice. Recover the correct
|
|
509
|
+
// loan-token amount from the USD value instead of discarding the data point.
|
|
510
|
+
// We skip normalized markets (e.g. USDC/ETH where totalSupply is already in
|
|
511
|
+
// collateral units after normalization) to avoid false corrections.
|
|
512
|
+
const sanitizedSnapshots = normalizeToCollateral
|
|
513
|
+
? allSnapshots
|
|
514
|
+
: allSnapshots.map((snapshot) => {
|
|
515
|
+
if (snapshot.totalSupply === 0 || snapshot.loanTokenPrice === 0)
|
|
516
|
+
return snapshot;
|
|
517
|
+
const impliedLoanPrice = snapshot.totalSupplyUsd / snapshot.totalSupply;
|
|
518
|
+
if (impliedLoanPrice < snapshot.loanTokenPrice * 0.1) {
|
|
519
|
+
return {
|
|
520
|
+
...snapshot,
|
|
521
|
+
totalSupply: snapshot.totalSupplyUsd / snapshot.loanTokenPrice,
|
|
522
|
+
totalLiquidity:
|
|
523
|
+
snapshot.totalLiquidityUsd / snapshot.loanTokenPrice,
|
|
524
|
+
};
|
|
711
525
|
}
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
const result = await fetchMorphoGraphQL(
|
|
716
|
-
environment,
|
|
717
|
-
query,
|
|
718
|
-
operationName,
|
|
719
|
-
variables,
|
|
720
|
-
);
|
|
526
|
+
return snapshot;
|
|
527
|
+
});
|
|
721
528
|
|
|
722
|
-
if (
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
): MarketSnapshot => {
|
|
733
|
-
const loanDecimals =
|
|
734
|
-
result.marketTotalTimeseries.loanAsset.decimals;
|
|
735
|
-
|
|
736
|
-
const borrowAssetsUsd =
|
|
737
|
-
result.marketTotalTimeseries.historicalState.borrowAssetsUsd[
|
|
738
|
-
index
|
|
739
|
-
];
|
|
740
|
-
|
|
741
|
-
const supplyAssets =
|
|
742
|
-
result.marketTotalTimeseries.historicalState.supplyAssets[index];
|
|
743
|
-
|
|
744
|
-
const supplyAssetsUsd =
|
|
745
|
-
result.marketTotalTimeseries.historicalState.supplyAssetsUsd[
|
|
746
|
-
index
|
|
747
|
-
];
|
|
748
|
-
|
|
749
|
-
const liquidityAssets =
|
|
750
|
-
result.marketTotalTimeseries.historicalState.liquidityAssets[
|
|
751
|
-
index
|
|
752
|
-
];
|
|
753
|
-
|
|
754
|
-
const liquidityAssetsUsd =
|
|
755
|
-
result.marketTotalTimeseries.historicalState.liquidityAssetsUsd[
|
|
756
|
-
index
|
|
757
|
-
];
|
|
758
|
-
|
|
759
|
-
const supplyApy =
|
|
760
|
-
result.marketTotalTimeseries.historicalState.supplyApy[index];
|
|
761
|
-
|
|
762
|
-
const borrowApy =
|
|
763
|
-
result.marketTotalTimeseries.historicalState.borrowApy[index];
|
|
764
|
-
|
|
765
|
-
let collateralTokenPrice =
|
|
766
|
-
result.marketTotalTimeseries.collateralAsset.priceUsd;
|
|
767
|
-
const loanTokenPrice =
|
|
768
|
-
result.marketTotalTimeseries.loanAsset.priceUsd;
|
|
769
|
-
|
|
770
|
-
if (isStkWellMarket && wellPrice !== null) {
|
|
771
|
-
collateralTokenPrice = wellPrice;
|
|
772
|
-
}
|
|
529
|
+
if (isStkWellMarket) {
|
|
530
|
+
const wellPriceByTimestampMs = await wellPricesPromise;
|
|
531
|
+
return sanitizedSnapshots.map((snapshot) => {
|
|
532
|
+
// Resolve the collateral (stkWELL) price: use indexed price when available,
|
|
533
|
+
// fall back to the WELL market price fetched concurrently.
|
|
534
|
+
let collateralTokenPrice = snapshot.collateralTokenPrice;
|
|
535
|
+
if (collateralTokenPrice === 0) {
|
|
536
|
+
const wellPrice = wellPriceByTimestampMs.get(snapshot.timestamp);
|
|
537
|
+
if (wellPrice) collateralTokenPrice = wellPrice;
|
|
538
|
+
}
|
|
773
539
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
totalLiquidity,
|
|
799
|
-
totalLiquidityUsd: Number(liquidityAssetsUsd.y),
|
|
800
|
-
totalReallocatableLiquidity: 0,
|
|
801
|
-
totalReallocatableLiquidityUsd: 0,
|
|
802
|
-
baseSupplyApy: supplyApy.y,
|
|
803
|
-
baseBorrowApy: borrowApy.y,
|
|
804
|
-
loanTokenPrice,
|
|
805
|
-
collateralTokenPrice,
|
|
806
|
-
};
|
|
807
|
-
},
|
|
808
|
-
);
|
|
809
|
-
|
|
810
|
-
return markets;
|
|
811
|
-
} catch (ex) {
|
|
812
|
-
return [];
|
|
813
|
-
}
|
|
814
|
-
} else {
|
|
815
|
-
return [];
|
|
540
|
+
// The lunar indexer stores totalSupplyAssets in loan-token (USDC) units.
|
|
541
|
+
// Convert to collateral (stkWELL) units for a consistent chart axis:
|
|
542
|
+
// totalSupply = totalSupplyUsd / collateralTokenPrice
|
|
543
|
+
const totalSupply =
|
|
544
|
+
collateralTokenPrice > 0
|
|
545
|
+
? snapshot.totalSupplyUsd / collateralTokenPrice
|
|
546
|
+
: snapshot.totalSupply;
|
|
547
|
+
const totalLiquidity =
|
|
548
|
+
collateralTokenPrice > 0
|
|
549
|
+
? snapshot.totalLiquidityUsd / collateralTokenPrice
|
|
550
|
+
: snapshot.totalLiquidity;
|
|
551
|
+
const totalReallocatableLiquidity =
|
|
552
|
+
collateralTokenPrice > 0
|
|
553
|
+
? snapshot.totalReallocatableLiquidityUsd / collateralTokenPrice
|
|
554
|
+
: snapshot.totalReallocatableLiquidity;
|
|
555
|
+
|
|
556
|
+
return {
|
|
557
|
+
...snapshot,
|
|
558
|
+
collateralTokenPrice,
|
|
559
|
+
totalSupply,
|
|
560
|
+
totalLiquidity,
|
|
561
|
+
totalReallocatableLiquidity,
|
|
562
|
+
};
|
|
563
|
+
});
|
|
816
564
|
}
|
|
565
|
+
|
|
566
|
+
return sanitizedSnapshots;
|
|
817
567
|
}
|