Skip to content

Commit b876bef

Browse files
committed
Add generic token support to |sys account sweep|
1 parent 2e2379e commit b876bef

File tree

1 file changed

+89
-51
lines changed

1 file changed

+89
-51
lines changed

src/main.rs

+89-51
Original file line numberDiff line numberDiff line change
@@ -2716,15 +2716,14 @@ async fn process_account_sweep<T: Signers>(
27162716
db: &mut Db,
27172717
rpc_client: &RpcClient,
27182718
from_address: Pubkey,
2719+
token: MaybeToken,
27192720
retain_amount: u64,
27202721
no_sweep_ok: bool,
27212722
from_authority_address: Pubkey,
27222723
signers: T,
27232724
to_address: Option<Pubkey>,
27242725
notifier: &Notifier,
27252726
) -> Result<(), Box<dyn std::error::Error>> {
2726-
let token = MaybeToken::SOL();
2727-
27282727
let (recent_blockhash, last_valid_block_height) =
27292728
rpc_client.get_latest_blockhash_with_commitment(rpc_client.commitment())?;
27302729
let fee_calculator = get_deprecated_fee_calculator(rpc_client)?;
@@ -2738,16 +2737,6 @@ async fn process_account_sweep<T: Signers>(
27382737
.get_account(from_address, token)
27392738
.ok_or_else(|| format!("Account, {from_address}, is not tracked"))?;
27402739

2741-
if from_account.lamports < from_tracked_account.last_update_balance {
2742-
return Err(format!(
2743-
"{}: On-chain account balance ({}) less than tracked balance ({})",
2744-
from_address,
2745-
token.ui_amount(from_account.lamports),
2746-
token.ui_amount(from_tracked_account.last_update_balance)
2747-
)
2748-
.into());
2749-
}
2750-
27512740
let authority_account = if from_address == from_authority_address {
27522741
from_account.clone()
27532742
} else {
@@ -2765,6 +2754,10 @@ async fn process_account_sweep<T: Signers>(
27652754
.ok_or_else(|| format!("Account {to_address} ({token}) does not exist"))?;
27662755
(to_address, None)
27672756
} else {
2757+
if !token.is_sol() {
2758+
return Err("--to <ADDRESS> must be provided for token sweeps".into());
2759+
}
2760+
27682761
let transitory_stake_account = Keypair::new();
27692762

27702763
let sweep_stake_account = db
@@ -2804,60 +2797,94 @@ async fn process_account_sweep<T: Signers>(
28042797
.into());
28052798
}
28062799

2807-
let (mut instructions, sweep_amount) = if from_account.owner == system_program::id() {
2808-
let lamports = if from_address == from_authority_address {
2809-
from_tracked_account.last_update_balance.saturating_sub(
2810-
num_transaction_signatures * fee_calculator.lamports_per_signature + retain_amount,
2800+
let (mut instructions, sweep_amount) = if token.is_sol() {
2801+
if from_account.lamports < from_tracked_account.last_update_balance {
2802+
return Err(format!(
2803+
"{}: On-chain account balance ({}) less than tracked balance ({})",
2804+
from_address,
2805+
token.ui_amount(from_account.lamports),
2806+
token.ui_amount(from_tracked_account.last_update_balance)
28112807
)
2812-
} else {
2813-
from_tracked_account
2814-
.last_update_balance
2815-
.saturating_sub(retain_amount)
2816-
};
2808+
.into());
2809+
}
28172810

2818-
(
2819-
vec![system_instruction::transfer(
2820-
&from_address,
2821-
&to_address,
2811+
if from_account.owner == system_program::id() {
2812+
let lamports = if from_address == from_authority_address {
2813+
from_tracked_account.last_update_balance.saturating_sub(
2814+
num_transaction_signatures * fee_calculator.lamports_per_signature
2815+
+ retain_amount,
2816+
)
2817+
} else {
2818+
from_tracked_account
2819+
.last_update_balance
2820+
.saturating_sub(retain_amount)
2821+
};
2822+
2823+
(
2824+
vec![system_instruction::transfer(
2825+
&from_address,
2826+
&to_address,
2827+
lamports,
2828+
)],
28222829
lamports,
2823-
)],
2824-
lamports,
2825-
)
2826-
} else if from_account.owner == solana_vote_program::id() {
2827-
let minimum_balance = rpc_client.get_minimum_balance_for_rent_exemption(
2828-
solana_vote_program::vote_state::VoteState::size_of(),
2829-
)?;
2830+
)
2831+
} else if from_account.owner == solana_vote_program::id() {
2832+
let minimum_balance = rpc_client.get_minimum_balance_for_rent_exemption(
2833+
solana_vote_program::vote_state::VoteState::size_of(),
2834+
)?;
28302835

2831-
let lamports = from_tracked_account
2832-
.last_update_balance
2833-
.saturating_sub(minimum_balance + retain_amount);
2836+
let lamports = from_tracked_account
2837+
.last_update_balance
2838+
.saturating_sub(minimum_balance + retain_amount);
28342839

2835-
(
2836-
vec![solana_vote_program::vote_instruction::withdraw(
2837-
&from_address,
2838-
&from_authority_address,
2840+
(
2841+
vec![solana_vote_program::vote_instruction::withdraw(
2842+
&from_address,
2843+
&from_authority_address,
2844+
lamports,
2845+
&to_address,
2846+
)],
28392847
lamports,
2840-
&to_address,
2841-
)],
2842-
lamports,
2843-
)
2844-
} else if from_account.owner == solana_sdk::stake::program::id() {
2848+
)
2849+
} else if from_account.owner == solana_sdk::stake::program::id() {
2850+
let lamports = from_tracked_account
2851+
.last_update_balance
2852+
.saturating_sub(retain_amount);
2853+
2854+
(
2855+
vec![solana_sdk::stake::instruction::withdraw(
2856+
&from_address,
2857+
&from_authority_address,
2858+
&to_address,
2859+
lamports,
2860+
None,
2861+
)],
2862+
lamports,
2863+
)
2864+
} else {
2865+
return Err(format!("Unsupported `from` account owner: {}", from_account.owner).into());
2866+
}
2867+
} else {
2868+
let token = token.token().unwrap();
2869+
28452870
let lamports = from_tracked_account
28462871
.last_update_balance
28472872
.saturating_sub(retain_amount);
28482873

28492874
(
2850-
vec![solana_sdk::stake::instruction::withdraw(
2851-
&from_address,
2875+
vec![spl_token::instruction::transfer_checked(
2876+
&spl_token::id(),
2877+
&token.ata(&from_address),
2878+
&token.mint(),
2879+
&token.ata(&to_address),
28522880
&from_authority_address,
2853-
&to_address,
2881+
&[],
28542882
lamports,
2855-
None,
2856-
)],
2883+
token.decimals(),
2884+
)
2885+
.unwrap()],
28572886
lamports,
28582887
)
2859-
} else {
2860-
return Err(format!("Unsupported `from` account owner: {}", from_account.owner).into());
28612888
};
28622889

28632890
if sweep_amount < token.amount(1.) {
@@ -4286,6 +4313,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
42864313
.subcommand(
42874314
SubCommand::with_name("sweep")
42884315
.about("Sweep SOL into the sweep stake account")
4316+
.arg(
4317+
Arg::with_name("token")
4318+
.value_name("SOL or SPL Token")
4319+
.takes_value(true)
4320+
.required(true)
4321+
.validator(is_valid_token_or_sol)
4322+
.default_value("SOL")
4323+
.help("Token type"),
4324+
)
42894325
.arg(
42904326
Arg::with_name("address")
42914327
.value_name("ADDRESS")
@@ -5698,6 +5734,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
56985734
.await?;
56995735
}
57005736
("sweep", Some(arg_matches)) => {
5737+
let token = value_t!(arg_matches, "token", Token).ok();
57015738
let from_address = pubkey_of(arg_matches, "address").unwrap();
57025739
let (from_authority_signer, from_authority_address) =
57035740
signer_of(arg_matches, "authority", &mut wallet_manager)?;
@@ -5712,6 +5749,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
57125749
&mut db,
57135750
&rpc_client,
57145751
from_address,
5752+
token.into(),
57155753
retain_amount,
57165754
no_sweep_ok,
57175755
from_authority_address,

0 commit comments

Comments
 (0)