Code cleanup v1

This commit is contained in:
Michael Vines 2021-03-31 10:54:55 -07:00
parent eb1bf2eb44
commit 2cd7adbf87
2 changed files with 208 additions and 189 deletions

View File

@ -0,0 +1,115 @@
use {
bincode::deserialize,
borsh::BorshDeserialize,
solana_account_decoder::UiAccountEncoding,
solana_client::{
client_error::ClientError,
rpc_client::RpcClient,
rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig},
rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType},
},
solana_program::{program_pack::Pack, pubkey::Pubkey},
spl_stake_pool::{
borsh::try_from_slice_unchecked,
stake_program,
state::{StakePool, ValidatorList},
},
};
type Error = Box<dyn std::error::Error>;
pub(crate) fn get_stake_pool(
rpc_client: &RpcClient,
pool_address: &Pubkey,
) -> Result<StakePool, Error> {
let account_data = rpc_client.get_account_data(pool_address)?;
let stake_pool = StakePool::try_from_slice(account_data.as_slice())
.map_err(|err| format!("Invalid stake pool {}: {}", pool_address, err))?;
Ok(stake_pool)
}
pub(crate) fn get_validator_list(
rpc_client: &RpcClient,
validator_list_address: &Pubkey,
) -> Result<ValidatorList, Error> {
let account_data = rpc_client.get_account_data(validator_list_address)?;
let validator_list = try_from_slice_unchecked::<ValidatorList>(&account_data.as_slice())
.map_err(|err| format!("Invalid validator list {}: {}", validator_list_address, err))?;
Ok(validator_list)
}
pub(crate) fn get_token_account(
rpc_client: &RpcClient,
token_account_address: &Pubkey,
expected_token_mint: &Pubkey,
) -> Result<spl_token::state::Account, Error> {
let account_data = rpc_client.get_account_data(token_account_address)?;
let token_account = spl_token::state::Account::unpack_from_slice(account_data.as_slice())
.map_err(|err| format!("Invalid token account {}: {}", token_account_address, err))?;
if token_account.mint != *expected_token_mint {
Err(format!(
"Invalid token mint for {}, expected mint is {}",
token_account_address, expected_token_mint
)
.into())
} else {
Ok(token_account)
}
}
pub(crate) fn get_token_mint(
rpc_client: &RpcClient,
token_mint_address: &Pubkey,
) -> Result<spl_token::state::Mint, Error> {
let account_data = rpc_client.get_account_data(token_mint_address)?;
let token_mint = spl_token::state::Mint::unpack_from_slice(account_data.as_slice())
.map_err(|err| format!("Invalid token mint {}: {}", token_mint_address, err))?;
Ok(token_mint)
}
pub(crate) fn get_stake_state(
rpc_client: &RpcClient,
stake_address: &Pubkey,
) -> Result<stake_program::StakeState, Error> {
let account_data = rpc_client.get_account_data(stake_address)?;
let stake_state = deserialize(account_data.as_slice())
.map_err(|err| format!("Invalid stake account {}: {}", stake_address, err))?;
Ok(stake_state)
}
pub(crate) fn get_stake_accounts_by_withdrawer(
rpc_client: &RpcClient,
withdrawer: &Pubkey,
) -> Result<Vec<(Pubkey, u64, stake_program::StakeState)>, ClientError> {
rpc_client
.get_program_accounts_with_config(
&stake_program::id(),
RpcProgramAccountsConfig {
filters: Some(vec![RpcFilterType::Memcmp(Memcmp {
offset: 44, // 44 is Withdrawer authority offset in stake account stake
bytes: MemcmpEncodedBytes::Binary(format!("{}", withdrawer)),
encoding: None,
})]),
account_config: RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Base64),
..RpcAccountInfoConfig::default()
},
},
)
.map(|accounts| {
accounts
.into_iter()
.filter_map(
|(address, account)| match deserialize(account.data.as_slice()) {
Ok(stake_state) => Some((address, account.lamports, stake_state)),
Err(err) => {
eprintln!("Invalid stake account data for {}: {}", address, err);
None
}
},
)
.collect()
})
}

View File

