Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 203db7b

Browse files
authored
stake-pool-cli: Improve deposit and withdraw UX (#2530)
1 parent c9a918f commit 203db7b

File tree

2 files changed

+86
-35
lines changed

2 files changed

+86
-35
lines changed

docs/src/stake-pool.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -734,23 +734,25 @@ Stake pools allow SOL withdrawals directly from the reserve and into a normal
734734
SOL wallet account, and in exchange burns the provided pool tokens.
735735

736736
```console
737-
$ spl-stake-pool withdraw-sol Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 2
737+
$ spl-stake-pool withdraw-sol Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 7VXPpSxneL6JLj18Naw2gkukXtjBZfbmPh18cnoUCMD8 2
738738
Signature: 4bqZKUUrjVspqTGqGqX4zxnHnJB67WbeukKUZRmxJ2yFmr275CtHPjZNzQJD9Pe7Q6mSxnUpcVv9FUdAbGP9RyBc
739739
```
740740

741-
The stake pool burned 2 pool tokens. In return, the stake pool sent SOL to the
742-
fee payer for the transaction. You can check that the pool tokens have been burned:
741+
The stake pool has burned 2 pool tokens, and in return, sent SOL to
742+
`7VXPpSxneL6JLj18Naw2gkukXtjBZfbmPh18cnoUCMD8`.
743+
744+
You can check that the pool tokens have been burned:
743745

744746
```console
745747
$ spl-token balance BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB
746748
98.00000000
747749
```
748750

749-
And you can check that the fee payer has been credited:
751+
And you can check that the recipient has been credited:
750752

751753
```console
752-
$ solana balance
753-
49.660334743 SOL
754+
$ solana balance 7VXPpSxneL6JLj18Naw2gkukXtjBZfbmPh18cnoUCMD8
755+
2 SOL
754756
```
755757

756758
### Deposit stake
@@ -788,12 +790,15 @@ Signature: 45x2UtA1b49eBPtRHdkvA3k8JneZzfwjptNN1kKQZaPABYiJ4hSA8qwi7qLNN5b3Fr4Z6
788790
```
789791

790792
The CLI will default to using the fee payer's
791-
[Associated Token Account](associated-token-account.md) for stake pool tokens.
793+
[Associated Token Account](associated-token-account.md) for stake pool tokens
794+
and the withdraw authority on the deposited stake account.
795+
792796
Alternatively, you can create an SPL token account yourself and pass it as the
793-
`token-receiver` for the command.
797+
`token-receiver` for the command, and specify the withdraw authority on the
798+
stake account using the `withdraw-authority` flag.
794799

795800
```console
796-
$ spl-stake-pool deposit-stake Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 97wBBiLVA7fUViEew8yV8R6tTdKithZDVz8LHLfF9sTJ --token-receiver 34XMHa3JUPv46ftU4dGHvemZ9oKVjnciRePYMcX3rjEF
801+
$ spl-stake-pool deposit-stake Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 97wBBiLVA7fUViEew8yV8R6tTdKithZDVz8LHLfF9sTJ --token-receiver 34XMHa3JUPv46ftU4dGHvemZ9oKVjnciRePYMcX3rjEF --withdraw-authority authority.json
797802
Depositing stake 97wBBiLVA7fUViEew8yV8R6tTdKithZDVz8LHLfF9sTJ into stake pool account F8e8Ympp4MkDSPZdvRxdQUZXRkMBDdyqgHa363GShAPt
798803
Signature: 4AESGZzqBVfj5xQnMiPWAwzJnAtQDRFK1Ha6jqKKTs46Zm5fw3LqgU1mRAT6CKTywVfFMHZCLm1hcQNScSMwVvjQ
799804
```

stake-pool/cli/src/main.rs

Lines changed: 72 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ use {
1010
input_parsers::{keypair_of, pubkey_of},
1111
input_validators::{
1212
is_amount, is_keypair, is_keypair_or_ask_keyword, is_parsable, is_pubkey, is_url,
13-
is_valid_percentage,
13+
is_valid_percentage, is_valid_pubkey,
1414
},
15-
keypair::signer_from_path,
15+
keypair::{signer_from_path_with_config, SignerFromPathConfig},
1616
},
1717
solana_client::rpc_client::RpcClient,
1818
solana_program::{
@@ -88,12 +88,14 @@ fn get_signer(
8888
keypair_name: &str,
8989
keypair_path: &str,
9090
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
91+
signer_from_path_config: SignerFromPathConfig,
9192
) -> Box<dyn Signer> {
92-
signer_from_path(
93+
signer_from_path_with_config(
9394
matches,
9495
matches.value_of(keypair_name).unwrap_or(keypair_path),
9596
keypair_name,
9697
wallet_manager,
98+
&signer_from_path_config,
9799
)
98100
.unwrap_or_else(|e| {
99101
eprintln!("error: {}", e);
@@ -596,6 +598,7 @@ fn command_deposit_stake(
596598
config: &Config,
597599
stake_pool_address: &Pubkey,
598600
stake: &Pubkey,
601+
withdraw_authority: Box<dyn Signer>,
599602
pool_token_receiver_account: &Option<Pubkey>,
600603
referrer_token_account: &Option<Pubkey>,
601604
) -> CommandResult {
@@ -634,7 +637,7 @@ fn command_deposit_stake(
634637
}
635638

636639
let mut instructions: Vec<Instruction> = vec![];
637-
let mut signers = vec![config.fee_payer.as_ref(), config.staker.as_ref()];
640+
let mut signers = vec![config.fee_payer.as_ref(), withdraw_authority.as_ref()];
638641

639642
let mut total_rent_free_balances: u64 = 0;
640643

@@ -672,7 +675,7 @@ fn command_deposit_stake(
672675
&stake_deposit_authority.pubkey(),
673676
&pool_withdraw_authority,
674677
stake,
675-
&config.staker.pubkey(),
678+
&withdraw_authority.pubkey(),
676679
&validator_stake_account,
677680
&stake_pool.reserve_stake,
678681
&pool_token_receiver_account,
@@ -688,7 +691,7 @@ fn command_deposit_stake(
688691
&stake_pool.validator_list,
689692
&pool_withdraw_authority,
690693
stake,
691-
&config.staker.pubkey(),
694+
&withdraw_authority.pubkey(),
692695
&validator_stake_account,
693696
&stake_pool.reserve_stake,
694697
&pool_token_receiver_account,
@@ -1371,8 +1374,8 @@ fn command_withdraw_stake(
13711374
fn command_withdraw_sol(
13721375
config: &Config,
13731376
stake_pool_address: &Pubkey,
1374-
sol_receiver: &Option<Pubkey>,
13751377
pool_token_account: &Option<Pubkey>,
1378+
sol_receiver: &Pubkey,
13761379
pool_amount: f64,
13771380
) -> CommandResult {
13781381
if !config.no_update {
@@ -1383,7 +1386,6 @@ fn command_withdraw_sol(
13831386
let pool_mint = get_token_mint(&config.rpc_client, &stake_pool.pool_mint)?;
13841387
let pool_amount = spl_token::ui_amount_to_amount(pool_amount, pool_mint.decimals);
13851388

1386-
let sol_receiver = sol_receiver.unwrap_or_else(|| config.fee_payer.pubkey());
13871389
let pool_token_account = pool_token_account.unwrap_or(get_associated_token_address(
13881390
&config.token_owner.pubkey(),
13891391
&stake_pool.pool_mint,
@@ -1450,7 +1452,7 @@ fn command_withdraw_sol(
14501452
&user_transfer_authority.pubkey(),
14511453
&pool_token_account,
14521454
&stake_pool.reserve_stake,
1453-
&sol_receiver,
1455+
sol_receiver,
14541456
&stake_pool.manager_fee_account,
14551457
&stake_pool.pool_mint,
14561458
&spl_token::id(),
@@ -1464,7 +1466,7 @@ fn command_withdraw_sol(
14641466
&user_transfer_authority.pubkey(),
14651467
&pool_token_account,
14661468
&stake_pool.reserve_stake,
1467-
&sol_receiver,
1469+
sol_receiver,
14681470
&stake_pool.manager_fee_account,
14691471
&stake_pool.pool_mint,
14701472
&spl_token::id(),
@@ -2011,6 +2013,15 @@ fn main() {
20112013
.required(true)
20122014
.help("Stake address to join the pool"),
20132015
)
2016+
.arg(
2017+
Arg::with_name("withdraw_authority")
2018+
.long("withdraw-authority")
2019+
.validator(is_keypair)
2020+
.value_name("KEYPAIR")
2021+
.takes_value(true)
2022+
.help("Withdraw authority for the stake account to be deposited. \
2023+
Defaults to the fee payer."),
2024+
)
20142025
.arg(
20152026
Arg::with_name("token_receiver")
20162027
.long("token-receiver")
@@ -2181,8 +2192,17 @@ fn main() {
21812192
.help("Stake pool address."),
21822193
)
21832194
.arg(
2184-
Arg::with_name("amount")
2195+
Arg::with_name("sol_receiver")
21852196
.index(2)
2197+
.validator(is_valid_pubkey)
2198+
.value_name("SYSTEM_ACCOUNT_ADDRESS_OR_KEYPAIR")
2199+
.takes_value(true)
2200+
.required(true)
2201+
.help("System account to receive SOL from the stake pool. Defaults to the payer."),
2202+
)
2203+
.arg(
2204+
Arg::with_name("amount")
2205+
.index(3)
21862206
.validator(is_amount)
21872207
.value_name("AMOUNT")
21882208
.takes_value(true)
@@ -2197,14 +2217,6 @@ fn main() {
21972217
.takes_value(true)
21982218
.help("Pool token account to withdraw tokens from. Defaults to the token-owner's associated token account."),
21992219
)
2200-
.arg(
2201-
Arg::with_name("sol_receiver")
2202-
.long("sol-receiver")
2203-
.validator(is_pubkey)
2204-
.value_name("SYSTEM_ACCOUNT_ADDRESS")
2205-
.takes_value(true)
2206-
.help("System account to receive SOL from the stake pool. Defaults to the payer."),
2207-
)
22082220
)
22092221
.subcommand(SubCommand::with_name("set-manager")
22102222
.about("Change manager or fee receiver account for the stake pool. Must be signed by the current manager.")
@@ -2373,12 +2385,12 @@ fn main() {
23732385
.get_matches();
23742386

23752387
let mut wallet_manager = None;
2388+
let cli_config = if let Some(config_file) = matches.value_of("config_file") {
2389+
solana_cli_config::Config::load(config_file).unwrap_or_default()
2390+
} else {
2391+
solana_cli_config::Config::default()
2392+
};
23762393
let config = {
2377-
let cli_config = if let Some(config_file) = matches.value_of("config_file") {
2378-
solana_cli_config::Config::load(config_file).unwrap_or_default()
2379-
} else {
2380-
solana_cli_config::Config::default()
2381-
};
23822394
let json_rpc_url = value_t!(matches, "json_rpc_url", String)
23832395
.unwrap_or_else(|_| cli_config.json_rpc_url.clone());
23842396

@@ -2387,6 +2399,9 @@ fn main() {
23872399
"staker",
23882400
&cli_config.keypair_path,
23892401
&mut wallet_manager,
2402+
SignerFromPathConfig {
2403+
allow_null_signer: false,
2404+
},
23902405
);
23912406

23922407
let funding_authority = if matches.is_present("funding_authority") {
@@ -2395,6 +2410,9 @@ fn main() {
23952410
"funding_authority",
23962411
&cli_config.keypair_path,
23972412
&mut wallet_manager,
2413+
SignerFromPathConfig {
2414+
allow_null_signer: false,
2415+
},
23982416
))
23992417
} else {
24002418
None
@@ -2404,18 +2422,27 @@ fn main() {
24042422
"manager",
24052423
&cli_config.keypair_path,
24062424
&mut wallet_manager,
2425+
SignerFromPathConfig {
2426+
allow_null_signer: false,
2427+
},
24072428
);
24082429
let token_owner = get_signer(
24092430
&matches,
24102431
"token_owner",
24112432
&cli_config.keypair_path,
24122433
&mut wallet_manager,
2434+
SignerFromPathConfig {
2435+
allow_null_signer: false,
2436+
},
24132437
);
24142438
let fee_payer = get_signer(
24152439
&matches,
24162440
"fee_payer",
24172441
&cli_config.keypair_path,
24182442
&mut wallet_manager,
2443+
SignerFromPathConfig {
2444+
allow_null_signer: false,
2445+
},
24192446
);
24202447
let verbose = matches.is_present("verbose");
24212448
let dry_run = matches.is_present("dry_run");
@@ -2523,10 +2550,20 @@ fn main() {
25232550
let stake_account = pubkey_of(arg_matches, "stake_account").unwrap();
25242551
let token_receiver: Option<Pubkey> = pubkey_of(arg_matches, "token_receiver");
25252552
let referrer: Option<Pubkey> = pubkey_of(arg_matches, "referrer");
2553+
let withdraw_authority = get_signer(
2554+
arg_matches,
2555+
"withdraw_authority",
2556+
&cli_config.keypair_path,
2557+
&mut wallet_manager,
2558+
SignerFromPathConfig {
2559+
allow_null_signer: false,
2560+
},
2561+
);
25262562
command_deposit_stake(
25272563
&config,
25282564
&stake_pool_address,
25292565
&stake_account,
2566+
withdraw_authority,
25302567
&token_receiver,
25312568
&referrer,
25322569
)
@@ -2577,12 +2614,21 @@ fn main() {
25772614
let stake_pool_address = pubkey_of(arg_matches, "pool").unwrap();
25782615
let pool_account = pubkey_of(arg_matches, "pool_account");
25792616
let pool_amount = value_t_or_exit!(arg_matches, "amount", f64);
2580-
let sol_receiver = pubkey_of(arg_matches, "sol_receiver");
2617+
let sol_receiver = get_signer(
2618+
arg_matches,
2619+
"sol_receiver",
2620+
&cli_config.keypair_path,
2621+
&mut wallet_manager,
2622+
SignerFromPathConfig {
2623+
allow_null_signer: true,
2624+
},
2625+
)
2626+
.pubkey();
25812627
command_withdraw_sol(
25822628
&config,
25832629
&stake_pool_address,
2584-
&sol_receiver,
25852630
&pool_account,
2631+
&sol_receiver,
25862632
pool_amount,
25872633
)
25882634
}

0 commit comments

Comments
 (0)