@ignitionfi/spl-stake-pool 1.1.21 → 1.1.23

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.
@@ -19020,6 +19020,8 @@ var solanaStakePool = (function (exports, node_buffer) {
19020
19020
  const EPHEMERAL_STAKE_SEED_PREFIX = node_buffer.Buffer.from('ephemeral');
19021
19021
  // Seed used to derive transient stake accounts.
19022
19022
  const TRANSIENT_STAKE_SEED_PREFIX = node_buffer.Buffer.from('transient');
19023
+ // Seed for user stake account created during session withdrawal
19024
+ const USER_STAKE_SEED_PREFIX = node_buffer.Buffer.from('user_stake');
19023
19025
  // Minimum amount of staked SOL required in a validator stake account to allow
19024
19026
  // for merges without a mismatch on credits observed
19025
19027
  const MINIMUM_ACTIVE_STAKE = LAMPORTS_PER_SOL;
@@ -19128,6 +19130,19 @@ var solanaStakePool = (function (exports, node_buffer) {
19128
19130
  const [publicKey] = PublicKey.findProgramAddressSync([node_buffer.Buffer.from('metadata'), METADATA_PROGRAM_ID.toBuffer(), stakePoolMintAddress.toBuffer()], METADATA_PROGRAM_ID);
19129
19131
  return publicKey;
19130
19132
  }
19133
+ /**
19134
+ * Generates the user stake account PDA for session-based withdrawals.
19135
+ * The PDA is derived from the user's wallet and a unique seed.
19136
+ */
19137
+ function findUserStakeProgramAddress(programId, userWallet, seed) {
19138
+ const seedBN = typeof seed === 'number' ? new BN(seed) : seed;
19139
+ const [publicKey] = PublicKey.findProgramAddressSync([
19140
+ USER_STAKE_SEED_PREFIX,
19141
+ userWallet.toBuffer(),
19142
+ seedBN.toArrayLike(node_buffer.Buffer, 'le', 8),
19143
+ ], programId);
19144
+ return publicKey;
19145
+ }
19131
19146
 
19132
19147
  var Layout = {};
19133
19148
 
@@ -22304,6 +22319,7 @@ var solanaStakePool = (function (exports, node_buffer) {
22304
22319
  LayoutExports$1.u8('instruction'),
22305
22320
  LayoutExports$1.ns64('poolTokensIn'),
22306
22321
  LayoutExports$1.ns64('minimumLamportsOut'),
22322
+ LayoutExports$1.ns64('userStakeSeed'),
22307
22323
  ]),
22308
22324
  },
22309
22325
  });