@ -1,26 +1,20 @@
#[macro_use]
extern crate lazy_static;
mod client;
use {
bincode::deserialize,
borsh::BorshDeserialize,
crate::client::*,
clap::{
crate_description, crate_name, crate_version, value_t, value_t_or_exit, App, AppSettings,
Arg, ArgGroup, SubCommand,
},
solana_account_decoder::UiAccountEncoding,
solana_clap_utils::{
input_parsers::pubkey_of,
input_validators::{is_amount, is_keypair, is_parsable, is_pubkey, is_url},
keypair::signer_from_path,
},
solana_client::{
client_error::ClientError,
rpc_client::RpcClient,
rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig},
rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType},
rpc_response::StakeActivationState,
},
solana_client::{rpc_client::RpcClient, rpc_response::StakeActivationState},
solana_program::{
borsh::get_packed_len, instruction::Instruction, program_pack::Pack, pubkey::Pubkey,
},
@ -32,22 +26,13 @@ use {
transaction::Transaction,
},
spl_stake_pool::{
borsh::{get_instance_packed_len, try_from_slice_unchecked},
self,
borsh::get_instance_packed_len,
create_pool_authority_address, find_authority_bump_seed, find_stake_address_for_validator,
instruction::{
add_validator_to_pool, create_validator_stake_account, deposit,
initialize as initialize_pool, remove_validator_from_pool, set_owner,
update_stake_pool_balance, update_validator_list_balance, withdraw, Fee as PoolFee,
},
stake_program::{self, StakeAuthorize, StakeState},
state::{StakePool, ValidatorList},
AUTHORITY_DEPOSIT, AUTHORITY_WITHDRAW,
},
spl_token::{
self, instruction::approve as approve_token, instruction::initialize_account,
instruction::initialize_mint, native_mint, state::Account as TokenAccount,
state::Mint as TokenMint,
},
std::process::exit,
};
@ -91,41 +76,6 @@ fn check_fee_payer_balance(config: &Config, required_balance: u64) -> Result<(),
}
}
fn get_stake_accounts_by_withdrawer(
rpc_client: &RpcClient,
withdrawer: &Pubkey,
) -> Result<Vec<(Pubkey, u64, StakeState)>, ClientError> {
rpc_client
.get_program_accounts_with_config(
&stake_program::id(),
RpcProgramAccountsConfig {
filters: Some(vec![RpcFilterType::Memcmp(Memcmp {
offset: 44, // 44 is Withdrawer authority offset in stake account stake
bytes: MemcmpEncodedBytes::Binary(format!("{}", withdrawer)),
encoding: None,
})]),
account_config: RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Base64),
..RpcAccountInfoConfig::default()
},
},
)
.map(|accounts| {
accounts
.into_iter()
.filter_map(
|(address, account)| match deserialize(account.data.as_slice()) {
Ok(stake_state) => Some((address, account.lamports, stake_state)),
Err(err) => {
eprintln!("Invalid stake account data for {}: {}", address, err);
None
}
},
)
.collect()
})
}
fn send_transaction(
config: &Config,
transaction: Transaction,
@ -142,7 +92,11 @@ fn send_transaction(
Ok(())
}
fn command_create_pool(config: &Config, fee: PoolFee, max_validators: u32) -> CommandResult {
fn command_create_pool(
config: &Config,
fee: spl_stake_pool::instruction::Fee,
max_validators: u32,
) -> CommandResult {
let mint_account = Keypair::new();
println!("Creating mint {}", mint_account.pubkey());
@ -159,10 +113,10 @@ fn command_create_pool(config: &Config, fee: PoolFee, max_validators: u32) -> Co
let mint_account_balance = config
.rpc_client
.get_minimum_balance_for_rent_exemption(TokenMint::LEN)?;
.get_minimum_balance_for_rent_exemption(spl_token::state::Mint::LEN)?;
let pool_fee_account_balance = config
.rpc_client
.get_minimum_balance_for_rent_exemption(TokenAccount::LEN)?;
.get_minimum_balance_for_rent_exemption(spl_token::state::Account::LEN)?;
let pool_account_balance = config
.rpc_client
.get_minimum_balance_for_rent_exemption(get_packed_len::<StakePool>())?;
@ -176,7 +130,7 @@ fn command_create_pool(config: &Config, fee: PoolFee, max_validators: u32) -> Co
+ pool_account_balance
+ validator_list_balance;
let default_decimals = native_mint::DECIMALS;
let default_decimals = spl_token::native_mint::DECIMALS;
// Calculate withdraw authority used for minting pool tokens
let (withdraw_authority, _) = find_authority_bump_seed(
@ -196,7 +150,7 @@ fn command_create_pool(config: &Config, fee: PoolFee, max_validators: u32) -> Co
&config.fee_payer.pubkey(),
&mint_account.pubkey(),
mint_account_balance,
TokenMint::LEN as u64,
spl_token::state::Mint::LEN as u64,
&spl_token::id(),
),
// Account for the pool fee accumulation
@ -204,7 +158,7 @@ fn command_create_pool(config: &Config, fee: PoolFee, max_validators: u32) -> Co
&config.fee_payer.pubkey(),
&pool_fee_account.pubkey(),
pool_fee_account_balance,
TokenAccount::LEN as u64,
spl_token::state::Account::LEN as u64,
&spl_token::id(),
),
// Account for the stake pool
@ -224,7 +178,7 @@ fn command_create_pool(config: &Config, fee: PoolFee, max_validators: u32) -> Co
&spl_stake_pool::id(),
),
// Initialize pool token mint account
initialize_mint(
spl_token::instruction::initialize_mint(
&spl_token::id(),
&mint_account.pubkey(),
&withdraw_authority,
@ -232,14 +186,14 @@ fn command_create_pool(config: &Config, fee: PoolFee, max_validators: u32) -> Co
default_decimals,
)?,
// Initialize fee receiver account
initialize_account(
spl_token::instruction::initialize_account(
&spl_token::id(),
&pool_fee_account.pubkey(),
&mint_account.pubkey(),
&config.owner.pubkey(),
)?,
// Initialize stake pool account
initialize_pool(
spl_stake_pool::instruction::initialize(
&spl_stake_pool::id(),
&pool_account.pubkey(),
&config.owner.pubkey(),
@ -282,7 +236,7 @@ fn command_vsa_create(config: &Config, pool: &Pubkey, vote_account: &Pubkey) ->
let mut transaction = Transaction::new_with_payer(
&[
// Create new validator stake account address
create_validator_stake_account(
spl_stake_pool::instruction::create_validator_stake_account(
&spl_stake_pool::id(),
&pool,
&config.owner.pubkey(),
@ -318,9 +272,7 @@ fn command_vsa_add(
command_update(config, pool)?;
}
// Get stake pool state
let pool_data = config.rpc_client.get_account_data(&pool)?;
let pool_data = StakePool::try_from_slice(pool_data.as_slice()).unwrap();
let pool_data = get_stake_pool(&config.rpc_client, pool)?;
let mut total_rent_free_balances: u64 = 0;
@ -374,7 +326,7 @@ fn command_vsa_add(
StakeAuthorize::Staker,
),
// Add validator stake account to the pool
add_validator_to_pool(
spl_stake_pool::instruction::add_validator_to_pool(
&spl_stake_pool::id(),
&pool,
&config.owner.pubkey(),
@ -413,10 +365,7 @@ fn command_vsa_remove(
command_update(config, pool)?;
}
// Get stake pool state
let pool_data = config.rpc_client.get_account_data(&pool)?;
let pool_data: StakePool = StakePool::try_from_slice(pool_data.as_slice()).unwrap();
let pool_data = get_stake_pool(&config.rpc_client, pool)?;
let pool_withdraw_authority: Pubkey = create_pool_authority_address(
&spl_stake_pool::id(),
pool,
@ -435,17 +384,11 @@ fn command_vsa_remove(
.unwrap();
// Check balance and mint
let account_data = config.rpc_client.get_account_data(&withdraw_from)?;
let account_data: TokenAccount =
TokenAccount::unpack_from_slice(account_data.as_slice()).unwrap();
let token_account =
get_token_account(&config.rpc_client, &withdraw_from, &pool_data.pool_mint)?;
if account_data.mint != pool_data.pool_mint {
return Err("Wrong token account.".into());
}
if account_data.amount < tokens_to_withdraw {
let pool_mint_data = config.rpc_client.get_account_data(&pool_data.pool_mint)?;
let pool_mint = TokenMint::unpack_from_slice(pool_mint_data.as_slice()).unwrap();
if token_account.amount < tokens_to_withdraw {
let pool_mint = get_token_mint(&config.rpc_client, &pool_data.pool_mint)?;
return Err(format!(
"Not enough balance to burn to remove validator stake account from the pool. {} pool tokens needed.",
spl_token::amount_to_ui_amount(tokens_to_withdraw, pool_mint.decimals)
@ -455,7 +398,7 @@ fn command_vsa_remove(
let mut transaction = Transaction::new_with_payer(
&[
// Approve spending token
approve_token(
spl_token::instruction::approve(
&spl_token::id(),
&withdraw_from,
&pool_withdraw_authority,
@ -464,7 +407,7 @@ fn command_vsa_remove(
tokens_to_withdraw,
)?,
// Create new validator stake account address
remove_validator_from_pool(
spl_stake_pool::instruction::remove_validator_from_pool(
&spl_stake_pool::id(),
&pool,
&config.owner.pubkey(),
@ -509,7 +452,7 @@ where
let min_account_balance = config
.rpc_client
.get_minimum_balance_for_rent_exemption(TokenAccount::LEN)?;
.get_minimum_balance_for_rent_exemption(spl_token::state::Account::LEN)?;
instructions.extend(vec![
// Creating new account
@ -517,11 +460,11 @@ where
&config.fee_payer.pubkey(),
&keypair.pubkey(),
min_account_balance,
TokenAccount::LEN as u64,
spl_token::state::Account::LEN as u64,
&spl_token::id(),
),
// Initialize token receiver account
initialize_account(
spl_token::instruction::initialize_account(
&spl_token::id(),
&keypair.pubkey(),
mint,
@ -547,44 +490,31 @@ fn command_deposit(
command_update(config, pool)?;
}
// Get stake pool state
let pool_data = config.rpc_client.get_account_data(&pool)?;
let pool_data: StakePool = StakePool::try_from_slice(pool_data.as_slice()).unwrap();
let pool_data = get_stake_pool(&config.rpc_client, pool)?;
let stake_state = get_stake_state(&config.rpc_client, &stake)?;
// Get stake account data
let stake_data = config.rpc_client.get_account_data(&stake)?;
let stake_data: StakeState =
deserialize(stake_data.as_slice()).or(Err("Invalid stake account data"))?;
if config.verbose {
println!("Depositing stake account {:?}", stake_data);
println!("Depositing stake account {:?}", stake_state);
}
let vote_account: Pubkey = match stake_data {
let vote_account: Pubkey = match stake_state {
StakeState::Stake(_, stake) => Ok(stake.delegation.voter_pubkey),
_ => Err("Wrong stake account state, must be delegated to validator"),
}?;
// Check if this vote account has staking account in the pool
let validator_list_data = config
.rpc_client
.get_account_data(&pool_data.validator_list)?;
let validator_list_data =
try_from_slice_unchecked::<ValidatorList>(&validator_list_data.as_slice())?;
if !validator_list_data.contains(&vote_account) {
let validator_list = get_validator_list(&config.rpc_client, &pool_data.validator_list)?;
if !validator_list.contains(&vote_account) {
return Err("Stake account for this validator does not exist in the pool.".into());
}
// Calculate validator stake account address linked to the pool
let (validator_stake_account, _) =
find_stake_address_for_validator(&spl_stake_pool::id(), &vote_account, pool);
let validator_stake_data = config
.rpc_client
.get_account_data(&validator_stake_account)?;
let validator_stake_data: StakeState =
deserialize(validator_stake_data.as_slice()).or(Err("Invalid stake account data"))?;
let validator_stake_state = get_stake_state(&config.rpc_client, &validator_stake_account)?;
println!("Depositing into stake account {}", validator_stake_account);
if config.verbose {
println!("Depositing into stake account {:?}", validator_stake_data);
} else {
println!("Depositing into stake account {}", validator_stake_account);
println!("{:?}", validator_stake_state);
}
let mut instructions: Vec<Instruction> = vec![];
@ -639,7 +569,7 @@ fn command_deposit(
StakeAuthorize::Staker,
),
// Add stake account to the pool
deposit(
spl_stake_pool::instruction::deposit(
&spl_stake_pool::id(),
&pool,
&pool_data.validator_list,
@ -669,26 +599,12 @@ fn command_deposit(
}
fn command_list(config: &Config, pool: &Pubkey) -> CommandResult {
// Get stake pool state
let pool_data = config.rpc_client.get_account_data(&pool)?;
let pool_data = StakePool::try_from_slice(pool_data.as_slice())
.map_err(|err| format!("Invalid pool {}: {}", pool, err))?;
let pool_data = get_stake_pool(&config.rpc_client, pool)?;
if config.verbose {
let validator_list = config
.rpc_client
.get_account_data(&pool_data.validator_list)?;
let validator_list_data = try_from_slice_unchecked::<ValidatorList>(
&validator_list.as_slice(),
)
.map_err(|err| {
format!(
"Invalid validator list{}: {}",
pool_data.validator_list, err
)
})?;
println!("Current validator list");
for validator in validator_list_data.validators {
let validator_list = get_validator_list(&config.rpc_client, &pool_data.validator_list)?;
for validator in validator_list.validators {
println!(
"Vote Account: {}\tBalance: {}\tEpoch: {}",
validator.validator_account, validator.balance, validator.last_update_epoch
@ -725,18 +641,11 @@ fn command_list(config: &Config, pool: &Pubkey) -> CommandResult {
}
fn command_update(config: &Config, pool: &Pubkey) -> CommandResult {
// Get stake pool state
let pool_data = config.rpc_client.get_account_data(&pool)?;
let pool_data = StakePool::try_from_slice(pool_data.as_slice()).unwrap();
let validator_list_data = config
.rpc_client
.get_account_data(&pool_data.validator_list)?;
let validator_list_data =
try_from_slice_unchecked::<ValidatorList>(&validator_list_data.as_slice())?;
let pool_data = get_stake_pool(&config.rpc_client, pool)?;
let validator_list = get_validator_list(&config.rpc_client, &pool_data.validator_list)?;
let epoch_info = config.rpc_client.get_epoch_info()?;
let accounts_to_update: Vec<Pubkey> = validator_list_data
let accounts_to_update: Vec<Pubkey> = validator_list
.validators
.iter()
.filter_map(|item| {
@ -756,7 +665,7 @@ fn command_update(config: &Config, pool: &Pubkey) -> CommandResult {
let mut instructions: Vec<Instruction> = vec![];
for chunk in accounts_to_update.chunks(MAX_ACCOUNTS_TO_UPDATE) {
instructions.push(update_validator_list_balance(
instructions.push(spl_stake_pool::instruction::update_validator_list_balance(
&spl_stake_pool::id(),
&pool_data.validator_list,
&chunk,
@ -768,7 +677,7 @@ fn command_update(config: &Config, pool: &Pubkey) -> CommandResult {
Ok(())
} else {
println!("Updating stake pool...");
instructions.push(update_stake_pool_balance(
instructions.push(spl_stake_pool::instruction::update_stake_pool_balance(
&spl_stake_pool::id(),
pool,
&pool_data.validator_list,
@ -802,8 +711,7 @@ fn prepare_withdraw_accounts(
return Err("No accounts found.".to_string().into());
}
let min_balance = rpc_client.get_minimum_balance_for_rent_exemption(STAKE_STATE_LEN)? + 1;
let pool_mint_data = rpc_client.get_account_data(&stake_pool.pool_mint)?;
let pool_mint = TokenMint::unpack_from_slice(pool_mint_data.as_slice()).unwrap();
let pool_mint = get_token_mint(rpc_client, &stake_pool.pool_mint)?;
// Sort from highest to lowest balance
accounts.sort_by(|a, b| b.1.cmp(&a.1));
@ -857,12 +765,8 @@ fn command_withdraw(
command_update(config, pool)?;
}
// Get stake pool state
let pool_data = config.rpc_client.get_account_data(&pool)?;
let pool_data = StakePool::try_from_slice(pool_data.as_slice()).unwrap();
let pool_mint_data = config.rpc_client.get_account_data(&pool_data.pool_mint)?;
let pool_mint = TokenMint::unpack_from_slice(pool_mint_data.as_slice()).unwrap();
let pool_data = get_stake_pool(&config.rpc_client, pool)?;
let pool_mint = get_token_mint(&config.rpc_client, &pool_data.pool_mint)?;
let pool_amount = spl_token::ui_amount_to_amount(pool_amount, pool_mint.decimals);
let pool_withdraw_authority: Pubkey = create_pool_authority_address(
@ -874,20 +778,15 @@ fn command_withdraw(
.unwrap();
// Check withdraw_from account type
let account_data = config.rpc_client.get_account_data(&withdraw_from)?;
let account_data: TokenAccount =
TokenAccount::unpack_from_slice(account_data.as_slice()).unwrap();
if account_data.mint != pool_data.pool_mint {
return Err("Wrong token account.".into());
}
let token_account =
get_token_account(&config.rpc_client, &withdraw_from, &pool_data.pool_mint)?;
// Check withdraw_from balance
if account_data.amount < pool_amount {
if token_account.amount < pool_amount {
return Err(format!(
"Not enough token balance to withdraw {} pool tokens.\nMaximum withdraw amount is {} pool tokens.",
spl_token::amount_to_ui_amount(pool_amount, pool_mint.decimals),
spl_token::amount_to_ui_amount(account_data.amount, pool_mint.decimals)
spl_token::amount_to_ui_amount(token_account.amount, pool_mint.decimals)
)
.into());
}
@ -907,7 +806,7 @@ fn command_withdraw(
instructions.push(
// Approve spending token
approve_token(
spl_token::instruction::approve(
&spl_token::id(),
&withdraw_from,
&pool_withdraw_authority,
@ -965,7 +864,7 @@ fn command_withdraw(
stake_receiver = Some(stake_receiver_account.pubkey());
}
instructions.push(withdraw(
instructions.push(spl_stake_pool::instruction::withdraw(
&spl_stake_pool::id(),
&pool,
&pool_data.validator_list,
@ -1000,27 +899,19 @@ fn command_set_owner(
new_owner: &Option<Pubkey>,
new_fee_receiver: &Option<Pubkey>,
) -> CommandResult {
let pool_data = config.rpc_client.get_account_data(&pool)?;
let pool_data: StakePool = StakePool::try_from_slice(pool_data.as_slice()).unwrap();
let pool_data = get_stake_pool(&config.rpc_client, pool)?;
// If new accounts are missing in the arguments use the old ones
let new_owner: Pubkey = match new_owner {
let new_owner = match new_owner {
None => pool_data.owner,
Some(value) => *value,
};
let new_fee_receiver: Pubkey = match new_fee_receiver {
let new_fee_receiver = match new_fee_receiver {
None => pool_data.owner_fee_account,
Some(value) => {
// Check for fee receiver being a valid token account and have to same mint as the stake pool
let account_data = config.rpc_client.get_account_data(value)?;
let account_data: TokenAccount =
match TokenAccount::unpack_from_slice(account_data.as_slice()) {
Ok(data) => data,
Err(_) => {
return Err(format!("{} is not a token account", value).into());
}
};
if account_data.mint != pool_data.pool_mint {
let token_account = get_token_account(&config.rpc_client, value, &pool_data.pool_mint)?;
if token_account.mint != pool_data.pool_mint {
return Err("Fee receiver account belongs to a different mint"
.to_string()
.into());
@ -1030,7 +921,7 @@ fn command_set_owner(
};
let mut transaction = Transaction::new_with_payer(
&[set_owner(
&[spl_stake_pool::instruction::set_owner(
&spl_stake_pool::id(),
&pool,
&config.owner.pubkey(),
@ -1122,7 +1013,8 @@ fn main() {
Defaults to the client keypair.",
),
)
.subcommand(SubCommand::with_name("create-pool").about("Create a new stake pool")
.subcommand(SubCommand::with_name("create-pool")
.about("Create a new stake pool")
.arg(
Arg::with_name("fee_numerator")
.long("fee-numerator")
@ -1154,7 +1046,8 @@ fn main() {
.help("Max number of validators included in the stake pool"),
)
)
.subcommand(SubCommand::with_name("create-validator-stake").about("Create a new stake account to use with the pool. Must be signed by the pool owner.")
.subcommand(SubCommand::with_name("create-validator-stake")
.about("Create a new stake account to use with the pool. Must be signed by the pool owner.")
.arg(
Arg::with_name("pool")
.index(1)
@ -1174,7 +1067,8 @@ fn main() {
.help("The validator vote account that this stake will be delegated to"),
)
)
.subcommand(SubCommand::with_name("add-validator").about("Add validator account to the stake pool. Must be signed by the pool owner.")
.subcommand(SubCommand::with_name("add-validator")
.about("Add validator account to the stake pool. Must be signed by the pool owner.")
.arg(
Arg::with_name("pool")
.index(1)
@ -1199,10 +1093,12 @@ fn main() {
.validator(is_pubkey)
.value_name("ADDRESS")
.takes_value(true)
.help("Account to receive pool token. Must be initialized account of the stake pool token. Defaults to the new pool token account."),
.help("Account to receive pool token. Must be initialized account of the stake pool token. \
Defaults to the new pool token account."),
)
)
.subcommand(SubCommand::with_name("remove-validator").about("Remove validator account from the stake pool. Must be signed by the pool owner.")
.subcommand(SubCommand::with_name("remove-validator")
.about("Remove validator account from the stake pool. Must be signed by the pool owner.")
.arg(
Arg::with_name("pool")
.index(1)
@ -1228,7 +1124,8 @@ fn main() {
.value_name("ADDRESS")
.takes_value(true)
.required(true)
.help("Token account to withdraw pool token from. Must have enough tokens for the full stake address balance."),
.help("Token account to withdraw pool token from. \
Must have enough tokens for the full stake address balance."),
)
.arg(
Arg::with_name("new_authority")
@ -1236,10 +1133,12 @@ fn main() {
.validator(is_pubkey)
.value_name("ADDRESS")
.takes_value(true)
.help("New authority to set as Staker and Withdrawer in the stake account removed from the pool. Defaults to the wallet owner pubkey."),
.help("New authority to set as Staker and Withdrawer in the stake account removed from the pool.
Defaults to the wallet owner pubkey."),
)
)
.subcommand(SubCommand::with_name("deposit").about("Add stake account to the stake pool")
.subcommand(SubCommand::with_name("deposit")
.about("Add stake account to the stake pool")
.arg(
Arg::with_name("pool")
.index(1)
@ -1264,10 +1163,12 @@ fn main() {
.validator(is_pubkey)
.value_name("ADDRESS")
.takes_value(true)
.help("Account to receive pool token. Must be initialized account of the stake pool token. Defaults to the new pool token account."),
.help("Account to receive pool token. Must be initialized account of the stake pool token. \
Defaults to the new pool token account."),
)
)
.subcommand(SubCommand::with_name("list").about("List stake accounts managed by this pool")
.subcommand(SubCommand::with_name("list")
.about("List stake accounts managed by this pool")
.arg(
Arg::with_name("pool")
.index(1)
@ -1278,7 +1179,8 @@ fn main() {
.help("Stake pool address."),
)
)
.subcommand(SubCommand::with_name("update").about("Updates all balances in the pool after validator stake accounts receive rewards.")
.subcommand(SubCommand::with_name("update")
.about("Updates all balances in the pool after validator stake accounts receive rewards.")
.arg(
Arg::with_name("pool")
.index(1)
@ -1289,7 +1191,8 @@ fn main() {
.help("Stake pool address."),
)
)
.subcommand(SubCommand::with_name("withdraw").about("Withdraw amount from the stake pool")
.subcommand(SubCommand::with_name("withdraw")
.about("Withdraw amount from the stake pool")
.arg(
Arg::with_name("pool")
.index(1)
@ -1326,7 +1229,8 @@ fn main() {
.help("Stake account to receive SOL from the stake pool. Defaults to a new stake account."),
)
)
.subcommand(SubCommand::with_name("set-owner").about("Changes owner or fee receiver account for the stake pool.")
.subcommand(SubCommand::with_name("set-owner")
.about("Changes owner or fee receiver account for the stake pool.")
.arg(
Arg::with_name("pool")
.index(1)
@ -1414,7 +1318,7 @@ fn main() {
let max_validators = value_t_or_exit!(arg_matches, "max_validators", u32);
command_create_pool(
&config,
PoolFee {
spl_stake_pool::instruction::Fee {
denominator,
numerator,
},