@wireio/stake 0.0.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 (48) hide show
  1. package/LICENSE.md +114 -0
  2. package/README.md +28 -0
  3. package/lib/stake.browser.js +6875 -0
  4. package/lib/stake.browser.js.map +1 -0
  5. package/lib/stake.d.ts +6759 -0
  6. package/lib/stake.js +7178 -0
  7. package/lib/stake.js.map +1 -0
  8. package/lib/stake.m.js +6875 -0
  9. package/lib/stake.m.js.map +1 -0
  10. package/package.json +102 -0
  11. package/src/assets/ethereum/ABI/token/ERC1155Token.sol/ERC1155Token.dbg.json +4 -0
  12. package/src/assets/ethereum/ABI/token/ERC1155Token.sol/ERC1155Token.json +472 -0
  13. package/src/assets/ethereum/ABI/token/ERC20Token.sol/ERC20Token.dbg.json +4 -0
  14. package/src/assets/ethereum/ABI/token/ERC20Token.sol/ERC20Token.json +330 -0
  15. package/src/assets/ethereum/ABI/token/ERC721Token.sol/ERC721Token.dbg.json +4 -0
  16. package/src/assets/ethereum/ABI/token/ERC721Token.sol/ERC721Token.json +449 -0
  17. package/src/assets/solana/idl/deposit.json +260 -0
  18. package/src/assets/solana/idl/distribution.json +736 -0
  19. package/src/assets/solana/idl/liq_sol_token.json +275 -0
  20. package/src/assets/solana/idl/stake_controller.json +1788 -0
  21. package/src/assets/solana/idl/stake_registry.json +435 -0
  22. package/src/assets/solana/idl/treasury.json +336 -0
  23. package/src/assets/solana/idl/validator_leaderboard.json +528 -0
  24. package/src/assets/solana/idl/validator_registry.json +418 -0
  25. package/src/assets/solana/idl/yield_oracle.json +32 -0
  26. package/src/assets/solana/types/deposit.ts +266 -0
  27. package/src/assets/solana/types/distribution.ts +742 -0
  28. package/src/assets/solana/types/liq_sol_token.ts +281 -0
  29. package/src/assets/solana/types/stake_controller.ts +1794 -0
  30. package/src/assets/solana/types/stake_registry.ts +441 -0
  31. package/src/assets/solana/types/treasury.ts +342 -0
  32. package/src/assets/solana/types/validator_leaderboard.ts +534 -0
  33. package/src/assets/solana/types/validator_registry.ts +424 -0
  34. package/src/assets/solana/types/yield_oracle.ts +38 -0
  35. package/src/index.ts +21 -0
  36. package/src/networks/ethereum/contract.ts +167 -0
  37. package/src/networks/ethereum/ethereum.ts +64 -0
  38. package/src/networks/ethereum/types.ts +6 -0
  39. package/src/networks/solana/clients/deposit.client.ts +178 -0
  40. package/src/networks/solana/clients/distribution.client.ts +230 -0
  41. package/src/networks/solana/clients/leaderboard.client.ts +179 -0
  42. package/src/networks/solana/constants.ts +73 -0
  43. package/src/networks/solana/program.ts +113 -0
  44. package/src/networks/solana/solana.ts +84 -0
  45. package/src/networks/solana/utils.ts +122 -0
  46. package/src/staker/staker.ts +38 -0
  47. package/src/staker/types.ts +26 -0
  48. package/src/utils.ts +9 -0
