@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.
Files changed (114) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/_cjs/actions/core/markets/common.js +11 -4
  3. package/_cjs/actions/core/markets/common.js.map +1 -1
  4. package/_cjs/actions/core/user-rewards/common.js +6 -5
  5. package/_cjs/actions/core/user-rewards/common.js.map +1 -1
  6. package/_cjs/actions/governance/getDelegates.js.map +1 -1
  7. package/_cjs/actions/governance/getStakingInfo.js +113 -31
  8. package/_cjs/actions/governance/getStakingInfo.js.map +1 -1
  9. package/_cjs/actions/governance/getUserStakingInfo.js +106 -18
  10. package/_cjs/actions/governance/getUserStakingInfo.js.map +1 -1
  11. package/_cjs/actions/governance/getUserVotingPowers.js +21 -6
  12. package/_cjs/actions/governance/getUserVotingPowers.js.map +1 -1
  13. package/_cjs/actions/governance/getWellPrice.js +26 -0
  14. package/_cjs/actions/governance/getWellPrice.js.map +1 -0
  15. package/_cjs/actions/morpho/user-rewards/common.js +87 -12
  16. package/_cjs/actions/morpho/user-rewards/common.js.map +1 -1
  17. package/_cjs/actions/morpho/user-rewards/getMorphoUserRewards.js +46 -10
  18. package/_cjs/actions/morpho/user-rewards/getMorphoUserRewards.js.map +1 -1
  19. package/_cjs/actions/morpho/vaults/common.js +19 -6
  20. package/_cjs/actions/morpho/vaults/common.js.map +1 -1
  21. package/_cjs/environments/definitions/ethereum/contracts.js +12 -0
  22. package/_cjs/environments/definitions/ethereum/contracts.js.map +1 -0
  23. package/_cjs/environments/definitions/ethereum/custom.js +18 -0
  24. package/_cjs/environments/definitions/ethereum/custom.js.map +1 -0
  25. package/_cjs/environments/definitions/ethereum/environment.js +9 -5
  26. package/_cjs/environments/definitions/ethereum/environment.js.map +1 -1
  27. package/_cjs/environments/definitions/ethereum/tokens.js +12 -0
  28. package/_cjs/environments/definitions/ethereum/tokens.js.map +1 -1
  29. package/_cjs/environments/definitions/governance.js +1 -1
  30. package/_cjs/environments/definitions/governance.js.map +1 -1
  31. package/_cjs/errors/version.js +1 -1
  32. package/_cjs/index.js +5 -1
  33. package/_cjs/index.js.map +1 -1
  34. package/_esm/actions/core/markets/common.js +11 -4
  35. package/_esm/actions/core/markets/common.js.map +1 -1
  36. package/_esm/actions/core/user-rewards/common.js +6 -5
  37. package/_esm/actions/core/user-rewards/common.js.map +1 -1
  38. package/_esm/actions/governance/getDelegates.js +2 -0
  39. package/_esm/actions/governance/getDelegates.js.map +1 -1
  40. package/_esm/actions/governance/getStakingInfo.js +136 -32
  41. package/_esm/actions/governance/getStakingInfo.js.map +1 -1
  42. package/_esm/actions/governance/getUserStakingInfo.js +120 -19
  43. package/_esm/actions/governance/getUserStakingInfo.js.map +1 -1
  44. package/_esm/actions/governance/getUserVotingPowers.js +24 -6
  45. package/_esm/actions/governance/getUserVotingPowers.js.map +1 -1
  46. package/_esm/actions/governance/getWellPrice.js +50 -0
  47. package/_esm/actions/governance/getWellPrice.js.map +1 -0
  48. package/_esm/actions/morpho/user-rewards/common.js +93 -12
  49. package/_esm/actions/morpho/user-rewards/common.js.map +1 -1
  50. package/_esm/actions/morpho/user-rewards/getMorphoUserRewards.js +51 -11
  51. package/_esm/actions/morpho/user-rewards/getMorphoUserRewards.js.map +1 -1
  52. package/_esm/actions/morpho/vaults/common.js +19 -6
  53. package/_esm/actions/morpho/vaults/common.js.map +1 -1
  54. package/_esm/environments/definitions/ethereum/contracts.js +10 -0
  55. package/_esm/environments/definitions/ethereum/contracts.js.map +1 -0
  56. package/_esm/environments/definitions/ethereum/custom.js +15 -0
  57. package/_esm/environments/definitions/ethereum/custom.js.map +1 -0
  58. package/_esm/environments/definitions/ethereum/environment.js +11 -5
  59. package/_esm/environments/definitions/ethereum/environment.js.map +1 -1
  60. package/_esm/environments/definitions/ethereum/tokens.js +12 -0
  61. package/_esm/environments/definitions/ethereum/tokens.js.map +1 -1
  62. package/_esm/environments/definitions/governance.js +2 -2
  63. package/_esm/environments/definitions/governance.js.map +1 -1
  64. package/_esm/errors/version.js +1 -1
  65. package/_esm/index.js +2 -0
  66. package/_esm/index.js.map +1 -1
  67. package/_types/actions/core/markets/common.d.ts.map +1 -1
  68. package/_types/actions/core/user-rewards/common.d.ts.map +1 -1
  69. package/_types/actions/governance/getDelegates.d.ts.map +1 -1
  70. package/_types/actions/governance/getStakingInfo.d.ts +1 -1
  71. package/_types/actions/governance/getStakingInfo.d.ts.map +1 -1
  72. package/_types/actions/governance/getUserStakingInfo.d.ts.map +1 -1
  73. package/_types/actions/governance/getUserVotingPowers.d.ts.map +1 -1
  74. package/_types/actions/governance/getWellPrice.d.ts +29 -0
  75. package/_types/actions/governance/getWellPrice.d.ts.map +1 -0
  76. package/_types/actions/morpho/user-rewards/common.d.ts +23 -0
  77. package/_types/actions/morpho/user-rewards/common.d.ts.map +1 -1
  78. package/_types/actions/morpho/user-rewards/getMorphoUserRewards.d.ts +22 -0
  79. package/_types/actions/morpho/user-rewards/getMorphoUserRewards.d.ts.map +1 -1
  80. package/_types/actions/morpho/vaults/common.d.ts.map +1 -1
  81. package/_types/client/createMoonwellClient.d.ts +62 -2
  82. package/_types/client/createMoonwellClient.d.ts.map +1 -1
  83. package/_types/environments/definitions/ethereum/contracts.d.ts +4 -0
  84. package/_types/environments/definitions/ethereum/contracts.d.ts.map +1 -0
  85. package/_types/environments/definitions/ethereum/custom.d.ts +18 -0
  86. package/_types/environments/definitions/ethereum/custom.d.ts.map +1 -0
  87. package/_types/environments/definitions/ethereum/environment.d.ts +52 -2
  88. package/_types/environments/definitions/ethereum/environment.d.ts.map +1 -1
  89. package/_types/environments/definitions/ethereum/tokens.d.ts +12 -0
  90. package/_types/environments/definitions/ethereum/tokens.d.ts.map +1 -1
  91. package/_types/environments/definitions/governance.d.ts.map +1 -1
  92. package/_types/environments/index.d.ts +34 -4
  93. package/_types/environments/index.d.ts.map +1 -1
  94. package/_types/errors/version.d.ts +1 -1
  95. package/_types/index.d.ts +2 -0
  96. package/_types/index.d.ts.map +1 -1
  97. package/actions/core/markets/common.ts +11 -6
  98. package/actions/core/user-rewards/common.ts +6 -5
  99. package/actions/governance/getDelegates.ts +2 -0
  100. package/actions/governance/getStakingInfo.ts +195 -87
  101. package/actions/governance/getUserStakingInfo.ts +168 -54
  102. package/actions/governance/getUserVotingPowers.ts +30 -15
  103. package/actions/governance/getWellPrice.ts +66 -0
  104. package/actions/morpho/user-rewards/common.ts +91 -14
  105. package/actions/morpho/user-rewards/getMorphoUserRewards.ts +77 -12
  106. package/actions/morpho/vaults/common.ts +19 -12
  107. package/environments/definitions/ethereum/contracts.ts +10 -0
  108. package/environments/definitions/ethereum/custom.ts +15 -0
  109. package/environments/definitions/ethereum/environment.ts +15 -6
  110. package/environments/definitions/ethereum/tokens.ts +12 -0
  111. package/environments/definitions/governance.ts +2 -2
  112. package/errors/version.ts +1 -1
  113. package/index.ts +3 -0
  114. 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
