@wireio/stake 0.0.5 → 0.1.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.
Files changed (44) hide show
  1. package/README.md +203 -13
  2. package/lib/stake.browser.js +2803 -3331
  3. package/lib/stake.browser.js.map +1 -1
  4. package/lib/stake.d.ts +377 -6260
  5. package/lib/stake.js +2940 -3478
  6. package/lib/stake.js.map +1 -1
  7. package/lib/stake.m.js +2803 -3331
  8. package/lib/stake.m.js.map +1 -1
  9. package/package.json +2 -2
  10. package/src/assets/solana/idl/deposit.json +46 -10
  11. package/src/assets/solana/idl/distribution.json +40 -8
  12. package/src/assets/solana/idl/liq_sol_token.json +25 -2
  13. package/src/assets/solana/idl/mint_helper.json +110 -0
  14. package/src/assets/solana/idl/read_tracked_balance.json +140 -0
  15. package/src/assets/solana/idl/stake_controller.json +1141 -780
  16. package/src/assets/solana/idl/treasury.json +1 -227
  17. package/src/assets/solana/idl/validator_leaderboard.json +88 -47
  18. package/src/assets/solana/idl/validator_registry.json +115 -46
  19. package/src/assets/solana/idl/yield_oracle.json +1 -1
  20. package/src/assets/solana/types/deposit.ts +46 -10
  21. package/src/assets/solana/types/distribution.ts +40 -8
  22. package/src/assets/solana/types/liq_sol_token.ts +25 -2
  23. package/src/assets/solana/types/mint_helper.ts +116 -0
  24. package/src/assets/solana/types/read_tracked_balance.ts +146 -0
  25. package/src/assets/solana/types/stake_controller.ts +1141 -780
  26. package/src/assets/solana/types/treasury.ts +1 -227
  27. package/src/assets/solana/types/validator_leaderboard.ts +88 -47
  28. package/src/assets/solana/types/validator_registry.ts +115 -46
  29. package/src/assets/solana/types/yield_oracle.ts +1 -1
  30. package/src/index.ts +3 -4
  31. package/src/networks/ethereum/ethereum.ts +2 -2
  32. package/src/networks/solana/clients/deposit.client.ts +71 -80
  33. package/src/networks/solana/clients/distribution.client.ts +392 -141
  34. package/src/networks/solana/clients/leaderboard.client.ts +82 -107
  35. package/src/networks/solana/constants.ts +141 -56
  36. package/src/networks/solana/program.ts +36 -89
  37. package/src/networks/solana/solana.ts +173 -36
  38. package/src/networks/solana/types.ts +57 -0
  39. package/src/scripts/fetch-artifacts.sh +24 -0
  40. package/src/staker/staker.ts +32 -28
  41. package/src/staker/types.ts +25 -21
  42. package/src/assets/solana/idl/stake_registry.json +0 -435
  43. package/src/networks/solana/utils.ts +0 -122
  44. /package/src/{utils.ts → common/utils.ts} +0 -0
@@ -1,76 +1,66 @@
1
- // src/solana/clients/ValidatorLeaderboardClient.ts
2
1
  import { AnchorProvider, Program, BN } from '@coral-xyz/anchor';
3
- import { PublicKey, Transaction, TransactionInstruction, SystemProgram, VersionedTransaction } from '@solana/web3.js';
2
+ import { PublicKey, SystemProgram, Transaction, TransactionInstruction } from '@solana/web3.js';
3
+ import { SolanaProgramService } from '../program';
4
+ import type { ValidatorLeaderboard } from '../../../assets/solana/types/validator_leaderboard';
4
5
  import {
5
6
  deriveLeaderboardHeadPDA,
6
7
  deriveValidatorRecordPDA,
7
8
  deriveTop10CachePDA,
8
- } from '../utils';
9
- import { VALIDATOR_LEADERBOARD_PROGRAM_ID, ValidatorLeaderboard, ValidatorLeaderboardIDL } from '../constants';
9
+ } from '../constants';
10
10
 
