@wireio/stake 2.1.0 → 2.2.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.
@@ -1,7 +1,7 @@
1
1
  import { SolChainID, PublicKey as PublicKey$1, KeyType, EvmChainID } from '@wireio/core';
2
- import { SystemProgram, StakeProgram, SYSVAR_INSTRUCTIONS_PUBKEY, SYSVAR_CLOCK_PUBKEY, SYSVAR_STAKE_HISTORY_PUBKEY, SYSVAR_RENT_PUBKEY, Transaction, PublicKey, Keypair, Connection, TransactionMessage, ComputeBudgetProgram, SendTransactionError } from '@solana/web3.js';
2
+ import { SystemProgram, StakeProgram, SYSVAR_INSTRUCTIONS_PUBKEY, SYSVAR_CLOCK_PUBKEY, SYSVAR_STAKE_HISTORY_PUBKEY, SYSVAR_RENT_PUBKEY, PublicKey, Keypair, Connection, ComputeBudgetProgram, TransactionMessage, Transaction, SendTransactionError } from '@solana/web3.js';
3
3
  import { BN, Program, AnchorProvider } from '@coral-xyz/anchor';
4
- import { getAssociatedTokenAddressSync, TOKEN_2022_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddress, createAssociatedTokenAccountInstruction } from '@solana/spl-token';
4
+ import { getAssociatedTokenAddressSync, TOKEN_2022_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddress } from '@solana/spl-token';
5
5
  import * as multisig from '@sqds/multisig';
6
6
  import bs58 from 'bs58';
7
7
  import { ethers, Contract, BigNumber } from 'ethers';
@@ -141,7 +141,7 @@ class DepositClient {
141
141
  true,
142
142
  TOKEN_2022_PROGRAM_ID
143
143
  );
