@wireio/stake 0.0.6 → 0.1.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/README.md +260 -13
- package/lib/stake.browser.js +4861 -4218
- package/lib/stake.browser.js.map +1 -1
- package/lib/stake.d.ts +434 -6484
- package/lib/stake.js +5059 -4371
- package/lib/stake.js.map +1 -1
- package/lib/stake.m.js +4861 -4218
- package/lib/stake.m.js.map +1 -1
- package/package.json +2 -2
- package/src/assets/solana/idl/liqsol_core.json +4239 -0
- package/src/assets/solana/idl/liqsol_token.json +183 -0
- package/src/assets/solana/idl/validator_leaderboard.json +296 -250
- package/src/assets/solana/types/liqsol_core.ts +4245 -0
- package/src/assets/solana/types/liqsol_token.ts +189 -0
- package/src/assets/solana/types/validator_leaderboard.ts +296 -250
- package/src/index.ts +2 -5
- package/src/networks/ethereum/contract.ts +138 -36
- package/src/networks/ethereum/ethereum.ts +167 -38
- package/src/networks/ethereum/types.ts +32 -1
- package/src/networks/solana/clients/deposit.client.ts +92 -139
- package/src/networks/solana/clients/distribution.client.ts +302 -178
- package/src/networks/solana/clients/leaderboard.client.ts +40 -160
- package/src/networks/solana/constants.ts +238 -69
- package/src/networks/solana/program.ts +27 -93
- package/src/networks/solana/solana.ts +181 -36
- package/src/networks/solana/types.ts +47 -0
- package/src/networks/solana/utils.ts +522 -93
- package/src/scripts/fetch-artifacts.sh +24 -0
- package/src/scripts/tsconfig.json +17 -0
- package/src/staker/staker.ts +35 -30
- package/src/staker/types.ts +25 -22
- package/src/assets/solana/idl/deposit.json +0 -260
- package/src/assets/solana/idl/distribution.json +0 -736
- package/src/assets/solana/idl/liq_sol_token.json +0 -275
- package/src/assets/solana/idl/stake_controller.json +0 -1788
- package/src/assets/solana/idl/stake_registry.json +0 -435
- package/src/assets/solana/idl/treasury.json +0 -336
- package/src/assets/solana/idl/validator_registry.json +0 -418
- package/src/assets/solana/idl/yield_oracle.json +0 -32
- package/src/assets/solana/types/deposit.ts +0 -266
- package/src/assets/solana/types/distribution.ts +0 -742
- package/src/assets/solana/types/liq_sol_token.ts +0 -281
- package/src/assets/solana/types/stake_controller.ts +0 -1794
- package/src/assets/solana/types/stake_registry.ts +0 -441
- package/src/assets/solana/types/treasury.ts +0 -342
- package/src/assets/solana/types/validator_registry.ts +0 -424
- package/src/assets/solana/types/yield_oracle.ts +0 -38
- package/src/utils.ts +0 -9
|
@@ -1,179 +1,59 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import { PublicKey, Transaction, TransactionInstruction, SystemProgram, VersionedTransaction } from '@solana/web3.js';
|
|
4
|
-
import {
|
|
5
|
-
deriveLeaderboardHeadPDA,
|
|
6
|
-
deriveValidatorRecordPDA,
|
|
7
|
-
deriveTop10CachePDA,
|
|
8
|
-
} from '../utils';
|
|
9
|
-
import { VALIDATOR_LEADERBOARD_PROGRAM_ID, ValidatorLeaderboard, ValidatorLeaderboardIDL } from '../constants';
|
|
10
|
-
|
|
11
|
-
export class ValidatorLeaderboardClient {
|
|
12
|
-
constructor(private provider: AnchorProvider) { }
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Wrapped Anchor Program for ValidatorLeaderboard
|
|
16
|
-
*/
|
|
17
|
-
private get program(): Program<ValidatorLeaderboard> {
|
|
18
|
-
const idlWithAddress = {
|
|
19
|
-
...JSON.parse(JSON.stringify(ValidatorLeaderboardIDL)),
|
|
20
|
-
address: VALIDATOR_LEADERBOARD_PROGRAM_ID.toString(),
|
|
21
|
-
};
|
|
22
|
-
return new Program(idlWithAddress as any, this.provider) as Program<ValidatorLeaderboard>;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** Derive the PDA for the leaderboard head */
|
|
26
|
-
deriveHeadPDA(): PublicKey {
|
|
27
|
-
return deriveLeaderboardHeadPDA()[0];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** Derive the PDA for a given validator record */
|
|
31
|
-
deriveRecordPDA(voteAccount: PublicKey): PublicKey {
|
|
32
|
-
return deriveValidatorRecordPDA(voteAccount)[0];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Build the initialize instruction as a Transaction
|
|
37
|
-
*/
|
|
38
|
-
async buildInitializeTransaction(authority: PublicKey): Promise<Transaction> {
|
|
39
|
-
const [headPda] = deriveLeaderboardHeadPDA();
|
|
40
|
-
const ix = await this.program.methods
|
|
41
|
-
.initialize()
|
|
42
|
-
.accounts({
|
|
43
|
-
authority,
|
|
44
|
-
leaderboardHead: headPda,
|
|
45
|
-
systemProgram: SystemProgram.programId,
|
|
46
|
-
} as any)
|
|
47
|
-
.instruction();
|
|
48
|
-
|
|
49
|
-
return new Transaction().add(ix);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Build an updateValidator transaction
|
|
54
|
-
*/
|
|
55
|
-
async buildUpdateValidatorTransaction(params: {
|
|
56
|
-
authority: PublicKey;
|
|
57
|
-
registrant: PublicKey;
|
|
58
|
-
voteAccount: PublicKey;
|
|
59
|
-
vpp: number;
|
|
60
|
-
insertAfter?: PublicKey;
|
|
61
|
-
insertBefore?: PublicKey;
|
|
62
|
-
currentPrev?: PublicKey;
|
|
63
|
-
currentNext?: PublicKey;
|
|
64
|
-
}): Promise<Transaction> {
|
|
65
|
-
const { authority, registrant, voteAccount, vpp, insertAfter, insertBefore, currentPrev, currentNext } = params;
|
|
66
|
-
const [headPda] = deriveLeaderboardHeadPDA();
|
|
67
|
-
const [recPda] = deriveValidatorRecordPDA(voteAccount);
|
|
68
|
-
|
|
69
|
-
const accounts: any = {
|
|
70
|
-
registrant,
|
|
71
|
-
voteAccount,
|
|
72
|
-
validatorRecord: recPda,
|
|
73
|
-
leaderboardHead: headPda,
|
|
74
|
-
systemProgram: SystemProgram.programId,
|
|
75
|
-
...(insertAfter && { insertAfter }),
|
|
76
|
-
...(insertBefore && { insertBefore }),
|
|
77
|
-
...(currentPrev && { currentPrev }),
|
|
78
|
-
...(currentNext && { currentNext }),
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const ix = await this.program.methods
|
|
82
|
-
.updateValidator(new BN(vpp))
|
|
83
|
-
.accounts(accounts)
|
|
84
|
-
.instruction();
|
|
1
|
+
import { AnchorProvider, Program } from '@coral-xyz/anchor';
|
|
2
|
+
import { PublicKey } from '@solana/web3.js';
|
|
85
3
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
async buildUpdateTop10CacheTransaction(params: {
|
|
93
|
-
authority: PublicKey;
|
|
94
|
-
top10Validators: PublicKey[];
|
|
95
|
-
}): Promise<Transaction> {
|
|
96
|
-
const { authority, top10Validators } = params;
|
|
97
|
-
if (top10Validators.length !== 10) {
|
|
98
|
-
throw new Error('Must supply exactly 10 validators');
|
|
99
|
-
}
|
|
100
|
-
const [cachePda] = deriveTop10CachePDA();
|
|
101
|
-
const ix = await this.program.methods
|
|
102
|
-
.updateTop10Cache(top10Validators)
|
|
103
|
-
.accounts({ authority, cache: cachePda, systemProgram: SystemProgram.programId } as any)
|
|
104
|
-
.instruction();
|
|
4
|
+
import { SolanaProgramService } from '../program';
|
|
5
|
+
import type { ValidatorLeaderboard } from '../../../assets/solana/types/validator_leaderboard';
|
|
6
|
+
import {
|
|
7
|
+
deriveLeaderboardStatePda,
|
|
8
|
+
deriveValidatorRecordPda,
|
|
9
|
+
} from '../constants';
|
|
105
10
|
|
|
106
|
-
|
|
107
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Simple read client for the validator_leaderboard program.
|
|
13
|
+
*
|
|
14
|
+
* Adjust account names/fields to match your IDL (state, validatorRecord, etc).
|
|
15
|
+
*/
|
|
16
|
+
export class LeaderboardClient {
|
|
17
|
+
private program: Program<ValidatorLeaderboard>;
|
|
108
18
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
async getCachedTop10(): Promise<PublicKey[]> {
|
|
113
|
-
const [cachePda] = deriveTop10CachePDA();
|
|
114
|
-
return this.program.methods
|
|
115
|
-
.getCachedTop10()
|
|
116
|
-
.accounts({ cache: cachePda } as any)
|
|
117
|
-
.view();
|
|
19
|
+
constructor(private provider: AnchorProvider) {
|
|
20
|
+
const svc = new SolanaProgramService(provider);
|
|
21
|
+
this.program = svc.getProgram('validatorLeaderboard');
|
|
118
22
|
}
|
|
119
23
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
*/
|
|
123
|
-
async getLeaderboard(): Promise<PublicKey[]> {
|
|
124
|
-
const [headPda] = deriveLeaderboardHeadPDA();
|
|
125
|
-
let headAccount;
|
|
24
|
+
async getState(): Promise<any | null> {
|
|
25
|
+
const pda = deriveLeaderboardStatePda();
|
|
126
26
|
try {
|
|
127
|
-
|
|
27
|
+
// Assumes account name "leaderboardState"
|
|
28
|
+
return await this.program.account.leaderboardState.fetch(pda);
|
|
128
29
|
} catch {
|
|
129
|
-
return
|
|
130
|
-
}
|
|
131
|
-
const result: PublicKey[] = [];
|
|
132
|
-
let cursor: PublicKey = headAccount.nextValidator;
|
|
133
|
-
while (cursor && !cursor.equals(PublicKey.default)) {
|
|
134
|
-
result.push(cursor);
|
|
135
|
-
const rec = await this.program.account.validatorRecord.fetch(cursor);
|
|
136
|
-
cursor = rec.nextValidator;
|
|
30
|
+
return null;
|
|
137
31
|
}
|
|
138
|
-
return result;
|
|
139
32
|
}
|
|
140
33
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
*/
|
|
144
|
-
async getRecord(voteAccount: PublicKey): Promise<any | null> {
|
|
145
|
-
const [recPda] = deriveValidatorRecordPDA(voteAccount);
|
|
34
|
+
async getValidatorRecord(voteAccount: PublicKey): Promise<any | null> {
|
|
35
|
+
const pda = deriveValidatorRecordPda(voteAccount);
|
|
146
36
|
try {
|
|
147
|
-
|
|
37
|
+
// Assumes account name "validatorRecord"
|
|
38
|
+
return await this.program.account.validatorRecord.fetchNullable(pda);
|
|
148
39
|
} catch {
|
|
149
40
|
return null;
|
|
150
41
|
}
|
|
151
42
|
}
|
|
152
43
|
|
|
153
44
|
/**
|
|
154
|
-
*
|
|
155
|
-
|
|
156
|
-
async sendTransaction(
|
|
157
|
-
tx: Transaction,
|
|
158
|
-
signers: import('@solana/web3.js').Signer[] = []
|
|
159
|
-
): Promise<string> {
|
|
160
|
-
tx.feePayer = this.provider.wallet.publicKey;
|
|
161
|
-
const { blockhash } = await this.provider.connection.getLatestBlockhash();
|
|
162
|
-
tx.recentBlockhash = blockhash;
|
|
163
|
-
return this.provider.sendAndConfirm(tx, signers);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Simulate a single-IX Transaction; returns any err + compute units consumed
|
|
45
|
+
* Convenience helper to fetch and sort top validators by score.
|
|
46
|
+
* Assumes `validatorRecord` has a numeric `score` field in the IDL.
|
|
168
47
|
*/
|
|
169
|
-
async
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
48
|
+
async getTopValidators(limit = 20): Promise<any[]> {
|
|
49
|
+
const records = await (this.program.account as any).validatorRecord.all();
|
|
50
|
+
const sorted = (records as Array<{ publicKey: PublicKey; account: any }>).sort(
|
|
51
|
+
(a, b) => {
|
|
52
|
+
const sa = BigInt(a.account.score?.toString?.() ?? '0');
|
|
53
|
+
const sb = BigInt(b.account.score?.toString?.() ?? '0');
|
|
54
|
+
return sb > sa ? 1 : sb < sa ? -1 : 0;
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
return sorted.slice(0, limit);
|
|
178
58
|
}
|
|
179
|
-
}
|
|
59
|
+
}
|
|
@@ -1,73 +1,242 @@
|
|
|
1
1
|
// src/networks/solana/constants.ts
|
|
2
|
+
import { PublicKey, StakeProgram } from '@solana/web3.js';
|
|
2
3
|
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
4
|
+
import liqsolCoreIDL from "../../assets/solana/idl/liqsol_core.json";
|
|
5
|
+
import liqSolTokenIDL from "../../assets/solana/idl/liqsol_token.json";
|
|
6
|
+
import validatorLeaderboardIDL from "../../assets/solana/idl/validator_leaderboard.json";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* ---------------------------------------------------------------------------
|
|
10
|
+
* PROGRAM IDS
|
|
11
|
+
* ---------------------------------------------------------------------------
|
|
12
|
+
*
|
|
13
|
+
* These should match:
|
|
14
|
+
* - `metadata.address` in your Anchor IDLs under src/assets/solana/idl/*.json
|
|
15
|
+
* - The program IDs printed by your deploy scripts
|
|
16
|
+
*/
|
|
17
|
+
// Extract program IDs from IDL files
|
|
18
|
+
export const PROGRAM_IDS = {
|
|
19
|
+
LIQSOL_CORE: new PublicKey(liqsolCoreIDL.address),
|
|
20
|
+
LIQSOL_TOKEN: new PublicKey(liqSolTokenIDL.address),
|
|
21
|
+
VALIDATOR_LEADERBOARD: new PublicKey(validatorLeaderboardIDL.address),
|
|
22
|
+
} as const;
|
|
23
|
+
|
|
24
|
+
// Export individual program IDs for convenience
|
|
25
|
+
export const {
|
|
26
|
+
LIQSOL_CORE,
|
|
27
|
+
LIQSOL_TOKEN,
|
|
28
|
+
VALIDATOR_LEADERBOARD,
|
|
29
|
+
} = PROGRAM_IDS;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* ---------------------------------------------------------------------------
|
|
33
|
+
* PDA SEEDS (must match on-chain programs)
|
|
34
|
+
* ---------------------------------------------------------------------------
|
|
35
|
+
*
|
|
36
|
+
* These strings are baked into the on-chain programs and are already used in
|
|
37
|
+
* your test utils. We centralize them here so all clients share them.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
export const PDA_SEEDS = {
|
|
41
|
+
// liqsol_core: deposit / stake controller
|
|
42
|
+
DEPOSIT_AUTHORITY: 'deposit_authority',
|
|
43
|
+
VAULT: 'vault',
|
|
44
|
+
RESERVE_POOL: 'reserve_pool',
|
|
45
|
+
STAKE_CONTROLLER_STATE: 'stake_controller',
|
|
46
|
+
PAYOUT_STATE: 'payout-state',
|
|
47
|
+
|
|
48
|
+
// liqsol_token: mint + bucket
|
|
49
|
+
LIQSOL_MINT: 'liqsol_mint',
|
|
50
|
+
LIQSOL_MINT_AUTHORITY: 'mint_authority',
|
|
51
|
+
BUCKET_AUTHORITY: 'liqsol_bucket',
|
|
52
|
+
|
|
53
|
+
// distribution program (embedded in liqsol_core)
|
|
54
|
+
DISTRIBUTION_STATE: 'distribution_state',
|
|
55
|
+
USER_RECORD: 'user_record',
|
|
56
|
+
|
|
57
|
+
// pay-rate history
|
|
58
|
+
PAY_RATE_HISTORY: 'pay_rate_history',
|
|
59
|
+
|
|
60
|
+
// validator leaderboard (state + records)
|
|
61
|
+
LEADERBOARD_STATE: 'leaderboard_state',
|
|
62
|
+
VALIDATOR_RECORD: 'validator',
|
|
63
|
+
GLOBAL_STAKE_INFO: 'global_stake_info',
|
|
64
|
+
} as const;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Helpers for PDA derivation so clients don’t duplicate logic.
|
|
68
|
+
*/
|
|
69
|
+
|
|
70
|
+
export const deriveLiqsolMintPda = () =>
|
|
71
|
+
PublicKey.findProgramAddressSync(
|
|
72
|
+
[Buffer.from(PDA_SEEDS.LIQSOL_MINT)],
|
|
73
|
+
PROGRAM_IDS.LIQSOL_TOKEN,
|
|
74
|
+
)[0];
|
|
75
|
+
|
|
76
|
+
export const deriveLiqsolMintAuthorityPda = () =>
|
|
77
|
+
PublicKey.findProgramAddressSync(
|
|
78
|
+
[Buffer.from(PDA_SEEDS.LIQSOL_MINT_AUTHORITY)],
|
|
79
|
+
PROGRAM_IDS.LIQSOL_TOKEN,
|
|
80
|
+
)[0];
|
|
81
|
+
|
|
82
|
+
export const deriveDepositAuthorityPda = () =>
|
|
83
|
+
PublicKey.findProgramAddressSync(
|
|
84
|
+
[Buffer.from(PDA_SEEDS.DEPOSIT_AUTHORITY)],
|
|
85
|
+
PROGRAM_IDS.LIQSOL_CORE,
|
|
86
|
+
)[0];
|
|
87
|
+
|
|
88
|
+
export const deriveVaultPda = () =>
|
|
89
|
+
PublicKey.findProgramAddressSync(
|
|
90
|
+
[Buffer.from(PDA_SEEDS.VAULT)],
|
|
91
|
+
PROGRAM_IDS.LIQSOL_CORE,
|
|
92
|
+
)[0];
|
|
93
|
+
|
|
94
|
+
export const deriveReservePoolPda = () =>
|
|
95
|
+
PublicKey.findProgramAddressSync(
|
|
96
|
+
[Buffer.from(PDA_SEEDS.RESERVE_POOL)],
|
|
97
|
+
PROGRAM_IDS.LIQSOL_CORE,
|
|
98
|
+
)[0];
|
|
99
|
+
|
|
100
|
+
export const deriveStakeControllerStatePda = () =>
|
|
101
|
+
PublicKey.findProgramAddressSync(
|
|
102
|
+
[Buffer.from(PDA_SEEDS.STAKE_CONTROLLER_STATE)],
|
|
103
|
+
PROGRAM_IDS.LIQSOL_CORE,
|
|
104
|
+
)[0];
|
|
105
|
+
|
|
106
|
+
export const derivePayoutStatePda = () =>
|
|
107
|
+
PublicKey.findProgramAddressSync(
|
|
108
|
+
[Buffer.from(PDA_SEEDS.PAYOUT_STATE)],
|
|
109
|
+
PROGRAM_IDS.LIQSOL_CORE,
|
|
110
|
+
)[0];
|
|
111
|
+
|
|
112
|
+
export const deriveBucketAuthorityPda = () =>
|
|
113
|
+
PublicKey.findProgramAddressSync(
|
|
114
|
+
[Buffer.from(PDA_SEEDS.BUCKET_AUTHORITY)],
|
|
115
|
+
PROGRAM_IDS.LIQSOL_CORE,
|
|
116
|
+
)[0];
|
|
117
|
+
|
|
118
|
+
export const deriveDistributionStatePda = () =>
|
|
119
|
+
PublicKey.findProgramAddressSync(
|
|
120
|
+
[Buffer.from(PDA_SEEDS.DISTRIBUTION_STATE)],
|
|
121
|
+
PROGRAM_IDS.LIQSOL_CORE,
|
|
122
|
+
)[0];
|
|
123
|
+
|
|
124
|
+
export const deriveUserRecordPda = (user: PublicKey) =>
|
|
125
|
+
PublicKey.findProgramAddressSync(
|
|
126
|
+
[Buffer.from(PDA_SEEDS.USER_RECORD), user.toBuffer()],
|
|
127
|
+
PROGRAM_IDS.LIQSOL_CORE,
|
|
128
|
+
)[0];
|
|
129
|
+
|
|
130
|
+
export const derivePayRateHistoryPda = () =>
|
|
131
|
+
PublicKey.findProgramAddressSync(
|
|
132
|
+
[Buffer.from(PDA_SEEDS.PAY_RATE_HISTORY)],
|
|
133
|
+
PROGRAM_IDS.LIQSOL_CORE,
|
|
134
|
+
)[0];
|
|
135
|
+
|
|
136
|
+
// export const deriveGlobalStakeInfoPda = () =>
|
|
137
|
+
// PublicKey.findProgramAddressSync(
|
|
138
|
+
// [Buffer.from(PDA_SEEDS.GLOBAL_STAKE_INFO)],
|
|
139
|
+
// PROGRAM_IDS.LIQSOL_CORE,
|
|
140
|
+
// )[0];
|
|
141
|
+
|
|
142
|
+
export const deriveLeaderboardStatePda = () =>
|
|
143
|
+
PublicKey.findProgramAddressSync(
|
|
144
|
+
[Buffer.from(PDA_SEEDS.LEADERBOARD_STATE)],
|
|
145
|
+
PROGRAM_IDS.VALIDATOR_LEADERBOARD,
|
|
146
|
+
)[0];
|
|
147
|
+
|
|
148
|
+
export const deriveValidatorRecordPda = (voteAccount: PublicKey) =>
|
|
149
|
+
PublicKey.findProgramAddressSync(
|
|
150
|
+
[Buffer.from(PDA_SEEDS.VALIDATOR_RECORD), voteAccount.toBuffer()],
|
|
151
|
+
PROGRAM_IDS.VALIDATOR_LEADERBOARD,
|
|
152
|
+
)[0];
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Stake controller vault PDA (reserve pool SOL vault).
|
|
156
|
+
* This is the same as VAULT, but named more explicitly for SDK callers.
|
|
157
|
+
*/
|
|
158
|
+
export const deriveStakeControllerVaultPda = () =>
|
|
159
|
+
PublicKey.findProgramAddressSync(
|
|
160
|
+
[Buffer.from(PDA_SEEDS.VAULT)],
|
|
161
|
+
PROGRAM_IDS.LIQSOL_CORE,
|
|
162
|
+
)[0];
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Ephemeral stake account address used per-deposit.
|
|
166
|
+
* On-chain convention: seed = `ephemeral_<u32>` under StakeProgram.programId.
|
|
167
|
+
*/
|
|
168
|
+
export const deriveEphemeralStakeAddress = async (
|
|
169
|
+
user: PublicKey,
|
|
170
|
+
seed: any,
|
|
171
|
+
): Promise<PublicKey> => {
|
|
172
|
+
const seedStr = `ephemeral_${seed}`;
|
|
173
|
+
return await PublicKey.createWithSeed(user, seedStr, StakeProgram.programId);
|
|
48
174
|
};
|
|
49
175
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
export const
|
|
60
|
-
|
|
61
|
-
//
|
|
62
|
-
export const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
export const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* ---------------------------------------------------------------------------
|
|
180
|
+
* ECONOMICS & MATH CONSTANTS
|
|
181
|
+
* ---------------------------------------------------------------------------
|
|
182
|
+
*/
|
|
183
|
+
|
|
184
|
+
// Same scale factor used on-chain for pay-rate math
|
|
185
|
+
export const PAY_RATE_SCALE_FACTOR = BigInt(1_000_000_000_000); // 10^12
|
|
186
|
+
|
|
187
|
+
// Default pay rate fallback used in tests & utils
|
|
188
|
+
export const DEFAULT_AVERAGE_PAY_RATE = BigInt(191_780_821);
|
|
189
|
+
|
|
190
|
+
// How many history entries to average when computing expected fee
|
|
191
|
+
export const DEFAULT_PAY_RATE_LOOKBACK = 5;
|
|
192
|
+
|
|
193
|
+
// Rent exemption for ephemeral stake account (lamports)
|
|
194
|
+
// Mirrors EPHEMERAL_RENT_EXEMPTION = 2_282_880 used in tests
|
|
195
|
+
export const EPHEMERAL_RENT_EXEMPTION = 2_282_880;
|
|
196
|
+
|
|
197
|
+
// For convenience: lamports <-> SOL helpers (no RPC dependency)
|
|
198
|
+
export const LAMPORTS_PER_SOL = 1_000_000_000;
|
|
199
|
+
|
|
200
|
+
export const lamportsToSol = (lamports: number | bigint): number =>
|
|
201
|
+
Number(lamports) / LAMPORTS_PER_SOL;
|
|
202
|
+
|
|
203
|
+
export const solToLamports = (sol: number): number =>
|
|
204
|
+
Math.round(sol * LAMPORTS_PER_SOL);
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* ---------------------------------------------------------------------------
|
|
208
|
+
* CLUSTER / ENVIRONMENT CONFIG (optional but handy)
|
|
209
|
+
* ---------------------------------------------------------------------------
|
|
210
|
+
*/
|
|
211
|
+
|
|
212
|
+
export type SolanaCluster = 'localnet' | 'devnet' | 'mainnet';
|
|
213
|
+
|
|
214
|
+
// export interface SolanaStakeProgramAddresses {
|
|
215
|
+
// liqsolCore: PublicKey;
|
|
216
|
+
// liqsolToken: PublicKey;
|
|
217
|
+
// validatorLeaderboard: PublicKey;
|
|
218
|
+
// }
|
|
219
|
+
|
|
220
|
+
// export const PROGRAMS_BY_CLUSTER: Record<SolanaCluster, SolanaStakeProgramAddresses> = {
|
|
221
|
+
// localnet: {
|
|
222
|
+
// liqsolCore: PROGRAM_IDS.LIQSOL_CORE,
|
|
223
|
+
// liqsolToken: PROGRAM_IDS.LIQSOL_TOKEN,
|
|
224
|
+
// validatorLeaderboard: PROGRAM_IDS.VALIDATOR_LEADERBOARD,
|
|
225
|
+
// },
|
|
226
|
+
// devnet: {
|
|
227
|
+
// liqsolCore: PROGRAM_IDS.LIQSOL_CORE,
|
|
228
|
+
// liqsolToken: PROGRAM_IDS.LIQSOL_TOKEN,
|
|
229
|
+
// validatorLeaderboard: PROGRAM_IDS.VALIDATOR_LEADERBOARD,
|
|
230
|
+
// },
|
|
231
|
+
// mainnet: {
|
|
232
|
+
// liqsolCore: PROGRAM_IDS.LIQSOL_CORE,
|
|
233
|
+
// liqsolToken: PROGRAM_IDS.LIQSOL_TOKEN,
|
|
234
|
+
// validatorLeaderboard: PROGRAM_IDS.VALIDATOR_LEADERBOARD,
|
|
235
|
+
// },
|
|
236
|
+
// };
|
|
237
|
+
|
|
238
|
+
// export const DEFAULT_CLUSTER: SolanaCluster = 'localnet';
|
|
239
|
+
|
|
240
|
+
// export function getProgramIds(cluster: SolanaCluster = DEFAULT_CLUSTER): SolanaStakeProgramAddresses {
|
|
241
|
+
// return PROGRAMS_BY_CLUSTER[cluster];
|
|
242
|
+
// }
|