@moonwell-fi/moonwell-sdk 0.13.0 → 0.14.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 +20 -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/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/getUserVoteReceipt.js +39 -25
- package/_cjs/actions/governance/getUserVoteReceipt.js.map +1 -1
- package/_cjs/actions/governance/getWellPrice.js +26 -0
- package/_cjs/actions/governance/getWellPrice.js.map +1 -0
- package/_cjs/actions/governance/governor-api-client.js +70 -33
- package/_cjs/actions/governance/governor-api-client.js.map +1 -1
- package/_cjs/actions/governance/proposals/common.js +29 -1
- package/_cjs/actions/governance/proposals/common.js.map +1 -1
- package/_cjs/actions/governance/proposals/getProposal.js +24 -17
- package/_cjs/actions/governance/proposals/getProposal.js.map +1 -1
- package/_cjs/actions/governance/proposals/getProposals.js +27 -9
- package/_cjs/actions/governance/proposals/getProposals.js.map +1 -1
- package/_cjs/actions/morpho/user-rewards/common.js +10 -3
- package/_cjs/actions/morpho/user-rewards/common.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/errors/version.js +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/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/getUserVoteReceipt.js +48 -26
- package/_esm/actions/governance/getUserVoteReceipt.js.map +1 -1
- package/_esm/actions/governance/getWellPrice.js +50 -0
- package/_esm/actions/governance/getWellPrice.js.map +1 -0
- package/_esm/actions/governance/governor-api-client.js +87 -35
- package/_esm/actions/governance/governor-api-client.js.map +1 -1
- package/_esm/actions/governance/proposals/common.js +44 -1
- package/_esm/actions/governance/proposals/common.js.map +1 -1
- package/_esm/actions/governance/proposals/getProposal.js +36 -23
- package/_esm/actions/governance/proposals/getProposal.js.map +1 -1
- package/_esm/actions/governance/proposals/getProposals.js +44 -10
- package/_esm/actions/governance/proposals/getProposals.js.map +1 -1
- package/_esm/actions/morpho/user-rewards/common.js +10 -3
- package/_esm/actions/morpho/user-rewards/common.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/errors/version.js +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/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/getUserVoteReceipt.d.ts +16 -0
- package/_types/actions/governance/getUserVoteReceipt.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/governance/governor-api-client.d.ts +37 -12
- package/_types/actions/governance/governor-api-client.d.ts.map +1 -1
- package/_types/actions/governance/proposals/common.d.ts +14 -1
- package/_types/actions/governance/proposals/common.d.ts.map +1 -1
- package/_types/actions/governance/proposals/getProposal.d.ts +6 -1
- package/_types/actions/governance/proposals/getProposal.d.ts.map +1 -1
- package/_types/actions/governance/proposals/getProposals.d.ts +1 -1
- package/_types/actions/governance/proposals/getProposals.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/errors/version.d.ts +1 -1
- package/actions/core/markets/common.ts +11 -6
- package/actions/core/user-rewards/common.ts +6 -5
- package/actions/governance/getStakingInfo.ts +195 -87
- package/actions/governance/getUserStakingInfo.ts +168 -54
- package/actions/governance/getUserVoteReceipt.ts +71 -31
- package/actions/governance/getWellPrice.ts +66 -0
- package/actions/governance/governor-api-client.ts +136 -62
- package/actions/governance/proposals/common.ts +51 -1
- package/actions/governance/proposals/getProposal.ts +46 -26
- package/actions/governance/proposals/getProposals.ts +48 -14
- package/actions/morpho/user-rewards/common.ts +10 -3
- package/actions/morpho/vaults/common.ts +19 -12
- package/errors/version.ts +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getProposals.d.ts","sourceRoot":"","sources":["../../../../actions/governance/proposals/getProposals.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAE9E,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,KAAK,EAAE,KAAK,EAAe,MAAM,gCAAgC,CAAC;AAEzE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"getProposals.d.ts","sourceRoot":"","sources":["../../../../actions/governance/proposals/getProposals.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAE9E,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,KAAK,EAAE,KAAK,EAAe,MAAM,gCAAgC,CAAC;AAEzE,OAAO,EAAE,KAAK,QAAQ,EAAiB,MAAM,4BAA4B,CAAC;AAY1E,MAAM,MAAM,sBAAsB,CAChC,YAAY,EACZ,OAAO,SAAS,KAAK,GAAG,SAAS,IAC/B,4BAA4B,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;AAExD,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;AAEzD,wBAAsB,YAAY,CAChC,YAAY,EACZ,OAAO,SAAS,KAAK,GAAG,SAAS,EAEjC,MAAM,EAAE,cAAc,EACtB,IAAI,CAAC,EAAE,sBAAsB,CAAC,YAAY,EAAE,OAAO,CAAC,GACnD,sBAAsB,CAyCxB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../../actions/morpho/user-rewards/common.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,WAAW,EAGjB,MAAM,gCAAgC,CAAC;AAKxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../../actions/morpho/user-rewards/common.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,WAAW,EAGjB,MAAM,gCAAgC,CAAC;AAKxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AAGzF;;;;;;;GAOG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,MAAM,EAAE;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAChC,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB;CAWF;AAED,wBAAsB,wBAAwB,CAAC,MAAM,EAAE;IACrD,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE,KAAK,MAAM,EAAE,CAAC;IACvB,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAsF9B;AAED,wBAAsB,+BAA+B,CAAC,MAAM,EAAE;IAC5D,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE,KAAK,MAAM,EAAE,CAAC;CACxB,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC,CA4GrC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../../actions/morpho/vaults/common.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,WAAW,EAEjB,MAAM,gCAAgC,CAAC;AAKxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EACV,WAAW,EAEZ,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../../actions/morpho/vaults/common.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,WAAW,EAEjB,MAAM,gCAAgC,CAAC;AAKxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EACV,WAAW,EAEZ,MAAM,+BAA+B,CAAC;AAsavC,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAChD,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAazB;AA43BD,KAAK,4BAA4B,GAAG;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,WAAW,CAAC;IACxB,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,WAAW,EAAE,EACrB,uBAAuB,CAAC,EAAE,OAAO,GAChC,OAAO,CAAC,4BAA4B,EAAE,CAAC,CA8NzC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "0.
|
|
1
|
+
export declare const version = "0.14.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
findTokenByAddress,
|
|
18
18
|
} from "../../../environments/utils/index.js";
|
|
19
19
|
import type { Market } from "../../../types/market.js";
|
|
20
|
+
import { getGovernanceTokenPriceFor } from "../../governance/getWellPrice.js";
|
|
20
21
|
|
|
21
22
|
export const getMarketsData = async (environment: Environment) => {
|
|
22
23
|
// Moonriver (chainId 1285) should always use on-chain data
|
|
@@ -54,7 +55,7 @@ export const getMarketsData = async (environment: Environment) => {
|
|
|
54
55
|
viewsContract?.read.getProtocolInfo(),
|
|
55
56
|
viewsContract?.read.getAllMarketsInfo(),
|
|
56
57
|
homeViewsContract?.read.getNativeTokenPrice(),
|
|
57
|
-
|
|
58
|
+
getGovernanceTokenPriceFor(environment),
|
|
58
59
|
]);
|
|
59
60
|
|
|
60
61
|
// If getAllMarketsInfo failed (e.g. broken on-chain oracle), fall back to
|
|
@@ -506,13 +507,17 @@ async function fetchMarketsFromLunar(
|
|
|
506
507
|
|
|
507
508
|
const [nativeTokenPriceRaw, governanceTokenPriceRaw] = await Promise.all([
|
|
508
509
|
homeEnvironment.contracts.views?.read.getNativeTokenPrice(),
|
|
509
|
-
|
|
510
|
+
getGovernanceTokenPriceFor(environment).catch((err) => {
|
|
511
|
+
environment.onError?.(err, {
|
|
512
|
+
source: "governance-token-price",
|
|
513
|
+
chainId: environment.chainId,
|
|
514
|
+
});
|
|
515
|
+
return 0n;
|
|
516
|
+
}),
|
|
510
517
|
]);
|
|
511
518
|
|
|
512
|
-
if (
|
|
513
|
-
throw new Error(
|
|
514
|
-
"Failed to fetch native or governance token prices from home chain",
|
|
515
|
-
);
|
|
519
|
+
if (nativeTokenPriceRaw === undefined) {
|
|
520
|
+
throw new Error("Failed to fetch native token price from home chain");
|
|
516
521
|
}
|
|
517
522
|
|
|
518
523
|
governanceTokenPrice = new Amount(governanceTokenPriceRaw, 18);
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
findTokenByAddress,
|
|
10
10
|
} from "../../../environments/utils/index.js";
|
|
11
11
|
import type { UserReward } from "../../../types/userReward.js";
|
|
12
|
+
import { getGovernanceTokenPriceFor } from "../../governance/getWellPrice.js";
|
|
12
13
|
|
|
13
14
|
export const getUserRewardsData = async (params: {
|
|
14
15
|
environment: Environment;
|
|
@@ -27,7 +28,7 @@ export const getUserRewardsData = async (params: {
|
|
|
27
28
|
viewsContract?.read.getAllMarketsInfo(),
|
|
28
29
|
viewsContract?.read.getUserRewards([params.account]),
|
|
29
30
|
homeViewsContract?.read.getNativeTokenPrice(),
|
|
30
|
-
|
|
31
|
+
getGovernanceTokenPriceFor(params.environment),
|
|
31
32
|
] as const);
|
|
32
33
|
|
|
33
34
|
// Narrow each one by status and coerce to undefined on failure:
|
|
@@ -43,14 +44,14 @@ export const getUserRewardsData = async (params: {
|
|
|
43
44
|
if (
|
|
44
45
|
!allMarkets ||
|
|
45
46
|
!userRewards ||
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
nativeTokenPriceRaw === undefined ||
|
|
48
|
+
governanceTokenPriceRaw === undefined
|
|
48
49
|
) {
|
|
49
50
|
return [];
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
const governanceTokenPrice = new Amount(governanceTokenPriceRaw
|
|
53
|
-
const nativeTokenPrice = new Amount(nativeTokenPriceRaw
|
|
53
|
+
const governanceTokenPrice = new Amount(governanceTokenPriceRaw, 18);
|
|
54
|
+
const nativeTokenPrice = new Amount(nativeTokenPriceRaw, 18);
|
|
54
55
|
|
|
55
56
|
let tokenPrices =
|
|
56
57
|
allMarkets
|
|
@@ -7,14 +7,10 @@ import {
|
|
|
7
7
|
getEnvironmentsFromArgs,
|
|
8
8
|
} from "../../common/index.js";
|
|
9
9
|
import type { NetworkParameterType } from "../../common/types.js";
|
|
10
|
-
import {
|
|
11
|
-
type Chain,
|
|
12
|
-
type Environment,
|
|
13
|
-
type TokensType,
|
|
14
|
-
publicEnvironments,
|
|
15
|
-
} from "../../environments/index.js";
|
|
10
|
+
import type { Chain, Environment } from "../../environments/index.js";
|
|
16
11
|
import type { StakingInfo } from "../../types/staking.js";
|
|
17
12
|
import { getMerklStakingApr } from "./common.js";
|
|
13
|
+
import { getGovernanceTokenPriceFor } from "./getWellPrice.js";
|
|
18
14
|
|
|
19
15
|
export type GetStakingInfoParameters<
|
|
20
16
|
environments,
|
|
@@ -23,6 +19,108 @@ export type GetStakingInfoParameters<
|
|
|
23
19
|
|
|
24
20
|
export type GetStakingInfoReturnType = Promise<StakingInfo[]>;
|
|
25
21
|
|
|
22
|
+
type StakingInfoStruct = {
|
|
23
|
+
cooldown: bigint;
|
|
24
|
+
distributionEnd: bigint;
|
|
25
|
+
emissionPerSecond: bigint;
|
|
26
|
+
totalSupply: bigint;
|
|
27
|
+
unstakeWindow: bigint;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const isStakingInfoStruct = (value: unknown): value is StakingInfoStruct => {
|
|
31
|
+
if (typeof value !== "object" || value === null) return false;
|
|
32
|
+
const v = value as Record<string, unknown>;
|
|
33
|
+
return (
|
|
34
|
+
typeof v.cooldown === "bigint" &&
|
|
35
|
+
typeof v.distributionEnd === "bigint" &&
|
|
36
|
+
typeof v.emissionPerSecond === "bigint" &&
|
|
37
|
+
typeof v.totalSupply === "bigint" &&
|
|
38
|
+
typeof v.unstakeWindow === "bigint"
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Reads the staking fields directly from the stkWELL token contract when the
|
|
44
|
+
* core views' getStakingInfo() is unavailable or returns zeroed data
|
|
45
|
+
* (e.g. reverts on Moonbeam). Reads each field independently so a single
|
|
46
|
+
* transient RPC failure doesn't erase the whole fallback.
|
|
47
|
+
*
|
|
48
|
+
* The `assets` mapping is keyed by the stkWELL contract's own address — that's
|
|
49
|
+
* the Aave-fork convention (`address(this)` in StakedAave._initialize), not
|
|
50
|
+
* the underlying staked token. Verified on Moonbeam: assets(stkWELL) returns
|
|
51
|
+
* non-zero emissionPerSecond; assets(WELL) returns zero.
|
|
52
|
+
*/
|
|
53
|
+
async function getStakingInfoFromStkWell(
|
|
54
|
+
environment: Environment,
|
|
55
|
+
): Promise<StakingInfoStruct | undefined> {
|
|
56
|
+
const stakingToken = environment.contracts.stakingToken;
|
|
57
|
+
const stakingTokenKey = environment.config.contracts.stakingToken;
|
|
58
|
+
const tokens = environment.config.tokens as Record<
|
|
59
|
+
string,
|
|
60
|
+
{ address: `0x${string}` } | undefined
|
|
61
|
+
>;
|
|
62
|
+
const stakingTokenAddress = stakingTokenKey
|
|
63
|
+
? tokens[stakingTokenKey]?.address
|
|
64
|
+
: undefined;
|
|
65
|
+
if (!stakingToken || !stakingTokenAddress) {
|
|
66
|
+
environment.onError?.(
|
|
67
|
+
new Error("getStakingInfoFromStkWell: missing stkWELL config"),
|
|
68
|
+
{ source: "staking-fallback", chainId: environment.chainId },
|
|
69
|
+
);
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const [
|
|
74
|
+
cooldownR,
|
|
75
|
+
unstakeWindowR,
|
|
76
|
+
distributionEndR,
|
|
77
|
+
totalSupplyR,
|
|
78
|
+
assetDataR,
|
|
79
|
+
] = await Promise.allSettled([
|
|
80
|
+
stakingToken.read.COOLDOWN_SECONDS(),
|
|
81
|
+
stakingToken.read.UNSTAKE_WINDOW(),
|
|
82
|
+
stakingToken.read.DISTRIBUTION_END(),
|
|
83
|
+
stakingToken.read.totalSupply(),
|
|
84
|
+
stakingToken.read.assets([stakingTokenAddress]),
|
|
85
|
+
]);
|
|
86
|
+
|
|
87
|
+
// Surface every rejection so operators don't have to guess which read failed.
|
|
88
|
+
for (const r of [
|
|
89
|
+
cooldownR,
|
|
90
|
+
unstakeWindowR,
|
|
91
|
+
distributionEndR,
|
|
92
|
+
totalSupplyR,
|
|
93
|
+
assetDataR,
|
|
94
|
+
]) {
|
|
95
|
+
if (r.status === "rejected") {
|
|
96
|
+
environment.onError?.(r.reason, {
|
|
97
|
+
source: "staking-fallback",
|
|
98
|
+
chainId: environment.chainId,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// totalSupply is load-bearing for APR; if its read failed (vs. legitimately
|
|
104
|
+
// returning 0n on an empty new chain) we can't produce a sensible struct.
|
|
105
|
+
if (totalSupplyR.status === "rejected") return undefined;
|
|
106
|
+
|
|
107
|
+
const assetData =
|
|
108
|
+
assetDataR.status === "fulfilled" ? assetDataR.value : undefined;
|
|
109
|
+
// viem returns multi-output reads as a tuple (Readonly<[bigint, bigint, bigint]>)
|
|
110
|
+
// even when the ABI names the outputs.
|
|
111
|
+
const emissionPerSecond = assetData ? assetData[0] : 0n;
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
cooldown: cooldownR.status === "fulfilled" ? cooldownR.value : 0n,
|
|
115
|
+
unstakeWindow:
|
|
116
|
+
unstakeWindowR.status === "fulfilled" ? unstakeWindowR.value : 0n,
|
|
117
|
+
distributionEnd:
|
|
118
|
+
distributionEndR.status === "fulfilled" ? distributionEndR.value : 0n,
|
|
119
|
+
totalSupply: totalSupplyR.value,
|
|
120
|
+
emissionPerSecond,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
26
124
|
export async function getStakingInfo<
|
|
27
125
|
environments,
|
|
28
126
|
Network extends Chain | undefined,
|
|
@@ -36,85 +134,104 @@ export async function getStakingInfo<
|
|
|
36
134
|
(env) => env.config.contracts.stakingToken,
|
|
37
135
|
);
|
|
38
136
|
|
|
137
|
+
const baseEnvironment = (
|
|
138
|
+
client.environments as { base?: Environment } | undefined
|
|
139
|
+
)?.base;
|
|
140
|
+
|
|
39
141
|
const envStakingInfoSettlements = await Promise.allSettled(
|
|
40
142
|
envsWithStaking.map(async (environment) => {
|
|
41
|
-
const homeEnvironment =
|
|
42
|
-
(Object.values(publicEnvironments) as Environment[]).find((e) =>
|
|
43
|
-
e.custom?.governance?.chainIds?.includes(environment.chainId),
|
|
44
|
-
) || environment;
|
|
45
|
-
|
|
46
143
|
const isBase = environment.chainId === base.id;
|
|
47
144
|
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
environment.contracts.views?.read.getStakingInfo({
|
|
145
|
+
const [viewsStakingResult, historicalStakingResult, priceResult] =
|
|
146
|
+
await Promise.allSettled([
|
|
147
|
+
environment.contracts.views?.read.getStakingInfo(),
|
|
148
|
+
isBase
|
|
149
|
+
? environment.contracts.views?.read.getStakingInfo({
|
|
54
150
|
blockNumber: BigInt(34149943),
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
151
|
+
})
|
|
152
|
+
: Promise.resolve(undefined),
|
|
153
|
+
getGovernanceTokenPriceFor(environment, baseEnvironment),
|
|
154
|
+
]);
|
|
155
|
+
|
|
156
|
+
const viewsStaking =
|
|
157
|
+
viewsStakingResult.status === "fulfilled"
|
|
158
|
+
? viewsStakingResult.value
|
|
159
|
+
: undefined;
|
|
160
|
+
|
|
161
|
+
// Fall back to direct stkWELL reads when the views call rejected (the
|
|
162
|
+
// known Moonbeam failure mode) or returned a fully-zeroed struct
|
|
163
|
+
// (suspicious — a real deployment always has cooldown and unstake
|
|
164
|
+
// window configured > 0). A new chain with zero stakers but real
|
|
165
|
+
// schedule constants still goes through views.
|
|
166
|
+
const allZeroed =
|
|
167
|
+
isStakingInfoStruct(viewsStaking) &&
|
|
168
|
+
viewsStaking.cooldown === 0n &&
|
|
169
|
+
viewsStaking.unstakeWindow === 0n &&
|
|
170
|
+
viewsStaking.totalSupply === 0n &&
|
|
171
|
+
viewsStaking.emissionPerSecond === 0n;
|
|
172
|
+
const viewsValid = isStakingInfoStruct(viewsStaking) && !allZeroed;
|
|
173
|
+
const stakingInfo: StakingInfoStruct | undefined = viewsValid
|
|
174
|
+
? viewsStaking
|
|
175
|
+
: await getStakingInfoFromStkWell(environment);
|
|
176
|
+
|
|
177
|
+
const historicalStaking =
|
|
178
|
+
historicalStakingResult.status === "fulfilled"
|
|
179
|
+
? historicalStakingResult.value
|
|
180
|
+
: undefined;
|
|
181
|
+
|
|
182
|
+
const price = priceResult.status === "fulfilled" ? priceResult.value : 0n;
|
|
183
|
+
|
|
184
|
+
if (priceResult.status === "rejected") {
|
|
185
|
+
environment.onError?.(priceResult.reason, {
|
|
186
|
+
source: "governance-token-price",
|
|
187
|
+
chainId: environment.chainId,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return { stakingInfo, historicalStaking, price };
|
|
63
192
|
}),
|
|
64
193
|
);
|
|
65
194
|
|
|
66
|
-
const envStakingInfo = envStakingInfoSettlements
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
s as PromiseFulfilledResult<
|
|
72
|
-
(
|
|
73
|
-
| bigint
|
|
74
|
-
| {
|
|
75
|
-
cooldown: bigint;
|
|
76
|
-
unstakeWindow: bigint;
|
|
77
|
-
distributionEnd: bigint;
|
|
78
|
-
totalSupply: bigint;
|
|
79
|
-
emissionPerSecond: bigint;
|
|
80
|
-
lastUpdateTimestamp: bigint;
|
|
81
|
-
index: bigint;
|
|
82
|
-
}
|
|
83
|
-
| undefined
|
|
84
|
-
)[]
|
|
85
|
-
>
|
|
86
|
-
).value,
|
|
87
|
-
)
|
|
88
|
-
.filter((val) => val !== undefined);
|
|
195
|
+
const envStakingInfo = envStakingInfoSettlements.map((s) =>
|
|
196
|
+
s.status === "fulfilled"
|
|
197
|
+
? s.value
|
|
198
|
+
: { stakingInfo: undefined, historicalStaking: undefined, price: 0n },
|
|
199
|
+
);
|
|
89
200
|
|
|
90
201
|
const baseEnv = envsWithStaking.find((env) => env.chainId === base.id);
|
|
91
|
-
const
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
202
|
+
const baseStakingTokenKey = baseEnv?.config.contracts.stakingToken;
|
|
203
|
+
const baseTokens = baseEnv?.config.tokens as
|
|
204
|
+
| Record<string, { address: `0x${string}` } | undefined>
|
|
205
|
+
| undefined;
|
|
206
|
+
const baseStkTokenAddress = baseStakingTokenKey
|
|
207
|
+
? baseTokens?.[baseStakingTokenKey]?.address
|
|
208
|
+
: undefined;
|
|
209
|
+
const baseStakingApr = baseStkTokenAddress
|
|
210
|
+
? await getMerklStakingApr(baseStkTokenAddress)
|
|
211
|
+
: 0;
|
|
98
212
|
|
|
99
213
|
const result = envsWithStaking.flatMap((curr, index) => {
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
214
|
+
const govKey = curr.config.contracts.governanceToken;
|
|
215
|
+
const stkKey = curr.config.contracts.stakingToken;
|
|
216
|
+
const currTokens = curr.config.tokens as Record<
|
|
217
|
+
string,
|
|
218
|
+
{ address: `0x${string}`; decimals: number; name: string; symbol: string }
|
|
219
|
+
>;
|
|
220
|
+
if (!govKey || !stkKey) return [];
|
|
221
|
+
const token = currTokens[govKey];
|
|
222
|
+
const stakingToken = currTokens[stkKey];
|
|
223
|
+
if (!token || !stakingToken) return [];
|
|
224
|
+
|
|
225
|
+
// envStakingInfo is built via Promise.allSettled with an explicit
|
|
226
|
+
// fallback object at the .map below, so entries are always defined here.
|
|
227
|
+
const {
|
|
228
|
+
stakingInfo: envStakingInfoData,
|
|
229
|
+
historicalStaking,
|
|
230
|
+
price,
|
|
231
|
+
} = envStakingInfo[index];
|
|
112
232
|
const isBase = curr.chainId === base.id;
|
|
113
233
|
|
|
114
|
-
if (
|
|
115
|
-
!envStakingInfoData ||
|
|
116
|
-
(isBase && !envStakingInfoDataAfterX28Proposal)
|
|
117
|
-
) {
|
|
234
|
+
if (!envStakingInfoData || (isBase && !historicalStaking)) {
|
|
118
235
|
return [];
|
|
119
236
|
}
|
|
120
237
|
|
|
@@ -124,20 +241,9 @@ export async function getStakingInfo<
|
|
|
124
241
|
emissionPerSecond: emissionPerSecondRaw,
|
|
125
242
|
totalSupply: totalSupplyRaw,
|
|
126
243
|
unstakeWindow,
|
|
127
|
-
} = envStakingInfoData
|
|
128
|
-
cooldown: bigint;
|
|
129
|
-
distributionEnd: bigint;
|
|
130
|
-
emissionPerSecond: bigint;
|
|
131
|
-
totalSupply: bigint;
|
|
132
|
-
unstakeWindow: bigint;
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
//Quick workaround to get governance token price from some other environment
|
|
136
|
-
const governanceTokenPrice = new Amount(
|
|
137
|
-
(envGovernanceTokenPriceData ?? 0n) as bigint,
|
|
138
|
-
18,
|
|
139
|
-
);
|
|
244
|
+
} = envStakingInfoData;
|
|
140
245
|
|
|
246
|
+
const tokenPrice = new Amount(price, 18);
|
|
141
247
|
const totalSupply = new Amount(totalSupplyRaw, 18);
|
|
142
248
|
const emissionPerSecond = new Amount(emissionPerSecondRaw, 18);
|
|
143
249
|
|
|
@@ -145,7 +251,9 @@ export async function getStakingInfo<
|
|
|
145
251
|
emissionPerSecond.value * SECONDS_PER_DAY * DAYS_PER_YEAR;
|
|
146
252
|
|
|
147
253
|
const apr =
|
|
148
|
-
|
|
254
|
+
totalSupply.value > 0
|
|
255
|
+
? ((emissionPerYear + totalSupply.value) / totalSupply.value - 1) * 100
|
|
256
|
+
: 0;
|
|
149
257
|
|
|
150
258
|
const stakingInfo: StakingInfo = {
|
|
151
259
|
apr: isBase ? baseStakingApr : apr,
|
|
@@ -153,10 +261,10 @@ export async function getStakingInfo<
|
|
|
153
261
|
cooldown: Number(cooldown),
|
|
154
262
|
distributionEnd: Number(distributionEnd),
|
|
155
263
|
token,
|
|
156
|
-
tokenPrice:
|
|
264
|
+
tokenPrice: tokenPrice.value,
|
|
157
265
|
stakingToken,
|
|
158
266
|
totalSupply,
|
|
159
|
-
totalSupplyUSD: totalSupply.value *
|
|
267
|
+
totalSupplyUSD: totalSupply.value * tokenPrice.value,
|
|
160
268
|
unstakeWindow: Number(unstakeWindow),
|
|
161
269
|
};
|
|
162
270
|
|