11
11
  export class ValidatorLeaderboardClient {
12
- constructor(private provider: AnchorProvider) { }
12
+ private programs: SolanaProgramService;
13
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>;
14
+ constructor(private provider: AnchorProvider) {
15
+ this.programs = new SolanaProgramService(provider);
23
16
  }
24
17
 
25
- /** Derive the PDA for the leaderboard head */
26
- deriveHeadPDA(): PublicKey {
27
- return deriveLeaderboardHeadPDA()[0];
18
+ /** Anchor Program<ValidatorLeaderboard> via ProgramService */
19
+ private get program(): Program<ValidatorLeaderboard> {
20
+ return this.programs.getProgram('validatorLeaderboard') as Program<ValidatorLeaderboard>;
28
21
  }
29
22
 
30
- /** Derive the PDA for a given validator record */
31
- deriveRecordPDA(voteAccount: PublicKey): PublicKey {
32
- return deriveValidatorRecordPDA(voteAccount)[0];
33
- }
23
+ // ───────────────────────────────────────────────────────────────────────────────
24
+ // BUILDERS (return Ixs so you can batch)
25
+ // ───────────────────────────────────────────────────────────────────────────────
34
26
 
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
27
+ /** Initialize the leaderboard head account. */
28
+ async buildInitializeIx(authority: PublicKey): Promise<TransactionInstruction> {
29
+ const [leaderboardHead] = deriveLeaderboardHeadPDA();
30
+ return this.program.methods
41
31
  .initialize()
42
32
  .accounts({
43
33
  authority,
44
- leaderboardHead: headPda,
34
+ // @ts-ignore
35
+ leaderboardHead,
45
36
  systemProgram: SystemProgram.programId,
46
- } as any)
37
+ })
47
38
  .instruction();
48
-
49
- return new Transaction().add(ix);
50
39
  }
51
40
 
52
41
  /**
53
- * Build an updateValidator transaction
42
+ * Upsert/update a validator record and (optionally) reposition it in the linked list.
43
+ * Any of insertAfter/insertBefore/currentPrev/currentNext can be omitted.
54
44
  */
