@moonwell-fi/moonwell-sdk 0.23.0 → 0.25.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 +36 -0
- package/_cjs/actions/axiosWithRetry.js +10 -11
- package/_cjs/actions/axiosWithRetry.js.map +1 -1
- package/_cjs/actions/core/getUserBalances.js +63 -32
- package/_cjs/actions/core/getUserBalances.js.map +1 -1
- package/_cjs/actions/core/markets/common.js +31 -42
- package/_cjs/actions/core/markets/common.js.map +1 -1
- package/_cjs/actions/core/markets/getMarkets.js +7 -3
- package/_cjs/actions/core/markets/getMarkets.js.map +1 -1
- package/_cjs/actions/core/user-positions/common.js +56 -60
- package/_cjs/actions/core/user-positions/common.js.map +1 -1
- package/_cjs/actions/core/user-positions/getUserPositions.js +9 -6
- package/_cjs/actions/core/user-positions/getUserPositions.js.map +1 -1
- package/_cjs/actions/governance/getStakingInfo.js +1 -7
- package/_cjs/actions/governance/getStakingInfo.js.map +1 -1
- package/_cjs/actions/governance/getUserStakingInfo.js +1 -7
- package/_cjs/actions/governance/getUserStakingInfo.js.map +1 -1
- package/_cjs/actions/governance/getWellPrice.js +51 -1
- package/_cjs/actions/governance/getWellPrice.js.map +1 -1
- package/_cjs/actions/governance/proposals/common.js +34 -15
- package/_cjs/actions/governance/proposals/common.js.map +1 -1
- package/_cjs/actions/governance/proposals/getProposals.js +5 -4
- package/_cjs/actions/governance/proposals/getProposals.js.map +1 -1
- package/_cjs/actions/index.js +3 -1
- package/_cjs/actions/index.js.map +1 -1
- package/_cjs/actions/morpho/markets/common.js +155 -26
- package/_cjs/actions/morpho/markets/common.js.map +1 -1
- package/_cjs/actions/morpho/markets/getMorphoMarket.js +1 -0
- package/_cjs/actions/morpho/markets/getMorphoMarket.js.map +1 -1
- package/_cjs/actions/morpho/markets/getMorphoMarkets.js +1 -0
- package/_cjs/actions/morpho/markets/getMorphoMarkets.js.map +1 -1
- package/_cjs/actions/morpho/markets/getMorphoMarketsSharedLiquidity.js +46 -0
- package/_cjs/actions/morpho/markets/getMorphoMarketsSharedLiquidity.js.map +1 -0
- package/_cjs/actions/morpho/user-positions/common.js +26 -24
- package/_cjs/actions/morpho/user-positions/common.js.map +1 -1
- package/_cjs/actions/morpho/user-positions/getMorphoMarketUserPositions.js +7 -8
- package/_cjs/actions/morpho/user-positions/getMorphoMarketUserPositions.js.map +1 -1
- package/_cjs/actions/morpho/user-positions/getMorphoVaultUserPositions.js +7 -8
- package/_cjs/actions/morpho/user-positions/getMorphoVaultUserPositions.js.map +1 -1
- package/_cjs/actions/morpho/user-rewards/common.js +1 -7
- package/_cjs/actions/morpho/user-rewards/common.js.map +1 -1
- package/_cjs/actions/morpho/vaults/common.js +104 -87
- package/_cjs/actions/morpho/vaults/common.js.map +1 -1
- package/_cjs/actions/morpho/vaults/lunarIndexerTransform.js +31 -3
- package/_cjs/actions/morpho/vaults/lunarIndexerTransform.js.map +1 -1
- package/_cjs/actions/retry.js +43 -13
- package/_cjs/actions/retry.js.map +1 -1
- package/_cjs/client/createActions.js +2 -0
- package/_cjs/client/createActions.js.map +1 -1
- package/_cjs/common/error.js +37 -1
- package/_cjs/common/error.js.map +1 -1
- package/_cjs/common/index.js +2 -1
- package/_cjs/common/index.js.map +1 -1
- package/_cjs/common/readAcrossEnvironments.js +17 -0
- package/_cjs/common/readAcrossEnvironments.js.map +1 -0
- package/_cjs/environments/types/config.js.map +1 -1
- package/_cjs/errors/version.js +1 -1
- package/_cjs/index.js +3 -1
- package/_cjs/index.js.map +1 -1
- package/_esm/actions/axiosWithRetry.js +11 -13
- package/_esm/actions/axiosWithRetry.js.map +1 -1
- package/_esm/actions/core/getUserBalances.js +72 -35
- package/_esm/actions/core/getUserBalances.js.map +1 -1
- package/_esm/actions/core/markets/common.js +36 -43
- package/_esm/actions/core/markets/common.js.map +1 -1
- package/_esm/actions/core/markets/getMarkets.js +7 -3
- package/_esm/actions/core/markets/getMarkets.js.map +1 -1
- package/_esm/actions/core/user-positions/common.js +65 -63
- package/_esm/actions/core/user-positions/common.js.map +1 -1
- package/_esm/actions/core/user-positions/getUserPositions.js +14 -6
- package/_esm/actions/core/user-positions/getUserPositions.js.map +1 -1
- package/_esm/actions/governance/getStakingInfo.js +2 -8
- package/_esm/actions/governance/getStakingInfo.js.map +1 -1
- package/_esm/actions/governance/getUserStakingInfo.js +2 -8
- package/_esm/actions/governance/getUserStakingInfo.js.map +1 -1
- package/_esm/actions/governance/getWellPrice.js +67 -7
- package/_esm/actions/governance/getWellPrice.js.map +1 -1
- package/_esm/actions/governance/proposals/common.js +37 -12
- package/_esm/actions/governance/proposals/common.js.map +1 -1
- package/_esm/actions/governance/proposals/getProposals.js +7 -5
- package/_esm/actions/governance/proposals/getProposals.js.map +1 -1
- package/_esm/actions/index.js +1 -0
- package/_esm/actions/index.js.map +1 -1
- package/_esm/actions/morpho/markets/common.js +168 -27
- package/_esm/actions/morpho/markets/common.js.map +1 -1
- package/_esm/actions/morpho/markets/getMorphoMarket.js +1 -0
- package/_esm/actions/morpho/markets/getMorphoMarket.js.map +1 -1
- package/_esm/actions/morpho/markets/getMorphoMarkets.js +1 -0
- package/_esm/actions/morpho/markets/getMorphoMarkets.js.map +1 -1
- package/_esm/actions/morpho/markets/getMorphoMarketsSharedLiquidity.js +48 -0
- package/_esm/actions/morpho/markets/getMorphoMarketsSharedLiquidity.js.map +1 -0
- package/_esm/actions/morpho/user-positions/common.js +31 -24
- package/_esm/actions/morpho/user-positions/common.js.map +1 -1
- package/_esm/actions/morpho/user-positions/getMorphoMarketUserPositions.js +12 -8
- package/_esm/actions/morpho/user-positions/getMorphoMarketUserPositions.js.map +1 -1
- package/_esm/actions/morpho/user-positions/getMorphoVaultUserPositions.js +12 -8
- package/_esm/actions/morpho/user-positions/getMorphoVaultUserPositions.js.map +1 -1
- package/_esm/actions/morpho/user-rewards/common.js +2 -8
- package/_esm/actions/morpho/user-rewards/common.js.map +1 -1
- package/_esm/actions/morpho/vaults/common.js +110 -91
- package/_esm/actions/morpho/vaults/common.js.map +1 -1
- package/_esm/actions/morpho/vaults/lunarIndexerTransform.js +36 -4
- package/_esm/actions/morpho/vaults/lunarIndexerTransform.js.map +1 -1
- package/_esm/actions/retry.js +45 -15
- package/_esm/actions/retry.js.map +1 -1
- package/_esm/client/createActions.js +2 -0
- package/_esm/client/createActions.js.map +1 -1
- package/_esm/common/error.js +49 -0
- package/_esm/common/error.js.map +1 -1
- package/_esm/common/index.js +1 -1
- package/_esm/common/index.js.map +1 -1
- package/_esm/common/readAcrossEnvironments.js +30 -0
- package/_esm/common/readAcrossEnvironments.js.map +1 -0
- package/_esm/environments/types/config.js.map +1 -1
- package/_esm/errors/version.js +1 -1
- package/_esm/index.js +1 -0
- package/_esm/index.js.map +1 -1
- package/_types/actions/axiosWithRetry.d.ts +1 -0
- package/_types/actions/axiosWithRetry.d.ts.map +1 -1
- package/_types/actions/core/getUserBalances.d.ts.map +1 -1
- package/_types/actions/core/markets/common.d.ts.map +1 -1
- package/_types/actions/core/markets/getMarkets.d.ts.map +1 -1
- package/_types/actions/core/user-positions/common.d.ts.map +1 -1
- package/_types/actions/core/user-positions/getUserPositions.d.ts +5 -0
- package/_types/actions/core/user-positions/getUserPositions.d.ts.map +1 -1
- package/_types/actions/governance/getStakingInfo.d.ts.map +1 -1
- package/_types/actions/governance/getUserStakingInfo.d.ts.map +1 -1
- package/_types/actions/governance/getWellPrice.d.ts +9 -1
- package/_types/actions/governance/getWellPrice.d.ts.map +1 -1
- package/_types/actions/governance/proposals/common.d.ts.map +1 -1
- package/_types/actions/governance/proposals/getProposals.d.ts +10 -1
- package/_types/actions/governance/proposals/getProposals.d.ts.map +1 -1
- package/_types/actions/index.d.ts +1 -0
- package/_types/actions/index.d.ts.map +1 -1
- package/_types/actions/morpho/markets/common.d.ts +7 -10
- package/_types/actions/morpho/markets/common.d.ts.map +1 -1
- package/_types/actions/morpho/markets/getMorphoMarket.d.ts +2 -0
- package/_types/actions/morpho/markets/getMorphoMarket.d.ts.map +1 -1
- package/_types/actions/morpho/markets/getMorphoMarkets.d.ts +2 -0
- package/_types/actions/morpho/markets/getMorphoMarkets.d.ts.map +1 -1
- package/_types/actions/morpho/markets/getMorphoMarketsSharedLiquidity.d.ts +17 -0
- package/_types/actions/morpho/markets/getMorphoMarketsSharedLiquidity.d.ts.map +1 -0
- package/_types/actions/morpho/user-positions/common.d.ts.map +1 -1
- package/_types/actions/morpho/user-positions/getMorphoMarketUserPositions.d.ts +5 -0
- package/_types/actions/morpho/user-positions/getMorphoMarketUserPositions.d.ts.map +1 -1
- package/_types/actions/morpho/user-positions/getMorphoVaultUserPositions.d.ts +5 -0
- package/_types/actions/morpho/user-positions/getMorphoVaultUserPositions.d.ts.map +1 -1
- package/_types/actions/morpho/user-rewards/common.d.ts.map +1 -1
- package/_types/actions/morpho/vaults/common.d.ts.map +1 -1
- package/_types/actions/morpho/vaults/lunarIndexerTransform.d.ts.map +1 -1
- package/_types/actions/retry.d.ts +5 -4
- package/_types/actions/retry.d.ts.map +1 -1
- package/_types/client/createActions.d.ts +2 -0
- package/_types/client/createActions.d.ts.map +1 -1
- package/_types/common/error.d.ts +31 -0
- package/_types/common/error.d.ts.map +1 -1
- package/_types/common/index.d.ts +2 -2
- package/_types/common/index.d.ts.map +1 -1
- package/_types/common/readAcrossEnvironments.d.ts +23 -0
- package/_types/common/readAcrossEnvironments.d.ts.map +1 -0
- package/_types/environments/types/config.d.ts +11 -1
- package/_types/environments/types/config.d.ts.map +1 -1
- package/_types/errors/version.d.ts +1 -1
- package/_types/index.d.ts +3 -1
- package/_types/index.d.ts.map +1 -1
- package/_types/types/morphoMarket.d.ts +9 -0
- package/_types/types/morphoMarket.d.ts.map +1 -1
- package/actions/axiosWithRetry.ts +19 -13
- package/actions/core/getUserBalances.ts +98 -51
- package/actions/core/markets/common.ts +49 -51
- package/actions/core/markets/getMarkets.ts +9 -5
- package/actions/core/user-positions/common.ts +107 -111
- package/actions/core/user-positions/getUserPositions.ts +11 -10
- package/actions/governance/getStakingInfo.ts +2 -9
- package/actions/governance/getUserStakingInfo.ts +2 -8
- package/actions/governance/getWellPrice.ts +99 -7
- package/actions/governance/proposals/common.ts +44 -19
- package/actions/governance/proposals/getProposals.ts +22 -5
- package/actions/index.ts +5 -0
- package/actions/morpho/markets/common.ts +324 -125
- package/actions/morpho/markets/getMorphoMarket.ts +3 -0
- package/actions/morpho/markets/getMorphoMarkets.ts +3 -0
- package/actions/morpho/markets/getMorphoMarketsSharedLiquidity.ts +93 -0
- package/actions/morpho/user-positions/common.ts +48 -42
- package/actions/morpho/user-positions/getMorphoMarketUserPositions.ts +14 -15
- package/actions/morpho/user-positions/getMorphoVaultUserPositions.ts +14 -15
- package/actions/morpho/user-rewards/common.ts +2 -8
- package/actions/morpho/vaults/common.ts +161 -127
- package/actions/morpho/vaults/lunarIndexerTransform.ts +41 -6
- package/actions/retry.ts +53 -18
- package/client/createActions.ts +13 -0
- package/common/error.ts +45 -0
- package/common/index.ts +2 -2
- package/common/readAcrossEnvironments.ts +45 -0
- package/environments/types/config.ts +11 -1
- package/errors/version.ts +1 -1
- package/index.ts +3 -0
- package/package.json +1 -1
- package/types/morphoMarket.ts +10 -0
|
@@ -248,13 +248,14 @@ export function transformVaultFromIndexer(
|
|
|
248
248
|
// where totalLiquidity briefly exceeds totalAssets.
|
|
249
249
|
const vaultSupplyValue = Math.max(0, totalAssetsValue - totalLiquidityValue);
|
|
250
250
|
|
|
251
|
-
// Transform markets
|
|
252
|
-
|
|
251
|
+
// Transform markets. The indexer has served vaults without `markets` /
|
|
252
|
+
// `rewards` (Sentry MOONWELL-FRONTEND-GX); keep the vault with empty lists.
|
|
253
|
+
const markets = (indexerVault.markets ?? []).map((market) =>
|
|
253
254
|
transformMarket(market, underlyingDecimals, totalAssetsValue, tokenMap),
|
|
254
255
|
);
|
|
255
256
|
|
|
256
257
|
// Transform rewards
|
|
257
|
-
const rewards = transformRewards(indexerVault.rewards, tokenMap);
|
|
258
|
+
const rewards = transformRewards(indexerVault.rewards ?? [], tokenMap);
|
|
258
259
|
|
|
259
260
|
// Build vault object
|
|
260
261
|
const vault: MorphoVault = {
|
|
@@ -313,9 +314,43 @@ export function transformVaultsFromIndexer(
|
|
|
313
314
|
environment: Environment,
|
|
314
315
|
tokenMap: Map<string, LunarIndexerToken>,
|
|
315
316
|
): MorphoVault[] {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
317
|
+
// A malformed record costs only that record, never the chain's whole list.
|
|
318
|
+
// Missing `markets` / `rewards` keep the vault (as empty lists); a vault
|
|
319
|
+
// that cannot be built at all is dropped. Both are reported once per call.
|
|
320
|
+
const malformed: string[] = [];
|
|
321
|
+
let firstError: unknown;
|
|
322
|
+
const vaults = indexerVaults.flatMap((vault) => {
|
|
323
|
+
if (!Array.isArray(vault.markets) || !Array.isArray(vault.rewards)) {
|
|
324
|
+
malformed.push(vault.address);
|
|
325
|
+
firstError ??= new Error(
|
|
326
|
+
`Lunar Indexer vault ${vault.address} is missing ${!Array.isArray(vault.markets) ? "markets" : "rewards"}`,
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
try {
|
|
330
|
+
return [transformVaultFromIndexer(vault, environment, tokenMap)];
|
|
331
|
+
} catch (error) {
|
|
332
|
+
if (!malformed.includes(vault.address)) malformed.push(vault.address);
|
|
333
|
+
firstError ??= error;
|
|
334
|
+
return [];
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
if (malformed.length > 0) {
|
|
339
|
+
console.warn(
|
|
340
|
+
`Malformed Lunar Indexer vault record(s) on chain ${environment.chainId}: ${malformed.join(", ")}`,
|
|
341
|
+
firstError,
|
|
342
|
+
);
|
|
343
|
+
environment.onError?.(firstError, {
|
|
344
|
+
source: "vaults",
|
|
345
|
+
chainId: environment.chainId,
|
|
346
|
+
operation: "malformed-vault-records",
|
|
347
|
+
failedCount: malformed.length,
|
|
348
|
+
totalCount: indexerVaults.length,
|
|
349
|
+
items: malformed,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return vaults;
|
|
319
354
|
}
|
|
320
355
|
|
|
321
356
|
/**
|
package/actions/retry.ts
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
* where the existing `environment.onError(...)` wiring picks it up
|
|
17
17
|
*/
|
|
18
18
|
import axios, {
|
|
19
|
-
type AxiosError,
|
|
20
19
|
type AxiosInstance,
|
|
20
|
+
type GenericAbortSignal,
|
|
21
21
|
type InternalAxiosRequestConfig,
|
|
22
22
|
} from "axios";
|
|
23
23
|
|
|
@@ -25,14 +25,30 @@ export interface RetryOptions {
|
|
|
25
25
|
maxAttempts?: number;
|
|
26
26
|
initialDelay?: number;
|
|
27
27
|
maxDelay?: number;
|
|
28
|
+
signal?: GenericAbortSignal | undefined;
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
const DEFAULT_MAX_ATTEMPTS = 3;
|
|
31
32
|
const DEFAULT_INITIAL_DELAY_MS = 250;
|
|
32
33
|
const DEFAULT_MAX_DELAY_MS = 5_000;
|
|
33
34
|
|
|
34
|
-
async function sleep(ms: number): Promise<void> {
|
|
35
|
-
return new Promise((resolve) =>
|
|
35
|
+
async function sleep(ms: number, signal?: GenericAbortSignal): Promise<void> {
|
|
36
|
+
return new Promise((resolve, reject) => {
|
|
37
|
+
if (signal?.aborted) {
|
|
38
|
+
reject(new axios.CanceledError());
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const onAbort = (): void => {
|
|
42
|
+
clearTimeout(timer);
|
|
43
|
+
signal?.removeEventListener?.("abort", onAbort);
|
|
44
|
+
reject(new axios.CanceledError());
|
|
45
|
+
};
|
|
46
|
+
const timer = setTimeout(() => {
|
|
47
|
+
signal?.removeEventListener?.("abort", onAbort);
|
|
48
|
+
resolve();
|
|
49
|
+
}, ms);
|
|
50
|
+
signal?.addEventListener?.("abort", onAbort, { once: true });
|
|
51
|
+
});
|
|
36
52
|
}
|
|
37
53
|
|
|
38
54
|
function backoffDelay(
|
|
@@ -51,6 +67,7 @@ function backoffDelay(
|
|
|
51
67
|
* - Non-axios errors (parse errors, code bugs) → do NOT retry
|
|
52
68
|
*/
|
|
53
69
|
export function isRetriableError(error: unknown): boolean {
|
|
70
|
+
if (axios.isCancel(error)) return false;
|
|
54
71
|
if (!axios.isAxiosError(error)) return false;
|
|
55
72
|
if (!error.response) return true;
|
|
56
73
|
return error.response.status >= 500;
|
|
@@ -59,33 +76,49 @@ export function isRetriableError(error: unknown): boolean {
|
|
|
59
76
|
/**
|
|
60
77
|
* Attach a retry-on-failure interceptor to an axios instance. Every request
|
|
61
78
|
* made through this instance is retried up to `maxAttempts` times when the
|
|
62
|
-
* failure is retriable.
|
|
63
|
-
*
|
|
79
|
+
* failure is retriable. Axios merges into a new config on every request, so
|
|
80
|
+
* the attempt counter must travel with that config rather than its identity.
|
|
64
81
|
*/
|
|
65
82
|
export function attachRetryInterceptor(
|
|
66
83
|
instance: AxiosInstance,
|
|
67
|
-
options: RetryOptions = {},
|
|
84
|
+
options: Omit<RetryOptions, "signal"> = {},
|
|
68
85
|
): void {
|
|
69
86
|
const {
|
|
70
87
|
maxAttempts = DEFAULT_MAX_ATTEMPTS,
|
|
71
88
|
initialDelay = DEFAULT_INITIAL_DELAY_MS,
|
|
72
89
|
maxDelay = DEFAULT_MAX_DELAY_MS,
|
|
73
90
|
} = options;
|
|
74
|
-
|
|
91
|
+
interface RetryConfig extends InternalAxiosRequestConfig {
|
|
92
|
+
moonwellRetryAttempts?: number | undefined;
|
|
93
|
+
}
|
|
75
94
|
|
|
76
95
|
instance.interceptors.response.use(
|
|
77
|
-
(response) =>
|
|
78
|
-
|
|
79
|
-
|
|
96
|
+
(response) => {
|
|
97
|
+
const config: RetryConfig = response.config;
|
|
98
|
+
config.moonwellRetryAttempts = undefined;
|
|
99
|
+
return response;
|
|
100
|
+
},
|
|
101
|
+
async (error: unknown) => {
|
|
102
|
+
if (!axios.isAxiosError(error)) throw error;
|
|
103
|
+
const config: RetryConfig | undefined = error.config;
|
|
80
104
|
if (!config) throw error;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
105
|
+
const previousAttempts = config.moonwellRetryAttempts ?? 0;
|
|
106
|
+
if (!isRetriableError(error) || previousAttempts >= maxAttempts - 1) {
|
|
107
|
+
config.moonwellRetryAttempts = undefined;
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
85
110
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
111
|
+
config.moonwellRetryAttempts = previousAttempts + 1;
|
|
112
|
+
try {
|
|
113
|
+
await sleep(
|
|
114
|
+
backoffDelay(previousAttempts, initialDelay, maxDelay),
|
|
115
|
+
config.signal,
|
|
116
|
+
);
|
|
117
|
+
return await instance.request(config);
|
|
118
|
+
} catch (retryError) {
|
|
119
|
+
config.moonwellRetryAttempts = undefined;
|
|
120
|
+
throw retryError;
|
|
121
|
+
}
|
|
89
122
|
},
|
|
90
123
|
);
|
|
91
124
|
}
|
|
@@ -103,10 +136,12 @@ export async function retry<T>(
|
|
|
103
136
|
maxAttempts = DEFAULT_MAX_ATTEMPTS,
|
|
104
137
|
initialDelay = DEFAULT_INITIAL_DELAY_MS,
|
|
105
138
|
maxDelay = DEFAULT_MAX_DELAY_MS,
|
|
139
|
+
signal,
|
|
106
140
|
} = options;
|
|
107
141
|
let attempt = 0;
|
|
108
142
|
let lastError: unknown;
|
|
109
143
|
while (attempt < maxAttempts) {
|
|
144
|
+
if (signal?.aborted) throw new axios.CanceledError();
|
|
110
145
|
try {
|
|
111
146
|
return await fn();
|
|
112
147
|
} catch (error) {
|
|
@@ -114,7 +149,7 @@ export async function retry<T>(
|
|
|
114
149
|
attempt++;
|
|
115
150
|
if (!isRetriableError(error)) throw error;
|
|
116
151
|
if (attempt >= maxAttempts) break;
|
|
117
|
-
await sleep(backoffDelay(attempt - 1, initialDelay, maxDelay));
|
|
152
|
+
await sleep(backoffDelay(attempt - 1, initialDelay, maxDelay), signal);
|
|
118
153
|
}
|
|
119
154
|
}
|
|
120
155
|
throw lastError;
|
package/client/createActions.ts
CHANGED
|
@@ -143,6 +143,11 @@ import {
|
|
|
143
143
|
type GetMorphoMarketsReturnType,
|
|
144
144
|
getMorphoMarkets,
|
|
145
145
|
} from "../actions/morpho/markets/getMorphoMarkets.js";
|
|
146
|
+
import {
|
|
147
|
+
type GetMorphoMarketsSharedLiquidityParameters,
|
|
148
|
+
type GetMorphoMarketsSharedLiquidityReturnType,
|
|
149
|
+
getMorphoMarketsSharedLiquidity,
|
|
150
|
+
} from "../actions/morpho/markets/getMorphoMarketsSharedLiquidity.js";
|
|
146
151
|
import {
|
|
147
152
|
type GetMorphoMarketUserPositionParameters,
|
|
148
153
|
type GetMorphoMarketUserPositionReturnType,
|
|
@@ -288,6 +293,12 @@ export type Actions<
|
|
|
288
293
|
args?: GetMorphoMarketsParameters<environments, chain>,
|
|
289
294
|
) => GetMorphoMarketsReturnType;
|
|
290
295
|
|
|
296
|
+
getMorphoMarketsSharedLiquidity: <
|
|
297
|
+
chain extends Chain | undefined = Chain | undefined,
|
|
298
|
+
>(
|
|
299
|
+
args: GetMorphoMarketsSharedLiquidityParameters<environments, chain>,
|
|
300
|
+
) => GetMorphoMarketsSharedLiquidityReturnType;
|
|
301
|
+
|
|
291
302
|
getMorphoMarketUserPosition: <
|
|
292
303
|
chain extends Chain | undefined = Chain | undefined,
|
|
293
304
|
>(
|
|
@@ -399,6 +410,8 @@ export const actions = <
|
|
|
399
410
|
getUserVotingPowers: (args) => getUserVotingPowers(client, args),
|
|
400
411
|
getMorphoMarket: (args) => getMorphoMarket(client, args),
|
|
401
412
|
getMorphoMarkets: (args) => getMorphoMarkets(client, args),
|
|
413
|
+
getMorphoMarketsSharedLiquidity: (args) =>
|
|
414
|
+
getMorphoMarketsSharedLiquidity(client, args),
|
|
402
415
|
getMorphoMarketUserPosition: (args) =>
|
|
403
416
|
getMorphoMarketUserPosition(client, args),
|
|
404
417
|
getMorphoMarketUserPositions: (args) =>
|
package/common/error.ts
CHANGED
|
@@ -28,3 +28,48 @@ export class HttpRequestError extends BaseError {
|
|
|
28
28
|
Object.setPrototypeOf(this, HttpRequestError.prototype);
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
+
|
|
32
|
+
/** One failed per-chain read inside a multi-chain action. */
|
|
33
|
+
export type ChainReadFailure = {
|
|
34
|
+
chainId: number;
|
|
35
|
+
/** The original error from the RPC / contract read, unchanged. */
|
|
36
|
+
reason: unknown;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Thrown by multi-chain read actions (`getUserPositions`,
|
|
41
|
+
* `getMorphoMarketUserPositions`, `getMorphoVaultUserPositions`) when the read
|
|
42
|
+
* fails on one or more of the requested chains.
|
|
43
|
+
*
|
|
44
|
+
* `failures` lists every failed chain with its original error and `data`
|
|
45
|
+
* carries the results from the chains that succeeded, so a consumer can keep
|
|
46
|
+
* rendering the healthy chains while flagging the broken one. `errors` (from
|
|
47
|
+
* `AggregateError`) holds the same original errors in `failures` order.
|
|
48
|
+
*
|
|
49
|
+
* These failures are surfaced only through this rejection, not additionally
|
|
50
|
+
* through `onError`: a rejection is the consumer's to report, and reporting it
|
|
51
|
+
* on both paths doubled telemetry under query-library retries.
|
|
52
|
+
*/
|
|
53
|
+
export class ChainReadError<T = unknown> extends AggregateError {
|
|
54
|
+
override readonly name = "ChainReadError";
|
|
55
|
+
readonly source: string;
|
|
56
|
+
readonly failures: ChainReadFailure[];
|
|
57
|
+
readonly data: T[];
|
|
58
|
+
|
|
59
|
+
constructor(params: {
|
|
60
|
+
source: string;
|
|
61
|
+
failures: ChainReadFailure[];
|
|
62
|
+
data: T[];
|
|
63
|
+
}) {
|
|
64
|
+
const chainIds = params.failures
|
|
65
|
+
.map((failure) => failure.chainId)
|
|
66
|
+
.join(", ");
|
|
67
|
+
super(
|
|
68
|
+
params.failures.map((failure) => failure.reason),
|
|
69
|
+
`[moonwell-sdk] ${params.source}: read failed on chainIds ${chainIds}`,
|
|
70
|
+
);
|
|
71
|
+
this.source = params.source;
|
|
72
|
+
this.failures = params.failures;
|
|
73
|
+
this.data = params.data;
|
|
74
|
+
}
|
|
75
|
+
}
|
package/common/index.ts
CHANGED
|
@@ -5,8 +5,8 @@ import type { Environment } from "../environments/index.js";
|
|
|
5
5
|
|
|
6
6
|
dayjs.extend(utc);
|
|
7
7
|
export { Amount } from "./amount.js";
|
|
8
|
-
export { BaseError, HttpRequestError } from "./error.js";
|
|
9
|
-
export type { HttpRequestErrorType } from "./error.js";
|
|
8
|
+
export { BaseError, ChainReadError, HttpRequestError } from "./error.js";
|
|
9
|
+
export type { ChainReadFailure, HttpRequestErrorType } from "./error.js";
|
|
10
10
|
export { getBlockNumberAtTimestamp } from "./getBlockNumberAtTimestamp.js";
|
|
11
11
|
export type { MultichainReturnType } from "./types.js";
|
|
12
12
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Environment } from "../environments/index.js";
|
|
2
|
+
import { ChainReadError } from "./error.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Run a per-environment read on every environment and flatten the results.
|
|
6
|
+
*
|
|
7
|
+
* Unlike a bare `Promise.allSettled` that keeps only fulfilled entries, a
|
|
8
|
+
* rejected environment is never dropped silently: if any environment fails,
|
|
9
|
+
* the call rejects with a `ChainReadError` that lists every failed chain with
|
|
10
|
+
* its original error and carries the results of the chains that succeeded.
|
|
11
|
+
* For user positions a silently missing chain is indistinguishable from "no
|
|
12
|
+
* position", which drives wrong balances and borrow limits downstream; the
|
|
13
|
+
* partial `data` on the error lets a consumer keep rendering the healthy
|
|
14
|
+
* chains while flagging the broken one.
|
|
15
|
+
*
|
|
16
|
+
* Failures are surfaced only through the rejection, not additionally through
|
|
17
|
+
* `environment.onError`, so a consumer that retries the call is not told about
|
|
18
|
+
* the same outage once per attempt per chain.
|
|
19
|
+
*/
|
|
20
|
+
export async function readAcrossEnvironments<T>(params: {
|
|
21
|
+
environments: Environment[];
|
|
22
|
+
source: string;
|
|
23
|
+
read: (environment: Environment) => Promise<T[]>;
|
|
24
|
+
}): Promise<T[]> {
|
|
25
|
+
const { environments, source, read } = params;
|
|
26
|
+
|
|
27
|
+
const settled = await Promise.allSettled(
|
|
28
|
+
environments.map((environment) => read(environment)),
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const data = settled.flatMap((result) =>
|
|
32
|
+
result.status === "fulfilled" ? result.value : [],
|
|
33
|
+
);
|
|
34
|
+
const failures = settled.flatMap((result, index) =>
|
|
35
|
+
result.status === "rejected"
|
|
36
|
+
? [{ chainId: environments[index].chainId, reason: result.reason }]
|
|
37
|
+
: [],
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
if (failures.length > 0) {
|
|
41
|
+
throw new ChainReadError({ source, failures, data });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return data;
|
|
45
|
+
}
|
|
@@ -228,11 +228,21 @@ export type ContractsConfig<contracts, tokens> = {} extends contracts
|
|
|
228
228
|
? {}
|
|
229
229
|
: { [name in keyof ContractConfig<tokens>]?: ContractConfig<tokens>[name] };
|
|
230
230
|
|
|
231
|
-
/**
|
|
231
|
+
/**
|
|
232
|
+
* Context passed to `onError` callbacks. `token` is set for per-token read failures.
|
|
233
|
+
*
|
|
234
|
+
* Batched reads report once per operation rather than once per item: `error`
|
|
235
|
+
* is the first failure, `failedCount`/`totalCount` size the batch and `items`
|
|
236
|
+
* identifies what failed (proposalIds, token/vault addresses, chainIds...).
|
|
237
|
+
*/
|
|
232
238
|
export type OnErrorContext = {
|
|
233
239
|
source: string;
|
|
234
240
|
chainId: number;
|
|
235
241
|
token?: Address;
|
|
242
|
+
operation?: string;
|
|
243
|
+
failedCount?: number;
|
|
244
|
+
totalCount?: number;
|
|
245
|
+
items?: string[];
|
|
236
246
|
};
|
|
237
247
|
|
|
238
248
|
export type CustomConfig<custom> = {} extends custom
|
package/errors/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '0.
|
|
1
|
+
export const version = '0.25.0'
|
package/index.ts
CHANGED
|
@@ -5,6 +5,8 @@ export {
|
|
|
5
5
|
|
|
6
6
|
export { MerklApiError } from "./actions/morpho/user-rewards/common.js";
|
|
7
7
|
export { MorphoUserRewardsAggregateError } from "./actions/morpho/user-rewards/getMorphoUserRewards.js";
|
|
8
|
+
export { ChainReadError } from "./common/error.js";
|
|
9
|
+
export type { ChainReadFailure } from "./common/error.js";
|
|
8
10
|
|
|
9
11
|
export type {
|
|
10
12
|
MarketConfig,
|
|
@@ -18,6 +20,7 @@ export type { Discussion } from "./types/discussion.js";
|
|
|
18
20
|
export type { Market, MarketReward, MarketSnapshot } from "./types/market.js";
|
|
19
21
|
export type {
|
|
20
22
|
MorphoMarket,
|
|
23
|
+
MorphoMarketSharedLiquidity,
|
|
21
24
|
MorphoMarketParamsType,
|
|
22
25
|
PublicAllocatorSharedLiquidityType,
|
|
23
26
|
} from "./types/morphoMarket.js";
|
package/package.json
CHANGED
package/types/morphoMarket.ts
CHANGED
|
@@ -41,6 +41,16 @@ export type MorphoMarket = {
|
|
|
41
41
|
totalBorrowApr: number;
|
|
42
42
|
rewards: Required<MorphoReward>[];
|
|
43
43
|
publicAllocatorSharedLiquidity: PublicAllocatorSharedLiquidityType[];
|
|
44
|
+
/** Whether allocator liquidity was fetched. An empty list is not proof of zero
|
|
45
|
+
* reallocatable liquidity when this is "not-requested" or "unavailable". */
|
|
46
|
+
sharedLiquidityStatus?: "available" | "unavailable" | "not-requested";
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type MorphoMarketSharedLiquidity = {
|
|
50
|
+
chainId: number;
|
|
51
|
+
marketId: string;
|
|
52
|
+
reallocatableLiquidityAssets: Amount;
|
|
53
|
+
publicAllocatorSharedLiquidity: PublicAllocatorSharedLiquidityType[];
|
|
44
54
|
};
|
|
45
55
|
|
|
46
56
|
export type MorphoMarketParamsType = {
|