@chorus-one/polygon 1.0.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/.mocharc.json +6 -0
- package/LICENSE +13 -0
- package/README.md +233 -0
- package/dist/cjs/constants.d.ts +187 -0
- package/dist/cjs/constants.js +141 -0
- package/dist/cjs/index.d.ts +4 -0
- package/dist/cjs/index.js +12 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/referrer.d.ts +2 -0
- package/dist/cjs/referrer.js +15 -0
- package/dist/cjs/staker.d.ts +335 -0
- package/dist/cjs/staker.js +716 -0
- package/dist/cjs/types.d.ts +40 -0
- package/dist/cjs/types.js +2 -0
- package/dist/mjs/constants.d.ts +187 -0
- package/dist/mjs/constants.js +138 -0
- package/dist/mjs/index.d.ts +4 -0
- package/dist/mjs/index.js +2 -0
- package/dist/mjs/package.json +3 -0
- package/dist/mjs/referrer.d.ts +2 -0
- package/dist/mjs/referrer.js +11 -0
- package/dist/mjs/staker.d.ts +335 -0
- package/dist/mjs/staker.js +712 -0
- package/dist/mjs/types.d.ts +40 -0
- package/dist/mjs/types.js +1 -0
- package/hardhat.config.ts +27 -0
- package/package.json +50 -0
- package/src/constants.ts +151 -0
- package/src/index.ts +14 -0
- package/src/referrer.ts +15 -0
- package/src/staker.ts +878 -0
- package/src/types.ts +45 -0
- package/test/fixtures/expected-data.ts +17 -0
- package/test/integration/localSigner.spec.ts +128 -0
- package/test/integration/setup.ts +41 -0
- package/test/integration/staker.spec.ts +587 -0
- package/test/integration/testStaker.ts +130 -0
- package/test/integration/utils.ts +263 -0
- package/test/lib/networks.json +14 -0
- package/test/staker.spec.ts +154 -0
- package/tsconfig.cjs.json +9 -0
- package/tsconfig.json +13 -0
- package/tsconfig.mjs.json +9 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Hex, TransactionReceipt } from 'viem';
|
|
2
|
+
import type { PolygonNetworks } from './constants';
|
|
3
|
+
export interface PolygonNetworkConfig {
|
|
4
|
+
/** Network to use: 'mainnet' (Ethereum L1) or 'testnet' (Sepolia L1) */
|
|
5
|
+
network: PolygonNetworks;
|
|
6
|
+
/** Optional RPC endpoint URL override. If not provided, uses viem's default for the network. */
|
|
7
|
+
rpcUrl?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface Transaction {
|
|
10
|
+
/** The recipient (contract) address in hexadecimal format */
|
|
11
|
+
to: Hex;
|
|
12
|
+
/** The data to be included in the transaction in hexadecimal format (includes referrer tracking suffix) */
|
|
13
|
+
data: Hex;
|
|
14
|
+
/** The amount of ETH (in wei) to be sent with the transaction */
|
|
15
|
+
value?: bigint;
|
|
16
|
+
}
|
|
17
|
+
export interface PolygonTxStatus {
|
|
18
|
+
/** Status of the transaction */
|
|
19
|
+
status: 'success' | 'failure' | 'unknown';
|
|
20
|
+
/** Transaction receipt (null if unknown) */
|
|
21
|
+
receipt: TransactionReceipt | null;
|
|
22
|
+
}
|
|
23
|
+
export interface StakeInfo {
|
|
24
|
+
/** Total staked amount formatted in POL */
|
|
25
|
+
balance: string;
|
|
26
|
+
/** Total shares held by the delegator */
|
|
27
|
+
shares: bigint;
|
|
28
|
+
/** Current exchange rate between shares and POL (with high precision) */
|
|
29
|
+
exchangeRate: bigint;
|
|
30
|
+
}
|
|
31
|
+
export interface UnbondInfo {
|
|
32
|
+
/** Amount pending unbonding in POL */
|
|
33
|
+
amount: string;
|
|
34
|
+
/** Whether the unbond can be withdrawn now */
|
|
35
|
+
isWithdrawable: boolean;
|
|
36
|
+
/** Shares amount pending unbonding */
|
|
37
|
+
shares: bigint;
|
|
38
|
+
/** Epoch number when the unbond becomes claimable */
|
|
39
|
+
withdrawEpoch: bigint;
|
|
40
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import type { Address } from 'viem';
|
|
2
|
+
export type PolygonNetworks = 'mainnet' | 'testnet';
|
|
3
|
+
export interface NetworkContracts {
|
|
4
|
+
stakeManagerAddress: Address;
|
|
5
|
+
stakingTokenAddress: Address;
|
|
6
|
+
}
|
|
7
|
+
/** Contract addresses per network (mainnet = Ethereum L1, testnet = Sepolia L1) */
|
|
8
|
+
export declare const NETWORK_CONTRACTS: Record<PolygonNetworks, NetworkContracts>;
|
|
9
|
+
/** Chorus One Polygon ValidatorShare contract addresses */
|
|
10
|
+
export declare const CHORUS_ONE_POLYGON_VALIDATORS: {
|
|
11
|
+
readonly mainnet: `0x${string}`;
|
|
12
|
+
readonly testnet: `0x${string}`;
|
|
13
|
+
};
|
|
14
|
+
export declare const VALIDATOR_SHARE_ABI: readonly [{
|
|
15
|
+
readonly type: "function";
|
|
16
|
+
readonly name: "buyVoucherPOL";
|
|
17
|
+
readonly inputs: readonly [{
|
|
18
|
+
readonly name: "_amount";
|
|
19
|
+
readonly type: "uint256";
|
|
20
|
+
readonly internalType: "uint256";
|
|
21
|
+
}, {
|
|
22
|
+
readonly name: "_minSharesToMint";
|
|
23
|
+
readonly type: "uint256";
|
|
24
|
+
readonly internalType: "uint256";
|
|
25
|
+
}];
|
|
26
|
+
readonly outputs: readonly [{
|
|
27
|
+
readonly name: "amountToDeposit";
|
|
28
|
+
readonly type: "uint256";
|
|
29
|
+
readonly internalType: "uint256";
|
|
30
|
+
}];
|
|
31
|
+
readonly stateMutability: "nonpayable";
|
|
32
|
+
}, {
|
|
33
|
+
readonly type: "function";
|
|
34
|
+
readonly name: "sellVoucher_newPOL";
|
|
35
|
+
readonly inputs: readonly [{
|
|
36
|
+
readonly name: "claimAmount";
|
|
37
|
+
readonly type: "uint256";
|
|
38
|
+
readonly internalType: "uint256";
|
|
39
|
+
}, {
|
|
40
|
+
readonly name: "maximumSharesToBurn";
|
|
41
|
+
readonly type: "uint256";
|
|
42
|
+
readonly internalType: "uint256";
|
|
43
|
+
}];
|
|
44
|
+
readonly outputs: readonly [];
|
|
45
|
+
readonly stateMutability: "nonpayable";
|
|
46
|
+
}, {
|
|
47
|
+
readonly type: "function";
|
|
48
|
+
readonly name: "unstakeClaimTokens_newPOL";
|
|
49
|
+
readonly inputs: readonly [{
|
|
50
|
+
readonly name: "unbondNonce";
|
|
51
|
+
readonly type: "uint256";
|
|
52
|
+
readonly internalType: "uint256";
|
|
53
|
+
}];
|
|
54
|
+
readonly outputs: readonly [];
|
|
55
|
+
readonly stateMutability: "nonpayable";
|
|
56
|
+
}, {
|
|
57
|
+
readonly type: "function";
|
|
58
|
+
readonly name: "withdrawRewardsPOL";
|
|
59
|
+
readonly inputs: readonly [];
|
|
60
|
+
readonly outputs: readonly [];
|
|
61
|
+
readonly stateMutability: "nonpayable";
|
|
62
|
+
}, {
|
|
63
|
+
readonly type: "function";
|
|
64
|
+
readonly name: "restakePOL";
|
|
65
|
+
readonly inputs: readonly [];
|
|
66
|
+
readonly outputs: readonly [{
|
|
67
|
+
readonly name: "amountRestaked";
|
|
68
|
+
readonly type: "uint256";
|
|
69
|
+
readonly internalType: "uint256";
|
|
70
|
+
}, {
|
|
71
|
+
readonly name: "liquidReward";
|
|
72
|
+
readonly type: "uint256";
|
|
73
|
+
readonly internalType: "uint256";
|
|
74
|
+
}];
|
|
75
|
+
readonly stateMutability: "nonpayable";
|
|
76
|
+
}, {
|
|
77
|
+
readonly type: "function";
|
|
78
|
+
readonly name: "getTotalStake";
|
|
79
|
+
readonly inputs: readonly [{
|
|
80
|
+
readonly name: "user";
|
|
81
|
+
readonly type: "address";
|
|
82
|
+
readonly internalType: "address";
|
|
83
|
+
}];
|
|
84
|
+
readonly outputs: readonly [{
|
|
85
|
+
readonly name: "";
|
|
86
|
+
readonly type: "uint256";
|
|
87
|
+
readonly internalType: "uint256";
|
|
88
|
+
}, {
|
|
89
|
+
readonly name: "";
|
|
90
|
+
readonly type: "uint256";
|
|
91
|
+
readonly internalType: "uint256";
|
|
92
|
+
}];
|
|
93
|
+
readonly stateMutability: "view";
|
|
94
|
+
}, {
|
|
95
|
+
readonly type: "function";
|
|
96
|
+
readonly name: "unbondNonces";
|
|
97
|
+
readonly inputs: readonly [{
|
|
98
|
+
readonly name: "";
|
|
99
|
+
readonly type: "address";
|
|
100
|
+
readonly internalType: "address";
|
|
101
|
+
}];
|
|
102
|
+
readonly outputs: readonly [{
|
|
103
|
+
readonly name: "";
|
|
104
|
+
readonly type: "uint256";
|
|
105
|
+
readonly internalType: "uint256";
|
|
106
|
+
}];
|
|
107
|
+
readonly stateMutability: "view";
|
|
108
|
+
}, {
|
|
109
|
+
readonly type: "function";
|
|
110
|
+
readonly name: "unbonds_new";
|
|
111
|
+
readonly inputs: readonly [{
|
|
112
|
+
readonly name: "";
|
|
113
|
+
readonly type: "address";
|
|
114
|
+
readonly internalType: "address";
|
|
115
|
+
}, {
|
|
116
|
+
readonly name: "";
|
|
117
|
+
readonly type: "uint256";
|
|
118
|
+
readonly internalType: "uint256";
|
|
119
|
+
}];
|
|
120
|
+
readonly outputs: readonly [{
|
|
121
|
+
readonly name: "shares";
|
|
122
|
+
readonly type: "uint256";
|
|
123
|
+
readonly internalType: "uint256";
|
|
124
|
+
}, {
|
|
125
|
+
readonly name: "withdrawEpoch";
|
|
126
|
+
readonly type: "uint256";
|
|
127
|
+
readonly internalType: "uint256";
|
|
128
|
+
}];
|
|
129
|
+
readonly stateMutability: "view";
|
|
130
|
+
}, {
|
|
131
|
+
readonly type: "function";
|
|
132
|
+
readonly name: "getLiquidRewards";
|
|
133
|
+
readonly inputs: readonly [{
|
|
134
|
+
readonly name: "user";
|
|
135
|
+
readonly type: "address";
|
|
136
|
+
readonly internalType: "address";
|
|
137
|
+
}];
|
|
138
|
+
readonly outputs: readonly [{
|
|
139
|
+
readonly name: "";
|
|
140
|
+
readonly type: "uint256";
|
|
141
|
+
readonly internalType: "uint256";
|
|
142
|
+
}];
|
|
143
|
+
readonly stateMutability: "view";
|
|
144
|
+
}, {
|
|
145
|
+
readonly type: "function";
|
|
146
|
+
readonly name: "validatorId";
|
|
147
|
+
readonly inputs: readonly [];
|
|
148
|
+
readonly outputs: readonly [{
|
|
149
|
+
readonly name: "";
|
|
150
|
+
readonly type: "uint256";
|
|
151
|
+
readonly internalType: "uint256";
|
|
152
|
+
}];
|
|
153
|
+
readonly stateMutability: "view";
|
|
154
|
+
}, {
|
|
155
|
+
readonly type: "function";
|
|
156
|
+
readonly name: "withdrawExchangeRate";
|
|
157
|
+
readonly inputs: readonly [];
|
|
158
|
+
readonly outputs: readonly [{
|
|
159
|
+
readonly name: "";
|
|
160
|
+
readonly type: "uint256";
|
|
161
|
+
readonly internalType: "uint256";
|
|
162
|
+
}];
|
|
163
|
+
readonly stateMutability: "view";
|
|
164
|
+
}];
|
|
165
|
+
export declare const EXCHANGE_RATE_PRECISION = 100n;
|
|
166
|
+
export declare const EXCHANGE_RATE_HIGH_PRECISION: bigint;
|
|
167
|
+
export declare const STAKE_MANAGER_ABI: readonly [{
|
|
168
|
+
readonly type: "function";
|
|
169
|
+
readonly name: "epoch";
|
|
170
|
+
readonly inputs: readonly [];
|
|
171
|
+
readonly outputs: readonly [{
|
|
172
|
+
readonly name: "";
|
|
173
|
+
readonly type: "uint256";
|
|
174
|
+
readonly internalType: "uint256";
|
|
175
|
+
}];
|
|
176
|
+
readonly stateMutability: "view";
|
|
177
|
+
}, {
|
|
178
|
+
readonly type: "function";
|
|
179
|
+
readonly name: "withdrawalDelay";
|
|
180
|
+
readonly inputs: readonly [];
|
|
181
|
+
readonly outputs: readonly [{
|
|
182
|
+
readonly name: "";
|
|
183
|
+
readonly type: "uint256";
|
|
184
|
+
readonly internalType: "uint256";
|
|
185
|
+
}];
|
|
186
|
+
readonly stateMutability: "view";
|
|
187
|
+
}];
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/** Contract addresses per network (mainnet = Ethereum L1, testnet = Sepolia L1) */
|
|
2
|
+
// Reference: https://docs.polygon.technology/pos/reference/rpc-endpoints/
|
|
3
|
+
export const NETWORK_CONTRACTS = {
|
|
4
|
+
mainnet: {
|
|
5
|
+
stakeManagerAddress: '0x5e3Ef299fDDf15eAa0432E6e66473ace8c13D908',
|
|
6
|
+
stakingTokenAddress: '0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6'
|
|
7
|
+
},
|
|
8
|
+
testnet: {
|
|
9
|
+
stakeManagerAddress: '0x4AE8f648B1Ec892B6cc68C89cc088583964d08bE',
|
|
10
|
+
stakingTokenAddress: '0x44499312f493F62f2DFd3C6435Ca3603EbFCeeBa'
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
/** Chorus One Polygon ValidatorShare contract addresses */
|
|
14
|
+
// Reference mainnet: https://staking.polygon.technology/validators/106
|
|
15
|
+
// Reference testnet (Random Validator): https://staking.polygon.technology/validators/31
|
|
16
|
+
export const CHORUS_ONE_POLYGON_VALIDATORS = {
|
|
17
|
+
mainnet: '0xD9E6987D77bf2c6d0647b8181fd68A259f838C36',
|
|
18
|
+
testnet: '0x91344055cb0511b3aa36c561d741ee356b95f1c9'
|
|
19
|
+
};
|
|
20
|
+
// Reference: https://github.com/0xPolygon/pos-contracts/blob/main/contracts/staking/validatorShare/ValidatorShare.sol
|
|
21
|
+
export const VALIDATOR_SHARE_ABI = [
|
|
22
|
+
{
|
|
23
|
+
type: 'function',
|
|
24
|
+
name: 'buyVoucherPOL',
|
|
25
|
+
inputs: [
|
|
26
|
+
{ name: '_amount', type: 'uint256', internalType: 'uint256' },
|
|
27
|
+
{ name: '_minSharesToMint', type: 'uint256', internalType: 'uint256' }
|
|
28
|
+
],
|
|
29
|
+
outputs: [{ name: 'amountToDeposit', type: 'uint256', internalType: 'uint256' }],
|
|
30
|
+
stateMutability: 'nonpayable'
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
type: 'function',
|
|
34
|
+
name: 'sellVoucher_newPOL',
|
|
35
|
+
inputs: [
|
|
36
|
+
{ name: 'claimAmount', type: 'uint256', internalType: 'uint256' },
|
|
37
|
+
{ name: 'maximumSharesToBurn', type: 'uint256', internalType: 'uint256' }
|
|
38
|
+
],
|
|
39
|
+
outputs: [],
|
|
40
|
+
stateMutability: 'nonpayable'
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: 'function',
|
|
44
|
+
name: 'unstakeClaimTokens_newPOL',
|
|
45
|
+
inputs: [{ name: 'unbondNonce', type: 'uint256', internalType: 'uint256' }],
|
|
46
|
+
outputs: [],
|
|
47
|
+
stateMutability: 'nonpayable'
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
type: 'function',
|
|
51
|
+
name: 'withdrawRewardsPOL',
|
|
52
|
+
inputs: [],
|
|
53
|
+
outputs: [],
|
|
54
|
+
stateMutability: 'nonpayable'
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
type: 'function',
|
|
58
|
+
name: 'restakePOL',
|
|
59
|
+
inputs: [],
|
|
60
|
+
outputs: [
|
|
61
|
+
{ name: 'amountRestaked', type: 'uint256', internalType: 'uint256' },
|
|
62
|
+
{ name: 'liquidReward', type: 'uint256', internalType: 'uint256' }
|
|
63
|
+
],
|
|
64
|
+
stateMutability: 'nonpayable'
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
type: 'function',
|
|
68
|
+
name: 'getTotalStake',
|
|
69
|
+
inputs: [{ name: 'user', type: 'address', internalType: 'address' }],
|
|
70
|
+
outputs: [
|
|
71
|
+
{ name: '', type: 'uint256', internalType: 'uint256' },
|
|
72
|
+
{ name: '', type: 'uint256', internalType: 'uint256' }
|
|
73
|
+
],
|
|
74
|
+
stateMutability: 'view'
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
type: 'function',
|
|
78
|
+
name: 'unbondNonces',
|
|
79
|
+
inputs: [{ name: '', type: 'address', internalType: 'address' }],
|
|
80
|
+
outputs: [{ name: '', type: 'uint256', internalType: 'uint256' }],
|
|
81
|
+
stateMutability: 'view'
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
type: 'function',
|
|
85
|
+
name: 'unbonds_new',
|
|
86
|
+
inputs: [
|
|
87
|
+
{ name: '', type: 'address', internalType: 'address' },
|
|
88
|
+
{ name: '', type: 'uint256', internalType: 'uint256' }
|
|
89
|
+
],
|
|
90
|
+
outputs: [
|
|
91
|
+
{ name: 'shares', type: 'uint256', internalType: 'uint256' },
|
|
92
|
+
{ name: 'withdrawEpoch', type: 'uint256', internalType: 'uint256' }
|
|
93
|
+
],
|
|
94
|
+
stateMutability: 'view'
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
type: 'function',
|
|
98
|
+
name: 'getLiquidRewards',
|
|
99
|
+
inputs: [{ name: 'user', type: 'address', internalType: 'address' }],
|
|
100
|
+
outputs: [{ name: '', type: 'uint256', internalType: 'uint256' }],
|
|
101
|
+
stateMutability: 'view'
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
type: 'function',
|
|
105
|
+
name: 'validatorId',
|
|
106
|
+
inputs: [],
|
|
107
|
+
outputs: [{ name: '', type: 'uint256', internalType: 'uint256' }],
|
|
108
|
+
stateMutability: 'view'
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
type: 'function',
|
|
112
|
+
name: 'withdrawExchangeRate',
|
|
113
|
+
inputs: [],
|
|
114
|
+
outputs: [{ name: '', type: 'uint256', internalType: 'uint256' }],
|
|
115
|
+
stateMutability: 'view'
|
|
116
|
+
}
|
|
117
|
+
];
|
|
118
|
+
// Exchange rate precision constants from the ValidatorShare contract
|
|
119
|
+
// Reference: https://github.com/0xPolygon/pos-contracts/blob/main/contracts/staking/validatorShare/ValidatorShare.sol
|
|
120
|
+
export const EXCHANGE_RATE_PRECISION = 100n;
|
|
121
|
+
export const EXCHANGE_RATE_HIGH_PRECISION = 10n ** 29n;
|
|
122
|
+
// Reference: https://github.com/0xPolygon/pos-contracts/blob/main/contracts/staking/stakeManager/StakeManager.sol
|
|
123
|
+
export const STAKE_MANAGER_ABI = [
|
|
124
|
+
{
|
|
125
|
+
type: 'function',
|
|
126
|
+
name: 'epoch',
|
|
127
|
+
inputs: [],
|
|
128
|
+
outputs: [{ name: '', type: 'uint256', internalType: 'uint256' }],
|
|
129
|
+
stateMutability: 'view'
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
type: 'function',
|
|
133
|
+
name: 'withdrawalDelay',
|
|
134
|
+
inputs: [],
|
|
135
|
+
outputs: [{ name: '', type: 'uint256', internalType: 'uint256' }],
|
|
136
|
+
stateMutability: 'view'
|
|
137
|
+
}
|
|
138
|
+
];
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { PolygonStaker } from './staker';
|
|
2
|
+
export { PolygonNetworkConfig, Transaction, PolygonTxStatus, StakeInfo, UnbondInfo } from './types';
|
|
3
|
+
export { NETWORK_CONTRACTS, CHORUS_ONE_POLYGON_VALIDATORS, VALIDATOR_SHARE_ABI, STAKE_MANAGER_ABI, EXCHANGE_RATE_PRECISION, EXCHANGE_RATE_HIGH_PRECISION } from './constants';
|
|
4
|
+
export type { PolygonNetworks, NetworkContracts } from './constants';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { keccak256, toHex } from 'viem';
|
|
2
|
+
const DEFAULT_REFERRER = 'sdk-chorusone-staking';
|
|
3
|
+
const REFERRER_MARKER = 'c1c1';
|
|
4
|
+
const encodeReferrer = (referrer) => {
|
|
5
|
+
const hash = keccak256(toHex(referrer));
|
|
6
|
+
return `0x${REFERRER_MARKER}${hash.slice(2, 8)}`;
|
|
7
|
+
};
|
|
8
|
+
export const appendReferrerTracking = (data, referrer) => {
|
|
9
|
+
const encoded = encodeReferrer(referrer ?? DEFAULT_REFERRER);
|
|
10
|
+
return `${data}${encoded.slice(2)}`;
|
|
11
|
+
};
|