withdrawSol static method

Future<List<TransactionInstruction>> withdrawSol({
  1. required SolanaRPC connection,
  2. required SolAddress stakePoolAddress,
  3. required SolAddress tokenOwner,
  4. required SolAddress solReceiver,
  5. required SolAddress userTransferAuthority,
  6. required BigInt poolAmountLamports,
  7. SolAddress? solWithdrawAuthority,
})

Creates instructions required to withdraw SOL directly from a stake pool.

Implementation

static Future<List<TransactionInstruction>> withdrawSol({
  required SolanaRPC connection,
  required SolAddress stakePoolAddress,
  required SolAddress tokenOwner,
  required SolAddress solReceiver,
  required SolAddress userTransferAuthority,
  required BigInt poolAmountLamports,
  SolAddress? solWithdrawAuthority,
}) async {
  final stakePool = await connection
      .request(SolanaRPCGetStakePoolAccount(address: stakePoolAddress));
  if (stakePool == null) {
    throw const MessageException("Stake pool account does not found.");
  }

  final poolTokenAccount =
      AssociatedTokenAccountProgramUtils.associatedTokenAccount(
    mint: stakePool.poolMint,
    owner: tokenOwner,
  );

  final tokenAccount = await connection
      .request(SolanaRPCGetAccountInfo(account: poolTokenAccount.address));
  if (tokenAccount == null) {
    throw const MessageException("Token account not found.");
  }
  // Check withdrawFrom balance
  if (tokenAccount.lamports < poolAmountLamports) {
    throw const MessageException('Not enough token balance to withdraw.');
  }

  // Construct transaction to withdraw from withdrawAccounts account list
  final instructions = <TransactionInstruction>[];

  instructions.add(
    SPLTokenProgram.approve(
      account: poolTokenAccount.address,
      delegate: userTransferAuthority,
      owner: tokenOwner,
      layout: SPLTokenApproveLayout(amount: poolAmountLamports),
    ),
  );

  final poolWithdrawAuthority =
      StakePoolProgramUtils.findWithdrawAuthorityProgramAddress(
          stakePoolAddress: stakePoolAddress);

  if (solWithdrawAuthority != null) {
    if (stakePool.solWithdrawAuthority == null) {
      throw const MessageException(
          'SOL withdraw authority specified in arguments but stake pool has none');
    }
    if (solWithdrawAuthority.address !=
        stakePool.solWithdrawAuthority?.address) {
      throw const MessageException("Invalid deposit withdraw specified");
    }
  }

  instructions.add(StakePoolProgram.withdrawSol(
    stakePool: stakePoolAddress,
    withdrawAuthority: poolWithdrawAuthority.address,
    reserveStake: stakePool.reserveStake,
    sourcePoolAccount: poolTokenAccount.address,
    sourceTransferAuthority: userTransferAuthority,
    destinationSystemAccount: solReceiver,
    managerFeeAccount: stakePool.managerFeeAccount,
    poolMint: stakePool.poolMint,
    layout: StakePoolWithdrawSolLayout(poolTokens: poolAmountLamports),
    solWithdrawAuthority: solWithdrawAuthority,
  ));

  return instructions;
}