- homeViewsContract?.read.getGovernanceTokenPrice(),
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 || 0n, 18);
135
- const nativeTokenPrice = new Amount(nativeTokenPriceRaw || 0n, 18);
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
- const response = await fetch(
305
- `https://api.merkl.xyz/v4/users/${account}/rewards?chainId=${environment.chainId}&test=false&breakdownPage=0&reloadChainId=${environment.chainId}`,
306
- {
307
- headers: MOONWELL_FETCH_JSON_HEADERS,
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
- if (!response.ok) {
312
- console.warn(
313
- `Merkl API request failed: ${response.status} ${response.statusText}`,
314
- );
315
- return [];
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
- console.error("Error in getMerklRewardsData:", error);
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 environments = getEnvironmentsFromArgs(client, args);
26
-
27
- const environmentsUserRewards = await Promise.all(
28
- environments
29
- .filter((environment) => environment.contracts.morphoViews !== undefined)
30
- .map((environment) => {
31
- return getUserMorphoRewardsData({
32
- environment,
33
- account: args.userAddress,
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
- return environmentsUserRewards.flat();
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
- homeViewsContract?.read.getGovernanceTokenPrice(),
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
- governanceTokenPriceRaw || 0n,
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
- homeViewsContract?.read.getGovernanceTokenPrice(),
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
- governanceTokenPriceRaw || 0n,
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 as ethereum } from "viem/chains";
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
- ): Environment<typeof tokens, {}, {}, {}, {}> =>
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.12.2'
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,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@moonwell-fi/moonwell-sdk",
3
3
  "description": "TypeScript Interface for Moonwell",
4
- "version": "0.12.2",
4
+ "version": "0.13.1",
5
5
  "main": "./_cjs/index.js",
6
6
  "module": "./_esm/index.js",
7
7
  "types": "./_types/index.d.ts",