144
- const ix = await this.program.methods.requestWithdraw(new BN(amount.toString())).accounts({
144
+ return await this.program.methods.requestWithdraw(new BN(amount.toString())).accounts({
145
145
  user,
146
146
  owner,
147
147
  global,
@@ -167,69 +167,6 @@ class DepositClient {
167
167
  rent: SYSVAR_RENT_PUBKEY,
168
168
  globalConfig
169
169
  }).instruction();
170
- return new Transaction().add(ix);
171
- }
172
- async buildDepositIxForUser(amount, user) {
173
- if (!user) {
174
- throw new Error("buildDepositIxForUser: user is required");
175
- }
176
- if (!amount || amount <= BigInt(0)) {
177
- throw new Error("buildDepositIxForUser: amount must be > 0");
178
- }
179
- const depositAuthority = this.pgs.deriveDepositAuthorityPda();
180
- const liqsolMint = this.pgs.deriveLiqsolMintPda();
181
- const liqsolMintAuthority = this.pgs.deriveLiqsolMintAuthorityPda();
182
- const reservePool = this.pgs.deriveReservePoolPda();
183
- const vault = this.pgs.deriveVaultPda();
184
- const controllerState = this.pgs.deriveStakeControllerStatePda();
185
- const payoutState = this.pgs.derivePayoutStatePda();
186
- const bucketAuthority = this.pgs.deriveBucketAuthorityPda();
187
- const payRateHistory = this.pgs.derivePayRateHistoryPda();
188
- const globalConfig = this.pgs.deriveGlobalConfigPda();
189
- const userAta = getAssociatedTokenAddressSync(
190
- liqsolMint,
191
- user,
192
- true,
193
- TOKEN_2022_PROGRAM_ID
194
- );
195
- const distributionState = this.pgs.deriveDistributionStatePda();
196
- const userRecord = this.pgs.deriveUserRecordPda(userAta);
197
- const bucketTokenAccount = getAssociatedTokenAddressSync(
198
- liqsolMint,
199
- bucketAuthority,
200
- true,
201
- TOKEN_2022_PROGRAM_ID
202
- );
203
- const seed = Math.floor(Math.random() * 2 ** 32);
204
- const ephemeralStake = await this.pgs.deriveEphemeralStakeAddress(user, seed);
205
- const ix = await this.program.methods.deposit(new BN(amount.toString()), seed).accounts({
206
- user,
207
- depositAuthority,
208
- systemProgram: SystemProgram.programId,
209
- tokenProgram: TOKEN_2022_PROGRAM_ID,
210
- associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
211
- liqsolProgram: this.pgs.PROGRAM_IDS.LIQSOL_TOKEN,
212
- stakeProgram: StakeProgram.programId,
213
- liqsolMint,
214
- userAta,
215
- liqsolMintAuthority,
216
- reservePool,
217
- vault,
218
- ephemeralStake,
219
- controllerState,
220
- payoutState,
221
- bucketAuthority,
222
- bucketTokenAccount,
223
- userRecord,
224
- distributionState,
225
- payRateHistory,
226
- instructionsSysvar: SYSVAR_INSTRUCTIONS_PUBKEY,
227
- clock: SYSVAR_CLOCK_PUBKEY,
228
- stakeHistory: SYSVAR_STAKE_HISTORY_PUBKEY,
229
- rent: SYSVAR_RENT_PUBKEY,
230
- globalConfig
231
- }).instruction();
232
- return { ix, seed, userAta, ephemeralStake };
233
170
  }
234
171
  }
235
172
 
@@ -14659,13 +14596,15 @@ const MAINNET_PROGRAM_IDS = {
14659
14596
  LIQSOL_CORE: new PublicKey(liqsolCoreMainnetJson.address),
14660
14597
  LIQSOL_TOKEN: new PublicKey(liqsolTokenMainnetJson.address),
14661
14598
  VALIDATOR_LEADERBOARD: new PublicKey(validatorLeaderboardMainnetJson.address),
14662
- TRANSFER_HOOK: new PublicKey(mainnetTransferHookIDL.address)
14599
+ TRANSFER_HOOK: new PublicKey(mainnetTransferHookIDL.address),
14600
+ ALT_LOOKUP_TABLE: new PublicKey("AQXTHwkdNBEiXeQuVA5uCoxvzgYUmudRxthQY4vWKCPS")
14663
14601
  };
14664
14602
  const DEVNET_PROGRAM_IDS = {
14665
14603
  LIQSOL_CORE: new PublicKey(liqsolCoreDevnetJson.address),
14666
14604
  LIQSOL_TOKEN: new PublicKey(liqsolTokenDevnetJson.address),
14667
14605
  VALIDATOR_LEADERBOARD: new PublicKey(validatorLeaderboardDevnetJson.address),
14668
- TRANSFER_HOOK: new PublicKey(devnetTransferHookIDL.address)
14606
+ TRANSFER_HOOK: new PublicKey(devnetTransferHookIDL.address),
14607
+ ALT_LOOKUP_TABLE: new PublicKey("3MbupRDxUqPtJzoLLmjEYV3dXJdh1jojQrpDEQUqv7xb")
14669
14608
  };
14670
14609
  const PROGRAM_IDS_BY_CHAIN = {
14671
14610
  [SolChainID.Mainnet]: MAINNET_PROGRAM_IDS,
@@ -14887,7 +14826,7 @@ async function buildOutpostAccounts(connection, user, pgs) {
14887
14826
  const userAta = await getAssociatedTokenAddress(
14888
14827
  liqsolMint,
14889
14828
  user,
14890
- false,
14829
+ true,
14891
14830
  TOKEN_2022_PROGRAM_ID
14892
14831
  );
14893
14832
  const bucketUserRecord = pgs.deriveUserRecordPda(bucketTokenAccount);
@@ -15269,14 +15208,13 @@ class OutpostClient {
15269
15208
  throw err;
15270
15209
  }
15271
15210
  }
15272
- async buildStakeIx(amountLamports, user) {
15273
- const userPk = user ?? this.wallet.publicKey;
15274
- if (!userPk) {
15211
+ async buildStakeIx(amountLamports, user = this.wallet.publicKey) {
15212
+ if (!user) {
15275
15213
  throw new Error("OutpostClient.buildStakeIx: wallet not connected");
15276
15214
  }
15277
- const a = await this.buildAccounts(userPk);
15215
+ const a = await this.buildAccounts(user);
15278
15216
  return this.program.methods.synd(new BN(amountLamports.toString())).accounts({
15279
- user: userPk,
15217
+ user,
15280
15218
  liqsolMint: a.liqsolMint,
15281
15219
  globalState: a.globalState,
15282
15220
  distributionState: a.distributionState,
@@ -15393,6 +15331,7 @@ class TokenClient {
15393
15331
  );
15394
15332
  }
15395
15333
  async buildPurchaseIx(amountLamports, user = this.wallet.publicKey) {
15334
+ console.log("build purchase for", user.toBase58());
15396
15335
  const a = await this.getAccounts(user);
15397
15336
  const extraAccountMetaList = this.pgs.deriveExtraAccountMetaListPda(a.liqsolMint);
15398
15337
  const liqsolCoreProgram = this.pgs.PROGRAM_IDS.LIQSOL_CORE;
@@ -15812,71 +15751,13 @@ const _SolanaStakingClient = class _SolanaStakingClient {
15812
15751
  const config = this.config.extras?.squadsX;
15813
15752
  return config ?? null;
15814
15753
  }
15815
- async createVaultLiqsolAtaOneShot(params) {
15816
- const { connection, payer, vaultPda } = params;
15817
- const liqsolMint = this.program.deriveLiqsolMintPda();
15818
- const vaultAta = getAssociatedTokenAddressSync(
15819
- liqsolMint,
15820
- vaultPda,
15821
- true,
15822
- TOKEN_2022_PROGRAM_ID,
15823
- ASSOCIATED_TOKEN_PROGRAM_ID
15824
- );
15825
- const info = await connection.getAccountInfo(vaultAta, "confirmed");
15826
- if (info) return null;
15827
- const ix = createAssociatedTokenAccountInstruction(
15828
- payer,
15829
- vaultAta,
15830
- vaultPda,
15831
- liqsolMint,
15832
- TOKEN_2022_PROGRAM_ID,
15833
- ASSOCIATED_TOKEN_PROGRAM_ID
15834
- );
15835
- const tx = new Transaction().add(ix);
15836
- return { tx, vaultAta };
15837
- }
15838
- async prepSquadsIxs(ix) {
15839
- if (!this.squadsX) throw new Error("Attempting to wrap Squads instruction without SquadsX config");
15840
- const multisigPda = this.squadsMultisigPDA;
15841
- const vaultPda = this.squadsVaultPDA;
15842
- const vaultIndex = this.squadsX?.vaultIndex ?? 0;
15843
- const creator = this.solPubKey;
15844
- const ms = await multisig.accounts.Multisig.fromAccountAddress(this.connection, multisigPda);
15845
- const current = BigInt(ms.transactionIndex?.toString() ?? 0);
15846
- const transactionIndex = current + BigInt(1);
15847
- const { blockhash } = await this.connection.getLatestBlockhash("confirmed");
15848
- const transactionMessage = new TransactionMessage({
15849
- payerKey: vaultPda,
15850
- recentBlockhash: blockhash,
15851
- instructions: [ix]
15852
- });
15853
- const createVaultTxIx = await multisig.instructions.vaultTransactionCreate({
15854
- multisigPda,
15855
- transactionIndex,
15856
- creator,
15857
- vaultIndex,
15858
- transactionMessage,
15859
- ephemeralSigners: 0
15860
- });
15861
- const createProposalIx = await multisig.instructions.proposalCreate({
15862
- multisigPda,
15863
- transactionIndex,
15864
- creator
15865
- });
15866
- return [createVaultTxIx, createProposalIx];
15867
- }
15868
15754
  async deposit(amountLamports) {
15869
15755
  this.ensureUser();
15870
- if (amountLamports <= BigInt(0)) {
15756
+ if (amountLamports <= BigInt(0))
15871
15757
  throw new Error("Deposit amount must be greater than zero.");
15872
- }
15873
15758
  try {
15874
- const cuIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 4e5 });
15875
- const ix = await this.depositClient.buildDepositTx(amountLamports);
15876
- const tx = new Transaction().add(ix);
15877
- const prepared = await this.prepareTx(tx);
15878
- const signed = await this.signTransaction(prepared.tx);
15879
- return this.sendAndConfirmHttp(signed, prepared);
15759
+ const ix = await this.depositClient.buildDepositTx(amountLamports, this.squadsVaultPDA);
15760
+ return !!this.squadsX ? await this.sendSquadsIxs(ix) : await this.buildAndSendIx(ix);
15880
15761
  } catch (err) {
15881
15762
  console.log(`Failed to deposit Solana: ${err}`);
15882
15763
  throw err;
@@ -15884,16 +15765,11 @@ const _SolanaStakingClient = class _SolanaStakingClient {
15884
15765
  }
15885
15766
  async withdraw(amountLamports) {
15886
15767
  this.ensureUser();
15887
- if (amountLamports <= BigInt(0)) {
15768
+ if (amountLamports <= BigInt(0))
15888
15769
  throw new Error("Withdraw amount must be greater than zero.");
15889
- }
15890
15770
  try {
15891
- const cuIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 4e5 });
15892
- const ix = await this.depositClient.buildWithdrawTx(amountLamports);
15893
- const tx = new Transaction().add(cuIx, ix);
15894
- const prepared = await this.prepareTx(tx);
15895
- const signed = await this.signTransaction(prepared.tx);
15896
- return this.sendAndConfirmHttp(signed, prepared);
15771
+ const ix = await this.depositClient.buildWithdrawTx(amountLamports, this.squadsVaultPDA);
15772
+ return !!this.squadsX ? await this.sendSquadsIxs(ix) : await this.buildAndSendIx(ix);
15897
15773
  } catch (err) {
15898
15774
  console.log(`Failed to withdraw Solana: ${err}`);
15899
15775
  throw err;
@@ -15901,17 +15777,11 @@ const _SolanaStakingClient = class _SolanaStakingClient {
15901
15777
  }
15902
15778
  async stake(amountLamports) {
15903
15779
  this.ensureUser();
15904
- if (!amountLamports || amountLamports <= BigInt(0)) {
15780
+ if (!amountLamports || amountLamports <= BigInt(0))
15905
15781
  throw new Error("Stake amount must be greater than zero.");
15906
- }
15907
15782
  try {
15908
- const user = this.solPubKey;
15909
- const cuIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 4e5 });
15910
- const ix = await this.outpostClient.buildStakeIx(amountLamports, user);
15911
- const tx = new Transaction().add(cuIx, ix);
15912
- const prepared = await this.prepareTx(tx);
15913
- const signed = await this.signTransaction(prepared.tx);
15914
- return this.sendAndConfirmHttp(signed, prepared);
15783
+ const ix = await this.outpostClient.buildStakeIx(amountLamports, this.squadsVaultPDA);
15784
+ return !!this.squadsX ? await this.sendSquadsIxs(ix) : await this.buildAndSendIx(ix);
15915
15785
  } catch (err) {
15916
15786
  console.log(`Failed to stake Solana: ${err}`);
15917
15787
  throw err;
@@ -15919,17 +15789,11 @@ const _SolanaStakingClient = class _SolanaStakingClient {
15919
15789
  }
15920
15790
  async unstake(amountLamports) {
15921
15791
  this.ensureUser();
15922
- if (!amountLamports || amountLamports <= BigInt(0)) {
15792
+ if (!amountLamports || amountLamports <= BigInt(0))
15923
15793
  throw new Error("Unstake amount must be greater than zero.");
15924
- }
15925
15794
  try {
15926
- const user = this.solPubKey;
15927
- const cuIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 4e5 });
15928
- const ix = await this.outpostClient.buildUnstakeIx(amountLamports, user);
15929
- const tx = new Transaction().add(cuIx, ix);
15930
- const prepared = await this.prepareTx(tx);
15931
- const signed = await this.signTransaction(prepared.tx);
15932
- return this.sendAndConfirmHttp(signed, prepared);
15795
+ const ix = await this.outpostClient.buildUnstakeIx(amountLamports, this.squadsVaultPDA);
15796
+ return !!this.squadsX ? await this.sendSquadsIxs(ix) : await this.buildAndSendIx(ix);
15933
15797
  } catch (err) {
15934
15798
  console.log(`Failed to unstake Solana: ${err}`);
15935
15799
  throw err;
@@ -15937,24 +15801,17 @@ const _SolanaStakingClient = class _SolanaStakingClient {
15937
15801
  }
15938
15802
  async buy(amountLamports) {
15939
15803
  this.ensureUser();
15940
- if (!amountLamports || amountLamports <= BigInt(0)) {
15804
+ if (!amountLamports || amountLamports <= BigInt(0))
15941
15805
  throw new Error("liqSOL pretoken purchase requires a positive amount.");
15942
- }
15943
15806
  try {
15944
- const user = this.solPubKey;
15945
- const cuIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 4e5 });
15946
- const ix = await this.tokenClient.buildPurchaseIx(amountLamports, user);
15947
- const tx = new Transaction().add(cuIx, ix);
15948
- const prepared = await this.prepareTx(tx);
15949
- const signed = await this.signTransaction(prepared.tx);
15950
- return this.sendAndConfirmHttp(signed, prepared);
15807
+ const ix = await this.tokenClient.buildPurchaseIx(amountLamports, this.squadsVaultPDA);
15808
+ return !!this.squadsX ? await this.sendSquadsIxs(ix) : await this.buildAndSendIx(ix);
15951
15809
  } catch (err) {
15952
15810
  console.log(`Failed to buy liqSOL pretokens: ${err}`);
15953
15811
  throw err;
15954
15812
  }
15955
15813
  }
15956
15814
  async getPortfolio() {
15957
- if (!this.pubKey) throw new Error("User pubKey is undefined");
15958
15815
  try {
15959
15816
  const user = !!this.squadsX ? this.squadsVaultPDA : this.solPubKey;
15960
15817
  const reservePoolPDA = this.program.deriveReservePoolPda();
@@ -16046,16 +15903,115 @@ const _SolanaStakingClient = class _SolanaStakingClient {
16046
15903
  return this.distributionClient.getUserRecord(this.solPubKey);
16047
15904
  }
16048
15905
  get squadsMultisigPDA() {
16049
- if (!this.squadsX) return null;
15906
+ if (!this.squadsX) return void 0;
16050
15907
  return new PublicKey(this.squadsX.multisigPDA);
16051
15908
  }
16052
15909
  get squadsVaultPDA() {
16053
- if (!this.squadsX || !this.squadsMultisigPDA) return null;
15910
+ if (!this.squadsX || !this.squadsMultisigPDA) return void 0;
16054
15911
  const multisigPda = this.squadsMultisigPDA;
16055
15912
  const index = this.squadsX.vaultIndex ?? 0;
16056
15913
  const pda = multisig.getVaultPda({ multisigPda, index });
16057
15914
  return pda[0];
16058
15915
  }
15916
+ async sendSquadsIxs(ix) {
15917
+ if (!this.squadsX) throw new Error("Attempting to wrap Squads instruction without SquadsX config");
15918
+ const multisigPda = this.squadsMultisigPDA;
15919
+ const vaultPda = this.squadsVaultPDA;
15920
+ const vaultIndex = this.squadsX?.vaultIndex ?? 0;
15921
+ const creator = this.solPubKey;
15922
+ const ms = await multisig.accounts.Multisig.fromAccountAddress(this.connection, multisigPda);
15923
+ const current = BigInt(ms.transactionIndex?.toString() ?? 0);
15924
+ const transactionIndex = current + BigInt(1);
15925
+ const altAddress = this.program.PROGRAM_IDS.ALT_LOOKUP_TABLE;
15926
+ const altAccount = await this.connection.getAddressLookupTable(altAddress);
15927
+ if (!altAccount.value) throw new Error("ALT not found on-chain or not yet active.");
15928
+ const lookupTable = altAccount.value;
15929
+ const computeLimitIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 4e5 });
15930
+ const computePriceIx = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 2e3 });
15931
+ const { blockhash } = await this.connection.getLatestBlockhash("confirmed");
15932
+ const transactionMessage = new TransactionMessage({
15933
+ payerKey: vaultPda,
15934
+ recentBlockhash: blockhash,
15935
+ instructions: [computeLimitIx, computePriceIx, ix]
15936
+ });
15937
+ const createVaultTxIx = await multisig.instructions.vaultTransactionCreate({
15938
+ multisigPda,
15939
+ transactionIndex,
15940
+ creator,
15941
+ vaultIndex,
15942
+ transactionMessage,
15943
+ ephemeralSigners: 0,
15944
+ addressLookupTableAccounts: [lookupTable]
15945
+ });
15946
+ const vaultTransactionCreate = await this.buildAndSendIx(createVaultTxIx);
15947
+ console.log("SQUADSX: vaultTransactionCreate", vaultTransactionCreate);
15948
+ const createProposalIx = await multisig.instructions.proposalCreate({
15949
+ multisigPda,
15950
+ transactionIndex,
15951
+ creator
15952
+ });
15953
+ const proposalCreate = await this.buildAndSendIx(createProposalIx);
15954
+ console.log("SQUADSX: proposalCreate", proposalCreate);
15955
+ return proposalCreate;
15956
+ }
15957
+ async buildAndSendIx(ix) {
15958
+ const cuIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 4e5 });
15959
+ const ixs = Array.isArray(ix) ? ix : [ix];
15960
+ const tx = new Transaction().add(cuIx, ...ixs);
15961
+ const prepared = await this.prepareTx(tx);
15962
+ const signed = await this.signTransaction(prepared.tx);
15963
+ return this.sendAndConfirmHttp(signed, prepared);
15964
+ }
15965
+ async sendAndConfirmHttp(signed, _ctx) {
15966
+ this.ensureUser();
15967
+ const rawTx = signed.serialize();
15968
+ try {
15969
+ const signature = await this.connection.sendRawTransaction(rawTx, {
15970
+ skipPreflight: false,
15971
+ preflightCommitment: commitment,
15972
+ maxRetries: 3
15973
+ });
15974
+ return signature;
15975
+ } catch (e) {
15976
+ const msg = e?.message ?? "";
15977
+ const isSendTxError = e instanceof SendTransactionError || e?.name === "SendTransactionError";
15978
+ if (isSendTxError && msg.includes("already been processed")) {
15979
+ console.warn(
15980
+ 'sendRawTransaction reports "already been processed"; treating as success without further confirmation.'
15981
+ );
15982
+ const legacy = signed;
15983
+ const first = legacy.signatures?.[0]?.signature;
15984
+ if (first) {
15985
+ return bs58.encode(first);
15986
+ }
15987
+ return "already-processed";
15988
+ }
15989
+ throw e;
15990
+ }
15991
+ }
15992
+ async signTransaction(tx) {
15993
+ this.ensureUser();
15994
+ return this.anchor.wallet.signTransaction(tx);
15995
+ }
15996
+ async sendTransaction(signed) {
15997
+ this.ensureUser();
15998
+ return this.anchor.sendAndConfirm(signed);
15999
+ }
16000
+ async prepareTx(tx) {
16001
+ const { blockhash, lastValidBlockHeight } = await this.connection.getLatestBlockhash("confirmed");
16002
+ tx.recentBlockhash = blockhash;
16003
+ tx.feePayer = this.feePayer;
16004
+ return { tx, blockhash, lastValidBlockHeight };
16005
+ }
16006
+ ensureUser() {
16007
+ if (!this.pubKey) throw new Error("User pubKey is undefined");
16008
+ const wallet = this.anchor?.wallet;
16009
+ const pk = wallet?.publicKey;
16010
+ if (!pk) throw new Error("Wallet not connected");
16011
+ if (typeof wallet.signTransaction !== "function") {
16012
+ throw new Error("Wallet does not support signTransaction");
16013
+ }
16014
+ }
16059
16015
  async getTrancheSnapshot(chainID) {
16060
16016
  try {
16061
16017
  const [globalState, trancheState] = await Promise.all([
@@ -16097,10 +16053,24 @@ const _SolanaStakingClient = class _SolanaStakingClient {
16097
16053
  return Number(DEFAULT_AVERAGE_PAY_RATE) / Number(PAY_RATE_SCALE_FACTOR);
16098
16054
  }
16099
16055
  const currentIndex = Number(payRateHistory.currentIndex);
16100
- const latestIdx = (currentIndex - 1 + maxEntries) % maxEntries;
16101
- const latestEntry = payRateHistory.entries[latestIdx];
16102
- const raw = BigInt(latestEntry.scaledRate.toString());
16103
- return Number(raw) / Number(PAY_RATE_SCALE_FACTOR);
16056
+ const processedCount = Math.min(totalEntriesAdded, maxEntries);
16057
+ let sum = BigInt(0);
16058
+ let validCount = 0;
16059
+ let idx = (currentIndex - 1 + maxEntries) % maxEntries;
16060
+ for (let i = 0; i < processedCount; i++) {
16061
+ const entry = payRateHistory.entries[idx];
16062
+ const scaledRate = BigInt(entry.scaledRate.toString());
16063
+ if (scaledRate > BigInt(0)) {
16064
+ sum += scaledRate;
16065
+ validCount++;
16066
+ }
16067
+ idx = (idx - 1 + maxEntries) % maxEntries;
16068
+ }
16069
+ if (validCount === 0) {
16070
+ return Number(DEFAULT_AVERAGE_PAY_RATE) / Number(PAY_RATE_SCALE_FACTOR);
16071
+ }
16072
+ const average = Number(sum / BigInt(validCount));
16073
+ return average / Number(PAY_RATE_SCALE_FACTOR);
16104
16074
  }
16105
16075
  async getEpochsPerYearFromCluster() {
16106
16076
  const now = Date.now();
@@ -16235,87 +16205,6 @@ const _SolanaStakingClient = class _SolanaStakingClient {
16235
16205
  };
16236
16206
  return singleTxFeeLamports;
16237
16207
  }
16238
- async sendAndConfirmHttp(signed, _ctx) {
16239
- this.ensureUser();
16240
- const rawTx = signed.serialize();
16241
- let signature;
16242
- try {
16243
- signature = await this.connection.sendRawTransaction(rawTx, {
16244
- skipPreflight: false,
16245
- preflightCommitment: commitment,
16246
- maxRetries: 3
16247
- });
16248
- } catch (e) {
16249
- const msg = e?.message ?? "";
16250
- const isSendTxError = e instanceof SendTransactionError || e?.name === "SendTransactionError";
16251
- if (isSendTxError && msg.includes("already been processed")) {
16252
- console.warn(
16253
- 'sendRawTransaction preflight says "already been processed"; treating as success and deriving signature from signed tx.'
16254
- );
16255
- const legacy = signed;
16256
- const first = legacy.signatures?.[0]?.signature;
16257
- if (!first) {
16258
- throw e;
16259
- }
16260
- signature = bs58.encode(first);
16261
- } else {
16262
- throw e;
16263
- }
16264
- }
16265
- const start = Date.now();
16266
- const timeoutMs = 3e4;
16267
- const pollIntervalMs = 500;
16268
- while (true) {
16269
- const { value } = await this.connection.getSignatureStatuses(
16270
- [signature],
16271
- { searchTransactionHistory: true }
16272
- );
16273
- const status = value[0];
16274
- if (status) {
16275
- if (status.err) {
16276
- throw new Error(
16277
- `Transaction failed: ${JSON.stringify(status.err)}`
16278
- );
16279
- }
16280
- const confirmations = status.confirmations;
16281
- const confirmationStatus = status.confirmationStatus;
16282
- const satisfied = confirmationStatus === "confirmed" || confirmationStatus === "finalized" || confirmations === null ||
16283
- (confirmations ?? 0) > 0;
16284
- if (satisfied) {
16285
- return signature;
16286
- }
16287
- }
16288
- if (Date.now() - start > timeoutMs) {
16289
- throw new Error(
16290
- `Transaction confirmation timed out for ${signature}`
16291
- );
16292
- }
16293
- await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
16294
- }
16295
- }
16296
- async signTransaction(tx) {
16297
- this.ensureUser();
16298
- return this.anchor.wallet.signTransaction(tx);
16299
- }
16300
- async sendTransaction(signed) {
16301
- this.ensureUser();
16302
- return this.anchor.sendAndConfirm(signed);
16303
- }
16304
- async prepareTx(tx) {
16305
- const { blockhash, lastValidBlockHeight } = await this.connection.getLatestBlockhash("confirmed");
16306
- tx.recentBlockhash = blockhash;
16307
- tx.feePayer = this.feePayer;
16308
- return { tx, blockhash, lastValidBlockHeight };
16309
- }
16310
- ensureUser() {
16311
- if (!this.pubKey) throw new Error("User pubKey is undefined");
16312
- const wallet = this.anchor?.wallet;
16313
- const pk = wallet?.publicKey;
16314
- if (!pk) throw new Error("Wallet not connected");
16315
- if (typeof wallet.signTransaction !== "function") {
16316
- throw new Error("Wallet does not support signTransaction");
16317
- }
16318
- }
16319
16208
  };
16320
16209
  _SolanaStakingClient.EPOCHS_PER_YEAR_TTL_MS = 10 * 60 * 1e3;
16321
16210
  _SolanaStakingClient.FEE_CACHE_TTL_MS = 6e4;