@@ -0,0 +1,6 @@
1
+ export const CONTRACT_NAMES = [
2
+ 'Stake',
3
+ ] as const;
4
+
5
+ export type ContractName = typeof CONTRACT_NAMES[number];
6
+ export type AddressBook = Record<ContractName, string>;
@@ -0,0 +1,178 @@
1
+ import { AnchorProvider } from '@coral-xyz/anchor';
2
+ import { BN } from '@coral-xyz/anchor';
3
+ import {
4
+ PublicKey,
5
+ Transaction,
6
+ SystemProgram,
7
+ SYSVAR_INSTRUCTIONS_PUBKEY,
8
+ SYSVAR_CLOCK_PUBKEY,
9
+ SYSVAR_RENT_PUBKEY,
10
+ SYSVAR_STAKE_HISTORY_PUBKEY,
11
+ StakeProgram,
12
+ ComputeBudgetProgram,
13
+ VersionedTransaction,
14
+ Signer,
15
+ TransactionSignature,
16
+ } from '@solana/web3.js';
17
+ import {
18
+ TOKEN_2022_PROGRAM_ID,
19
+ ASSOCIATED_TOKEN_PROGRAM_ID,
20
+ } from '@solana/spl-token';
21
+
22
+ import {
23
+ deriveDepositAuthorityPDA,
24
+ deriveLiqsolMintAuthorityPDA,
25
+ deriveStakeControllerVaultPDA,
26
+ deriveStakeControllerReservePoolPDA,
27
+ deriveStakeControllerStatePDA,
28
+ deriveDistributionStatePDA,
29
+ deriveUserRecordPDA,
30
+ getUserLiqsolATA,
31
+ } from '../utils';
32
+ import {
33
+ LIQSOL_MINT_ADDRESS,
34
+ TREASURY_WALLET_PDA,
35
+ STAKE_CONTROLLER_PROGRAM_ID,
36
+ LIQSOL_TOKEN_PROGRAM_ID,
37
+ YIELD_ORACLE_PROGRAM_ID,
38
+ DISTRIBUTION_PROGRAM_ID,
39
+ MIN_SOL_TO_PARTICIPATE,
40
+ } from '../constants';
41
+ import { SolanaProgramService } from '../program';
42
+
43
+ /**
44
+ * DepositClient provides methods for building, simulating, and sending deposit transactions
45
+ * to the Solana blockchain using the Anchor framework. It handles the creation of ephemeral
46
+ * stake accounts, derives necessary PDAs and ATAs, and manages transaction construction
47
+ * with compute budget adjustments. This client is designed to facilitate deposits into
48
+ * the Liqsol staking protocol, ensuring all required accounts and instructions are included.
49
+ *
50
+ * @remarks
51
+ * - Uses AnchorProvider for network interactions.
52
+ * - Enforces minimum deposit requirements.
53
+ * - Supports dry-run simulation for transaction debugging.
54
+ * - Provides high-level helper for building and sending deposit transactions.
55
+ */
56
+ export class DepositClient {
57
+ private program = new SolanaProgramService(this.provider);
58
+
59
+ constructor(private provider: AnchorProvider) { }
60
+
61
+ /** Minimum lamports (1 SOL) */
62
+ static readonly MIN_DEPOSIT = MIN_SOL_TO_PARTICIPATE;
63
+
64
+ /**
65
+ * Build the deposit transaction (compute-budget bump + deposit Ix).
66
+ * Returns both the Transaction and the ephemeral stake account Pubkey.
67
+ */
68
+ async buildDepositTx(
69
+ user: PublicKey,
70
+ amount: number
71
+ ): Promise<{ transaction: Transaction; ephemeralStakePubkey: PublicKey }> {
72
+ if (amount < MIN_SOL_TO_PARTICIPATE) {
73
+ throw new Error(
74
+ `Minimum deposit is ${MIN_SOL_TO_PARTICIPATE / 1e9} SOL`
75
+ );
76
+ }
77
+
78
+ // 1) grab your typed Anchor program
79
+ const program = this.program.getProgram('deposit');
80
+
81
+ // 2) PDAs & ATAs
82
+ const userAta = getUserLiqsolATA(user);
83
+ const [depositAuthPDA] = deriveDepositAuthorityPDA();
84
+ const [mintAuthPDA] = deriveLiqsolMintAuthorityPDA();
85
+ const [vaultPDA] = deriveStakeControllerVaultPDA();
86
+ const [reservePoolPDA] = deriveStakeControllerReservePoolPDA();
87
+ const [controllerStatePDA] = deriveStakeControllerStatePDA();
88
+ const [distStatePDA] = deriveDistributionStatePDA();
89
+ const [userRecordPDA] = deriveUserRecordPDA(user);
90
+
91
+ // 3) ephemeral stake account
92
+ const seed = Math.floor(Math.random() * 0xffffffff);
93
+ const ephemeralSeed = `ephemeral_${seed}`;
94
+ const ephemeralStakePubkey = await PublicKey.createWithSeed(
95
+ user,
96
+ ephemeralSeed,
97
+ StakeProgram.programId
98
+ );
99
+
100
+ // 4) build deposit instruction
101
+ const depositIx = await program.methods
102
+ .deposit(new BN(amount), seed)
103
+ .accounts({
104
+ user,
105
+ programAuthority: depositAuthPDA,
106
+ treasuryWallet: TREASURY_WALLET_PDA,
107
+ systemProgram: SystemProgram.programId,
108
+ tokenProgram: TOKEN_2022_PROGRAM_ID,
109
+ associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
110
+ stakeControllerProgram: STAKE_CONTROLLER_PROGRAM_ID,
111
+ liqsolProgram: LIQSOL_TOKEN_PROGRAM_ID,
112
+ yieldOracleProgram: YIELD_ORACLE_PROGRAM_ID,
113
+ stakeProgram: StakeProgram.programId,
114
+ distributionProgram: DISTRIBUTION_PROGRAM_ID,
115
+ liqsolMint: LIQSOL_MINT_ADDRESS,
116
+ userAta,
117
+ liqsolMintAuthority: mintAuthPDA,
118
+ reservePool: reservePoolPDA,
119
+ vault: vaultPDA,
120
+ ephemeralStake: ephemeralStakePubkey,
121
+ controllerState: controllerStatePDA,
122
+ userRecord: userRecordPDA,
123
+ distributionState: distStatePDA,
124
+ instructionsSysvar: SYSVAR_INSTRUCTIONS_PUBKEY,
125
+ clock: SYSVAR_CLOCK_PUBKEY,
126
+ stakeHistory: SYSVAR_STAKE_HISTORY_PUBKEY,
127
+ rent: SYSVAR_RENT_PUBKEY,
128
+ } as any)
129
+ .instruction();
130
+
131
+ // 5) prepend compute-budget bump
132
+ const computeIx = ComputeBudgetProgram.setComputeUnitLimit({
133
+ units: 400_000,
134
+ });
135
+
136
+ const tx = new Transaction().add(computeIx, depositIx);
137
+ return { transaction: tx, ephemeralStakePubkey };
138
+ }
139
+
140
+ /**
141
+ * Simulate (dry-run) a built transaction.
142
+ * Returns any error plus the total compute-units consumed.
143
+ */
144
+ async simulate(
145
+ tx: Transaction
146
+ ): Promise<{ err: any; unitsConsumed: number }> {
147
+ tx.feePayer = this.provider.wallet.publicKey;
148
+ const { blockhash } = await this.provider.connection.getLatestBlockhash();
149
+ tx.recentBlockhash = blockhash;
150
+
151
+ const versioned = new VersionedTransaction(tx.compileMessage());
152
+ const sim = await this.provider.connection.simulateTransaction(
153
+ versioned,
154
+ { sigVerify: false }
155
+ );
156
+ return { err: sim.value.err, unitsConsumed: sim.value.unitsConsumed! };
157
+ }
158
+
159
+ /**
160
+ * High-level “build & send” helper.
161
+ * Returns the confirmed signature.
162
+ */
163
+ async deposit(
164
+ user: PublicKey,
165
+ amount: number,
166
+ signers: Signer[] = []
167
+ ): Promise<TransactionSignature> {
168
+ const { transaction } = await this.buildDepositTx(user, amount);
169
+
170
+ // set feePayer & recent blockhash
171
+ transaction.feePayer = this.provider.wallet.publicKey;
172
+ const { blockhash } = await this.provider.connection.getLatestBlockhash();
173
+ transaction.recentBlockhash = blockhash;
174
+
175
+ // send + confirm
176
+ return this.provider.sendAndConfirm(transaction, signers);
177
+ }
178
+ }
@@ -0,0 +1,230 @@
1
+ // src/solana/clients/DistributionClient.ts
2
+ import { AnchorProvider, Program, BN, web3 } from '@coral-xyz/anchor';
3
+ import {
4
+ PublicKey,
5
+ Transaction,
6
+ TransactionInstruction,
7
+ SystemProgram,
8
+ VersionedTransaction,
9
+ } from '@solana/web3.js';
10
+ import {
11
+ TOKEN_2022_PROGRAM_ID,
12
+ ASSOCIATED_TOKEN_PROGRAM_ID,
13
+ getAssociatedTokenAddressSync,
14
+ } from '@solana/spl-token';
15
+ import {
16
+ DISTRIBUTION_PROGRAM_ID,
17
+ STAKE_CONTROLLER_PROGRAM_ID,
18
+ DistributionIDL,
19
+ Distribution,
20
+ YIELD_ORACLE_PROGRAM_ID,
21
+ LIQSOL_TOKEN_PROGRAM_ID,
22
+ } from '../constants';
23
+ import {
24
+ deriveDistributionStatePDA,
25
+ deriveUserRecordPDA,
26
+ deriveLiqsolMintAuthorityPDA,
27
+ } from '../utils';
28
+
29
+ export class DistributionClient {
30
+ constructor(private provider: AnchorProvider) { }
31
+
32
+ /** Wrapped Anchor Program for Distribution */
33
+ private get program(): Program<Distribution> {
34
+ const idlWithAddress = {
35
+ ...JSON.parse(JSON.stringify(DistributionIDL)),
36
+ address: DISTRIBUTION_PROGRAM_ID.toString(),
37
+ };
38
+ return new Program(idlWithAddress as any, this.provider) as Program<Distribution>;
39
+ }
40
+
41
+ /** Derive the PDA for global distribution state */
42
+ deriveStatePDA(): PublicKey {
43
+ return deriveDistributionStatePDA()[0];
44
+ }
45
+
46
+ /** Derive the PDA for a user’s record */
47
+ deriveUserRecordPDA(user: PublicKey): PublicKey {
48
+ return deriveUserRecordPDA(user)[0];
49
+ }
50
+
51
+ /** Fetch on-chain distribution state */
52
+ async getState(): Promise<any> {
53
+ return this.program.account.distributionState.fetch(this.deriveStatePDA());
54
+ }
55
+
56
+ /** Fetch a user’s record or return null if it doesn’t exist */
57
+ async getUserRecord(user: PublicKey): Promise<any | null> {
58
+ try {
59
+ return await this.program.account.userRecord.fetch(
60
+ this.deriveUserRecordPDA(user)
61
+ );
62
+ } catch {
63
+ return null;
64
+ }
65
+ }
66
+
67
+ /** Build an `initialize` transaction for the distribution program */
68
+ async buildInitializeTransaction(user: PublicKey): Promise<Transaction> {
69
+ const [statePda] = deriveDistributionStatePDA();
70
+ const ix = await this.program.methods
71
+ .initialize()
72
+ .accounts({
73
+ authority: user,
74
+ distributionState: statePda,
75
+ systemProgram: SystemProgram.programId,
76
+ rent: web3.SYSVAR_RENT_PUBKEY,
77
+ } as any)
78
+ .instruction();
79
+
80
+ return new Transaction().add(ix);
81
+ }
82
+
83
+ /** Build an `updateUser` transaction (register or refresh a user record) */
84
+ async buildUpdateUserTransaction(user: PublicKey): Promise<Transaction> {
85
+ const statePda = this.deriveStatePDA();
86
+ const userPda = this.deriveUserRecordPDA(user);
87
+
88
+ // Fetch state to get the liqSOL mint address
89
+ const state: any = await this.getState();
90
+ const liqsolMint: PublicKey = state.liqsolMint;
91
+ const userAta = getAssociatedTokenAddressSync(
92
+ liqsolMint,
93
+ user,
94
+ false,
95
+ TOKEN_2022_PROGRAM_ID,
96
+ ASSOCIATED_TOKEN_PROGRAM_ID
97
+ );
98
+
99
+ const [stakeControllerStatePda] = PublicKey.findProgramAddressSync(
100
+ [Buffer.from('stake_controller')],
101
+ STAKE_CONTROLLER_PROGRAM_ID
102
+ );
103
+
104
+ const ix = await this.program.methods
105
+ .updateUser()
106
+ .accounts({
107
+ user,
108
+ userAta,
109
+ userRecord: userPda,
110
+ authority: user,
111
+ payer: user,
112
+ distributionState: statePda,
113
+ stakeControllerState: stakeControllerStatePda,
114
+ tokenProgram: TOKEN_2022_PROGRAM_ID,
115
+ yieldOracleProgram: YIELD_ORACLE_PROGRAM_ID,
116
+ systemProgram: SystemProgram.programId,
117
+ } as any)
118
+ .instruction();
119
+
120
+ return new Transaction().add(ix);
121
+ }
122
+
123
+ /** Build a `withdraw` transaction */
124
+ async buildWithdrawTransaction(user: PublicKey, amount: number): Promise<Transaction> {
125
+ const statePda = this.deriveStatePDA();
126
+ const userPda = this.deriveUserRecordPDA(user);
127
+
128
+ // Fetch state for the mint
129
+ const state: any = await this.getState();
130
+ const liqsolMint: PublicKey = state.liqsolMint;
131
+ const userAta = getAssociatedTokenAddressSync(
132
+ liqsolMint,
133
+ user,
134
+ false,
135
+ TOKEN_2022_PROGRAM_ID,
136
+ ASSOCIATED_TOKEN_PROGRAM_ID
137
+ );
138
+
139
+ const [stakeControllerStatePda] = PublicKey.findProgramAddressSync(
140
+ [Buffer.from('stake_controller')],
141
+ STAKE_CONTROLLER_PROGRAM_ID
142
+ );
143
+ const [controllerAuthPda] = PublicKey.findProgramAddressSync(
144
+ [Buffer.from('stake_authority')],
145
+ STAKE_CONTROLLER_PROGRAM_ID
146
+ );
147
+
148
+ const ix = await this.program.methods
149
+ .withdraw(new BN(amount))
150
+ .accounts({
151
+ user,
152
+ userAta,
153
+ userRecord: userPda,
154
+ distributionState: statePda,
155
+ liqsolMint,
156
+ tokenProgram: TOKEN_2022_PROGRAM_ID,
157
+ stakeControllerProgram: STAKE_CONTROLLER_PROGRAM_ID,
158
+ stakeControllerState: stakeControllerStatePda,
159
+ controllerAuthority: controllerAuthPda,
160
+ yieldOracleProgram: YIELD_ORACLE_PROGRAM_ID,
161
+ systemProgram: SystemProgram.programId,
162
+ } as any)
163
+ .instruction();
164
+
165
+ return new Transaction().add(ix);
166
+ }
167
+
168
+ /** Build a `claimRewards` transaction */
169
+ async buildClaimRewardsTransaction(user: PublicKey): Promise<Transaction> {
170
+ const statePda = this.deriveStatePDA();
171
+ const userPda = this.deriveUserRecordPDA(user);
172
+
173
+ // Fetch state for the mint
174
+ const state: any = await this.getState();
175
+ const liqsolMint: PublicKey = state.liqsolMint;
176
+ const userAta = getAssociatedTokenAddressSync(
177
+ liqsolMint,
178
+ user,
179
+ false,
180
+ TOKEN_2022_PROGRAM_ID,
181
+ ASSOCIATED_TOKEN_PROGRAM_ID
182
+ );
183
+ const [mintAuthPda] = deriveLiqsolMintAuthorityPDA();
184
+
185
+ const ix = await this.program.methods
186
+ .claimRewards()
187
+ .accounts({
188
+ user,
189
+ userAta,
190
+ userRecord: userPda,
191
+ distributionState: statePda,
192
+ liqsolMint,
193
+ liqsolProgram: LIQSOL_TOKEN_PROGRAM_ID,
194
+ liqsolMintAuthority: mintAuthPda,
195
+ instructionsSysvar: web3.SYSVAR_INSTRUCTIONS_PUBKEY,
196
+ yieldOracleProgram: YIELD_ORACLE_PROGRAM_ID,
197
+ tokenProgram: TOKEN_2022_PROGRAM_ID,
198
+ associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
199
+ systemProgram: SystemProgram.programId,
200
+ } as any)
201
+ .instruction();
202
+
203
+ return new Transaction().add(ix);
204
+ }
205
+
206
+ /** Send & confirm a single-IX transaction; returns the tx signature */
207
+ async sendTransaction(
208
+ tx: Transaction,
209
+ signers: import('@solana/web3.js').Signer[] = []
210
+ ): Promise<string> {
211
+ tx.feePayer = this.provider.wallet.publicKey;
212
+ const { blockhash } = await this.provider.connection.getLatestBlockhash();
213
+ tx.recentBlockhash = blockhash;
214
+ return this.provider.sendAndConfirm(tx, signers);
215
+ }
216
+
217
+ /** Simulate a single-IX transaction; returns error (if any) + compute units used */
218
+ async simulateTransaction(
219
+ tx: Transaction
220
+ ): Promise<{ err: any; unitsConsumed: number }> {
221
+ tx.feePayer = this.provider.wallet.publicKey;
222
+ const { blockhash } = await this.provider.connection.getLatestBlockhash();
223
+ tx.recentBlockhash = blockhash;
224
+ const versioned = new VersionedTransaction(tx.compileMessage());
225
+ const sim = await this.provider.connection.simulateTransaction(versioned, {
226
+ sigVerify: false,
227
+ });
228
+ return { err: sim.value.err, unitsConsumed: sim.value.unitsConsumed! };
229
+ }
230
+ }
@@ -0,0 +1,179 @@
1
+ // src/solana/clients/ValidatorLeaderboardClient.ts
2
+ import { AnchorProvider, Program, BN } from '@coral-xyz/anchor';
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();
85
+
86
+ return new Transaction().add(ix);
87
+ }
88
+
89
+ /**
90
+ * Build an updateTop10Cache transaction
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();
105
+
106
+ return new Transaction().add(ix);
107
+ }
108
+
109
+ /**
110
+ * Fetch the cached top 10 validators via a view call
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();
118
+ }
119
+
120
+ /**
121
+ * Traverse the on-chain linked list and return the sequence of PublicKeys
122
+ */
123
+ async getLeaderboard(): Promise<PublicKey[]> {
124
+ const [headPda] = deriveLeaderboardHeadPDA();
125
+ let headAccount;
126
+ try {
127
+ headAccount = await this.program.account.leaderboardHead.fetch(headPda);
128
+ } 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;
137
+ }
138
+ return result;
139
+ }
140
+
141
+ /**
142
+ * Fetch a single validator record or null
143
+ */
144
+ async getRecord(voteAccount: PublicKey): Promise<any | null> {
145
+ const [recPda] = deriveValidatorRecordPDA(voteAccount);
146
+ try {
147
+ return await this.program.account.validatorRecord.fetch(recPda);
148
+ } catch {
149
+ return null;
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Send & confirm a single-IX Transaction; returns the signature
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
168
+ */
169
+ async simulateTransaction(
170
+ tx: Transaction
171
+ ): Promise<{ err: any; unitsConsumed: number }> {
172
+ tx.feePayer = this.provider.wallet.publicKey;
173
+ const { blockhash } = await this.provider.connection.getLatestBlockhash();
174
+ tx.recentBlockhash = blockhash;
175
+ const versioned = new VersionedTransaction(tx.compileMessage());
176
+ const sim = await this.provider.connection.simulateTransaction(versioned, { sigVerify: false });
177
+ return { err: sim.value.err, unitsConsumed: sim.value.unitsConsumed! };
178
+ }
179
+ }
@@ -0,0 +1,73 @@
1
+ // src/networks/solana/constants.ts
2
+
3
+ import { PublicKey } from '@solana/web3.js';
4
+ import { TOKEN_2022_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID } from '@solana/spl-token';
5
+
6
+ // — IDLs — (must match your filesystem: src/assets/solana/idl/*.json)
7
+ import DepositIDL from '../../assets/solana/idl/deposit.json';
8
+ import DistributionIDL from '../../assets/solana/idl/distribution.json';
9
+ import LiqSolTokenIDL from '../../assets/solana/idl/liq_sol_token.json';
10
+ import StakeControllerIDL from '../../assets/solana/idl/stake_controller.json';
11
+ import StakeRegistryIDL from '../../assets/solana/idl/stake_registry.json';
12
+ import TreasuryIDL from '../../assets/solana/idl/treasury.json';
13
+ import ValidatorLeaderboardIDL from '../../assets/solana/idl/validator_leaderboard.json';
14
+ import ValidatorRegistryIDL from '../../assets/solana/idl/validator_registry.json';
15
+ import YieldOracleIDL from '../../assets/solana/idl/yield_oracle.json';
16
+
17
+ // — Types — for your clients
18
+ import type { Deposit } from '../../assets/solana/types/deposit';
19
+ import type { Distribution } from '../../assets/solana/types/distribution';
20
+ import type { ValidatorLeaderboard } from '../../assets/solana/types/validator_leaderboard';
21
+ import type { LiqSolToken } from '../../assets/solana/types/liq_sol_token';
22
+ import type { StakeController } from '../../assets/solana/types/stake_controller';
23
+ import type { StakeRegistry } from '../../assets/solana/types/stake_registry';
24
+ import type { Treasury } from '../../assets/solana/types/treasury';
25
+ import type { ValidatorRegistry } from '../../assets/solana/types/validator_registry';
26
+ import type { YieldOracle } from '../../assets/solana/types/yield_oracle';
27
+
28
+ // Re-export for easy import elsewhere:
29
+ export {
30
+ Deposit,
31
+ DepositIDL,
32
+ Distribution,
33
+ DistributionIDL,
34
+ LiqSolToken,
35
+ LiqSolTokenIDL,
36
+ StakeController,
37
+ StakeControllerIDL,
38
+ StakeRegistry,
39
+ StakeRegistryIDL,
40
+ Treasury,
41
+ TreasuryIDL,
42
+ ValidatorLeaderboard,
43
+ ValidatorLeaderboardIDL,
44
+ ValidatorRegistry,
45
+ ValidatorRegistryIDL,
46
+ YieldOracle,
47
+ YieldOracleIDL,
48
+ };
49
+
50
+ // — Program IDs — anchor “address” fields inside each IDL must match these:
51
+ export const DEPOSIT_PROGRAM_ID = new PublicKey(DepositIDL.address);
52
+ export const DISTRIBUTION_PROGRAM_ID = new PublicKey(DistributionIDL.address);
53
+ export const LIQSOL_TOKEN_PROGRAM_ID = new PublicKey(LiqSolTokenIDL.address);
54
+ export const STAKE_CONTROLLER_PROGRAM_ID = new PublicKey(StakeControllerIDL.address);
55
+ export const STAKE_REGISTRY_PROGRAM_ID = new PublicKey(StakeRegistryIDL.address);
56
+ export const TREASURY_PROGRAM_ID = new PublicKey(TreasuryIDL.address);
57
+ export const VALIDATOR_LEADERBOARD_PROGRAM_ID = new PublicKey(ValidatorLeaderboardIDL.address);
58
+ export const VALIDATOR_REGISTRY_PROGRAM_ID = new PublicKey(ValidatorRegistryIDL.address);
59
+ export const YIELD_ORACLE_PROGRAM_ID = new PublicKey(YieldOracleIDL.address);
60
+
61
+ // — Protocol constants — tweak as needed:
62
+ export const MIN_SOL_TO_PARTICIPATE = 1_000_000_000; // 1 SOL in lamports
63
+ export const MIN_FUNDS_THRESHOLD = 10_000_000_000; // 10 SOL in lamports
64
+ export const RESERVE_FOR_FEES = 1_000_000_000; // 1 SOL
65
+
66
+ // — Pre-derived PDA seeds for your convenience —
67
+ // (you can still use your utils.ts helpers instead)
68
+ export const TREASURY_WALLET_PDA = new PublicKey('9gLj1MRrm66GNYqnMLPGUzyYqYJpVLQgFSbtCQV9Ta4G');
69
+ export const LIQSOL_MINT_ADDRESS = new PublicKey('B2XtJABkc6eUoYUNgSfZVb3kYckmbh2zxp4rp2hX2Xwa');
70
+ export const STAKE_VAULT_PDA = new PublicKey('AY83EfU5LXJGDhbLeP45H3tLKisGZgSe2G4mGYfPimqN');
71
+
72
+ // re-export SPL token constants:
73
+ export { TOKEN_2022_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID };