@ignitionfi/spl-stake-pool 1.1.20 → 1.1.21

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.
@@ -1062,7 +1062,8 @@ const STAKE_POOL_INSTRUCTION_LAYOUTS = Object.freeze({
1062
1062
  index: 24,
1063
1063
  layout: BufferLayout.struct([
1064
1064
  BufferLayout.u8('instruction'),
1065
- BufferLayout.ns64('lamports'),
1065
+ BufferLayout.ns64('poolTokensIn'),
1066
+ BufferLayout.ns64('minimumLamportsOut'),
1066
1067
  ]),
1067
1068
  },
1068
1069
  DepositSolWithSlippage: {
@@ -1095,6 +1096,14 @@ const STAKE_POOL_INSTRUCTION_LAYOUTS = Object.freeze({
1095
1096
  BufferLayout.ns64('minimumLamportsOut'),
1096
1097
  ]),
1097
1098
  },
1099
+ WithdrawStakeWithSession: {
1100
+ index: 29,
1101
+ layout: BufferLayout.struct([
1102
+ BufferLayout.u8('instruction'),
1103
+ BufferLayout.ns64('poolTokensIn'),
1104
+ BufferLayout.ns64('minimumLamportsOut'),
1105
+ ]),
1106
+ },
1098
1107
  });
