@moonwell-fi/moonwell-sdk 0.10.7 → 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 +12 -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/lunar-indexer-client.js +32 -0
- package/_cjs/actions/lunar-indexer-client.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 +41 -56
- 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/lunar-indexer-client.js +35 -0
- package/_esm/actions/lunar-indexer-client.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 +42 -54
- 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/lunar-indexer-client.d.ts +26 -0
- package/_types/actions/lunar-indexer-client.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 +9 -3
- 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/lunar-indexer-client.ts +64 -0
- package/actions/morpho/markets/common.ts +32 -43
- package/actions/morpho/user-positions/getMorphoVaultUserPositionSnapshots.ts +76 -87
- 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
|
@@ -74,6 +74,30 @@ export interface LunarPortfolioOptions {
|
|
|
74
74
|
market?: string;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
export interface LunarVaultPortfolioOptions {
|
|
78
|
+
startTime: number;
|
|
79
|
+
endTime: number;
|
|
80
|
+
granularity?: "1h" | "6h" | "1d";
|
|
81
|
+
chainId?: number;
|
|
82
|
+
vault?: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface LunarVaultPosition {
|
|
86
|
+
chainId: number;
|
|
87
|
+
vaultAddress: string;
|
|
88
|
+
shareBalance: string;
|
|
89
|
+
shareBalanceUsd: number;
|
|
90
|
+
assetsValue: number;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface LunarVaultPortfolio {
|
|
94
|
+
account: string;
|
|
95
|
+
positions: Array<{
|
|
96
|
+
timestamp: number;
|
|
97
|
+
vaults: LunarVaultPosition[];
|
|
98
|
+
}>;
|
|
99
|
+
}
|
|
100
|
+
|
|
77
101
|
export interface LunarComptroller {
|
|
78
102
|
id: string;
|
|
79
103
|
chainId: number;
|
|
@@ -251,6 +275,7 @@ export const DEFAULT_LUNAR_TIMEOUT_MS = 10_000;
|
|
|
251
275
|
export class LunarIndexerClient {
|
|
252
276
|
private client: AxiosInstance;
|
|
253
277
|
private stakingClient: AxiosInstance;
|
|
278
|
+
private vaultsClient: AxiosInstance;
|
|
254
279
|
|
|
255
280
|
constructor(config: LunarIndexerConfig) {
|
|
256
281
|
this.client = axios.create({
|
|
@@ -268,6 +293,14 @@ export class LunarIndexerClient {
|
|
|
268
293
|
"Content-Type": "application/json",
|
|
269
294
|
},
|
|
270
295
|
});
|
|
296
|
+
|
|
297
|
+
this.vaultsClient = axios.create({
|
|
298
|
+
baseURL: `${config.baseUrl}/api/v1/vaults`,
|
|
299
|
+
timeout: config.timeout || DEFAULT_LUNAR_TIMEOUT_MS,
|
|
300
|
+
headers: {
|
|
301
|
+
"Content-Type": "application/json",
|
|
302
|
+
},
|
|
303
|
+
});
|
|
271
304
|
}
|
|
272
305
|
|
|
273
306
|
/**
|
|
@@ -469,6 +502,37 @@ export class LunarIndexerClient {
|
|
|
469
502
|
}
|
|
470
503
|
}
|
|
471
504
|
|
|
505
|
+
/**
|
|
506
|
+
* Get vault account portfolio with historical positions
|
|
507
|
+
*/
|
|
508
|
+
async getVaultAccountPortfolio(
|
|
509
|
+
accountAddress: string,
|
|
510
|
+
options: LunarVaultPortfolioOptions,
|
|
511
|
+
): Promise<LunarVaultPortfolio> {
|
|
512
|
+
try {
|
|
513
|
+
const params: Record<string, string> = {
|
|
514
|
+
startTime: options.startTime.toString(),
|
|
515
|
+
endTime: options.endTime.toString(),
|
|
516
|
+
};
|
|
517
|
+
if (options.granularity) params.granularity = options.granularity;
|
|
518
|
+
if (options.chainId) params.chainId = options.chainId.toString();
|
|
519
|
+
if (options.vault) params.vault = options.vault;
|
|
520
|
+
|
|
521
|
+
const response = await this.vaultsClient.get<LunarVaultPortfolio>(
|
|
522
|
+
`/account/${accountAddress.toLowerCase()}/portfolio`,
|
|
523
|
+
{ params },
|
|
524
|
+
);
|
|
525
|
+
return response.data;
|
|
526
|
+
} catch (error) {
|
|
527
|
+
throw new LunarIndexerError(
|
|
528
|
+
`Failed to fetch vault portfolio for account ${accountAddress}`,
|
|
529
|
+
axios.isAxiosError(error) ? error.response?.status : undefined,
|
|
530
|
+
`/account/${accountAddress}/portfolio`,
|
|
531
|
+
error as Error,
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
472
536
|
/**
|
|
473
537
|
* Get vault staking snapshots for a specific chain (MetaMorpho vault staking)
|
|
474
538
|
*/
|
|
@@ -8,7 +8,6 @@ import type {
|
|
|
8
8
|
PublicAllocatorSharedLiquidityType,
|
|
9
9
|
} from "../../../types/morphoMarket.js";
|
|
10
10
|
import type { MorphoReward } from "../../../types/morphoReward.js";
|
|
11
|
-
import { shouldFallback } from "../../lunar-indexer-client.js";
|
|
12
11
|
import { getGraphQL } from "../utils/graphql.js";
|
|
13
12
|
import {
|
|
14
13
|
type GetMorphoMarketsRewardsReturnType as LunarIndexerRewardsType,
|
|
@@ -829,7 +828,10 @@ async function getMorphoMarketsDataFromIndexer(params: {
|
|
|
829
828
|
`Failed to fetch markets from Lunar Indexer for chain ${environment.chainId}, falling back to on-chain:`,
|
|
830
829
|
error,
|
|
831
830
|
);
|
|
832
|
-
|
|
831
|
+
environment.onError?.(error, {
|
|
832
|
+
source: "morpho-markets",
|
|
833
|
+
chainId: environment.chainId,
|
|
834
|
+
});
|
|
833
835
|
return Promise.reject({ environment, error });
|
|
834
836
|
}
|
|
835
837
|
}),
|
|
@@ -841,9 +843,9 @@ async function getMorphoMarketsDataFromIndexer(params: {
|
|
|
841
843
|
|
|
842
844
|
// Collect environments that failed to fetch from indexer for fallback
|
|
843
845
|
const failedEnvironments = marketsSettlements
|
|
844
|
-
.filter((s) => s.status === "rejected")
|
|
845
|
-
.map((s
|
|
846
|
-
.filter((env) => env !== undefined);
|
|
846
|
+
.filter((s): s is PromiseRejectedResult => s.status === "rejected")
|
|
847
|
+
.map((s) => (s.reason as { environment?: Environment }).environment)
|
|
848
|
+
.filter((env): env is Environment => env !== undefined);
|
|
847
849
|
|
|
848
850
|
// Fall back to on-chain for environments where indexer failed
|
|
849
851
|
let fallbackMarkets: MorphoMarket[] = [];
|
|
@@ -851,16 +853,27 @@ async function getMorphoMarketsDataFromIndexer(params: {
|
|
|
851
853
|
console.warn(
|
|
852
854
|
`Falling back to on-chain for ${failedEnvironments.length} environment(s)`,
|
|
853
855
|
);
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
856
|
+
try {
|
|
857
|
+
fallbackMarkets = await getMorphoMarketsDataFromOnChain({
|
|
858
|
+
environments: failedEnvironments,
|
|
859
|
+
markets: params.markets,
|
|
860
|
+
includeRewards: params.includeRewards,
|
|
861
|
+
});
|
|
862
|
+
} catch (rpcError) {
|
|
863
|
+
console.warn(
|
|
864
|
+
`RPC fallback also failed for ${failedEnvironments.length} environment(s):`,
|
|
865
|
+
rpcError,
|
|
866
|
+
);
|
|
867
|
+
for (const env of failedEnvironments) {
|
|
868
|
+
env.onError?.(rpcError, {
|
|
869
|
+
source: "morpho-markets-rpc-fallback",
|
|
870
|
+
chainId: env.chainId,
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
}
|
|
859
874
|
}
|
|
860
875
|
|
|
861
|
-
// Fetch shared liquidity from lunar-indexer
|
|
862
|
-
// fell back so we can fill them from api.morpho.org after.
|
|
863
|
-
const fallbackChainIds = new Set<number>();
|
|
876
|
+
// Fetch shared liquidity from lunar-indexer.
|
|
864
877
|
const sharedLiquiditySettlements = await Promise.allSettled(
|
|
865
878
|
fulfilledMarkets.map(async ({ environment, markets }) => {
|
|
866
879
|
const lunarIndexerUrl = environment.lunarIndexerUrl;
|
|
@@ -903,12 +916,14 @@ async function getMorphoMarketsDataFromIndexer(params: {
|
|
|
903
916
|
);
|
|
904
917
|
return { environment, data };
|
|
905
918
|
} catch (error) {
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
"[Lunar fallback] Falling back to Morpho API for shared liquidity:",
|
|
919
|
+
console.warn(
|
|
920
|
+
`[getMorphoMarketsData] Lunar shared liquidity failed for chain ${environment.chainId}:`,
|
|
909
921
|
error,
|
|
910
922
|
);
|
|
911
|
-
|
|
923
|
+
environment.onError?.(error, {
|
|
924
|
+
source: "morpho-shared-liquidity",
|
|
925
|
+
chainId: environment.chainId,
|
|
926
|
+
});
|
|
912
927
|
return {
|
|
913
928
|
environment,
|
|
914
929
|
data: [] as GetMorphoMarketsPublicAllocatorSharedLiquidityReturnType[],
|
|
@@ -963,32 +978,6 @@ async function getMorphoMarketsDataFromIndexer(params: {
|
|
|
963
978
|
});
|
|
964
979
|
});
|
|
965
980
|
|
|
966
|
-
// Fallback: if the lunar shared-liquidity endpoint failed for some environments,
|
|
967
|
-
// fetch publicAllocatorSharedLiquidity from the Morpho API for those environments only.
|
|
968
|
-
if (fallbackChainIds.size > 0) {
|
|
969
|
-
const fallbackMarketIds = fulfilledMarkets
|
|
970
|
-
.filter(({ environment }) => fallbackChainIds.has(environment.chainId))
|
|
971
|
-
.flatMap(({ environment, markets }) =>
|
|
972
|
-
markets.map((m) => ({
|
|
973
|
-
marketId: m.marketId,
|
|
974
|
-
chainId: environment.chainId,
|
|
975
|
-
})),
|
|
976
|
-
);
|
|
977
|
-
const rewardEnvironment =
|
|
978
|
-
params.environments.find((env) => env.custom?.morpho?.apiUrl) ??
|
|
979
|
-
params.environments[0];
|
|
980
|
-
const morphoApiData = await getMorphoMarketRewards(
|
|
981
|
-
rewardEnvironment,
|
|
982
|
-
fallbackMarketIds,
|
|
983
|
-
);
|
|
984
|
-
morphoApiData.forEach((item) => {
|
|
985
|
-
const key = `${item.chainId}-${item.marketId.toLowerCase()}`;
|
|
986
|
-
if (!sharedLiquidityMap.has(key)) {
|
|
987
|
-
sharedLiquidityMap.set(key, item.publicAllocatorSharedLiquidity);
|
|
988
|
-
}
|
|
989
|
-
});
|
|
990
|
-
}
|
|
991
|
-
|
|
992
981
|
// Overlay rewards from the indexer when requested
|
|
993
982
|
if (params.includeRewards) {
|
|
994
983
|
fulfilledMarkets.forEach(({ environment, markets }) => {
|
|
@@ -1,23 +1,32 @@
|
|
|
1
|
-
import axios from "axios";
|
|
2
|
-
import dayjs from "dayjs";
|
|
3
|
-
import utc from "dayjs/plugin/utc.js";
|
|
4
1
|
import type { Address } from "viem";
|
|
5
2
|
import type { MoonwellClient } from "../../../client/createMoonwellClient.js";
|
|
6
|
-
import { getEnvironmentFromArgs
|
|
3
|
+
import { getEnvironmentFromArgs } from "../../../common/index.js";
|
|
4
|
+
import type { NetworkParameterType } from "../../../common/types.js";
|
|
7
5
|
import type {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
Chain,
|
|
7
|
+
Environment,
|
|
8
|
+
GetEnvironment,
|
|
9
|
+
VaultsType,
|
|
10
|
+
} from "../../../environments/index.js";
|
|
12
11
|
import type { MorphoVaultUserPositionSnapshot } from "../../../types/morphoUserPosition.js";
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
import {
|
|
13
|
+
DEFAULT_LUNAR_TIMEOUT_MS,
|
|
14
|
+
createLunarIndexerClient,
|
|
15
|
+
} from "../../lunar-indexer-client.js";
|
|
15
16
|
|
|
16
17
|
export type GetMorphoVaultUserPositionSnapshotsParameters<
|
|
17
18
|
environments,
|
|
18
19
|
network extends Chain | undefined,
|
|
19
20
|
> = NetworkParameterType<environments, network> &
|
|
20
|
-
|
|
21
|
+
(undefined extends network
|
|
22
|
+
? {
|
|
23
|
+
/** Address of the vault token (omit to get all vaults for the account) */
|
|
24
|
+
vaultAddress?: Address;
|
|
25
|
+
}
|
|
26
|
+
: {
|
|
27
|
+
/** Vault key */
|
|
28
|
+
vault: keyof VaultsType<GetEnvironment<network>>;
|
|
29
|
+
}) & {
|
|
21
30
|
userAddress: Address;
|
|
22
31
|
};
|
|
23
32
|
|
|
@@ -38,95 +47,75 @@ export async function getMorphoVaultUserPositionSnapshots<
|
|
|
38
47
|
return [];
|
|
39
48
|
}
|
|
40
49
|
|
|
41
|
-
|
|
42
|
-
vaultAddress: Address;
|
|
43
|
-
vault: string;
|
|
50
|
+
const { vaultAddress: rawVaultAddress, vault } = args as unknown as {
|
|
51
|
+
vaultAddress: Address | undefined;
|
|
52
|
+
vault: string | undefined;
|
|
44
53
|
};
|
|
45
54
|
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
const vaultAddress: Address | undefined =
|
|
56
|
+
rawVaultAddress ?? (vault ? environment.vaults[vault].address : undefined);
|
|
57
|
+
|
|
58
|
+
const lunarIndexerUrl = environment.lunarIndexerUrl;
|
|
59
|
+
|
|
60
|
+
if (!lunarIndexerUrl) {
|
|
61
|
+
return [];
|
|
48
62
|
}
|
|
49
63
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
64
|
+
try {
|
|
65
|
+
return await fetchUserPositionSnapshotsFromLunar(
|
|
66
|
+
args.userAddress,
|
|
67
|
+
vaultAddress,
|
|
68
|
+
lunarIndexerUrl,
|
|
69
|
+
environment,
|
|
70
|
+
);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.warn(
|
|
73
|
+
`[getMorphoVaultUserPositionSnapshots] Lunar Indexer failed for chain ${environment.chainId}:`,
|
|
74
|
+
error,
|
|
75
|
+
);
|
|
76
|
+
environment.onError?.(error, {
|
|
77
|
+
source: "morpho-vault-user-position-snapshots",
|
|
78
|
+
chainId: environment.chainId,
|
|
79
|
+
});
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
55
82
|
}
|
|
56
83
|
|
|
57
|
-
async function
|
|
84
|
+
async function fetchUserPositionSnapshotsFromLunar(
|
|
58
85
|
userAddress: Address,
|
|
59
|
-
vaultAddress: Address,
|
|
86
|
+
vaultAddress: Address | undefined,
|
|
87
|
+
lunarIndexerUrl: string,
|
|
60
88
|
environment: Environment,
|
|
61
89
|
): Promise<MorphoVaultUserPositionSnapshot[]> {
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
90
|
+
const lunarClient = createLunarIndexerClient({
|
|
91
|
+
baseUrl: lunarIndexerUrl,
|
|
92
|
+
timeout: DEFAULT_LUNAR_TIMEOUT_MS,
|
|
93
|
+
});
|
|
65
94
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
timestamp: number;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
while (hasNextPage) {
|
|
72
|
-
const result = await axios.post<{
|
|
73
|
-
data: {
|
|
74
|
-
accountVaultDailySnapshots: {
|
|
75
|
-
items: MorphoVaultUserDailyData[];
|
|
76
|
-
pageInfo: {
|
|
77
|
-
hasNextPage: boolean;
|
|
78
|
-
endCursor: string;
|
|
79
|
-
};
|
|
80
|
-
};
|
|
81
|
-
};
|
|
82
|
-
}>(environment.indexerUrl, {
|
|
83
|
-
query: `
|
|
84
|
-
query {
|
|
85
|
-
accountVaultDailySnapshots(
|
|
86
|
-
limit: 365,
|
|
87
|
-
orderDirection: "desc",
|
|
88
|
-
orderBy: "timestamp",
|
|
89
|
-
where: { vaultAddress: "${vaultAddress.toLowerCase()}", accountAddress: "${userAddress.toLowerCase()}", chainId: ${environment.chainId} }
|
|
90
|
-
${endCursor ? `after: "${endCursor}"` : ""}
|
|
91
|
-
) {
|
|
92
|
-
items {
|
|
93
|
-
totalSuppliesUSD
|
|
94
|
-
timestamp
|
|
95
|
-
}
|
|
96
|
-
pageInfo {
|
|
97
|
-
hasNextPage
|
|
98
|
-
endCursor
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
`,
|
|
103
|
-
});
|
|
95
|
+
const endTime = Math.floor(Date.now() / 1000);
|
|
96
|
+
const startTime = endTime - 3 * 365 * 24 * 60 * 60;
|
|
104
97
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
endCursor = result.data.data.accountVaultDailySnapshots.pageInfo.endCursor;
|
|
113
|
-
}
|
|
98
|
+
const portfolio = await lunarClient.getVaultAccountPortfolio(userAddress, {
|
|
99
|
+
startTime,
|
|
100
|
+
endTime,
|
|
101
|
+
granularity: "1d",
|
|
102
|
+
chainId: environment.chainId,
|
|
103
|
+
...(vaultAddress ? { vault: vaultAddress } : {}),
|
|
104
|
+
});
|
|
114
105
|
|
|
115
|
-
|
|
116
|
-
return dailyData.map((point: MorphoVaultUserDailyData) => {
|
|
117
|
-
const suppliedUsd = Number(point.totalSuppliesUSD);
|
|
106
|
+
const snapshots: MorphoVaultUserPositionSnapshot[] = [];
|
|
118
107
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
108
|
+
for (const position of portfolio.positions) {
|
|
109
|
+
for (const v of position.vaults) {
|
|
110
|
+
snapshots.push({
|
|
111
|
+
chainId: v.chainId,
|
|
123
112
|
account: userAddress,
|
|
124
|
-
vaultAddress: vaultAddress,
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
} else {
|
|
130
|
-
return [];
|
|
113
|
+
vaultAddress: v.vaultAddress as Address,
|
|
114
|
+
suppliedUsd: v.shareBalanceUsd,
|
|
115
|
+
timestamp: position.timestamp * 1000,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
131
118
|
}
|
|
119
|
+
|
|
120
|
+
return snapshots;
|
|
132
121
|
}
|
|
@@ -153,14 +153,13 @@ async function getMorphoVaultsDataFromIndexer(params: {
|
|
|
153
153
|
// Filter environments that have vaults and Lunar Indexer URL configured
|
|
154
154
|
const environmentsWithVaults = environments.filter(
|
|
155
155
|
(environment) =>
|
|
156
|
-
Object.keys(environment.vaults).length > 0 &&
|
|
157
|
-
environment.custom?.morpho?.lunarIndexerUrl,
|
|
156
|
+
Object.keys(environment.vaults).length > 0 && environment.lunarIndexerUrl,
|
|
158
157
|
);
|
|
159
158
|
|
|
160
159
|
// Fetch vaults from Lunar Indexer for each environment
|
|
161
160
|
const environmentsVaultsSettlements = await Promise.allSettled(
|
|
162
161
|
environmentsWithVaults.map(async (environment) => {
|
|
163
|
-
const lunarIndexerUrl = environment.
|
|
162
|
+
const lunarIndexerUrl = environment.lunarIndexerUrl!;
|
|
164
163
|
|
|
165
164
|
try {
|
|
166
165
|
// Fetch tokens and vaults in parallel
|
|
@@ -228,6 +227,10 @@ async function getMorphoVaultsDataFromIndexer(params: {
|
|
|
228
227
|
`Failed to fetch vaults from Lunar Indexer for chain ${environment.chainId}, falling back to on-chain:`,
|
|
229
228
|
error,
|
|
230
229
|
);
|
|
230
|
+
environment.onError?.(error, {
|
|
231
|
+
source: "vaults",
|
|
232
|
+
chainId: environment.chainId,
|
|
233
|
+
});
|
|
231
234
|
throw { environment, error };
|
|
232
235
|
}
|
|
233
236
|
}),
|
|
@@ -442,9 +445,7 @@ export async function getMorphoVaultsData(params: {
|
|
|
442
445
|
const { environments } = params;
|
|
443
446
|
|
|
444
447
|
// Check if any environment has Lunar Indexer URL configured
|
|
445
|
-
const hasLunarIndexer = environments.some(
|
|
446
|
-
(env) => env.custom?.morpho?.lunarIndexerUrl,
|
|
447
|
-
);
|
|
448
|
+
const hasLunarIndexer = environments.some((env) => env.lunarIndexerUrl);
|
|
448
449
|
|
|
449
450
|
// Use Lunar Indexer implementation if available
|
|
450
451
|
if (hasLunarIndexer) {
|
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import axios from "axios";
|
|
2
1
|
import type { MoonwellClient } from "../../../client/createMoonwellClient.js";
|
|
3
2
|
import {
|
|
4
3
|
applyGranularity,
|
|
5
4
|
calculateTimeRange,
|
|
6
5
|
getEnvironmentFromArgs,
|
|
7
|
-
isStartOfDay,
|
|
8
6
|
toApiGranularity,
|
|
9
7
|
} from "../../../common/index.js";
|
|
10
8
|
import type {
|
|
11
9
|
MorphoVaultParameterType,
|
|
12
10
|
NetworkParameterType,
|
|
13
11
|
} from "../../../common/types.js";
|
|
14
|
-
import type { Chain
|
|
12
|
+
import type { Chain } from "../../../environments/index.js";
|
|
15
13
|
import type { MorphoVaultSnapshot } from "../../../types/morphoVault.js";
|
|
16
14
|
import {
|
|
17
15
|
fetchVaultSnapshotsFromIndexer,
|
|
@@ -76,29 +74,43 @@ export async function getMorphoVaultSnapshots<
|
|
|
76
74
|
}
|
|
77
75
|
}
|
|
78
76
|
|
|
79
|
-
const lunarIndexerUrl = environment.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
fetchAddress,
|
|
84
|
-
environment.chainId,
|
|
85
|
-
lunarIndexerUrl,
|
|
86
|
-
period,
|
|
87
|
-
customStartTime,
|
|
88
|
-
customEndTime,
|
|
89
|
-
)
|
|
90
|
-
: await fetchVaultSnapshotsFromPonder(fetchAddress, environment);
|
|
91
|
-
|
|
92
|
-
// Restore the originally-requested vault address on every snapshot so
|
|
93
|
-
// callers keying by address see the V2 address they asked for.
|
|
94
|
-
if (fetchAddress.toLowerCase() !== requestedVaultAddress.toLowerCase()) {
|
|
95
|
-
return snapshots.map((s) => ({
|
|
96
|
-
...s,
|
|
97
|
-
vaultAddress: requestedVaultAddress.toLowerCase(),
|
|
98
|
-
}));
|
|
77
|
+
const lunarIndexerUrl = environment.lunarIndexerUrl;
|
|
78
|
+
|
|
79
|
+
if (!lunarIndexerUrl) {
|
|
80
|
+
return [];
|
|
99
81
|
}
|
|
100
82
|
|
|
101
|
-
|
|
83
|
+
try {
|
|
84
|
+
const snapshots = await fetchVaultSnapshotsFromLunarIndexer(
|
|
85
|
+
fetchAddress,
|
|
86
|
+
environment.chainId,
|
|
87
|
+
lunarIndexerUrl,
|
|
88
|
+
period,
|
|
89
|
+
customStartTime,
|
|
90
|
+
customEndTime,
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
// Restore the originally-requested vault address on every snapshot so
|
|
94
|
+
// callers keying by address see the V2 address they asked for.
|
|
95
|
+
if (fetchAddress.toLowerCase() !== requestedVaultAddress.toLowerCase()) {
|
|
96
|
+
return snapshots.map((s) => ({
|
|
97
|
+
...s,
|
|
98
|
+
vaultAddress: requestedVaultAddress.toLowerCase(),
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return snapshots;
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.warn(
|
|
105
|
+
`[getMorphoVaultSnapshots] Lunar Indexer failed for chain ${environment.chainId}:`,
|
|
106
|
+
error,
|
|
107
|
+
);
|
|
108
|
+
environment.onError?.(error, {
|
|
109
|
+
source: "morpho-vault-snapshots",
|
|
110
|
+
chainId: environment.chainId,
|
|
111
|
+
});
|
|
112
|
+
return [];
|
|
113
|
+
}
|
|
102
114
|
}
|
|
103
115
|
|
|
104
116
|
async function fetchVaultSnapshotsFromLunarIndexer(
|
|
@@ -147,99 +159,3 @@ async function fetchVaultSnapshotsFromLunarIndexer(
|
|
|
147
159
|
allSnapshots.sort((a, b) => a.timestamp - b.timestamp);
|
|
148
160
|
return applyGranularity(allSnapshots, granularity);
|
|
149
161
|
}
|
|
150
|
-
|
|
151
|
-
async function fetchVaultSnapshotsFromPonder(
|
|
152
|
-
vaultAddress: string,
|
|
153
|
-
environment: Environment,
|
|
154
|
-
): Promise<MorphoVaultSnapshot[]> {
|
|
155
|
-
const dailyData: VaultDailyData[] = [];
|
|
156
|
-
let hasNextPage = true;
|
|
157
|
-
let endCursor: string | undefined;
|
|
158
|
-
|
|
159
|
-
interface VaultDailyData {
|
|
160
|
-
totalBorrows: number;
|
|
161
|
-
totalBorrowsUSD: number;
|
|
162
|
-
totalSupplies: number;
|
|
163
|
-
totalSuppliesUSD: number;
|
|
164
|
-
totalLiquidity: number;
|
|
165
|
-
totalLiquidityUSD: number;
|
|
166
|
-
timestamp: number;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
while (hasNextPage) {
|
|
170
|
-
const result = await axios.post<{
|
|
171
|
-
data: {
|
|
172
|
-
vaultDailySnapshots: {
|
|
173
|
-
items: VaultDailyData[];
|
|
174
|
-
pageInfo: {
|
|
175
|
-
hasNextPage: boolean;
|
|
176
|
-
endCursor: string;
|
|
177
|
-
};
|
|
178
|
-
};
|
|
179
|
-
};
|
|
180
|
-
}>(environment.indexerUrl, {
|
|
181
|
-
query: `
|
|
182
|
-
query {
|
|
183
|
-
vaultDailySnapshots (
|
|
184
|
-
limit: 365,
|
|
185
|
-
orderBy: "timestamp"
|
|
186
|
-
orderDirection: "desc"
|
|
187
|
-
where: {vaultAddress: "${vaultAddress.toLowerCase()}", chainId: ${environment.chainId}}
|
|
188
|
-
${endCursor ? `after: "${endCursor}"` : ""}
|
|
189
|
-
) {
|
|
190
|
-
items {
|
|
191
|
-
totalBorrows
|
|
192
|
-
totalBorrowsUSD
|
|
193
|
-
totalSupplies
|
|
194
|
-
totalSuppliesUSD
|
|
195
|
-
totalLiquidity
|
|
196
|
-
totalLiquidityUSD
|
|
197
|
-
timestamp
|
|
198
|
-
}
|
|
199
|
-
pageInfo {
|
|
200
|
-
hasNextPage
|
|
201
|
-
endCursor
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
`,
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
if (result.data.data.vaultDailySnapshots) {
|
|
209
|
-
dailyData.push(
|
|
210
|
-
...result.data.data.vaultDailySnapshots.items.filter(
|
|
211
|
-
(f: { timestamp: number }) => isStartOfDay(f.timestamp),
|
|
212
|
-
),
|
|
213
|
-
);
|
|
214
|
-
hasNextPage = result.data.data.vaultDailySnapshots.pageInfo.hasNextPage;
|
|
215
|
-
endCursor = result.data.data.vaultDailySnapshots.pageInfo.endCursor;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (dailyData.length > 0) {
|
|
220
|
-
return dailyData.map((point: VaultDailyData) => {
|
|
221
|
-
const supplied = Number(point.totalSupplies);
|
|
222
|
-
const borrow = Number(point.totalBorrows);
|
|
223
|
-
const borrowUsd = Number(point.totalBorrowsUSD);
|
|
224
|
-
const suppliedUsd = Number(point.totalSuppliesUSD);
|
|
225
|
-
const liquidity = Number(point.totalLiquidity);
|
|
226
|
-
const liquidityUsd = Number(point.totalLiquidityUSD);
|
|
227
|
-
|
|
228
|
-
const result: MorphoVaultSnapshot = {
|
|
229
|
-
vaultAddress: vaultAddress.toLowerCase(),
|
|
230
|
-
chainId: environment.chainId,
|
|
231
|
-
timestamp: point.timestamp * 1000,
|
|
232
|
-
totalSupply: supplied,
|
|
233
|
-
totalSupplyUsd: suppliedUsd,
|
|
234
|
-
totalBorrows: borrow,
|
|
235
|
-
totalBorrowsUsd: borrowUsd,
|
|
236
|
-
totalLiquidity: liquidity,
|
|
237
|
-
totalLiquidityUsd: liquidityUsd,
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
return result;
|
|
241
|
-
});
|
|
242
|
-
} else {
|
|
243
|
-
return [];
|
|
244
|
-
}
|
|
245
|
-
}
|