@@ -22789,6 +22805,7 @@ var solanaStakePool = (function (exports, node_buffer) {
22789
22805
  const data = encodeData(type, {
22790
22806
  poolTokensIn: params.poolTokensIn,
22791
22807
  minimumLamportsOut: params.minimumLamportsOut,
22808
+ userStakeSeed: params.userStakeSeed,
22792
22809
  });
22793
22810
  const keys = [
22794
22811
  { pubkey: params.stakePool, isSigner: false, isWritable: true },
@@ -22805,6 +22822,8 @@ var solanaStakePool = (function (exports, node_buffer) {
22805
22822
  { pubkey: params.tokenProgramId, isSigner: false, isWritable: false },
22806
22823
  { pubkey: StakeProgram.programId, isSigner: false, isWritable: false },
22807
22824
  { pubkey: params.programSigner, isSigner: false, isWritable: false },
22825
+ { pubkey: params.payer, isSigner: true, isWritable: true },
22826
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
22808
22827
  ];
22809
22828
  return new TransactionInstruction({
22810
22829
  programId: params.programId,
@@ -23422,10 +23441,46 @@ var solanaStakePool = (function (exports, node_buffer) {
23422
23441
  };
23423
23442
  }
23424
23443
  /**
23425
- * Creates instructions required to withdraw stake from a stake pool using a Fogo session.
23426
- * The withdrawn stake account will be authorized to the user's wallet.
23427
- */
23428
- async function withdrawStakeWithSession(connection, stakePoolAddress, signerOrSession, userPubkey, amount, useReserve = false, voteAccountAddress, minimumLamportsOut = 0, payer, validatorComparator) {
23444
+ * Finds the next available seed for creating a user stake PDA.
23445
+ * Scans from startSeed until an unused PDA is found.
23446
+ *
23447
+ * @param connection - Solana connection
23448
+ * @param programId - The stake pool program ID
23449
+ * @param userPubkey - User's wallet (used for PDA derivation)
23450
+ * @param startSeed - Starting seed to search from (default: 0)
23451
+ * @param maxSeed - Maximum seed to check before giving up (default: 1000)
23452
+ * @returns The next available seed
23453
+ * @throws Error if no available seed found within maxSeed
23454
+ */
23455
+ async function findNextUserStakeSeed(connection, programId, userPubkey, startSeed = 0, maxSeed = 1000) {
23456
+ for (let seed = startSeed; seed < startSeed + maxSeed; seed++) {
23457
+ const pda = findUserStakeProgramAddress(programId, userPubkey, seed);
23458
+ const account = await connection.getAccountInfo(pda);
23459
+ if (!account) {
23460
+ return seed;
23461
+ }
23462
+ }
23463
+ throw new Error(`No available user stake seed found between ${startSeed} and ${startSeed + maxSeed - 1}`);
23464
+ }
23465
+ /**
23466
+ * Withdraws stake from a stake pool using a Fogo session.
23467
+ *
23468
+ * The on-chain program creates stake account PDAs, so no pre-creation step is needed.
23469
+ * The paymaster payer provides rent for the stake account PDAs.
23470
+ *
23471
+ * @param connection - Solana connection
23472
+ * @param stakePoolAddress - The stake pool to withdraw from
23473
+ * @param signerOrSession - The session signer public key
23474
+ * @param userPubkey - User's wallet (used for PDA derivation and token ownership)
23475
+ * @param payer - Payer for stake account rent (paymaster payer in session context)
23476
+ * @param amount - Amount of pool tokens to withdraw
23477
+ * @param userStakeSeedStart - Starting seed for user stake PDA derivation (default: 0)
23478
+ * @param useReserve - Whether to withdraw from reserve (default: false)
23479
+ * @param voteAccountAddress - Optional specific validator to withdraw from
23480
+ * @param minimumLamportsOut - Minimum lamports to receive (slippage protection)
23481
+ * @param validatorComparator - Optional comparator for validator selection
23482
+ */
23483
+ async function withdrawStakeWithSession(connection, stakePoolAddress, signerOrSession, userPubkey, payer, amount, userStakeSeedStart = 0, useReserve = false, voteAccountAddress, minimumLamportsOut = 0, validatorComparator) {
23429
23484
  const stakePoolAccount = await getStakePoolAccount(connection, stakePoolAddress);
23430
23485
  const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
23431
23486
  const stakePool = stakePoolAccount.account.data;
@@ -23475,8 +23530,8 @@ var solanaStakePool = (function (exports, node_buffer) {
23475
23530
  withdrawAccounts.push(...(await prepareWithdrawAccounts(connection, stakePool, stakePoolAddress, poolAmount, validatorComparator, poolTokenAccount.equals(stakePool.managerFeeAccount))));
23476
23531
  }
23477
23532
  const instructions = [];
23478
- const signers = [];
23479
23533
  const stakeAccountPubkeys = [];
23534
+ const userStakeSeeds = [];
23480
23535
  // Max 5 accounts to prevent an error: "Transaction too large"
23481
23536
  const maxWithdrawAccounts = 5;
23482
23537
  let i = 0;
@@ -23484,41 +23539,36 @@ var solanaStakePool = (function (exports, node_buffer) {
23484
23539
  if (i >= maxWithdrawAccounts) {
23485
23540
  break;
23486
23541
  }
23487
- // Create a new stake account to receive the withdrawal
23488
- const stakeReceiver = Keypair.generate();
23489
- signers.push(stakeReceiver);
23490
- stakeAccountPubkeys.push(stakeReceiver.publicKey);
23491
- // Create the stake account that will receive the split stake
23492
- instructions.push(SystemProgram.createAccount({
23493
- fromPubkey: payer !== null && payer !== void 0 ? payer : userPubkey,
23494
- newAccountPubkey: stakeReceiver.publicKey,
23495
- lamports: stakeAccountRentExemption,
23496
- space: StakeProgram.space,
23497
- programId: StakeProgram.programId,
23498
- }));
23499
- // Add the withdraw stake with session instruction
23542
+ // Derive the stake account PDA for this withdrawal
23543
+ const userStakeSeed = userStakeSeedStart + i;
23544
+ const stakeReceiverPubkey = findUserStakeProgramAddress(stakePoolProgramId, userPubkey, userStakeSeed);
23545
+ stakeAccountPubkeys.push(stakeReceiverPubkey);
23546
+ userStakeSeeds.push(userStakeSeed);
23547
+ // The on-chain program will create the stake account PDA
23500
23548
  instructions.push(StakePoolInstruction.withdrawStakeWithSession({
23501
23549
  programId: stakePoolProgramId,
23502
23550
  stakePool: stakePoolAddress,
23503
23551
  validatorList: stakePool.validatorList,
23504
23552
  withdrawAuthority,
23505
23553
  stakeToSplit: withdrawAccount.stakeAddress,
23506
- stakeToReceive: stakeReceiver.publicKey,
23554
+ stakeToReceive: stakeReceiverPubkey,
23507
23555
  sessionSigner: signerOrSession,
23508
23556
  burnFromPool: poolTokenAccount,
23509
23557
  managerFeeAccount: stakePool.managerFeeAccount,
23510
23558
  poolMint: stakePool.poolMint,
23511
23559
  tokenProgramId: stakePool.tokenProgramId,
23512
23560
  programSigner,
23561
+ payer,
23513
23562
  poolTokensIn: withdrawAccount.poolAmount.toNumber(),
23514
- minimumLamportsOut: solToLamports(minimumLamportsOut),
23563
+ minimumLamportsOut,
23564
+ userStakeSeed,
23515
23565
  }));
23516
23566
  i++;
23517
23567
  }
23518
23568
  return {
23519
23569
  instructions,
23520
- signers,
23521
23570
  stakeAccountPubkeys,
23571
+ userStakeSeeds,
23522
23572
  };
23523
23573
  }
23524
23574
  async function addValidatorToPool(connection, stakePoolAddress, validatorVote, seed) {
@@ -23896,6 +23946,13 @@ var solanaStakePool = (function (exports, node_buffer) {
23896
23946
  exports.depositSol = depositSol;
23897
23947
  exports.depositStake = depositStake;
23898
23948
  exports.depositWsolWithSession = depositWsolWithSession;
23949
+ exports.findEphemeralStakeProgramAddress = findEphemeralStakeProgramAddress;
23950
+ exports.findNextUserStakeSeed = findNextUserStakeSeed;
23951
+ exports.findStakeProgramAddress = findStakeProgramAddress;
23952
+ exports.findTransientStakeProgramAddress = findTransientStakeProgramAddress;
23953
+ exports.findUserStakeProgramAddress = findUserStakeProgramAddress;
23954
+ exports.findWithdrawAuthorityProgramAddress = findWithdrawAuthorityProgramAddress;
23955
+ exports.findWsolTransientProgramAddress = findWsolTransientProgramAddress;
23899
23956
  exports.getStakeAccount = getStakeAccount;
23900
23957
  exports.getStakePoolAccount = getStakePoolAccount;
23901
23958
  exports.getStakePoolAccounts = getStakePoolAccounts;