1099
1108
  /**
1100
1109
  * Stake Pool Instruction class
@@ -1570,6 +1579,37 @@ class StakePoolInstruction {
1570
1579
  data,
1571
1580
  });
1572
1581
  }
1582
+ /**
1583
+ * Creates a transaction instruction to withdraw stake from a stake pool using a Fogo session.
1584
+ */
1585
+ static withdrawStakeWithSession(params) {
1586
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.WithdrawStakeWithSession;
1587
+ const data = encodeData(type, {
1588
+ poolTokensIn: params.poolTokensIn,
1589
+ minimumLamportsOut: params.minimumLamportsOut,
1590
+ });
1591
+ const keys = [
1592
+ { pubkey: params.stakePool, isSigner: false, isWritable: true },
1593
+ { pubkey: params.validatorList, isSigner: false, isWritable: true },
1594
+ { pubkey: params.withdrawAuthority, isSigner: false, isWritable: false },
1595
+ { pubkey: params.stakeToSplit, isSigner: false, isWritable: true },
1596
+ { pubkey: params.stakeToReceive, isSigner: false, isWritable: true },
1597
+ { pubkey: params.sessionSigner, isSigner: true, isWritable: false }, // user_stake_authority_info (signer_or_session)
1598
+ { pubkey: params.sessionSigner, isSigner: false, isWritable: false }, // user_transfer_authority_info (not used in session path)
1599
+ { pubkey: params.burnFromPool, isSigner: false, isWritable: true },
1600
+ { pubkey: params.managerFeeAccount, isSigner: false, isWritable: true },
1601
+ { pubkey: params.poolMint, isSigner: false, isWritable: true },
1602
+ { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1603
+ { pubkey: params.tokenProgramId, isSigner: false, isWritable: false },
1604
+ { pubkey: StakeProgram.programId, isSigner: false, isWritable: false },
1605
+ { pubkey: params.programSigner, isSigner: false, isWritable: false },
1606
+ ];
1607
+ return new TransactionInstruction({
1608
+ programId: params.programId,
1609
+ keys,
1610
+ data,
1611
+ });
1612
+ }
1573
1613
  /**
1574
1614
  * Creates an instruction to create metadata
1575
1615
  * using the mpl token metadata program for the pool token
@@ -2179,6 +2219,106 @@ async function withdrawWsolWithSession(connection, stakePoolAddress, signerOrSes
2179
2219
  signers,
2180
2220
  };
2181
2221
  }
2222
+ /**
2223
+ * Creates instructions required to withdraw stake from a stake pool using a Fogo session.
2224
+ * The withdrawn stake account will be authorized to the user's wallet.
2225
+ */
2226
+ async function withdrawStakeWithSession(connection, stakePoolAddress, signerOrSession, userPubkey, amount, useReserve = false, voteAccountAddress, minimumLamportsOut = 0, payer, validatorComparator) {
2227
+ const stakePoolAccount = await getStakePoolAccount(connection, stakePoolAddress);
2228
+ const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
2229
+ const stakePool = stakePoolAccount.account.data;
2230
+ const poolTokens = solToLamports(amount);
2231
+ const poolAmount = new BN(poolTokens);
2232
+ const poolTokenAccount = getAssociatedTokenAddressSync(stakePool.poolMint, userPubkey);
2233
+ const tokenAccount = await getAccount(connection, poolTokenAccount);
2234
+ if (tokenAccount.amount < poolTokens) {
2235
+ throw new Error(`Not enough token balance to withdraw ${amount} pool tokens.
2236
+ Maximum withdraw amount is ${lamportsToSol(tokenAccount.amount)} pool tokens.`);
2237
+ }
2238
+ const [programSigner] = PublicKey.findProgramAddressSync([Buffer.from('fogo_session_program_signer')], stakePoolProgramId);
2239
+ const withdrawAuthority = await findWithdrawAuthorityProgramAddress(stakePoolProgramId, stakePoolAddress);
2240
+ const stakeAccountRentExemption = await connection.getMinimumBalanceForRentExemption(StakeProgram.space);
2241
+ // Determine which stake accounts to withdraw from
2242
+ const withdrawAccounts = [];
2243
+ if (useReserve) {
2244
+ withdrawAccounts.push({
2245
+ stakeAddress: stakePool.reserveStake,
2246
+ voteAddress: undefined,
2247
+ poolAmount,
2248
+ });
2249
+ }
2250
+ else if (voteAccountAddress) {
2251
+ const stakeAccountAddress = await findStakeProgramAddress(stakePoolProgramId, voteAccountAddress, stakePoolAddress);
2252
+ const stakeAccount = await connection.getAccountInfo(stakeAccountAddress);
2253
+ if (!stakeAccount) {
2254
+ throw new Error(`Validator stake account not found for vote address ${voteAccountAddress.toBase58()}`);
2255
+ }
2256
+ const availableLamports = new BN(stakeAccount.lamports - MINIMUM_ACTIVE_STAKE - stakeAccountRentExemption);
2257
+ if (availableLamports.lt(new BN(0))) {
2258
+ throw new Error('Invalid Stake Account');
2259
+ }
2260
+ const availableForWithdrawal = calcLamportsWithdrawAmount(stakePool, availableLamports);
2261
+ if (availableForWithdrawal.lt(poolAmount)) {
2262
+ throw new Error(`Not enough lamports available for withdrawal from ${stakeAccountAddress},
2263
+ ${poolAmount} asked, ${availableForWithdrawal} available.`);
2264
+ }
2265
+ withdrawAccounts.push({
2266
+ stakeAddress: stakeAccountAddress,
2267
+ voteAddress: voteAccountAddress,
2268
+ poolAmount,
2269
+ });
2270
+ }
2271
+ else {
2272
+ // Get the list of accounts to withdraw from automatically
2273
+ withdrawAccounts.push(...(await prepareWithdrawAccounts(connection, stakePool, stakePoolAddress, poolAmount, validatorComparator, poolTokenAccount.equals(stakePool.managerFeeAccount))));
2274
+ }
2275
+ const instructions = [];
2276
+ const signers = [];
2277
+ const stakeAccountPubkeys = [];
2278
+ // Max 5 accounts to prevent an error: "Transaction too large"
2279
+ const maxWithdrawAccounts = 5;
2280
+ let i = 0;
2281
+ for (const withdrawAccount of withdrawAccounts) {
2282
+ if (i >= maxWithdrawAccounts) {
2283
+ break;
2284
+ }
2285
+ // Create a new stake account to receive the withdrawal
2286
+ const stakeReceiver = Keypair.generate();
2287
+ signers.push(stakeReceiver);
2288
+ stakeAccountPubkeys.push(stakeReceiver.publicKey);
2289
+ // Create the stake account that will receive the split stake
2290
+ instructions.push(SystemProgram.createAccount({
2291
+ fromPubkey: payer !== null && payer !== void 0 ? payer : userPubkey,
2292
+ newAccountPubkey: stakeReceiver.publicKey,
2293
+ lamports: stakeAccountRentExemption,
2294
+ space: StakeProgram.space,
2295
+ programId: StakeProgram.programId,
2296
+ }));
2297
+ // Add the withdraw stake with session instruction
2298
+ instructions.push(StakePoolInstruction.withdrawStakeWithSession({
2299
+ programId: stakePoolProgramId,
2300
+ stakePool: stakePoolAddress,
2301
+ validatorList: stakePool.validatorList,
2302
+ withdrawAuthority,
2303
+ stakeToSplit: withdrawAccount.stakeAddress,
2304
+ stakeToReceive: stakeReceiver.publicKey,
2305
+ sessionSigner: signerOrSession,
2306
+ burnFromPool: poolTokenAccount,
2307
+ managerFeeAccount: stakePool.managerFeeAccount,
2308
+ poolMint: stakePool.poolMint,
2309
+ tokenProgramId: stakePool.tokenProgramId,
2310
+ programSigner,
2311
+ poolTokensIn: withdrawAccount.poolAmount.toNumber(),
2312
+ minimumLamportsOut: solToLamports(minimumLamportsOut),
2313
+ }));
2314
+ i++;
2315
+ }
2316
+ return {
2317
+ instructions,
2318
+ signers,
2319
+ stakeAccountPubkeys,
2320
+ };
2321
+ }
2182
2322
  async function addValidatorToPool(connection, stakePoolAddress, validatorVote, seed) {
2183
2323
  const stakePoolAccount = await getStakePoolAccount(connection, stakePoolAddress);
2184
2324
  const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
@@ -2541,5 +2681,5 @@ async function updatePoolTokenMetadata(connection, stakePoolAddress, name, symbo
2541
2681
  };
2542
2682
  }
2543
2683
 
2544
- export { DEVNET_STAKE_POOL_PROGRAM_ID, STAKE_POOL_INSTRUCTION_LAYOUTS, STAKE_POOL_PROGRAM_ID, StakePoolInstruction, StakePoolLayout, ValidatorListLayout, ValidatorStakeInfoLayout, addValidatorToPool, createPoolTokenMetadata, decreaseValidatorStake, depositSol, depositStake, depositWsolWithSession, getStakeAccount, getStakePoolAccount, getStakePoolAccounts, getStakePoolProgramId, increaseValidatorStake, removeValidatorFromPool, stakePoolInfo, tokenMetadataLayout, updatePoolTokenMetadata, updateStakePool, withdrawSol, withdrawStake, withdrawWsolWithSession };
2684
+ export { DEVNET_STAKE_POOL_PROGRAM_ID, STAKE_POOL_INSTRUCTION_LAYOUTS, STAKE_POOL_PROGRAM_ID, StakePoolInstruction, StakePoolLayout, ValidatorListLayout, ValidatorStakeInfoLayout, addValidatorToPool, createPoolTokenMetadata, decreaseValidatorStake, depositSol, depositStake, depositWsolWithSession, getStakeAccount, getStakePoolAccount, getStakePoolAccounts, getStakePoolProgramId, increaseValidatorStake, removeValidatorFromPool, stakePoolInfo, tokenMetadataLayout, updatePoolTokenMetadata, updateStakePool, withdrawSol, withdrawStake, withdrawStakeWithSession, withdrawWsolWithSession };
2545
2685
  //# sourceMappingURL=index.browser.esm.js.map