@ignitionfi/spl-stake-pool 1.1.22 → 1.1.24

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
  });
@@ -22739,9 +22755,9 @@ var solanaStakePool = (function (exports, node_buffer) {
22739
22755
  }
22740
22756
  /**
22741
22757
  * Creates a transaction instruction to withdraw WSOL from a stake pool using a session.
22758
+ * Rent for ATA creation (if needed) is paid from the withdrawal amount.
22742
22759
  */
22743
22760
  static withdrawWsolWithSession(params) {
22744
- var _a;
22745
22761
  const type = STAKE_POOL_INSTRUCTION_LAYOUTS.WithdrawWsolWithSession;
22746
22762
  const data = encodeData(type, {
22747
22763
  poolTokensIn: params.poolTokensIn,
@@ -22762,7 +22778,6 @@ var solanaStakePool = (function (exports, node_buffer) {
22762
22778
  { pubkey: params.tokenProgramId, isSigner: false, isWritable: false },
22763
22779
  { pubkey: params.wsolMint, isSigner: false, isWritable: false },
22764
22780
  { pubkey: params.programSigner, isSigner: false, isWritable: true },
22765
- { pubkey: (_a = params.payer) !== null && _a !== void 0 ? _a : params.userTransferAuthority, isSigner: true, isWritable: true },
22766
22781
  { pubkey: params.userWallet, isSigner: false, isWritable: false },
22767
22782
  { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
22768
22783
  ];
@@ -22783,12 +22798,14 @@ var solanaStakePool = (function (exports, node_buffer) {
22783
22798
  }
22784
22799
  /**
22785
22800
  * Creates a transaction instruction to withdraw stake from a stake pool using a Fogo session.
22801
+ * The stake account is created as a PDA and rent is paid from the withdrawal amount.
22786
22802
  */
22787
22803
  static withdrawStakeWithSession(params) {
22788
22804
  const type = STAKE_POOL_INSTRUCTION_LAYOUTS.WithdrawStakeWithSession;
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,7 @@ 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: SystemProgram.programId, isSigner: false, isWritable: false },
22808
22826
  ];
22809
22827
  return new TransactionInstruction({
22810
22828
  programId: params.programId,
@@ -23378,8 +23396,9 @@ var solanaStakePool = (function (exports, node_buffer) {
23378
23396
  }
23379
23397
  /**
23380
23398
  * Creates instructions required to withdraw wSOL from a stake pool.
23399
+ * Rent for ATA creation (if needed) is paid from the withdrawal amount.
23381
23400
  */
23382
- async function withdrawWsolWithSession(connection, stakePoolAddress, signerOrSession, userPubkey, amount, minimumLamportsOut = 0, solWithdrawAuthority, payer) {
23401
+ async function withdrawWsolWithSession(connection, stakePoolAddress, signerOrSession, userPubkey, amount, minimumLamportsOut = 0, solWithdrawAuthority) {
23383
23402
  const stakePoolAccount = await getStakePoolAccount(connection, stakePoolAddress);
23384
23403
  const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
23385
23404
  const stakePool = stakePoolAccount.account.data;
@@ -23412,7 +23431,6 @@ var solanaStakePool = (function (exports, node_buffer) {
23412
23431
  wsolMint: NATIVE_MINT,
23413
23432
  programSigner,
23414
23433
  userWallet: userPubkey,
23415
- payer,
23416
23434
  poolTokensIn: poolTokens,
23417
23435
  minimumLamportsOut,
23418
23436
  }));
@@ -23422,10 +23440,45 @@ var solanaStakePool = (function (exports, node_buffer) {
23422
23440
  };
23423
23441
  }
23424
23442
  /**
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, payer, useReserve = false, voteAccountAddress, minimumLamportsOut = 0, validatorComparator) {
23443
+ * Finds the next available seed for creating a user stake PDA.
23444
+ * Scans from startSeed until an unused PDA is found.
23445
+ *
23446
+ * @param connection - Solana connection
23447
+ * @param programId - The stake pool program ID
23448
+ * @param userPubkey - User's wallet (used for PDA derivation)
23449
+ * @param startSeed - Starting seed to search from (default: 0)
23450
+ * @param maxSeed - Maximum seed to check before giving up (default: 1000)
23451
+ * @returns The next available seed
23452
+ * @throws Error if no available seed found within maxSeed
23453
+ */
23454
+ async function findNextUserStakeSeed(connection, programId, userPubkey, startSeed = 0, maxSeed = 1000) {
23455
+ for (let seed = startSeed; seed < startSeed + maxSeed; seed++) {
23456
+ const pda = findUserStakeProgramAddress(programId, userPubkey, seed);
23457
+ const account = await connection.getAccountInfo(pda);
23458
+ if (!account) {
23459
+ return seed;
23460
+ }
23461
+ }
23462
+ throw new Error(`No available user stake seed found between ${startSeed} and ${startSeed + maxSeed - 1}`);
23463
+ }
23464
+ /**
23465
+ * Withdraws stake from a stake pool using a Fogo session.
23466
+ *
23467
+ * The on-chain program creates stake account PDAs, so no pre-creation step is needed.
23468
+ * Rent for the stake account PDAs is paid from the withdrawal amount.
23469
+ *
23470
+ * @param connection - Solana connection
23471
+ * @param stakePoolAddress - The stake pool to withdraw from
23472
+ * @param signerOrSession - The session signer public key
23473
+ * @param userPubkey - User's wallet (used for PDA derivation and token ownership)
23474
+ * @param amount - Amount of pool tokens to withdraw
23475
+ * @param userStakeSeedStart - Starting seed for user stake PDA derivation (default: 0)
23476
+ * @param useReserve - Whether to withdraw from reserve (default: false)
23477
+ * @param voteAccountAddress - Optional specific validator to withdraw from
23478
+ * @param minimumLamportsOut - Minimum lamports to receive (slippage protection)
23479
+ * @param validatorComparator - Optional comparator for validator selection
23480
+ */
23481
+ async function withdrawStakeWithSession(connection, stakePoolAddress, signerOrSession, userPubkey, amount, userStakeSeedStart = 0, useReserve = false, voteAccountAddress, minimumLamportsOut = 0, validatorComparator) {
23429
23482
  const stakePoolAccount = await getStakePoolAccount(connection, stakePoolAddress);
23430
23483
  const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
23431
23484
  const stakePool = stakePoolAccount.account.data;
@@ -23476,6 +23529,7 @@ var solanaStakePool = (function (exports, node_buffer) {
23476
23529
  }
23477
23530
  const instructions = [];
23478
23531
  const stakeAccountPubkeys = [];
23532
+ const userStakeSeeds = [];
23479
23533
  // Max 5 accounts to prevent an error: "Transaction too large"
23480
23534
  const maxWithdrawAccounts = 5;
23481
23535
  let i = 0;
@@ -23483,26 +23537,12 @@ var solanaStakePool = (function (exports, node_buffer) {
23483
23537
  if (i >= maxWithdrawAccounts) {
23484
23538
  break;
23485
23539
  }
23486
- // Create a deterministic stake account address using a seed
23487
- // This avoids needing the new account to sign (required for sessions)
23488
- // We use payer as base so only payer needs to sign (payer = basePubkey)
23489
- // The seed includes timestamp + random component to ensure uniqueness
23490
- const uniqueId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
23491
- const seed = `ws:${uniqueId}:${i}`.slice(0, 32); // Seed max 32 chars
23492
- const stakeReceiverPubkey = await PublicKey.createWithSeed(payer, seed, StakeProgram.programId);
23540
+ // Derive the stake account PDA for this withdrawal
23541
+ const userStakeSeed = userStakeSeedStart + i;
23542
+ const stakeReceiverPubkey = findUserStakeProgramAddress(stakePoolProgramId, userPubkey, userStakeSeed);
23493
23543
  stakeAccountPubkeys.push(stakeReceiverPubkey);
23494
- // Create the stake account using createAccountWithSeed
23495
- // Since basePubkey === fromPubkey (both are payer), only payer needs to sign
23496
- instructions.push(SystemProgram.createAccountWithSeed({
23497
- fromPubkey: payer,
23498
- newAccountPubkey: stakeReceiverPubkey,
23499
- basePubkey: payer,
23500
- seed,
23501
- lamports: stakeAccountRentExemption,
23502
- space: StakeProgram.space,
23503
- programId: StakeProgram.programId,
23504
- }));
23505
- // Add the withdraw stake with session instruction
23544
+ userStakeSeeds.push(userStakeSeed);
23545
+ // The on-chain program will create the stake account PDA
23506
23546
  instructions.push(StakePoolInstruction.withdrawStakeWithSession({
23507
23547
  programId: stakePoolProgramId,
23508
23548
  stakePool: stakePoolAddress,
@@ -23518,12 +23558,14 @@ var solanaStakePool = (function (exports, node_buffer) {
23518
23558
  programSigner,
23519
23559
  poolTokensIn: withdrawAccount.poolAmount.toNumber(),
23520
23560
  minimumLamportsOut,
23561
+ userStakeSeed,
23521
23562
  }));
23522
23563
  i++;
23523
23564
  }
23524
23565
  return {
23525
23566
  instructions,
23526
23567
  stakeAccountPubkeys,
23568
+ userStakeSeeds,
23527
23569
  };
23528
23570
  }
23529
23571
  async function addValidatorToPool(connection, stakePoolAddress, validatorVote, seed) {
@@ -23901,6 +23943,13 @@ var solanaStakePool = (function (exports, node_buffer) {
23901
23943
  exports.depositSol = depositSol;
23902
23944
  exports.depositStake = depositStake;
23903
23945
  exports.depositWsolWithSession = depositWsolWithSession;
23946
+ exports.findEphemeralStakeProgramAddress = findEphemeralStakeProgramAddress;
23947
+ exports.findNextUserStakeSeed = findNextUserStakeSeed;
23948
+ exports.findStakeProgramAddress = findStakeProgramAddress;
23949
+ exports.findTransientStakeProgramAddress = findTransientStakeProgramAddress;
23950
+ exports.findUserStakeProgramAddress = findUserStakeProgramAddress;
23951
+ exports.findWithdrawAuthorityProgramAddress = findWithdrawAuthorityProgramAddress;
23952
+ exports.findWsolTransientProgramAddress = findWsolTransientProgramAddress;
23904
23953
  exports.getStakeAccount = getStakeAccount;
23905
23954
  exports.getStakePoolAccount = getStakePoolAccount;
23906
23955
  exports.getStakePoolAccounts = getStakePoolAccounts;