7
7
crate :: client:: * ,
8
8
clap:: {
9
9
crate_description, crate_name, crate_version, value_t, value_t_or_exit, App , AppSettings ,
10
- Arg , ArgGroup , SubCommand ,
10
+ Arg , ArgGroup , ArgMatches , SubCommand ,
11
11
} ,
12
12
solana_clap_utils:: {
13
13
input_parsers:: { keypair_of, pubkey_of} ,
23
23
program_pack:: Pack ,
24
24
pubkey:: Pubkey ,
25
25
} ,
26
+ solana_remote_wallet:: remote_wallet:: RemoteWalletManager ,
26
27
solana_sdk:: {
27
28
commitment_config:: CommitmentConfig ,
28
29
native_token:: { self , Sol } ,
38
39
stake_program:: { self , StakeState } ,
39
40
state:: { Fee , StakePool , ValidatorList } ,
40
41
} ,
41
- std:: process:: exit,
42
+ std:: { process:: exit, sync :: Arc } ,
42
43
} ;
43
44
44
45
struct Config {
@@ -83,6 +84,24 @@ fn check_fee_payer_balance(config: &Config, required_balance: u64) -> Result<(),
83
84
}
84
85
}
85
86
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
+
86
105
fn send_transaction_no_wait (
87
106
config : & Config ,
88
107
transaction : Transaction ,
@@ -316,16 +335,22 @@ fn command_vsa_create(
316
335
stake_pool_address : & Pubkey ,
317
336
vote_account : & Pubkey ,
318
337
) -> 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
+ ) ;
320
344
let transaction = checked_transaction_with_signers (
321
345
config,
322
346
& [
323
347
// 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 (
325
349
& spl_stake_pool:: id ( ) ,
326
350
stake_pool_address,
327
351
& config. staker . pubkey ( ) ,
328
352
& config. fee_payer . pubkey ( ) ,
353
+ & stake_account,
329
354
vote_account,
330
355
) ,
331
356
] ,
@@ -342,6 +367,10 @@ fn command_vsa_add(
342
367
) -> CommandResult {
343
368
let ( stake_account_address, _) =
344
369
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
+ ) ;
345
374
let stake_pool = get_stake_pool ( & config. rpc_client , stake_pool_address) ?;
346
375
let validator_list = get_validator_list ( & config. rpc_client , & stake_pool. validator_list ) ?;
347
376
if validator_list. contains ( vote_account) {
@@ -399,6 +428,13 @@ fn command_vsa_remove(
399
428
command_update ( config, stake_pool_address, false , false ) ?;
400
429
}
401
430
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
+
402
438
let stake_pool = get_stake_pool ( & config. rpc_client , stake_pool_address) ?;
403
439
404
440
let staker_pubkey = config. staker . pubkey ( ) ;
@@ -522,7 +558,7 @@ fn add_associated_token_account(
522
558
// Account for tokens not specified, creating one
523
559
let account = get_associated_token_address ( & config. fee_payer . pubkey ( ) , mint) ;
524
560
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 ( ) ) ;
526
562
527
563
let min_account_balance = config
528
564
. rpc_client
@@ -536,6 +572,8 @@ fn add_associated_token_account(
536
572
) ) ;
537
573
538
574
* 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( ) ) ;
539
577
}
540
578
541
579
account
@@ -573,7 +611,10 @@ fn command_deposit(
573
611
find_stake_program_address ( & spl_stake_pool:: id ( ) , & vote_account, stake_pool_address) ;
574
612
575
613
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
+ ) ;
577
618
if config. verbose {
578
619
println ! ( "{:?}" , validator_stake_state) ;
579
620
}
@@ -797,7 +838,8 @@ fn command_update(
797
838
798
839
#[ derive( PartialEq , Debug ) ]
799
840
struct WithdrawAccount {
800
- address : Pubkey ,
841
+ stake_address : Pubkey ,
842
+ vote_address : Option < Pubkey > ,
801
843
pool_amount : u64 ,
802
844
}
803
845
@@ -823,7 +865,7 @@ fn prepare_withdraw_accounts(
823
865
let mut remaining_amount = pool_amount;
824
866
825
867
// Go through available accounts and withdraw from largest to smallest
826
- for ( address , lamports, _ ) in accounts {
868
+ for ( stake_address , lamports, stake ) in accounts {
827
869
if lamports <= min_balance {
828
870
continue ;
829
871
}
@@ -834,7 +876,8 @@ fn prepare_withdraw_accounts(
834
876
835
877
// Those accounts will be withdrawn completely with `claim` instruction
836
878
withdraw_from. push ( WithdrawAccount {
837
- address,
879
+ stake_address,
880
+ vote_address : stake. delegation ( ) . map ( |x| x. voter_pubkey ) ,
838
881
pool_amount,
839
882
} ) ;
840
883
remaining_amount -= pool_amount;
@@ -898,7 +941,8 @@ fn command_withdraw(
898
941
899
942
let withdraw_accounts = if use_reserve {
900
943
vec ! [ WithdrawAccount {
901
- address: stake_pool. reserve_stake,
944
+ stake_address: stake_pool. reserve_stake,
945
+ vote_address: None ,
902
946
pool_amount,
903
947
} ]
904
948
} else if let Some ( vote_account_address) = vote_account_address {
@@ -919,7 +963,8 @@ fn command_withdraw(
919
963
. into ( ) ) ;
920
964
}
921
965
vec ! [ WithdrawAccount {
922
- address: stake_account_address,
966
+ stake_address: stake_account_address,
967
+ vote_address: Some ( * vote_account_address) ,
923
968
pool_amount,
924
969
} ]
925
970
} else {
@@ -940,7 +985,7 @@ fn command_withdraw(
940
985
config. token_owner. as_ref( ) ,
941
986
& user_transfer_authority,
942
987
] ;
943
- let stake_receiver_account = Keypair :: new ( ) ; // Will be added to signers if creating new account
988
+ let mut new_stake_keypairs = vec ! [ ] ;
944
989
945
990
instructions. push (
946
991
// Approve spending token
@@ -954,9 +999,6 @@ fn command_withdraw(
954
999
) ?,
955
1000
) ;
956
1001
957
- // Use separate mutable variable because withdraw might create a new account
958
- let mut stake_receiver: Option < Pubkey > = * stake_receiver_param;
959
-
960
1002
let mut total_rent_free_balances = 0 ;
961
1003
962
1004
// Go through prepared accounts and withdraw/claim them
@@ -967,48 +1009,52 @@ fn command_withdraw(
967
1009
. unwrap ( ) ;
968
1010
969
1011
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 {}" ,
972
1013
Sol ( sol_withdraw_amount) ,
973
1014
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( ) ,
974
1018
) ;
975
1019
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 ( || {
977
1022
// 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 ( ) ;
978
1025
println ! (
979
1026
"Creating account to receive stake {}" ,
980
- stake_receiver_account . pubkey ( )
1027
+ stake_receiver_pubkey
981
1028
) ;
982
1029
983
1030
let stake_receiver_account_balance = config
984
1031
. rpc_client
985
- . get_minimum_balance_for_rent_exemption ( STAKE_STATE_LEN ) ?;
1032
+ . get_minimum_balance_for_rent_exemption ( STAKE_STATE_LEN )
1033
+ . unwrap ( ) ;
986
1034
987
1035
instructions. push (
988
1036
// Creating new account
989
1037
system_instruction:: create_account (
990
1038
& config. fee_payer . pubkey ( ) ,
991
- & stake_receiver_account . pubkey ( ) ,
1039
+ & stake_receiver_pubkey ,
992
1040
stake_receiver_account_balance,
993
1041
STAKE_STATE_LEN as u64 ,
994
1042
& stake_program:: id ( ) ,
995
1043
) ,
996
1044
) ;
997
1045
998
- signers. push ( & stake_receiver_account) ;
999
-
1000
1046
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
+ } ) ;
1004
1050
1005
1051
instructions. push ( spl_stake_pool:: instruction:: withdraw (
1006
1052
& spl_stake_pool:: id ( ) ,
1007
1053
stake_pool_address,
1008
1054
& stake_pool. validator_list ,
1009
1055
& 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,
1012
1058
& config. staker . pubkey ( ) ,
1013
1059
& user_transfer_authority. pubkey ( ) ,
1014
1060
& pool_token_account,
@@ -1026,6 +1072,9 @@ fn command_withdraw(
1026
1072
config,
1027
1073
total_rent_free_balances + fee_calculator. calculate_fee ( transaction. message ( ) ) ,
1028
1074
) ?;
1075
+ for new_stake_keypair in & new_stake_keypairs {
1076
+ signers. push ( new_stake_keypair) ;
1077
+ }
1029
1078
unique_signers ! ( signers) ;
1030
1079
transaction. sign ( & signers, recent_blockhash) ;
1031
1080
send_transaction ( config, transaction) ?;
@@ -1562,6 +1611,7 @@ fn main() {
1562
1611
. validator ( is_pubkey)
1563
1612
. value_name ( "STAKE_ACCOUNT_ADDRESS" )
1564
1613
. takes_value ( true )
1614
+ . requires ( "withdraw_from" )
1565
1615
. help ( "Stake account to receive SOL from the stake pool. Defaults to a new stake account." ) ,
1566
1616
)
1567
1617
. arg (
@@ -1679,62 +1729,41 @@ fn main() {
1679
1729
let json_rpc_url = value_t ! ( matches, "json_rpc_url" , String )
1680
1730
. unwrap_or_else ( |_| cli_config. json_rpc_url . clone ( ) ) ;
1681
1731
1682
- let staker = signer_from_path (
1732
+ let staker = get_signer (
1683
1733
& matches,
1684
- & cli_config. keypair_path ,
1685
1734
"staker" ,
1735
+ & cli_config. keypair_path ,
1686
1736
& mut wallet_manager,
1687
- )
1688
- . unwrap_or_else ( |e| {
1689
- eprintln ! ( "error: {}" , e) ;
1690
- exit ( 1 ) ;
1691
- } ) ;
1737
+ ) ;
1738
+
1692
1739
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
+ ) )
1705
1746
} else {
1706
1747
None
1707
1748
} ;
1708
- let manager = signer_from_path (
1749
+ let manager = get_signer (
1709
1750
& matches,
1710
- & cli_config. keypair_path ,
1711
1751
"manager" ,
1752
+ & cli_config. keypair_path ,
1712
1753
& 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 (
1719
1756
& matches,
1720
- & cli_config. keypair_path ,
1721
1757
"token_owner" ,
1758
+ & cli_config. keypair_path ,
1722
1759
& 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 (
1729
1762
& matches,
1730
- & cli_config. keypair_path ,
1731
1763
"fee_payer" ,
1764
+ & cli_config. keypair_path ,
1732
1765
& mut wallet_manager,
1733
- )
1734
- . unwrap_or_else ( |e| {
1735
- eprintln ! ( "error: {}" , e) ;
1736
- exit ( 1 ) ;
1737
- } ) ;
1766
+ ) ;
1738
1767
let verbose = matches. is_present ( "verbose" ) ;
1739
1768
let dry_run = matches. is_present ( "dry_run" ) ;
1740
1769
let no_update = matches. is_present ( "no_update" ) ;
0 commit comments