From 06eed1684c50fa2147ce8e8294caff8e642f5443 Mon Sep 17 00:00:00 2001 From: Nathan Haim Date: Mon, 5 Feb 2024 08:16:30 +0100 Subject: [PATCH 1/2] cli: modify withdraw-stake command Amount ALL withdraws available SOL --- cli/src/spend_utils.rs | 38 +++++++++++++++++++++++++++++++++----- cli/src/stake.rs | 17 ++++++++++++++--- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/cli/src/spend_utils.rs b/cli/src/spend_utils.rs index 62f7a8dfd1f05f..9797cdc8019608 100644 --- a/cli/src/spend_utils.rs +++ b/cli/src/spend_utils.rs @@ -2,13 +2,17 @@ use { crate::{ checks::{check_account_for_balance_with_commitment, get_fee_for_messages}, cli::CliError, + stake, }, clap::ArgMatches, solana_clap_utils::{input_parsers::lamports_of_sol, offline::SIGN_ONLY_ARG}, solana_rpc_client::rpc_client::RpcClient, solana_sdk::{ - commitment_config::CommitmentConfig, hash::Hash, message::Message, - native_token::lamports_to_sol, pubkey::Pubkey, + commitment_config::CommitmentConfig, + hash::Hash, + message::Message, + native_token::lamports_to_sol, + pubkey::Pubkey, }, }; @@ -96,15 +100,39 @@ where )?; Ok((message, spend)) } else { - let from_balance = rpc_client - .get_balance_with_commitment(from_pubkey, commitment)? - .value; let from_rent_exempt_minimum = if amount == SpendAmount::RentExempt { let data = rpc_client.get_account_data(from_pubkey)?; rpc_client.get_minimum_balance_for_rent_exemption(data.len())? } else { 0 }; + + let mut from_balance: u64 = 0; + if let Some(account) = rpc_client + .get_account_with_commitment(from_pubkey, commitment)? + .value + { + if account.owner == solana_sdk::stake::program::id() { + let state = stake::get_account_stake_state( + rpc_client, + from_pubkey, + account, + true, + None, + false, + )?; + from_balance = state.account_balance; + if let Some(active_stake) = state.active_stake { + from_balance = from_balance.saturating_sub(active_stake); + } + } + } + if from_balance == 0 { + from_balance = rpc_client + .get_balance_with_commitment(from_pubkey, commitment)? + .value; + } + let (message, SpendAndFee { spend, fee }) = resolve_spend_message( rpc_client, amount, diff --git a/cli/src/stake.rs b/cli/src/stake.rs index f4bb8329278d94..9115113902137d 100644 --- a/cli/src/stake.rs +++ b/cli/src/stake.rs @@ -2415,8 +2415,7 @@ fn get_stake_account_state( stake_account.state().map_err(|err| { CliError::RpcRequestError(format!( "Account data could not be deserialized to stake state: {err}" - )) - .into() + )).into() }) } @@ -2529,6 +2528,18 @@ pub fn process_show_stake_account( use_csv: bool, ) -> ProcessResult { let stake_account = rpc_client.get_account(stake_account_address)?; + let state= get_account_stake_state(rpc_client, stake_account_address, stake_account, use_lamports_unit, with_rewards, use_csv)?; + return Ok(config.output_format.formatted_string(&state)); +} + +pub fn get_account_stake_state( + rpc_client: &RpcClient, + stake_account_address: &Pubkey, + stake_account: solana_sdk::account::Account, + use_lamports_unit: bool, + with_rewards: Option, + use_csv: bool, +) -> Result { if stake_account.owner != stake::program::id() { return Err(CliError::RpcRequestError(format!( "{stake_account_address:?} is not a stake account", @@ -2572,7 +2583,7 @@ pub fn process_show_stake_account( }); state.epoch_rewards = epoch_rewards; } - Ok(config.output_format.formatted_string(&state)) + Ok(state) } Err(err) => Err(CliError::RpcRequestError(format!( "Account data could not be deserialized to stake state: {err}" From ffbbff8b3fdd8074e2c5f8e50f0c21615c822501 Mon Sep 17 00:00:00 2001 From: Nathan Haim Date: Fri, 9 Feb 2024 09:32:44 +0100 Subject: [PATCH 2/2] format code --- cli/src/spend_utils.rs | 7 ++----- cli/src/stake.rs | 14 +++++++++++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/cli/src/spend_utils.rs b/cli/src/spend_utils.rs index 9797cdc8019608..c98f2facc78ff6 100644 --- a/cli/src/spend_utils.rs +++ b/cli/src/spend_utils.rs @@ -8,11 +8,8 @@ use { solana_clap_utils::{input_parsers::lamports_of_sol, offline::SIGN_ONLY_ARG}, solana_rpc_client::rpc_client::RpcClient, solana_sdk::{ - commitment_config::CommitmentConfig, - hash::Hash, - message::Message, - native_token::lamports_to_sol, - pubkey::Pubkey, + commitment_config::CommitmentConfig, hash::Hash, message::Message, + native_token::lamports_to_sol, pubkey::Pubkey, }, }; diff --git a/cli/src/stake.rs b/cli/src/stake.rs index 9115113902137d..670c8969abbaaa 100644 --- a/cli/src/stake.rs +++ b/cli/src/stake.rs @@ -2415,7 +2415,8 @@ fn get_stake_account_state( stake_account.state().map_err(|err| { CliError::RpcRequestError(format!( "Account data could not be deserialized to stake state: {err}" - )).into() + )) + .into() }) } @@ -2528,7 +2529,14 @@ pub fn process_show_stake_account( use_csv: bool, ) -> ProcessResult { let stake_account = rpc_client.get_account(stake_account_address)?; - let state= get_account_stake_state(rpc_client, stake_account_address, stake_account, use_lamports_unit, with_rewards, use_csv)?; + let state = get_account_stake_state( + rpc_client, + stake_account_address, + stake_account, + use_lamports_unit, + with_rewards, + use_csv, + )?; return Ok(config.output_format.formatted_string(&state)); } @@ -2538,7 +2546,7 @@ pub fn get_account_stake_state( stake_account: solana_sdk::account::Account, use_lamports_unit: bool, with_rewards: Option, - use_csv: bool, + use_csv: bool, ) -> Result { if stake_account.owner != stake::program::id() { return Err(CliError::RpcRequestError(format!(