@moonwell-fi/moonwell-sdk 0.12.2 → 0.13.1
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 +22 -0
- package/_cjs/actions/core/markets/common.js +11 -4
- package/_cjs/actions/core/markets/common.js.map +1 -1
- package/_cjs/actions/core/user-rewards/common.js +6 -5
- package/_cjs/actions/core/user-rewards/common.js.map +1 -1
- package/_cjs/actions/governance/getDelegates.js.map +1 -1
- package/_cjs/actions/governance/getStakingInfo.js +113 -31
- package/_cjs/actions/governance/getStakingInfo.js.map +1 -1
- package/_cjs/actions/governance/getUserStakingInfo.js +106 -18
- package/_cjs/actions/governance/getUserStakingInfo.js.map +1 -1
- package/_cjs/actions/governance/getUserVotingPowers.js +21 -6
- package/_cjs/actions/governance/getUserVotingPowers.js.map +1 -1
- package/_cjs/actions/governance/getWellPrice.js +26 -0
- package/_cjs/actions/governance/getWellPrice.js.map +1 -0
- package/_cjs/actions/morpho/user-rewards/common.js +87 -12
- package/_cjs/actions/morpho/user-rewards/common.js.map +1 -1
- package/_cjs/actions/morpho/user-rewards/getMorphoUserRewards.js +46 -10
- package/_cjs/actions/morpho/user-rewards/getMorphoUserRewards.js.map +1 -1
- package/_cjs/actions/morpho/vaults/common.js +19 -6
- package/_cjs/actions/morpho/vaults/common.js.map +1 -1
- package/_cjs/environments/definitions/ethereum/contracts.js +12 -0
- package/_cjs/environments/definitions/ethereum/contracts.js.map +1 -0
- package/_cjs/environments/definitions/ethereum/custom.js +18 -0
- package/_cjs/environments/definitions/ethereum/custom.js.map +1 -0
- package/_cjs/environments/definitions/ethereum/environment.js +9 -5
- package/_cjs/environments/definitions/ethereum/environment.js.map +1 -1
- package/_cjs/environments/definitions/ethereum/tokens.js +12 -0
- package/_cjs/environments/definitions/ethereum/tokens.js.map +1 -1
- package/_cjs/environments/definitions/governance.js +1 -1
- package/_cjs/environments/definitions/governance.js.map +1 -1
- package/_cjs/errors/version.js +1 -1
- package/_cjs/index.js +5 -1
- package/_cjs/index.js.map +1 -1
- package/_esm/actions/core/markets/common.js +11 -4
- package/_esm/actions/core/markets/common.js.map +1 -1
- package/_esm/actions/core/user-rewards/common.js +6 -5
- package/_esm/actions/core/user-rewards/common.js.map +1 -1
- package/_esm/actions/governance/getDelegates.js +2 -0
- package/_esm/actions/governance/getDelegates.js.map +1 -1
- package/_esm/actions/governance/getStakingInfo.js +136 -32
- package/_esm/actions/governance/getStakingInfo.js.map +1 -1
- package/_esm/actions/governance/getUserStakingInfo.js +120 -19
- package/_esm/actions/governance/getUserStakingInfo.js.map +1 -1
- package/_esm/actions/governance/getUserVotingPowers.js +24 -6
- package/_esm/actions/governance/getUserVotingPowers.js.map +1 -1
- package/_esm/actions/governance/getWellPrice.js +50 -0
- package/_esm/actions/governance/getWellPrice.js.map +1 -0
- package/_esm/actions/morpho/user-rewards/common.js +93 -12
- package/_esm/actions/morpho/user-rewards/common.js.map +1 -1
- package/_esm/actions/morpho/user-rewards/getMorphoUserRewards.js +51 -11
- package/_esm/actions/morpho/user-rewards/getMorphoUserRewards.js.map +1 -1
- package/_esm/actions/morpho/vaults/common.js +19 -6
- package/_esm/actions/morpho/vaults/common.js.map +1 -1
- package/_esm/environments/definitions/ethereum/contracts.js +10 -0
- package/_esm/environments/definitions/ethereum/contracts.js.map +1 -0
- package/_esm/environments/definitions/ethereum/custom.js +15 -0
- package/_esm/environments/definitions/ethereum/custom.js.map +1 -0
- package/_esm/environments/definitions/ethereum/environment.js +11 -5
- package/_esm/environments/definitions/ethereum/environment.js.map +1 -1
- package/_esm/environments/definitions/ethereum/tokens.js +12 -0
- package/_esm/environments/definitions/ethereum/tokens.js.map +1 -1
- package/_esm/environments/definitions/governance.js +2 -2
- package/_esm/environments/definitions/governance.js.map +1 -1
- package/_esm/errors/version.js +1 -1
- package/_esm/index.js +2 -0
- package/_esm/index.js.map +1 -1
- package/_types/actions/core/markets/common.d.ts.map +1 -1
- package/_types/actions/core/user-rewards/common.d.ts.map +1 -1
- package/_types/actions/governance/getDelegates.d.ts.map +1 -1
- package/_types/actions/governance/getStakingInfo.d.ts +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/getUserVotingPowers.d.ts.map +1 -1
- package/_types/actions/governance/getWellPrice.d.ts +29 -0
- package/_types/actions/governance/getWellPrice.d.ts.map +1 -0
- package/_types/actions/morpho/user-rewards/common.d.ts +23 -0
- package/_types/actions/morpho/user-rewards/common.d.ts.map +1 -1
- package/_types/actions/morpho/user-rewards/getMorphoUserRewards.d.ts +22 -0
- package/_types/actions/morpho/user-rewards/getMorphoUserRewards.d.ts.map +1 -1
- package/_types/actions/morpho/vaults/common.d.ts.map +1 -1
- package/_types/client/createMoonwellClient.d.ts +62 -2
- package/_types/client/createMoonwellClient.d.ts.map +1 -1
- package/_types/environments/definitions/ethereum/contracts.d.ts +4 -0
- package/_types/environments/definitions/ethereum/contracts.d.ts.map +1 -0
- package/_types/environments/definitions/ethereum/custom.d.ts +18 -0
- package/_types/environments/definitions/ethereum/custom.d.ts.map +1 -0
- package/_types/environments/definitions/ethereum/environment.d.ts +52 -2
- package/_types/environments/definitions/ethereum/environment.d.ts.map +1 -1
- package/_types/environments/definitions/ethereum/tokens.d.ts +12 -0
- package/_types/environments/definitions/ethereum/tokens.d.ts.map +1 -1
- package/_types/environments/definitions/governance.d.ts.map +1 -1
- package/_types/environments/index.d.ts +34 -4
- package/_types/environments/index.d.ts.map +1 -1
- package/_types/errors/version.d.ts +1 -1
- package/_types/index.d.ts +2 -0
- package/_types/index.d.ts.map +1 -1
- package/actions/core/markets/common.ts +11 -6
- package/actions/core/user-rewards/common.ts +6 -5
- package/actions/governance/getDelegates.ts +2 -0
- package/actions/governance/getStakingInfo.ts +195 -87
- package/actions/governance/getUserStakingInfo.ts +168 -54
- package/actions/governance/getUserVotingPowers.ts +30 -15
- package/actions/governance/getWellPrice.ts +66 -0
- package/actions/morpho/user-rewards/common.ts +91 -14
- package/actions/morpho/user-rewards/getMorphoUserRewards.ts +77 -12
- package/actions/morpho/vaults/common.ts +19 -12
- package/environments/definitions/ethereum/contracts.ts +10 -0
- package/environments/definitions/ethereum/custom.ts +15 -0
- package/environments/definitions/ethereum/environment.ts +15 -6
- package/environments/definitions/ethereum/tokens.ts +12 -0
- package/environments/definitions/governance.ts +2 -2
- package/errors/version.ts +1 -1
- package/index.ts +3 -0
- package/package.json +1 -1
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Environment,
|
|
3
|
+
publicEnvironments,
|
|
4
|
+
} from "../../environments/index.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Reads WELL/USD from Base's lending oracle via getUnderlyingPrice(mWELL).
|
|
8
|
+
*
|
|
9
|
+
* The Base oracle is Chainlink-fed and shared by the lending markets, so it's
|
|
10
|
+
* the authoritative WELL/USD source. Used in place of the per-chain
|
|
11
|
+
* views.getGovernanceTokenPrice() which is unreliable on Moonbeam (returns
|
|
12
|
+
* stale data) and Base (returns 0).
|
|
13
|
+
*
|
|
14
|
+
* Returns a uint256 already scaled to 18 decimals.
|
|
15
|
+
*
|
|
16
|
+
* @param baseEnvironment Pass the caller's Base environment when available so
|
|
17
|
+
* user-configured RPCs / onError handlers are honored. Falls back to the
|
|
18
|
+
* SDK's default public Base environment otherwise.
|
|
19
|
+
*/
|
|
20
|
+
export async function getWellPriceFromBaseOracle(
|
|
21
|
+
baseEnvironment?: Environment,
|
|
22
|
+
): Promise<bigint> {
|
|
23
|
+
const baseEnv = baseEnvironment ?? publicEnvironments.base;
|
|
24
|
+
const tokens = baseEnv.config.tokens as Record<
|
|
25
|
+
string,
|
|
26
|
+
{ address: `0x${string}` } | undefined
|
|
27
|
+
>;
|
|
28
|
+
const mWELL = tokens.MOONWELL_WELL?.address;
|
|
29
|
+
const oracle = baseEnv.contracts.oracle;
|
|
30
|
+
if (!mWELL || !oracle) {
|
|
31
|
+
// A custom Base env without MOONWELL_WELL or an oracle would silently
|
|
32
|
+
// zero out every WELL-priced read across the SDK. Surface it instead.
|
|
33
|
+
baseEnv.onError?.(
|
|
34
|
+
new Error(
|
|
35
|
+
`getWellPriceFromBaseOracle: missing ${!mWELL ? "MOONWELL_WELL token" : "oracle contract"} on Base env`,
|
|
36
|
+
),
|
|
37
|
+
{ source: "well-price", chainId: baseEnv.chainId },
|
|
38
|
+
);
|
|
39
|
+
return 0n;
|
|
40
|
+
}
|
|
41
|
+
return await oracle.read.getUnderlyingPrice([mWELL]);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Returns the governance-token-in-USD price for an environment.
|
|
46
|
+
*
|
|
47
|
+
* - For WELL-governed chains (Base, Optimism, Moonbeam), reads from the Base
|
|
48
|
+
* lending oracle's mWELL underlying price (authoritative, Chainlink-fed).
|
|
49
|
+
* - For non-WELL chains (currently only Moonriver / MFAM), reads from the
|
|
50
|
+
* env's own views.getGovernanceTokenPrice() — Moonriver has its own MFAM
|
|
51
|
+
* oracle and isn't priced from Base.
|
|
52
|
+
*
|
|
53
|
+
* Returns 0n if the lookup fails.
|
|
54
|
+
*/
|
|
55
|
+
export async function getGovernanceTokenPriceFor(
|
|
56
|
+
environment: Environment,
|
|
57
|
+
baseEnvironment?: Environment,
|
|
58
|
+
): Promise<bigint> {
|
|
59
|
+
if (environment.custom?.governance?.token === "WELL") {
|
|
60
|
+
return getWellPriceFromBaseOracle(baseEnvironment);
|
|
61
|
+
}
|
|
62
|
+
// Non-WELL (e.g. Moonriver / MFAM): the env itself is the governance "home".
|
|
63
|
+
const views = environment.contracts.views;
|
|
64
|
+
if (!views) return 0n;
|
|
65
|
+
return (await views.read.getGovernanceTokenPrice()) ?? 0n;
|
|
66
|
+
}
|
|
@@ -12,10 +12,46 @@ import {
|
|
|
12
12
|
} from "../../../environments/utils/index.js";
|
|
13
13
|
import type { MorphoUserReward } from "../../../types/morphoUserReward.js";
|
|
14
14
|
import type { MorphoUserStakingReward } from "../../../types/morphoUserStakingReward.js";
|
|
15
|
+
import { getGovernanceTokenPriceFor } from "../../governance/getWellPrice.js";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Error thrown for any failure communicating with the Merkl API: non-ok HTTP
|
|
19
|
+
* responses, network rejections (fetch threw), and response-body parse errors.
|
|
20
|
+
*
|
|
21
|
+
* - HTTP failures populate `status` and `statusText`.
|
|
22
|
+
* - Network and parse failures leave `status`/`statusText` undefined and
|
|
23
|
+
* carry the original error via `cause`.
|
|
24
|
+
*/
|
|
25
|
+
export class MerklApiError extends Error {
|
|
26
|
+
readonly status: number | undefined;
|
|
27
|
+
readonly statusText: string | undefined;
|
|
28
|
+
readonly url: string;
|
|
29
|
+
readonly chainId: number;
|
|
30
|
+
|
|
31
|
+
constructor(params: {
|
|
32
|
+
message: string;
|
|
33
|
+
url: string;
|
|
34
|
+
chainId: number;
|
|
35
|
+
status?: number | undefined;
|
|
36
|
+
statusText?: string | undefined;
|
|
37
|
+
cause?: unknown;
|
|
38
|
+
}) {
|
|
39
|
+
super(
|
|
40
|
+
params.message,
|
|
41
|
+
params.cause !== undefined ? { cause: params.cause } : undefined,
|
|
42
|
+
);
|
|
43
|
+
this.name = "MerklApiError";
|
|
44
|
+
this.url = params.url;
|
|
45
|
+
this.chainId = params.chainId;
|
|
46
|
+
this.status = params.status;
|
|
47
|
+
this.statusText = params.statusText;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
15
50
|
|
|
16
51
|
export async function getUserMorphoRewardsData(params: {
|
|
17
52
|
environment: Environment;
|
|
18
53
|
account: `0x${string}`;
|
|
54
|
+
throwOnExternalApiError?: boolean;
|
|
19
55
|
}): Promise<MorphoUserReward[]> {
|
|
20
56
|
// The Morpho URD distributions endpoint (rewards.morpho.org) was
|
|
21
57
|
// deprecated and now 301-redirects to a SPA, so JSON parsing fails.
|
|
@@ -23,6 +59,7 @@ export async function getUserMorphoRewardsData(params: {
|
|
|
23
59
|
const merklRewards = await getMerklRewardsData(
|
|
24
60
|
params.environment,
|
|
25
61
|
params.account,
|
|
62
|
+
{ throwOnError: params.throwOnExternalApiError ?? false },
|
|
26
63
|
);
|
|
27
64
|
|
|
28
65
|
const isFullDeployment =
|
|
@@ -128,11 +165,17 @@ export async function getUserMorphoStakingRewardsData(params: {
|
|
|
128
165
|
await Promise.all([
|
|
129
166
|
viewsContract?.read.getAllMarketsInfo(),
|
|
130
167
|
homeViewsContract?.read.getNativeTokenPrice(),
|
|
131
|
-
|
|
168
|
+
getGovernanceTokenPriceFor(params.environment).catch((err) => {
|
|
169
|
+
params.environment.onError?.(err, {
|
|
170
|
+
source: "governance-token-price",
|
|
171
|
+
chainId: params.environment.chainId,
|
|
172
|
+
});
|
|
173
|
+
return 0n;
|
|
174
|
+
}),
|
|
132
175
|
]);
|
|
133
176
|
|
|
134
|
-
const governanceTokenPrice = new Amount(governanceTokenPriceRaw
|
|
135
|
-
const nativeTokenPrice = new Amount(nativeTokenPriceRaw
|
|
177
|
+
const governanceTokenPrice = new Amount(governanceTokenPriceRaw, 18);
|
|
178
|
+
const nativeTokenPrice = new Amount(nativeTokenPriceRaw ?? 0n, 18);
|
|
136
179
|
|
|
137
180
|
let tokenPrices =
|
|
138
181
|
allMarkets
|
|
@@ -294,30 +337,64 @@ type MerklRewardsResponse = {
|
|
|
294
337
|
async function getMerklRewardsData(
|
|
295
338
|
environment: Environment,
|
|
296
339
|
account: Address,
|
|
340
|
+
options: { throwOnError: boolean } = { throwOnError: false },
|
|
297
341
|
): Promise<MerklRewardsResponse[]> {
|
|
342
|
+
const url = `https://api.merkl.xyz/v4/users/${account}/rewards?chainId=${environment.chainId}&test=false&breakdownPage=0&reloadChainId=${environment.chainId}`;
|
|
343
|
+
|
|
344
|
+
let response: Response;
|
|
298
345
|
try {
|
|
299
346
|
// Merkl campaigns always distribute rewards on the same chain as the
|
|
300
347
|
// opportunity, so environment.chainId is the only chain we need to query.
|
|
301
348
|
// The previous two-phase approach (fetch opportunities per vault → extract
|
|
302
349
|
// chain IDs → fetch rewards per chain) made N+1 HTTP calls to discover
|
|
303
350
|
// a chain ID we already know.
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
351
|
+
response = await fetch(url, { headers: MOONWELL_FETCH_JSON_HEADERS });
|
|
352
|
+
} catch (error) {
|
|
353
|
+
if (options.throwOnError) {
|
|
354
|
+
throw new MerklApiError({
|
|
355
|
+
message: `Merkl API network error for chain ${environment.chainId}`,
|
|
356
|
+
url,
|
|
357
|
+
chainId: environment.chainId,
|
|
358
|
+
cause: error,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
console.error(
|
|
362
|
+
`[getMerklRewardsData:network] chain=${environment.chainId} url=${url}`,
|
|
363
|
+
error,
|
|
309
364
|
);
|
|
365
|
+
return [];
|
|
366
|
+
}
|
|
310
367
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
368
|
+
if (!response.ok) {
|
|
369
|
+
const message = `Merkl API request failed for chain ${environment.chainId}: ${response.status} ${response.statusText}`;
|
|
370
|
+
if (options.throwOnError) {
|
|
371
|
+
throw new MerklApiError({
|
|
372
|
+
message,
|
|
373
|
+
url,
|
|
374
|
+
chainId: environment.chainId,
|
|
375
|
+
status: response.status,
|
|
376
|
+
statusText: response.statusText,
|
|
377
|
+
});
|
|
316
378
|
}
|
|
379
|
+
console.warn(`${message} (url=${url})`);
|
|
380
|
+
return [];
|
|
381
|
+
}
|
|
317
382
|
|
|
383
|
+
try {
|
|
318
384
|
return (await response.json()) as MerklRewardsResponse[];
|
|
319
385
|
} catch (error) {
|
|
320
|
-
|
|
386
|
+
if (options.throwOnError) {
|
|
387
|
+
throw new MerklApiError({
|
|
388
|
+
message: `Merkl API response parse error for chain ${environment.chainId}`,
|
|
389
|
+
url,
|
|
390
|
+
chainId: environment.chainId,
|
|
391
|
+
cause: error,
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
console.error(
|
|
395
|
+
`[getMerklRewardsData:parse] chain=${environment.chainId} url=${url}`,
|
|
396
|
+
error,
|
|
397
|
+
);
|
|
321
398
|
return [];
|
|
322
399
|
}
|
|
323
400
|
}
|
|
@@ -4,13 +4,41 @@ import { getEnvironmentsFromArgs } from "../../../common/index.js";
|
|
|
4
4
|
import type { OptionalNetworkParameterType } from "../../../common/types.js";
|
|
5
5
|
import type { Chain } from "../../../environments/index.js";
|
|
6
6
|
import type { MorphoUserReward } from "../../../types/morphoUserReward.js";
|
|
7
|
-
import { getUserMorphoRewardsData } from "./common.js";
|
|
7
|
+
import { MerklApiError, getUserMorphoRewardsData } from "./common.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* AggregateError thrown by `getMorphoUserRewards` when one or more chains
|
|
11
|
+
* fail and `throwOnExternalApiError` is `true`. The `rewards` property
|
|
12
|
+
* carries the rewards from any chains that succeeded so callers can still
|
|
13
|
+
* surface partial results alongside the per-chain failures in `errors`.
|
|
14
|
+
*/
|
|
15
|
+
export class MorphoUserRewardsAggregateError extends AggregateError {
|
|
16
|
+
readonly rewards: MorphoUserReward[];
|
|
17
|
+
|
|
18
|
+
constructor(errors: Error[], message: string, rewards: MorphoUserReward[]) {
|
|
19
|
+
super(errors, message);
|
|
20
|
+
this.name = "MorphoUserRewardsAggregateError";
|
|
21
|
+
this.rewards = rewards;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
8
24
|
|
|
9
25
|
export type GetMorphoUserRewardsParameters<
|
|
10
26
|
environments,
|
|
11
27
|
network extends Chain | undefined,
|
|
12
28
|
> = OptionalNetworkParameterType<environments, network> & {
|
|
13
29
|
userAddress: Address;
|
|
30
|
+
/**
|
|
31
|
+
* When true, errors from the external Merkl API are propagated to the
|
|
32
|
+
* caller instead of being swallowed and returning `[]`. Default `false`
|
|
33
|
+
* preserves the historical behavior for existing consumers.
|
|
34
|
+
*
|
|
35
|
+
* If multiple environments are queried and at least one fails while others
|
|
36
|
+
* succeed, this throws a `MorphoUserRewardsAggregateError` whose `errors`
|
|
37
|
+
* array contains the per-chain failures and whose `rewards` property
|
|
38
|
+
* carries the successful chains' rewards so the caller can still display
|
|
39
|
+
* partial results.
|
|
40
|
+
*/
|
|
41
|
+
throwOnExternalApiError?: boolean;
|
|
14
42
|
};
|
|
15
43
|
|
|
16
44
|
export type GetMorphoUserRewardsReturnType = Promise<MorphoUserReward[]>;
|
|
@@ -22,18 +50,55 @@ export async function getMorphoUserRewards<
|
|
|
22
50
|
client: MoonwellClient,
|
|
23
51
|
args: GetMorphoUserRewardsParameters<environments, Network>,
|
|
24
52
|
): GetMorphoUserRewardsReturnType {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
53
|
+
const targetEnvironments = getEnvironmentsFromArgs(client, args).filter(
|
|
54
|
+
(environment) => environment.contracts.morphoViews !== undefined,
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const settled = await Promise.allSettled(
|
|
58
|
+
targetEnvironments.map((environment) =>
|
|
59
|
+
getUserMorphoRewardsData({
|
|
60
|
+
environment,
|
|
61
|
+
account: args.userAddress,
|
|
62
|
+
...(args.throwOnExternalApiError !== undefined && {
|
|
63
|
+
throwOnExternalApiError: args.throwOnExternalApiError,
|
|
64
|
+
}),
|
|
35
65
|
}),
|
|
66
|
+
),
|
|
36
67
|
);
|
|
37
68
|
|
|
38
|
-
|
|
69
|
+
const fulfilled: MorphoUserReward[] = [];
|
|
70
|
+
const failures: Error[] = [];
|
|
71
|
+
const failedChainIds: number[] = [];
|
|
72
|
+
for (const [i, result] of settled.entries()) {
|
|
73
|
+
const environment = targetEnvironments[i];
|
|
74
|
+
if (result.status === "fulfilled") {
|
|
75
|
+
fulfilled.push(...result.value);
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const reason = result.reason;
|
|
79
|
+
if (reason instanceof MerklApiError) {
|
|
80
|
+
failures.push(reason);
|
|
81
|
+
failedChainIds.push(reason.chainId);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const baseError =
|
|
85
|
+
reason instanceof Error ? reason : new Error(String(reason));
|
|
86
|
+
failures.push(
|
|
87
|
+
new Error(
|
|
88
|
+
`getMorphoUserRewards failed for chain ${environment.chainId}: ${baseError.message}`,
|
|
89
|
+
{ cause: baseError },
|
|
90
|
+
),
|
|
91
|
+
);
|
|
92
|
+
failedChainIds.push(environment.chainId);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (failures.length > 0 && args.throwOnExternalApiError === true) {
|
|
96
|
+
throw new MorphoUserRewardsAggregateError(
|
|
97
|
+
failures,
|
|
98
|
+
`getMorphoUserRewards failed for chains: ${failedChainIds.join(", ")}`,
|
|
99
|
+
fulfilled,
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return fulfilled;
|
|
39
104
|
}
|
|
@@ -19,6 +19,7 @@ import type {
|
|
|
19
19
|
MorphoVault,
|
|
20
20
|
MorphoVaultMarket,
|
|
21
21
|
} from "../../../types/morphoVault.js";
|
|
22
|
+
import { getGovernanceTokenPriceFor } from "../../governance/getWellPrice.js";
|
|
22
23
|
import { getGraphQL, getVaultV2Apy } from "../utils/graphql.js";
|
|
23
24
|
import {
|
|
24
25
|
SECONDS_PER_YEAR,
|
|
@@ -321,16 +322,19 @@ async function getMorphoVaultsDataFromIndexer(params: {
|
|
|
321
322
|
const data = await Promise.all([
|
|
322
323
|
viewsContract?.read.getAllMarketsInfo(),
|
|
323
324
|
homeViewsContract?.read.getNativeTokenPrice(),
|
|
324
|
-
|
|
325
|
+
getGovernanceTokenPriceFor(environment).catch((err) => {
|
|
326
|
+
environment.onError?.(err, {
|
|
327
|
+
source: "governance-token-price",
|
|
328
|
+
chainId: environment.chainId,
|
|
329
|
+
});
|
|
330
|
+
return 0n;
|
|
331
|
+
}),
|
|
325
332
|
]);
|
|
326
333
|
|
|
327
334
|
const [allMarkets, nativeTokenPriceRaw, governanceTokenPriceRaw] = data;
|
|
328
335
|
|
|
329
|
-
const governanceTokenPrice = new Amount(
|
|
330
|
-
|
|
331
|
-
18,
|
|
332
|
-
);
|
|
333
|
-
const nativeTokenPrice = new Amount(nativeTokenPriceRaw || 0n, 18);
|
|
336
|
+
const governanceTokenPrice = new Amount(governanceTokenPriceRaw, 18);
|
|
337
|
+
const nativeTokenPrice = new Amount(nativeTokenPriceRaw ?? 0n, 18);
|
|
334
338
|
|
|
335
339
|
let tokenPrices =
|
|
336
340
|
allMarkets
|
|
@@ -1056,16 +1060,19 @@ async function getMorphoVaultsDataFromOnChain(params: {
|
|
|
1056
1060
|
const data = await Promise.all([
|
|
1057
1061
|
viewsContract?.read.getAllMarketsInfo(),
|
|
1058
1062
|
homeViewsContract?.read.getNativeTokenPrice(),
|
|
1059
|
-
|
|
1063
|
+
getGovernanceTokenPriceFor(environment).catch((err) => {
|
|
1064
|
+
environment.onError?.(err, {
|
|
1065
|
+
source: "governance-token-price",
|
|
1066
|
+
chainId: environment.chainId,
|
|
1067
|
+
});
|
|
1068
|
+
return 0n;
|
|
1069
|
+
}),
|
|
1060
1070
|
]);
|
|
1061
1071
|
|
|
1062
1072
|
const [allMarkets, nativeTokenPriceRaw, governanceTokenPriceRaw] = data;
|
|
1063
1073
|
|
|
1064
|
-
const governanceTokenPrice = new Amount(
|
|
1065
|
-
|
|
1066
|
-
18,
|
|
1067
|
-
);
|
|
1068
|
-
const nativeTokenPrice = new Amount(nativeTokenPriceRaw || 0n, 18);
|
|
1074
|
+
const governanceTokenPrice = new Amount(governanceTokenPriceRaw, 18);
|
|
1075
|
+
const nativeTokenPrice = new Amount(nativeTokenPriceRaw ?? 0n, 18);
|
|
1069
1076
|
|
|
1070
1077
|
let tokenPrices =
|
|
1071
1078
|
allMarkets
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createContractsConfig } from "../../types/config.js";
|
|
2
|
+
import { tokens } from "./tokens.js";
|
|
3
|
+
|
|
4
|
+
export const contracts = createContractsConfig({
|
|
5
|
+
tokens,
|
|
6
|
+
contracts: {
|
|
7
|
+
// `stakingToken` is intentionally omitted until Ethereum staking contracts ship.
|
|
8
|
+
governanceToken: "WELL",
|
|
9
|
+
},
|
|
10
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createCustomConfig } from "../../types/config.js";
|
|
2
|
+
|
|
3
|
+
export const custom = createCustomConfig({
|
|
4
|
+
governance: {
|
|
5
|
+
token: "WELL",
|
|
6
|
+
chainIds: [],
|
|
7
|
+
},
|
|
8
|
+
wormhole: {
|
|
9
|
+
chainId: 2,
|
|
10
|
+
tokenBridge: { address: "0x3ee18B2214AFF97000D974cf647E654bB5f1d8A8" },
|
|
11
|
+
},
|
|
12
|
+
xWELL: {
|
|
13
|
+
bridgeAdapter: { address: "0x734AbBCe07679C9A6B4Fe3bC16325e028fA6DbB7" },
|
|
14
|
+
},
|
|
15
|
+
});
|
|
@@ -1,15 +1,22 @@
|
|
|
1
|
-
import { http, fallback } from "viem";
|
|
2
|
-
import { mainnet
|
|
1
|
+
import { http, defineChain, fallback } from "viem";
|
|
2
|
+
import { mainnet } from "viem/chains";
|
|
3
3
|
import {
|
|
4
4
|
type Environment,
|
|
5
5
|
createEnvironmentConfig,
|
|
6
6
|
} from "../../types/config.js";
|
|
7
|
+
import { contracts } from "./contracts.js";
|
|
8
|
+
import { custom } from "./custom.js";
|
|
7
9
|
import { tokens } from "./tokens.js";
|
|
8
10
|
|
|
11
|
+
// viem's `mainnet` chain leaves `testnet` undefined; consumers
|
|
12
|
+
// (e.g. the bridge modal) check `env.chain.testnet === false` strictly.
|
|
13
|
+
const ethereum = defineChain({ ...mainnet, testnet: false });
|
|
14
|
+
|
|
9
15
|
const createEnvironment = (
|
|
10
16
|
rpcUrls?: string[],
|
|
11
17
|
governanceIndexerUrl?: string,
|
|
12
|
-
|
|
18
|
+
lunarIndexerUrl?: string,
|
|
19
|
+
): Environment<typeof tokens, {}, {}, typeof contracts, typeof custom> =>
|
|
13
20
|
createEnvironmentConfig({
|
|
14
21
|
key: "ethereum",
|
|
15
22
|
name: "Ethereum",
|
|
@@ -25,12 +32,14 @@ const createEnvironment = (
|
|
|
25
32
|
governanceIndexerUrl:
|
|
26
33
|
governanceIndexerUrl ||
|
|
27
34
|
"https://lunar-services-worker.moonwell.workers.dev",
|
|
35
|
+
lunarIndexerUrl:
|
|
36
|
+
lunarIndexerUrl || "https://lunar-services-worker.moonwell.workers.dev",
|
|
28
37
|
tokens,
|
|
29
38
|
markets: {},
|
|
30
39
|
vaults: {},
|
|
31
40
|
morphoMarkets: {},
|
|
32
|
-
contracts
|
|
33
|
-
custom
|
|
34
|
-
}) as Environment<typeof tokens, {}, {},
|
|
41
|
+
contracts,
|
|
42
|
+
custom,
|
|
43
|
+
}) as Environment<typeof tokens, {}, {}, typeof contracts, typeof custom>;
|
|
35
44
|
|
|
36
45
|
export { createEnvironment, ethereum, tokens };
|
|
@@ -14,4 +14,16 @@ export const tokens = createTokenConfig({
|
|
|
14
14
|
name: "USD Coin",
|
|
15
15
|
symbol: "USDC",
|
|
16
16
|
},
|
|
17
|
+
WELL: {
|
|
18
|
+
address: "0xA88594D404727625A9437C3f886C7643872296AE",
|
|
19
|
+
decimals: 18,
|
|
20
|
+
name: "Moonwell",
|
|
21
|
+
symbol: "WELL",
|
|
22
|
+
},
|
|
23
|
+
stkWELL: {
|
|
24
|
+
address: "0xb3a9E0DCf37658a48aa9f018C44f90378ddD4357",
|
|
25
|
+
decimals: 18,
|
|
26
|
+
name: "Moonwell Staked WELL",
|
|
27
|
+
symbol: "stkWELL",
|
|
28
|
+
},
|
|
17
29
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { base, moonbeam, moonriver, optimism } from "viem/chains";
|
|
1
|
+
import { base, mainnet, moonbeam, moonriver, optimism } from "viem/chains";
|
|
2
2
|
|
|
3
3
|
export interface GovernanceTokenInfo {
|
|
4
4
|
id: string;
|
|
@@ -30,7 +30,7 @@ export const GovernanceTokensConfig = createGovernanceTokensConfig({
|
|
|
30
30
|
id: "WELL",
|
|
31
31
|
symbol: "WELL",
|
|
32
32
|
name: "WELL",
|
|
33
|
-
chainIds: [moonbeam.id, base.id, optimism.id] as number[],
|
|
33
|
+
chainIds: [moonbeam.id, base.id, optimism.id, mainnet.id] as number[],
|
|
34
34
|
testnet: false,
|
|
35
35
|
},
|
|
36
36
|
MFAM: {
|
package/errors/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '0.
|
|
1
|
+
export const version = '0.13.1'
|
package/index.ts
CHANGED
|
@@ -3,6 +3,9 @@ export {
|
|
|
3
3
|
type MoonwellClient,
|
|
4
4
|
} from "./client/createMoonwellClient.js";
|
|
5
5
|
|
|
6
|
+
export { MerklApiError } from "./actions/morpho/user-rewards/common.js";
|
|
7
|
+
export { MorphoUserRewardsAggregateError } from "./actions/morpho/user-rewards/getMorphoUserRewards.js";
|
|
8
|
+
|
|
6
9
|
export type {
|
|
7
10
|
MarketConfig,
|
|
8
11
|
MorphoMarketConfig,
|