decreaseValidatorStake static method

Future<List<TransactionInstruction>> decreaseValidatorStake(
  1. SolanaProvider connection,
  2. SolAddress stakePoolAddress,
  3. SolAddress validatorVote,
  4. BigInt lamports, {
  5. BigInt? ephemeralStakeSeed,
})

Creates instructions required to decrease validator stake.

Implementation

static Future<List<TransactionInstruction>> decreaseValidatorStake(
  SolanaProvider connection,
  SolAddress stakePoolAddress,
  SolAddress validatorVote,
  BigInt lamports, {
  BigInt? ephemeralStakeSeed,
}) async {
  final stakePool = await connection.request(
    SolanaRPCGetStakePoolAccount(address: stakePoolAddress),
  );
  if (stakePool == null) {
    throw const SolanaPluginException('Stake pool account does not found.');
  }
  final validatorList = await connection.request(
    SolanaRPCGetStakePoolValidatorListAccount(
      address: stakePool.validatorList.address,
    ),
  );
  if (validatorList == null) {
    throw const SolanaPluginException(
      'Validator list account does not found.',
    );
  }

  final validatorInfo = validatorList.validators.firstWhere(
    (v) => v.voteAccountAddress.address == validatorVote.address,
    orElse:
        () =>
            throw const SolanaPluginException(
              'Vote account not found in validator list',
            ),
  );

  final withdrawAuthority =
      StakePoolProgramUtils.findWithdrawAuthorityProgramAddress(
        stakePoolAddress: stakePoolAddress,
      );

  final validatorStake = StakePoolProgramUtils.findStakeProgramAddress(
    voteAccountAddress: validatorInfo.voteAccountAddress,
    stakePoolAddress: stakePoolAddress,
  );
  // bump up by one to avoid reuse
  final transientStakeSeed =
      validatorInfo.transientSeedSuffixStart + BigInt.one;

  final transientStake =
      StakePoolProgramUtils.findTransientStakeProgramAddress(
        voteAccountAddress: validatorInfo.voteAccountAddress,
        stakePoolAddress: stakePoolAddress,
        seed: transientStakeSeed,
      );

  final instructions = <TransactionInstruction>[];

  if (ephemeralStakeSeed != null) {
    final ephemeralStake =
        StakePoolProgramUtils.findEphemeralStakeProgramAddress(
          stakePoolAddress: stakePoolAddress,
          seed: ephemeralStakeSeed,
        );
    instructions.add(
      StakePoolProgram.decreaseAdditionalValidatorStake(
        stakePool: stakePoolAddress,
        staker: stakePool.staker,
        validatorList: stakePool.validatorList,
        reserveStake: stakePool.reserveStake,
        withdrawAuthority: withdrawAuthority.address,
        validatorStake: validatorStake.address,
        transientStake: transientStake.address,
        ephemeralStake: ephemeralStake.address,
        layout: StakePoolDecreaseAdditionalValidatorStakeLayout(
          lamports: lamports,
          ephemeralStakeSeed: ephemeralStakeSeed,
          transientStakeSeed: transientStakeSeed,
        ),
      ),
    );
  } else {
    instructions.add(
      StakePoolProgram.decreaseValidatorStakeWithReserve(
        stakePool: stakePoolAddress,
        staker: stakePool.staker,
        validatorList: stakePool.validatorList,
        reserveStake: stakePool.reserveStake,
        withdrawAuthority: withdrawAuthority.address,
        validatorStake: validatorStake.address,
        transientStake: transientStake.address,
        layout: StakePoolDecreaseValidatorStakeWithReserveLayout(
          lamports: lamports,
          transientStakeSeed: transientStakeSeed,
        ),
      ),
    );
  }

  return instructions;
}