77 crate :: client:: * ,
88 clap:: {
99 crate_description, crate_name, crate_version, value_t, value_t_or_exit, App , AppSettings ,
10- Arg , ArgGroup , SubCommand ,
10+ Arg , ArgGroup , ArgMatches , SubCommand ,
1111 } ,
1212 solana_clap_utils:: {
1313 input_parsers:: { keypair_of, pubkey_of} ,
2323 program_pack:: Pack ,
2424 pubkey:: Pubkey ,
2525 } ,
26+ solana_remote_wallet:: remote_wallet:: RemoteWalletManager ,
2627 solana_sdk:: {
2728 commitment_config:: CommitmentConfig ,
2829 native_token:: { self , Sol } ,
3839 stake_program:: { self , StakeState } ,
3940 state:: { Fee , StakePool , ValidatorList } ,
4041 } ,
41- std:: process:: exit,
42+ std:: { process:: exit, sync :: Arc } ,
4243} ;
4344
4445struct Config {
@@ -83,6 +84,24 @@ fn check_fee_payer_balance(config: &Config, required_balance: u64) -> Result<(),
8384 }
8485}
8586
87+ fn get_signer (
88+ matches : & ArgMatches < ' _ > ,
89+ keypair_name : & str ,
90+ keypair_path : & str ,
91+ wallet_manager : & mut Option < Arc < RemoteWalletManager > > ,
92+ ) -> Box < dyn Signer > {
93+ signer_from_path (
94+ matches,
95+ matches. value_of ( keypair_name) . unwrap_or ( keypair_path) ,
96+ keypair_name,
97+ wallet_manager,
98+ )
99+ . unwrap_or_else ( |e| {
100+ eprintln ! ( "error: {}" , e) ;
101+ exit ( 1 ) ;
102+ } )
103+ }
104+
86105fn send_transaction_no_wait (
87106 config : & Config ,
88107 transaction : Transaction ,
@@ -316,16 +335,22 @@ fn command_vsa_create(
316335 stake_pool_address : & Pubkey ,
317336 vote_account : & Pubkey ,
318337) -> CommandResult {
319- println ! ( "Creating stake account on {}" , vote_account) ;
338+ let ( stake_account, _) =
339+ find_stake_program_address ( & spl_stake_pool:: id ( ) , vote_account, stake_pool_address) ;
340+ println ! (
341+ "Creating stake account {}, delegated to {}" ,
342+ stake_account, vote_account
343+ ) ;
320344 let transaction = checked_transaction_with_signers (
321345 config,
322346 & [
323347 // Create new validator stake account address
324- spl_stake_pool:: instruction:: create_validator_stake_account_with_vote (
348+ spl_stake_pool:: instruction:: create_validator_stake_account (
325349 & spl_stake_pool:: id ( ) ,
326350 stake_pool_address,
327351 & config. staker . pubkey ( ) ,
328352 & config. fee_payer . pubkey ( ) ,
353+ & stake_account,
329354 vote_account,
330355 ) ,
331356 ] ,
@@ -342,6 +367,10 @@ fn command_vsa_add(
342367) -> CommandResult {
343368 let ( stake_account_address, _) =
344369 find_stake_program_address ( & spl_stake_pool:: id ( ) , vote_account, stake_pool_address) ;
370+ println ! (
371+ "Adding stake account {}, delegated to {}" ,
372+ stake_account_address, vote_account
373+ ) ;
345374 let stake_pool = get_stake_pool ( & config. rpc_client , stake_pool_address) ?;
346375 let validator_list = get_validator_list ( & config. rpc_client , & stake_pool. validator_list ) ?;
347376 if validator_list. contains ( vote_account) {
@@ -399,6 +428,13 @@ fn command_vsa_remove(
399428 command_update ( config, stake_pool_address, false , false ) ?;
400429 }
401430
431+ let ( stake_account_address, _) =
432+ find_stake_program_address ( & spl_stake_pool:: id ( ) , vote_account, stake_pool_address) ;
433+ println ! (
434+ "Removing stake account {}, delegated to {}" ,
435+ stake_account_address, vote_account
436+ ) ;
437+
402438 let stake_pool = get_stake_pool ( & config. rpc_client , stake_pool_address) ?;
403439
404440 let staker_pubkey = config. staker . pubkey ( ) ;
@@ -522,7 +558,7 @@ fn add_associated_token_account(
522558 // Account for tokens not specified, creating one
523559 let account = get_associated_token_address ( & config. fee_payer . pubkey ( ) , mint) ;
524560 if get_token_account ( & config. rpc_client , & account, mint) . is_err ( ) {
525- println ! ( "Creating account to receive tokens {} " , account) ;
561+ println ! ( "Creating associated token account {} to receive stake pool tokens of mint {}, owned by {} " , account, mint , config . fee_payer . pubkey ( ) ) ;
526562
527563 let min_account_balance = config
528564 . rpc_client
@@ -536,6 +572,8 @@ fn add_associated_token_account(
536572 ) ) ;
537573
538574 * rent_free_balances += min_account_balance;
575+ } else {
576+ println ! ( "Using existing associated token account {} to receive stake pool tokens of mint {}, owned by {}" , account, mint, config. fee_payer. pubkey( ) ) ;
539577 }
540578
541579 account
@@ -573,7 +611,10 @@ fn command_deposit(
573611 find_stake_program_address ( & spl_stake_pool:: id ( ) , & vote_account, stake_pool_address) ;
574612
575613 let validator_stake_state = get_stake_state ( & config. rpc_client , & validator_stake_account) ?;
576- println ! ( "Depositing into stake account {}" , validator_stake_account) ;
614+ println ! (
615+ "Depositing stake {} into stake pool account {}" ,
616+ stake, validator_stake_account
617+ ) ;
577618 if config. verbose {
578619 println ! ( "{:?}" , validator_stake_state) ;
579620 }
@@ -797,7 +838,8 @@ fn command_update(
797838
798839#[ derive( PartialEq , Debug ) ]
799840struct WithdrawAccount {
800- address : Pubkey ,
841+ stake_address : Pubkey ,
842+ vote_address : Option < Pubkey > ,
801843 pool_amount : u64 ,
802844}
803845
@@ -823,7 +865,7 @@ fn prepare_withdraw_accounts(
823865 let mut remaining_amount = pool_amount;
824866
825867 // Go through available accounts and withdraw from largest to smallest
826- for ( address , lamports, _ ) in accounts {
868+ for ( stake_address , lamports, stake ) in accounts {
827869 if lamports <= min_balance {
828870 continue ;
829871 }
@@ -834,7 +876,8 @@ fn prepare_withdraw_accounts(
834876
835877 // Those accounts will be withdrawn completely with `claim` instruction
836878 withdraw_from. push ( WithdrawAccount {
837- address,
879+ stake_address,
880+ vote_address : stake. delegation ( ) . map ( |x| x. voter_pubkey ) ,
838881 pool_amount,
839882 } ) ;
840883 remaining_amount -= pool_amount;
@@ -898,7 +941,8 @@ fn command_withdraw(
898941
899942 let withdraw_accounts = if use_reserve {
900943 vec ! [ WithdrawAccount {
901- address: stake_pool. reserve_stake,
944+ stake_address: stake_pool. reserve_stake,
945+ vote_address: None ,
902946 pool_amount,
903947 } ]
904948 } else if let Some ( vote_account_address) = vote_account_address {
@@ -919,7 +963,8 @@ fn command_withdraw(
919963 . into ( ) ) ;
920964 }
921965 vec ! [ WithdrawAccount {
922- address: stake_account_address,
966+ stake_address: stake_account_address,
967+ vote_address: Some ( * vote_account_address) ,
923968 pool_amount,
924969 } ]
925970 } else {
@@ -940,7 +985,7 @@ fn command_withdraw(
940985 config. token_owner. as_ref( ) ,
941986 & user_transfer_authority,
942987 ] ;
943- let stake_receiver_account = Keypair :: new ( ) ; // Will be added to signers if creating new account
988+ let mut new_stake_keypairs = vec ! [ ] ;
944989
945990 instructions. push (
946991 // Approve spending token
@@ -954,9 +999,6 @@ fn command_withdraw(
954999 ) ?,
9551000 ) ;
9561001
957- // Use separate mutable variable because withdraw might create a new account
958- let mut stake_receiver: Option < Pubkey > = * stake_receiver_param;
959-
9601002 let mut total_rent_free_balances = 0 ;
9611003
9621004 // Go through prepared accounts and withdraw/claim them
@@ -967,48 +1009,52 @@ fn command_withdraw(
9671009 . unwrap ( ) ;
9681010
9691011 println ! (
970- "Withdrawing from account {}, amount {}, {} pool tokens" ,
971- withdraw_account. address,
1012+ "Withdrawing {}, or {} pool tokens, from stake account {}, delegated to {:?}, stake / withdraw authority {}" ,
9721013 Sol ( sol_withdraw_amount) ,
9731014 spl_token:: amount_to_ui_amount( withdraw_account. pool_amount, pool_mint. decimals) ,
1015+ withdraw_account. stake_address,
1016+ withdraw_account. vote_address,
1017+ config. staker. pubkey( ) ,
9741018 ) ;
9751019
976- if stake_receiver. is_none ( ) {
1020+ // Use separate mutable variable because withdraw might create a new account
1021+ let stake_receiver = stake_receiver_param. unwrap_or_else ( || {
9771022 // Account for tokens not specified, creating one
1023+ let stake_receiver_account = Keypair :: new ( ) ; // Will be added to signers if creating new account
1024+ let stake_receiver_pubkey = stake_receiver_account. pubkey ( ) ;
9781025 println ! (
9791026 "Creating account to receive stake {}" ,
980- stake_receiver_account . pubkey ( )
1027+ stake_receiver_pubkey
9811028 ) ;
9821029
9831030 let stake_receiver_account_balance = config
9841031 . rpc_client
985- . get_minimum_balance_for_rent_exemption ( STAKE_STATE_LEN ) ?;
1032+ . get_minimum_balance_for_rent_exemption ( STAKE_STATE_LEN )
1033+ . unwrap ( ) ;
9861034
9871035 instructions. push (
9881036 // Creating new account
9891037 system_instruction:: create_account (
9901038 & config. fee_payer . pubkey ( ) ,
991- & stake_receiver_account . pubkey ( ) ,
1039+ & stake_receiver_pubkey ,
9921040 stake_receiver_account_balance,
9931041 STAKE_STATE_LEN as u64 ,
9941042 & stake_program:: id ( ) ,
9951043 ) ,
9961044 ) ;
9971045
998- signers. push ( & stake_receiver_account) ;
999-
10001046 total_rent_free_balances += stake_receiver_account_balance;
1001-
1002- stake_receiver = Some ( stake_receiver_account . pubkey ( ) ) ;
1003- }
1047+ new_stake_keypairs . push ( stake_receiver_account ) ;
1048+ stake_receiver_pubkey
1049+ } ) ;
10041050
10051051 instructions. push ( spl_stake_pool:: instruction:: withdraw (
10061052 & spl_stake_pool:: id ( ) ,
10071053 stake_pool_address,
10081054 & stake_pool. validator_list ,
10091055 & pool_withdraw_authority,
1010- & withdraw_account. address ,
1011- & stake_receiver. unwrap ( ) , // Cannot be none at this point
1056+ & withdraw_account. stake_address ,
1057+ & stake_receiver,
10121058 & config. staker . pubkey ( ) ,
10131059 & user_transfer_authority. pubkey ( ) ,
10141060 & pool_token_account,
@@ -1026,6 +1072,9 @@ fn command_withdraw(
10261072 config,
10271073 total_rent_free_balances + fee_calculator. calculate_fee ( transaction. message ( ) ) ,
10281074 ) ?;
1075+ for new_stake_keypair in & new_stake_keypairs {
1076+ signers. push ( new_stake_keypair) ;
1077+ }
10291078 unique_signers ! ( signers) ;
10301079 transaction. sign ( & signers, recent_blockhash) ;
10311080 send_transaction ( config, transaction) ?;
@@ -1562,6 +1611,7 @@ fn main() {
15621611 . validator ( is_pubkey)
15631612 . value_name ( "STAKE_ACCOUNT_ADDRESS" )
15641613 . takes_value ( true )
1614+ . requires ( "withdraw_from" )
15651615 . help ( "Stake account to receive SOL from the stake pool. Defaults to a new stake account." ) ,
15661616 )
15671617 . arg (
@@ -1679,62 +1729,41 @@ fn main() {
16791729 let json_rpc_url = value_t ! ( matches, "json_rpc_url" , String )
16801730 . unwrap_or_else ( |_| cli_config. json_rpc_url . clone ( ) ) ;
16811731
1682- let staker = signer_from_path (
1732+ let staker = get_signer (
16831733 & matches,
1684- & cli_config. keypair_path ,
16851734 "staker" ,
1735+ & cli_config. keypair_path ,
16861736 & mut wallet_manager,
1687- )
1688- . unwrap_or_else ( |e| {
1689- eprintln ! ( "error: {}" , e) ;
1690- exit ( 1 ) ;
1691- } ) ;
1737+ ) ;
1738+
16921739 let depositor = if matches. is_present ( "depositor" ) {
1693- Some (
1694- signer_from_path (
1695- & matches,
1696- & cli_config. keypair_path ,
1697- "depositor" ,
1698- & mut wallet_manager,
1699- )
1700- . unwrap_or_else ( |e| {
1701- eprintln ! ( "error: {}" , e) ;
1702- exit ( 1 ) ;
1703- } ) ,
1704- )
1740+ Some ( get_signer (
1741+ & matches,
1742+ "depositor" ,
1743+ & cli_config. keypair_path ,
1744+ & mut wallet_manager,
1745+ ) )
17051746 } else {
17061747 None
17071748 } ;
1708- let manager = signer_from_path (
1749+ let manager = get_signer (
17091750 & matches,
1710- & cli_config. keypair_path ,
17111751 "manager" ,
1752+ & cli_config. keypair_path ,
17121753 & mut wallet_manager,
1713- )
1714- . unwrap_or_else ( |e| {
1715- eprintln ! ( "error: {}" , e) ;
1716- exit ( 1 ) ;
1717- } ) ;
1718- let token_owner = signer_from_path (
1754+ ) ;
1755+ let token_owner = get_signer (
17191756 & matches,
1720- & cli_config. keypair_path ,
17211757 "token_owner" ,
1758+ & cli_config. keypair_path ,
17221759 & mut wallet_manager,
1723- )
1724- . unwrap_or_else ( |e| {
1725- eprintln ! ( "error: {}" , e) ;
1726- exit ( 1 ) ;
1727- } ) ;
1728- let fee_payer = signer_from_path (
1760+ ) ;
1761+ let fee_payer = get_signer (
17291762 & matches,
1730- & cli_config. keypair_path ,
17311763 "fee_payer" ,
1764+ & cli_config. keypair_path ,
17321765 & mut wallet_manager,
1733- )
1734- . unwrap_or_else ( |e| {
1735- eprintln ! ( "error: {}" , e) ;
1736- exit ( 1 ) ;
1737- } ) ;
1766+ ) ;
17381767 let verbose = matches. is_present ( "verbose" ) ;
17391768 let dry_run = matches. is_present ( "dry_run" ) ;
17401769 let no_update = matches. is_present ( "no_update" ) ;
0 commit comments