55
- async buildUpdateValidatorTransaction(params: {
56
- authority: PublicKey;
45
+ async buildUpdateValidatorIx(params: {
57
46
  registrant: PublicKey;
58
47
  voteAccount: PublicKey;
59
- vpp: number;
48
+ vpp: number; // Validator Performance Points
60
49
  insertAfter?: PublicKey;
61
50
  insertBefore?: PublicKey;
62
51
  currentPrev?: PublicKey;
63
52
  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);
53
+ }): Promise<TransactionInstruction> {
54
+ const { registrant, voteAccount, vpp, insertAfter, insertBefore, currentPrev, currentNext } = params;
55
+
56
+ const [leaderboardHead] = deriveLeaderboardHeadPDA();
57
+ const [validatorRecord] = deriveValidatorRecordPDA(voteAccount);
68
58
 
69
59
  const accounts: any = {
70
60
  registrant,
71
61
  voteAccount,
72
- validatorRecord: recPda,
73
- leaderboardHead: headPda,
62
+ validatorRecord,
63
+ leaderboardHead,
74
64
  systemProgram: SystemProgram.programId,
75
65
  ...(insertAfter && { insertAfter }),
76
66
  ...(insertBefore && { insertBefore }),
@@ -78,70 +68,82 @@ export class ValidatorLeaderboardClient {
78
68
  ...(currentNext && { currentNext }),
79
69
  };
80
70
 
81
- const ix = await this.program.methods
71
+ return this.program.methods
82
72
  .updateValidator(new BN(vpp))
83
73
  .accounts(accounts)
84
74
  .instruction();
85
-
86
- return new Transaction().add(ix);
87
75
  }
88
76
 
89
- /**
90
- * Build an updateTop10Cache transaction
91
- */
92
- async buildUpdateTop10CacheTransaction(params: {
77
+ /** Update the Top-10 cache. Requires exactly 10 validator vote accounts. */
78
+ async buildUpdateTop10CacheIx(params: {
93
79
  authority: PublicKey;
94
80
  top10Validators: PublicKey[];
95
- }): Promise<Transaction> {
81
+ }): Promise<TransactionInstruction> {
96
82
  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
83
+ if (top10Validators.length !== 10) throw new Error('Must provide exactly 10 validators');
84
+
85
+ const [cache] = deriveTop10CachePDA();
86
+ return this.program.methods
102
87
  .updateTop10Cache(top10Validators)
103
- .accounts({ authority, cache: cachePda, systemProgram: SystemProgram.programId } as any)
88
+ .accounts({
89
+ // @ts-ignore
90
+ authority,
91
+ cache,
92
+ systemProgram: SystemProgram.programId,
93
+ })
104
94
  .instruction();
95
+ }
96
+
97
+ // Convenience wrappers if you want a ready-to-send Transaction
105
98
 
106
- return new Transaction().add(ix);
99
+ async buildInitializeTx(authority: PublicKey): Promise<Transaction> {
100
+ return new Transaction().add(await this.buildInitializeIx(authority));
107
101
  }
108
102
 
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();
103
+ async buildUpdateValidatorTx(params: {
104
+ registrant: PublicKey;
105
+ voteAccount: PublicKey;
106
+ vpp: number;
107
+ insertAfter?: PublicKey;
108
+ insertBefore?: PublicKey;
109
+ currentPrev?: PublicKey;
110
+ currentNext?: PublicKey;
111
+ }): Promise<Transaction> {
112
+ return new Transaction().add(await this.buildUpdateValidatorIx(params));
118
113
  }
119
114
 
120
- /**
121
- * Traverse the on-chain linked list and return the sequence of PublicKeys
122
- */
115
+ async buildUpdateTop10CacheTx(params: {
116
+ authority: PublicKey;
117
+ top10Validators: PublicKey[];
118
+ }): Promise<Transaction> {
119
+ return new Transaction().add(await this.buildUpdateTop10CacheIx(params));
120
+ }
121
+
122
+ // ───────────────────────────────────────────────────────────────────────────────
123
+ // READ HELPERS
124
+ // ───────────────────────────────────────────────────────────────────────────────
125
+
126
+ /** Traverse the linked-list leaderboard, returning vote accounts in order. */
123
127
  async getLeaderboard(): Promise<PublicKey[]> {
124
- const [headPda] = deriveLeaderboardHeadPDA();
125
- let headAccount;
128
+ const [head] = deriveLeaderboardHeadPDA();
129
+ let headAcc;
126
130
  try {
127
- headAccount = await this.program.account.leaderboardHead.fetch(headPda);
131
+ headAcc = await this.program.account.leaderboardHead.fetch(head);
128
132
  } catch {
129
133
  return [];
130
134
  }
131
- const result: PublicKey[] = [];
132
- let cursor: PublicKey = headAccount.nextValidator;
135
+ const out: PublicKey[] = [];
136
+ let cursor: PublicKey = headAcc.nextValidator;
133
137
  while (cursor && !cursor.equals(PublicKey.default)) {
134
- result.push(cursor);
138
+ out.push(cursor);
135
139
  const rec = await this.program.account.validatorRecord.fetch(cursor);
136
140
  cursor = rec.nextValidator;
137
141
  }
138
- return result;
142
+ return out;
139
143
  }
140
144
 
141
- /**
142
- * Fetch a single validator record or null
143
- */
144
- async getRecord(voteAccount: PublicKey): Promise<any | null> {
145
+ /** Fetch a single validator record (or null if it doesn't exist). */
146
+ async getValidatorRecord(voteAccount: PublicKey): Promise<any | null> {
145
147
  const [recPda] = deriveValidatorRecordPDA(voteAccount);
146
148
  try {
147
149
  return await this.program.account.validatorRecord.fetch(recPda);
@@ -149,31 +151,4 @@ export class ValidatorLeaderboardClient {
149
151
  return null;
150
152
  }
151
153
  }
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
- }
154
+ }
@@ -1,73 +1,158 @@
1
1
  // src/networks/solana/constants.ts
2
-
3
2
  import { PublicKey } from '@solana/web3.js';
4
- import { TOKEN_2022_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID } from '@solana/spl-token';
3
+ import {
4
+ ASSOCIATED_TOKEN_PROGRAM_ID,
5
+ TOKEN_2022_PROGRAM_ID,
6
+ getAssociatedTokenAddressSync,
7
+ } from '@solana/spl-token';
8
+ import { AnchorProvider, Program } from '@coral-xyz/anchor';
5
9
 
6
- // IDLs (must match your filesystem: src/assets/solana/idl/*.json)
10
+ // IDLs (as generated artifacts)
7
11
  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
12
  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
13
  import ValidatorLeaderboardIDL from '../../assets/solana/idl/validator_leaderboard.json';
14
- import ValidatorRegistryIDL from '../../assets/solana/idl/validator_registry.json';
14
+ import LiqSolTokenIDL from '../../assets/solana/idl/liq_sol_token.json';
15
+ import DistributionIDL from '../../assets/solana/idl/distribution.json';
15
16
  import YieldOracleIDL from '../../assets/solana/idl/yield_oracle.json';
16
17
 
17
- // Types for your clients
18
+ // Types (optional; keep the ones you use)
18
19
  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
20
 
50
- // Program IDs anchor “address fields inside each IDL must match these:
21
+ // ---------- Program IDs (from IDL.address) ----------
51
22
  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
23
  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
24
  export const VALIDATOR_LEADERBOARD_PROGRAM_ID = new PublicKey(ValidatorLeaderboardIDL.address);
58
- export const VALIDATOR_REGISTRY_PROGRAM_ID = new PublicKey(ValidatorRegistryIDL.address);
25
+ export const LIQSOL_TOKEN_PROGRAM_ID = new PublicKey(LiqSolTokenIDL.address);
26
+ export const DISTRIBUTION_PROGRAM_ID = new PublicKey(DistributionIDL.address);
59
27
  export const YIELD_ORACLE_PROGRAM_ID = new PublicKey(YieldOracleIDL.address);
60
28
 
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
29
+ // ---------- Protocol constants ----------
30
+ export const MIN_SOL_TO_PARTICIPATE = 1_000_000_000; // 1 SOL (lamports)
31
+
32
+ // The liqSOL Mint is a PDA on the LiqSOL token program
33
+ export const LIQSOL_MINT_ADDRESS: PublicKey = PublicKey.findProgramAddressSync(
34
+ [Buffer.from('liq_sol_mint')],
35
+ LIQSOL_TOKEN_PROGRAM_ID
36
+ )[0];
37
+
38
+ // Re-export SPL ids
39
+ export { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID };
40
+
41
+ // ---------- Program factories ----------
42
+ /** Create Anchor Program client for the Deposit program (with correct address) */
43
+ export const getDepositProgram = (provider: AnchorProvider): Program<Deposit> => {
44
+ const idlWithAddress = { ...JSON.parse(JSON.stringify(DepositIDL)), address: DEPOSIT_PROGRAM_ID.toString() };
45
+ return new Program(idlWithAddress as any, provider) as Program<Deposit>;
46
+ };
47
+
48
+ // You can add similar helpers for other programs if you want:
49
+ // export const getDistributionProgram = <T>(provider: AnchorProvider) => { ... }
50
+
51
+ // ---------- PDA helpers ----------
52
+
53
+ // Deposit
54
+ export const deriveDepositAuthorityPDA = (): [PublicKey, number] =>
55
+ PublicKey.findProgramAddressSync(
56
+ [Buffer.from('program_authority')],
57
+ DEPOSIT_PROGRAM_ID
58
+ );
59
+
60
+ // LiqSOL Token program
61
+ export const deriveLiqsolMintPDA = (): [PublicKey, number] =>
62
+ PublicKey.findProgramAddressSync(
63
+ [Buffer.from('liq_sol_mint')],
64
+ LIQSOL_TOKEN_PROGRAM_ID
65
+ );
66
+
67
+ /** ✅ FIXED: this must be derived with the LiqSOL token **program id**, not the mint address */
68
+ export const deriveLiqsolMintAuthorityPDA = (): [PublicKey, number] =>
69
+ PublicKey.findProgramAddressSync(
70
+ [Buffer.from('mint_authority')],
71
+ LIQSOL_TOKEN_PROGRAM_ID
72
+ );
73
+
74
+ // Stake Controller
75
+ export const deriveStakeControllerVaultPDA = (): [PublicKey, number] =>
76
+ PublicKey.findProgramAddressSync(
77
+ [Buffer.from('vault')],
78
+ STAKE_CONTROLLER_PROGRAM_ID
79
+ );
80
+
81
+ export const deriveStakeControllerReservePoolPDA = (): [PublicKey, number] =>
82
+ PublicKey.findProgramAddressSync(
83
+ [Buffer.from('reserve_pool')],
84
+ STAKE_CONTROLLER_PROGRAM_ID
85
+ );
86
+
87
+ export const deriveStakeControllerStatePDA = (): [PublicKey, number] =>
88
+ PublicKey.findProgramAddressSync(
89
+ [Buffer.from('stake_controller')],
90
+ STAKE_CONTROLLER_PROGRAM_ID
91
+ );
92
+
93
+ export const deriveGlobalStakeInfoPDA = (): [PublicKey, number] =>
94
+ PublicKey.findProgramAddressSync(
95
+ [Buffer.from('global_stake_info')],
96
+ STAKE_CONTROLLER_PROGRAM_ID
97
+ );
98
+
99
+ export const deriveBucketAuthorityPDA = (): [PublicKey, number] =>
100
+ PublicKey.findProgramAddressSync(
101
+ [Buffer.from('liqsol_bucket')],
102
+ STAKE_CONTROLLER_PROGRAM_ID
103
+ );
104
+
105
+ export const derivePayRateHistoryPDA = (): [PublicKey, number] =>
106
+ PublicKey.findProgramAddressSync(
107
+ [Buffer.from('pay_rate_history')],
108
+ STAKE_CONTROLLER_PROGRAM_ID
109
+ );
110
+
111
+ // Distribution
112
+ export const deriveDistributionStatePDA = (): [PublicKey, number] =>
113
+ PublicKey.findProgramAddressSync(
114
+ [Buffer.from('distribution_state')],
115
+ DISTRIBUTION_PROGRAM_ID
116
+ );
117
+
118
+ export const deriveUserRecordPDA = (user: PublicKey): [PublicKey, number] =>
119
+ PublicKey.findProgramAddressSync(
120
+ [Buffer.from('user_record'), user.toBuffer()],
121
+ DISTRIBUTION_PROGRAM_ID
122
+ );
123
+
124
+ // Validator Leaderboard
125
+ export const deriveLeaderboardHeadPDA = (): [PublicKey, number] =>
126
+ PublicKey.findProgramAddressSync(
127
+ [Buffer.from('leaderboard_head')],
128
+ VALIDATOR_LEADERBOARD_PROGRAM_ID
129
+ );
130
+
131
+ export const deriveValidatorRecordPDA = (voteAccount: PublicKey): [PublicKey, number] =>
132
+ PublicKey.findProgramAddressSync(
133
+ [Buffer.from('validator_record'), voteAccount.toBuffer()],
134
+ VALIDATOR_LEADERBOARD_PROGRAM_ID
135
+ );
136
+
137
+ export const deriveTop10CachePDA = (): [PublicKey, number] =>
138
+ PublicKey.findProgramAddressSync(
139
+ [Buffer.from('top_10_cache')],
140
+ VALIDATOR_LEADERBOARD_PROGRAM_ID
141
+ );
65
142
 
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');
143
+ export const deriveStakeControllerAuthorityPDA = (): [PublicKey, number] =>
144
+ PublicKey.findProgramAddressSync(
145
+ [Buffer.from('stake_authority')],
146
+ STAKE_CONTROLLER_PROGRAM_ID
147
+ );
71
148
 
72
- // re-export SPL token constants:
73
- export { TOKEN_2022_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID };
149
+ // ---------- SPL helper ----------
150
+ /** User’s liqSOL ATA (Token-2022) */
151
+ export const getUserLiqsolATA = (user: PublicKey): PublicKey =>
152
+ getAssociatedTokenAddressSync(
153
+ LIQSOL_MINT_ADDRESS,
154
+ user,
155
+ /* owner is PDA? */ false,
156
+ TOKEN_2022_PROGRAM_ID,
157
+ ASSOCIATED_TOKEN_PROGRAM_ID
158
+ );
@@ -1,113 +1,60 @@
1
- // src/solana/programService.ts
2
-
3
1
  import { AnchorProvider, Program } from '@coral-xyz/anchor';
4
- import { PublicKey } from '@solana/web3.js';
5
-
6
- // 1) pull in all your on-chain IDLs (must match lowercase `src/assets/solana/idl`)
7
2
  import depositJson from '../../assets/solana/idl/deposit.json';
8
- import distributionJson from '../../assets/solana/idl/distribution.json';
9
- import liqSolTokenJson from '../../assets/solana/idl/liq_sol_token.json';
10
3
  import stakeControllerJson from '../../assets/solana/idl/stake_controller.json';
11
- import stakeRegistryJson from '../../assets/solana/idl/stake_registry.json';
12
- import treasuryJson from '../../assets/solana/idl/treasury.json';
4
+ import liqSolTokenJson from '../../assets/solana/idl/liq_sol_token.json';
5
+ import distributionJson from '../../assets/solana/idl/distribution.json';
13
6
  import validatorLeaderboardJson from '../../assets/solana/idl/validator_leaderboard.json';
14
- import validatorRegistryJson from '../../assets/solana/idl/validator_registry.json';
15
- import yieldOracleJson from '../../assets/solana/idl/yield_oracle.json';
16
7
 
17
- // 2) import their companion TS types
18
8
  import type { Deposit } from '../../assets/solana/types/deposit';
19
- import type { Distribution } from '../../assets/solana/types/distribution';
20
- import type { LiqSolToken } from '../../assets/solana/types/liq_sol_token';
21
9
  import type { StakeController } from '../../assets/solana/types/stake_controller';
22
- import type { StakeRegistry } from '../../assets/solana/types/stake_registry';
23
- import type { Treasury } from '../../assets/solana/types/treasury';
10
+ import type { LiqSolToken } from '../../assets/solana/types/liq_sol_token';
11
+ import type { Distribution } from '../../assets/solana/types/distribution';
24
12
  import type { ValidatorLeaderboard } from '../../assets/solana/types/validator_leaderboard';
25
- import type { ValidatorRegistry } from '../../assets/solana/types/validator_registry';
26
- import type { YieldOracle } from '../../assets/solana/types/yield_oracle';
27
13
 
28
- type IdlEntry<IDL> = {
29
- idl: IDL & { address: string };
30
- address: PublicKey;
31
- };
14
+ import {
15
+ DEPOSIT_PROGRAM_ID,
16
+ STAKE_CONTROLLER_PROGRAM_ID,
17
+ LIQSOL_TOKEN_PROGRAM_ID,
18
+ DISTRIBUTION_PROGRAM_ID,
19
+ VALIDATOR_LEADERBOARD_PROGRAM_ID
20
+ } from '../solana/constants';
32
21
 
33
- export const PROGRAM_IDLS = {
22
+ type Entry<IDL> = { idl: IDL & { address: string }, address: string };
23
+
24
+ const PROGRAMS = {
34
25
  deposit: {
35
26
  idl: depositJson,
36
- address: new PublicKey(depositJson.address),
37
- } as IdlEntry<Deposit>,
38
-
39
- distribution: {
40
- idl: distributionJson,
41
- address: new PublicKey(distributionJson.address),
42
- } as IdlEntry<Distribution>,
43
-
44
- liqSolToken: {
45
- idl: liqSolTokenJson,
46
- address: new PublicKey(liqSolTokenJson.address),
47
- } as IdlEntry<LiqSolToken>,
48
-
27
+ address: DEPOSIT_PROGRAM_ID.toBase58()
28
+ } as Entry<Deposit>,
49
29
  stakeController: {
50
30
  idl: stakeControllerJson,
51
- address: new PublicKey(stakeControllerJson.address),
52
- } as IdlEntry<StakeController>,
53
-
54
- stakeRegistry: {
55
- idl: stakeRegistryJson,
56
- address: new PublicKey(stakeRegistryJson.address),
57
- } as IdlEntry<StakeRegistry>,
58
-
59
- treasury: {
60
- idl: treasuryJson,
61
- address: new PublicKey(treasuryJson.address),
62
- } as IdlEntry<Treasury>,
63
-
31
+ address: STAKE_CONTROLLER_PROGRAM_ID.toBase58()
32
+ } as Entry<StakeController>,
33
+ liqSolToken: {
34
+ idl: liqSolTokenJson,
35
+ address: LIQSOL_TOKEN_PROGRAM_ID.toBase58()
36
+ } as Entry<LiqSolToken>,
37
+ distribution: {
38
+ idl: distributionJson,
39
+ address: DISTRIBUTION_PROGRAM_ID.toBase58()
40
+ } as Entry<Distribution>,
64
41
  validatorLeaderboard: {
65
42
  idl: validatorLeaderboardJson,
66
- address: new PublicKey(validatorLeaderboardJson.address),
67
- } as IdlEntry<ValidatorLeaderboard>,
68
-
69
- validatorRegistry: {
70
- idl: validatorRegistryJson,
71
- address: new PublicKey(validatorRegistryJson.address),
72
- } as IdlEntry<ValidatorRegistry>,
43
+ address:VALIDATOR_LEADERBOARD_PROGRAM_ID.toBase58()
44
+ } as Entry<ValidatorLeaderboard>,
45
+ } as const;
73
46
 
74
- yieldOracle: {
75
- idl: yieldOracleJson,
76
- address: new PublicKey(yieldOracleJson.address),
77
- } as IdlEntry<YieldOracle>,
78
- };
79
-
80
- /**
81
- * Factory for Anchor Program clients.
82
- *
83
- * Anchor v0.28+ reads the program ID from `idl.address`, so
84
- * we call the 2-arg constructor: `new Program(idl, provider)`.
85
- */
86
47
  export class SolanaProgramService {
87
48
  constructor(private provider: AnchorProvider) { }
88
49
 
89
- /**
90
- * Returns a typed Anchor Program instance for the given key.
91
- */
92
- getProgram<K extends keyof typeof PROGRAM_IDLS>(
93
- name: K
94
- ): Program<(typeof PROGRAM_IDLS)[K]['idl']> {
95
- const entry = PROGRAM_IDLS[name];
96
- // stamp the correct address into a fresh copy of the IDL
97
- const idlWithAddr = { ...entry.idl, address: entry.address.toString() };
98
- // use the two-arg signature: (idl, provider)
99
- return new Program(idlWithAddr as any, this.provider) as Program<
100
- (typeof PROGRAM_IDLS)[K]['idl']
101
- >;
102
- }
103
-
104
- /** List all program keys */
105
- listProgramNames(): Array<keyof typeof PROGRAM_IDLS> {
106
- return Object.keys(PROGRAM_IDLS) as Array<keyof typeof PROGRAM_IDLS>;
50
+ getProgram<K extends keyof typeof PROGRAMS>(name: K): Program<(typeof PROGRAMS)[K]['idl']> {
51
+ const { idl, address } = PROGRAMS[name];
52
+ // Ensure the IDL has the right address (avoid drift)
53
+ const idlWithAddr = { ...idl, address };
54
+ return new Program(idlWithAddr as any, this.provider) as Program<(typeof PROGRAMS)[K]['idl']>;
107
55
  }
108
56
 
109
- /** Raw PublicKey of a program */
110
- getProgramId(name: keyof typeof PROGRAM_IDLS): PublicKey {
111
- return PROGRAM_IDLS[name].address;
57
+ listProgramNames(): Array<keyof typeof PROGRAMS> {
58
+ return Object.keys(PROGRAMS) as Array<keyof typeof PROGRAMS>;
112
59
  }
113
60
  }