Cli: promote commitment to a global arg + config.yml (#14684)
* Make commitment a global arg * Add commitment to solana/cli/config.yml * Fixup a couple Display/Verbose bugs
This commit is contained in:
@ -1,22 +0,0 @@
|
|||||||
use crate::ArgConstant;
|
|
||||||
use clap::Arg;
|
|
||||||
|
|
||||||
pub const COMMITMENT_ARG: ArgConstant<'static> = ArgConstant {
|
|
||||||
name: "commitment",
|
|
||||||
long: "commitment",
|
|
||||||
help: "Return information at the selected commitment level",
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn commitment_arg<'a, 'b>() -> Arg<'a, 'b> {
|
|
||||||
commitment_arg_with_default("recent")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn commitment_arg_with_default<'a, 'b>(default_value: &'static str) -> Arg<'a, 'b> {
|
|
||||||
Arg::with_name(COMMITMENT_ARG.name)
|
|
||||||
.long(COMMITMENT_ARG.long)
|
|
||||||
.takes_value(true)
|
|
||||||
.possible_values(&["recent", "single", "singleGossip", "root", "max"])
|
|
||||||
.default_value(default_value)
|
|
||||||
.value_name("COMMITMENT_LEVEL")
|
|
||||||
.help(COMMITMENT_ARG.help)
|
|
||||||
}
|
|
@ -184,14 +184,9 @@ pub fn cluster_type_of(matches: &ArgMatches<'_>, name: &str) -> Option<ClusterTy
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn commitment_of(matches: &ArgMatches<'_>, name: &str) -> Option<CommitmentConfig> {
|
pub fn commitment_of(matches: &ArgMatches<'_>, name: &str) -> Option<CommitmentConfig> {
|
||||||
matches.value_of(name).map(|value| match value {
|
matches
|
||||||
"max" => CommitmentConfig::max(),
|
.value_of(name)
|
||||||
"recent" => CommitmentConfig::recent(),
|
.map(|value| CommitmentConfig::from_str(value).unwrap_or_default())
|
||||||
"root" => CommitmentConfig::root(),
|
|
||||||
"single" => CommitmentConfig::single(),
|
|
||||||
"singleGossip" => CommitmentConfig::single_gossip(),
|
|
||||||
_ => CommitmentConfig::default(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -23,7 +23,6 @@ impl std::fmt::Debug for DisplayError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod commitment;
|
|
||||||
pub mod fee_payer;
|
pub mod fee_payer;
|
||||||
pub mod input_parsers;
|
pub mod input_parsers;
|
||||||
pub mod input_validators;
|
pub mod input_validators;
|
||||||
|
@ -17,9 +17,10 @@ pub struct Config {
|
|||||||
pub json_rpc_url: String,
|
pub json_rpc_url: String,
|
||||||
pub websocket_url: String,
|
pub websocket_url: String,
|
||||||
pub keypair_path: String,
|
pub keypair_path: String,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub address_labels: HashMap<String, String>,
|
pub address_labels: HashMap<String, String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub commitment: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
@ -41,11 +42,14 @@ impl Default for Config {
|
|||||||
"System Program".to_string(),
|
"System Program".to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let commitment = "singleGossip".to_string();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
json_rpc_url,
|
json_rpc_url,
|
||||||
websocket_url,
|
websocket_url,
|
||||||
keypair_path,
|
keypair_path,
|
||||||
address_labels,
|
address_labels,
|
||||||
|
commitment,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ use serde_json::{self, Value};
|
|||||||
use solana_account_decoder::{UiAccount, UiAccountEncoding};
|
use solana_account_decoder::{UiAccount, UiAccountEncoding};
|
||||||
use solana_clap_utils::{
|
use solana_clap_utils::{
|
||||||
self,
|
self,
|
||||||
commitment::commitment_arg_with_default,
|
|
||||||
fee_payer::{fee_payer_arg, FEE_PAYER_ARG},
|
fee_payer::{fee_payer_arg, FEE_PAYER_ARG},
|
||||||
input_parsers::*,
|
input_parsers::*,
|
||||||
input_validators::*,
|
input_validators::*,
|
||||||
@ -431,6 +430,10 @@ impl CliConfig<'_> {
|
|||||||
solana_cli_config::Config::default().websocket_url
|
solana_cli_config::Config::default().websocket_url
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_commitment() -> CommitmentConfig {
|
||||||
|
CommitmentConfig::single_gossip()
|
||||||
|
}
|
||||||
|
|
||||||
fn first_nonempty_setting(
|
fn first_nonempty_setting(
|
||||||
settings: std::vec::Vec<(SettingType, String)>,
|
settings: std::vec::Vec<(SettingType, String)>,
|
||||||
) -> (SettingType, String) {
|
) -> (SettingType, String) {
|
||||||
@ -440,6 +443,16 @@ impl CliConfig<'_> {
|
|||||||
.expect("no nonempty setting")
|
.expect("no nonempty setting")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn first_setting_is_some<T>(
|
||||||
|
settings: std::vec::Vec<(SettingType, Option<T>)>,
|
||||||
|
) -> (SettingType, T) {
|
||||||
|
let (setting_type, setting_option) = settings
|
||||||
|
.into_iter()
|
||||||
|
.find(|(_, value)| value.is_some())
|
||||||
|
.expect("all settings none");
|
||||||
|
(setting_type, setting_option.unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn compute_websocket_url_setting(
|
pub fn compute_websocket_url_setting(
|
||||||
websocket_cmd_url: &str,
|
websocket_cmd_url: &str,
|
||||||
websocket_cfg_url: &str,
|
websocket_cfg_url: &str,
|
||||||
@ -484,6 +497,23 @@ impl CliConfig<'_> {
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn compute_commitment_config(
|
||||||
|
commitment_cmd: &str,
|
||||||
|
commitment_cfg: &str,
|
||||||
|
) -> (SettingType, CommitmentConfig) {
|
||||||
|
Self::first_setting_is_some(vec![
|
||||||
|
(
|
||||||
|
SettingType::Explicit,
|
||||||
|
CommitmentConfig::from_str(commitment_cmd).ok(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
SettingType::Explicit,
|
||||||
|
CommitmentConfig::from_str(commitment_cfg).ok(),
|
||||||
|
),
|
||||||
|
(SettingType::SystemDefault, Some(Self::default_commitment())),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn pubkey(&self) -> Result<Pubkey, SignerError> {
|
pub(crate) fn pubkey(&self) -> Result<Pubkey, SignerError> {
|
||||||
if !self.signers.is_empty() {
|
if !self.signers.is_empty() {
|
||||||
self.signers[0].try_pubkey()
|
self.signers[0].try_pubkey()
|
||||||
@ -1019,7 +1049,9 @@ fn process_show_account(
|
|||||||
|
|
||||||
let mut account_string = config.output_format.formatted_string(&cli_account);
|
let mut account_string = config.output_format.formatted_string(&cli_account);
|
||||||
|
|
||||||
if config.output_format == OutputFormat::Display {
|
if config.output_format == OutputFormat::Display
|
||||||
|
|| config.output_format == OutputFormat::DisplayVerbose
|
||||||
|
{
|
||||||
if let Some(output_file) = output_file {
|
if let Some(output_file) = output_file {
|
||||||
let mut f = File::create(output_file)?;
|
let mut f = File::create(output_file)?;
|
||||||
f.write_all(&data)?;
|
f.write_all(&data)?;
|
||||||
@ -1107,12 +1139,13 @@ fn process_transfer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_command(config: &CliConfig) -> ProcessResult {
|
pub fn process_command(config: &CliConfig) -> ProcessResult {
|
||||||
if config.verbose && config.output_format == OutputFormat::Display {
|
if config.verbose && config.output_format == OutputFormat::DisplayVerbose {
|
||||||
println_name_value("RPC URL:", &config.json_rpc_url);
|
println_name_value("RPC URL:", &config.json_rpc_url);
|
||||||
println_name_value("Default Signer Path:", &config.keypair_path);
|
println_name_value("Default Signer Path:", &config.keypair_path);
|
||||||
if config.keypair_path.starts_with("usb://") {
|
if config.keypair_path.starts_with("usb://") {
|
||||||
println_name_value("Pubkey:", &format!("{:?}", config.pubkey()?));
|
println_name_value("Pubkey:", &format!("{:?}", config.pubkey()?));
|
||||||
}
|
}
|
||||||
|
println_name_value("Commitment:", &config.commitment.commitment.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut _rpc_client;
|
let mut _rpc_client;
|
||||||
@ -1851,8 +1884,7 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, '
|
|||||||
.long("lamports")
|
.long("lamports")
|
||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.help("Display balance in lamports instead of SOL"),
|
.help("Display balance in lamports instead of SOL"),
|
||||||
)
|
),
|
||||||
.arg(commitment_arg_with_default("singleGossip")),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("confirm")
|
SubCommand::with_name("confirm")
|
||||||
@ -1949,8 +1981,7 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, '
|
|||||||
.long("allow-excessive-deploy-account-balance")
|
.long("allow-excessive-deploy-account-balance")
|
||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.help("Use the designated program id, even if the account already holds a large balance of SOL")
|
.help("Use the designated program id, even if the account already holds a large balance of SOL")
|
||||||
)
|
),
|
||||||
.arg(commitment_arg_with_default("singleGossip")),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("pay")
|
SubCommand::with_name("pay")
|
||||||
|
@ -7,7 +7,6 @@ use chrono::{Local, TimeZone};
|
|||||||
use clap::{value_t, value_t_or_exit, App, AppSettings, Arg, ArgMatches, SubCommand};
|
use clap::{value_t, value_t_or_exit, App, AppSettings, Arg, ArgMatches, SubCommand};
|
||||||
use console::{style, Emoji};
|
use console::{style, Emoji};
|
||||||
use solana_clap_utils::{
|
use solana_clap_utils::{
|
||||||
commitment::{commitment_arg, commitment_arg_with_default},
|
|
||||||
input_parsers::*,
|
input_parsers::*,
|
||||||
input_validators::*,
|
input_validators::*,
|
||||||
keypair::DefaultSigner,
|
keypair::DefaultSigner,
|
||||||
@ -121,20 +120,17 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
|||||||
.long("log")
|
.long("log")
|
||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.help("Don't update the progress inplace; instead show updates with its own new lines"),
|
.help("Don't update the progress inplace; instead show updates with its own new lines"),
|
||||||
)
|
),
|
||||||
.arg(commitment_arg()),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("cluster-date")
|
SubCommand::with_name("cluster-date")
|
||||||
.about("Get current cluster date, computed from genesis creation time and network time")
|
.about("Get current cluster date, computed from genesis creation time and network time"),
|
||||||
.arg(commitment_arg()),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("cluster-version")
|
SubCommand::with_name("cluster-version")
|
||||||
.about("Get the version of the cluster entrypoint"),
|
.about("Get the version of the cluster entrypoint"),
|
||||||
)
|
)
|
||||||
.subcommand(SubCommand::with_name("fees").about("Display current cluster fees")
|
.subcommand(SubCommand::with_name("fees").about("Display current cluster fees"),
|
||||||
.arg(commitment_arg()),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("first-available-block")
|
SubCommand::with_name("first-available-block")
|
||||||
@ -165,8 +161,7 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
|||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("epoch-info")
|
SubCommand::with_name("epoch-info")
|
||||||
.about("Get information about the current epoch")
|
.about("Get information about the current epoch")
|
||||||
.alias("get-epoch-info")
|
.alias("get-epoch-info"),
|
||||||
.arg(commitment_arg()),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("genesis-hash")
|
SubCommand::with_name("genesis-hash")
|
||||||
@ -175,16 +170,13 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
|||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("slot").about("Get current slot")
|
SubCommand::with_name("slot").about("Get current slot")
|
||||||
.alias("get-slot")
|
.alias("get-slot"),
|
||||||
.arg(commitment_arg()),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("block-height").about("Get current block height")
|
SubCommand::with_name("block-height").about("Get current block height"),
|
||||||
.arg(commitment_arg()),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("epoch").about("Get current epoch")
|
SubCommand::with_name("epoch").about("Get current epoch"),
|
||||||
.arg(commitment_arg()),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("largest-accounts").about("Get addresses of largest cluster accounts")
|
SubCommand::with_name("largest-accounts").about("Get addresses of largest cluster accounts")
|
||||||
@ -200,8 +192,7 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
|||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.conflicts_with("circulating")
|
.conflicts_with("circulating")
|
||||||
.help("Filter address list to only non-circulating accounts")
|
.help("Filter address list to only non-circulating accounts")
|
||||||
)
|
),
|
||||||
.arg(commitment_arg()),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("supply").about("Get information about the cluster supply of SOL")
|
SubCommand::with_name("supply").about("Get information about the cluster supply of SOL")
|
||||||
@ -210,18 +201,15 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
|||||||
.long("print-accounts")
|
.long("print-accounts")
|
||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.help("Print list of non-circualting account addresses")
|
.help("Print list of non-circualting account addresses")
|
||||||
)
|
),
|
||||||
.arg(commitment_arg()),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("total-supply").about("Get total number of SOL")
|
SubCommand::with_name("total-supply").about("Get total number of SOL")
|
||||||
.setting(AppSettings::Hidden)
|
.setting(AppSettings::Hidden),
|
||||||
.arg(commitment_arg()),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("transaction-count").about("Get current transaction count")
|
SubCommand::with_name("transaction-count").about("Get current transaction count")
|
||||||
.alias("get-transaction-count")
|
.alias("get-transaction-count"),
|
||||||
.arg(commitment_arg()),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("ping")
|
SubCommand::with_name("ping")
|
||||||
@ -268,8 +256,7 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
|||||||
.default_value("15")
|
.default_value("15")
|
||||||
.help("Wait up to timeout seconds for transaction confirmation"),
|
.help("Wait up to timeout seconds for transaction confirmation"),
|
||||||
)
|
)
|
||||||
.arg(blockhash_arg())
|
.arg(blockhash_arg()),
|
||||||
.arg(commitment_arg()),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("live-slots")
|
SubCommand::with_name("live-slots")
|
||||||
@ -292,8 +279,7 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
|||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.conflicts_with("address")
|
.conflicts_with("address")
|
||||||
.help("Include vote transactions when monitoring all transactions")
|
.help("Include vote transactions when monitoring all transactions")
|
||||||
)
|
),
|
||||||
.arg(commitment_arg_with_default("singleGossip")),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("block-production")
|
SubCommand::with_name("block-production")
|
||||||
@ -343,8 +329,7 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
|||||||
.long("lamports")
|
.long("lamports")
|
||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.help("Display balance in lamports instead of SOL"),
|
.help("Display balance in lamports instead of SOL"),
|
||||||
)
|
),
|
||||||
.arg(commitment_arg()),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("transaction-history")
|
SubCommand::with_name("transaction-history")
|
||||||
@ -1984,8 +1969,6 @@ mod tests {
|
|||||||
"-t",
|
"-t",
|
||||||
"3",
|
"3",
|
||||||
"-D",
|
"-D",
|
||||||
"--commitment",
|
|
||||||
"max",
|
|
||||||
"--blockhash",
|
"--blockhash",
|
||||||
"4CCNp28j6AhGq7PkjPDP4wbQWBS8LLbQin2xV5n8frKX",
|
"4CCNp28j6AhGq7PkjPDP4wbQWBS8LLbQin2xV5n8frKX",
|
||||||
]);
|
]);
|
||||||
|
@ -3,10 +3,7 @@ use clap::{
|
|||||||
SubCommand,
|
SubCommand,
|
||||||
};
|
};
|
||||||
use console::style;
|
use console::style;
|
||||||
|
|
||||||
use solana_clap_utils::{
|
use solana_clap_utils::{
|
||||||
commitment::COMMITMENT_ARG,
|
|
||||||
input_parsers::commitment_of,
|
|
||||||
input_validators::{is_url, is_url_or_moniker},
|
input_validators::{is_url, is_url_or_moniker},
|
||||||
keypair::{CliSigners, DefaultSigner, SKIP_SEED_PHRASE_VALIDATION_ARG},
|
keypair::{CliSigners, DefaultSigner, SKIP_SEED_PHRASE_VALIDATION_ARG},
|
||||||
DisplayError,
|
DisplayError,
|
||||||
@ -19,7 +16,6 @@ use solana_cli_config::{Config, CONFIG_FILE};
|
|||||||
use solana_cli_output::{display::println_name_value, OutputFormat};
|
use solana_cli_output::{display::println_name_value, OutputFormat};
|
||||||
use solana_client::rpc_config::RpcSendTransactionConfig;
|
use solana_client::rpc_config::RpcSendTransactionConfig;
|
||||||
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
|
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
|
||||||
use solana_sdk::commitment_config::CommitmentConfig;
|
|
||||||
use std::{collections::HashMap, error, path::PathBuf, sync::Arc, time::Duration};
|
use std::{collections::HashMap, error, path::PathBuf, sync::Arc, time::Duration};
|
||||||
|
|
||||||
pub fn println_name_value_or(name: &str, value: &str, setting_type: SettingType) {
|
pub fn println_name_value_or(name: &str, value: &str, setting_type: SettingType) {
|
||||||
@ -64,12 +60,19 @@ fn parse_settings(matches: &ArgMatches<'_>) -> Result<bool, Box<dyn error::Error
|
|||||||
);
|
);
|
||||||
let (keypair_setting_type, keypair_path) =
|
let (keypair_setting_type, keypair_path) =
|
||||||
CliConfig::compute_keypair_path_setting("", &config.keypair_path);
|
CliConfig::compute_keypair_path_setting("", &config.keypair_path);
|
||||||
|
let (commitment_setting_type, commitment) =
|
||||||
|
CliConfig::compute_commitment_config("", &config.commitment);
|
||||||
|
|
||||||
if let Some(field) = subcommand_matches.value_of("specific_setting") {
|
if let Some(field) = subcommand_matches.value_of("specific_setting") {
|
||||||
let (field_name, value, setting_type) = match field {
|
let (field_name, value, setting_type) = match field {
|
||||||
"json_rpc_url" => ("RPC URL", json_rpc_url, url_setting_type),
|
"json_rpc_url" => ("RPC URL", json_rpc_url, url_setting_type),
|
||||||
"websocket_url" => ("WebSocket URL", websocket_url, ws_setting_type),
|
"websocket_url" => ("WebSocket URL", websocket_url, ws_setting_type),
|
||||||
"keypair" => ("Key Path", keypair_path, keypair_setting_type),
|
"keypair" => ("Key Path", keypair_path, keypair_setting_type),
|
||||||
|
"commitment" => (
|
||||||
|
"Commitment",
|
||||||
|
commitment.commitment.to_string(),
|
||||||
|
commitment_setting_type,
|
||||||
|
),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
println_name_value_or(&format!("{}:", field_name), &value, setting_type);
|
println_name_value_or(&format!("{}:", field_name), &value, setting_type);
|
||||||
@ -78,6 +81,11 @@ fn parse_settings(matches: &ArgMatches<'_>) -> Result<bool, Box<dyn error::Error
|
|||||||
println_name_value_or("RPC URL:", &json_rpc_url, url_setting_type);
|
println_name_value_or("RPC URL:", &json_rpc_url, url_setting_type);
|
||||||
println_name_value_or("WebSocket URL:", &websocket_url, ws_setting_type);
|
println_name_value_or("WebSocket URL:", &websocket_url, ws_setting_type);
|
||||||
println_name_value_or("Keypair Path:", &keypair_path, keypair_setting_type);
|
println_name_value_or("Keypair Path:", &keypair_path, keypair_setting_type);
|
||||||
|
println_name_value_or(
|
||||||
|
"Commitment:",
|
||||||
|
&commitment.commitment.to_string(),
|
||||||
|
commitment_setting_type,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
("set", Some(subcommand_matches)) => {
|
("set", Some(subcommand_matches)) => {
|
||||||
@ -93,6 +101,9 @@ fn parse_settings(matches: &ArgMatches<'_>) -> Result<bool, Box<dyn error::Error
|
|||||||
if let Some(keypair) = subcommand_matches.value_of("keypair") {
|
if let Some(keypair) = subcommand_matches.value_of("keypair") {
|
||||||
config.keypair_path = keypair.to_string();
|
config.keypair_path = keypair.to_string();
|
||||||
}
|
}
|
||||||
|
if let Some(commitment) = subcommand_matches.value_of("commitment") {
|
||||||
|
config.commitment = commitment.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
config.save(config_file)?;
|
config.save(config_file)?;
|
||||||
|
|
||||||
@ -106,11 +117,18 @@ fn parse_settings(matches: &ArgMatches<'_>) -> Result<bool, Box<dyn error::Error
|
|||||||
);
|
);
|
||||||
let (keypair_setting_type, keypair_path) =
|
let (keypair_setting_type, keypair_path) =
|
||||||
CliConfig::compute_keypair_path_setting("", &config.keypair_path);
|
CliConfig::compute_keypair_path_setting("", &config.keypair_path);
|
||||||
|
let (commitment_setting_type, commitment) =
|
||||||
|
CliConfig::compute_commitment_config("", &config.commitment);
|
||||||
|
|
||||||
println_name_value("Config File:", config_file);
|
println_name_value("Config File:", config_file);
|
||||||
println_name_value_or("RPC URL:", &json_rpc_url, url_setting_type);
|
println_name_value_or("RPC URL:", &json_rpc_url, url_setting_type);
|
||||||
println_name_value_or("WebSocket URL:", &websocket_url, ws_setting_type);
|
println_name_value_or("WebSocket URL:", &websocket_url, ws_setting_type);
|
||||||
println_name_value_or("Keypair Path:", &keypair_path, keypair_setting_type);
|
println_name_value_or("Keypair Path:", &keypair_path, keypair_setting_type);
|
||||||
|
println_name_value_or(
|
||||||
|
"Commitment:",
|
||||||
|
&commitment.commitment.to_string(),
|
||||||
|
commitment_setting_type,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
("import-address-labels", Some(subcommand_matches)) => {
|
("import-address-labels", Some(subcommand_matches)) => {
|
||||||
let filename = value_t_or_exit!(subcommand_matches, "filename", PathBuf);
|
let filename = value_t_or_exit!(subcommand_matches, "filename", PathBuf);
|
||||||
@ -183,16 +201,10 @@ pub fn parse_args<'a>(
|
|||||||
OutputFormat::Display
|
OutputFormat::Display
|
||||||
});
|
});
|
||||||
|
|
||||||
let commitment = {
|
let (_, commitment) = CliConfig::compute_commitment_config(
|
||||||
let mut sub_matches = matches;
|
matches.value_of("commitment").unwrap_or(""),
|
||||||
while let Some(subcommand_name) = sub_matches.subcommand_name() {
|
&config.commitment,
|
||||||
sub_matches = sub_matches
|
);
|
||||||
.subcommand_matches(subcommand_name)
|
|
||||||
.expect("subcommand_matches");
|
|
||||||
}
|
|
||||||
commitment_of(sub_matches, COMMITMENT_ARG.long)
|
|
||||||
}
|
|
||||||
.unwrap_or_else(CommitmentConfig::single_gossip);
|
|
||||||
|
|
||||||
let address_labels = if matches.is_present("no_address_labels") {
|
let address_labels = if matches.is_present("no_address_labels") {
|
||||||
HashMap::new()
|
HashMap::new()
|
||||||
@ -274,6 +286,15 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("Filepath or URL to a keypair"),
|
.help("Filepath or URL to a keypair"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("commitment")
|
||||||
|
.long("commitment")
|
||||||
|
.takes_value(true)
|
||||||
|
.possible_values(&["recent", "single", "singleGossip", "root", "max"])
|
||||||
|
.value_name("COMMITMENT_LEVEL")
|
||||||
|
.global(true)
|
||||||
|
.help("Return information at the selected commitment level"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("verbose")
|
Arg::with_name("verbose")
|
||||||
.long("verbose")
|
.long("verbose")
|
||||||
@ -325,7 +346,12 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||||||
.index(1)
|
.index(1)
|
||||||
.value_name("CONFIG_FIELD")
|
.value_name("CONFIG_FIELD")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.possible_values(&["json_rpc_url", "websocket_url", "keypair"])
|
.possible_values(&[
|
||||||
|
"json_rpc_url",
|
||||||
|
"websocket_url",
|
||||||
|
"keypair",
|
||||||
|
"commitment",
|
||||||
|
])
|
||||||
.help("Return a specific config setting"),
|
.help("Return a specific config setting"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -334,7 +360,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||||||
.about("Set a config setting")
|
.about("Set a config setting")
|
||||||
.group(
|
.group(
|
||||||
ArgGroup::with_name("config_settings")
|
ArgGroup::with_name("config_settings")
|
||||||
.args(&["json_rpc_url", "websocket_url", "keypair"])
|
.args(&["json_rpc_url", "websocket_url", "keypair", "commitment"])
|
||||||
.multiple(true)
|
.multiple(true)
|
||||||
.required(true),
|
.required(true),
|
||||||
),
|
),
|
||||||
|
@ -12,10 +12,7 @@ use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
|
|||||||
use log::*;
|
use log::*;
|
||||||
use serde_json::{self, json};
|
use serde_json::{self, json};
|
||||||
use solana_bpf_loader_program::{bpf_verifier, BPFError, ThisInstructionMeter};
|
use solana_bpf_loader_program::{bpf_verifier, BPFError, ThisInstructionMeter};
|
||||||
use solana_clap_utils::{
|
use solana_clap_utils::{self, input_parsers::*, input_validators::*, keypair::*};
|
||||||
self, commitment::commitment_arg_with_default, input_parsers::*, input_validators::*,
|
|
||||||
keypair::*,
|
|
||||||
};
|
|
||||||
use solana_cli_output::display::new_spinner_progress_bar;
|
use solana_cli_output::display::new_spinner_progress_bar;
|
||||||
use solana_client::{
|
use solana_client::{
|
||||||
rpc_client::RpcClient, rpc_config::RpcSendTransactionConfig,
|
rpc_client::RpcClient, rpc_config::RpcSendTransactionConfig,
|
||||||
@ -148,8 +145,7 @@ impl ProgramSubCommands for App<'_, '_> {
|
|||||||
.long("allow-excessive-deploy-account-balance")
|
.long("allow-excessive-deploy-account-balance")
|
||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.help("Use the designated program id even if the account already holds a large balance of SOL")
|
.help("Use the designated program id even if the account already holds a large balance of SOL")
|
||||||
)
|
),
|
||||||
.arg(commitment_arg_with_default("singleGossip")),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("write-buffer")
|
SubCommand::with_name("write-buffer")
|
||||||
@ -191,8 +187,7 @@ impl ProgramSubCommands for App<'_, '_> {
|
|||||||
.required(false)
|
.required(false)
|
||||||
.help("Maximum length of the upgradeable program \
|
.help("Maximum length of the upgradeable program \
|
||||||
[default: twice the length of the original deployed program]")
|
[default: twice the length of the original deployed program]")
|
||||||
)
|
),
|
||||||
.arg(commitment_arg_with_default("singleGossip")),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("set-buffer-authority")
|
SubCommand::with_name("set-buffer-authority")
|
||||||
@ -270,8 +265,7 @@ impl ProgramSubCommands for App<'_, '_> {
|
|||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.required(true)
|
.required(true)
|
||||||
.help("Public key of the account to query")
|
.help("Public key of the account to query")
|
||||||
)
|
),
|
||||||
.arg(commitment_arg_with_default("singleGossip")),
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ use crate::{
|
|||||||
use chrono::{Local, TimeZone};
|
use chrono::{Local, TimeZone};
|
||||||
use clap::{App, Arg, ArgGroup, ArgMatches, SubCommand};
|
use clap::{App, Arg, ArgGroup, ArgMatches, SubCommand};
|
||||||
use solana_clap_utils::{
|
use solana_clap_utils::{
|
||||||
commitment::commitment_arg_with_default,
|
|
||||||
fee_payer::{fee_payer_arg, FEE_PAYER_ARG},
|
fee_payer::{fee_payer_arg, FEE_PAYER_ARG},
|
||||||
input_parsers::*,
|
input_parsers::*,
|
||||||
input_validators::*,
|
input_validators::*,
|
||||||
@ -404,8 +403,7 @@ impl StakeSubCommands for App<'_, '_> {
|
|||||||
.long("lamports")
|
.long("lamports")
|
||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.help("Display balance in lamports instead of SOL")
|
.help("Display balance in lamports instead of SOL")
|
||||||
)
|
),
|
||||||
.arg(commitment_arg_with_default("singleGossip")),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("stake-history")
|
SubCommand::with_name("stake-history")
|
||||||
|
@ -8,7 +8,6 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use clap::{value_t_or_exit, App, Arg, ArgMatches, SubCommand};
|
use clap::{value_t_or_exit, App, Arg, ArgMatches, SubCommand};
|
||||||
use solana_clap_utils::{
|
use solana_clap_utils::{
|
||||||
commitment::commitment_arg_with_default,
|
|
||||||
input_parsers::*,
|
input_parsers::*,
|
||||||
input_validators::*,
|
input_validators::*,
|
||||||
keypair::{DefaultSigner, SignerIndex},
|
keypair::{DefaultSigner, SignerIndex},
|
||||||
@ -208,8 +207,7 @@ impl VoteSubCommands for App<'_, '_> {
|
|||||||
.long("lamports")
|
.long("lamports")
|
||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.help("Display balance in lamports instead of SOL"),
|
.help("Display balance in lamports instead of SOL"),
|
||||||
)
|
),
|
||||||
.arg(commitment_arg_with_default("singleGossip")),
|
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("withdraw-from-vote-account")
|
SubCommand::with_name("withdraw-from-vote-account")
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
use std::str::FromStr;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Default, Clone, Copy, Debug, PartialEq)]
|
#[derive(Serialize, Deserialize, Default, Clone, Copy, Debug, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CommitmentConfig {
|
pub struct CommitmentConfig {
|
||||||
@ -44,6 +47,14 @@ impl CommitmentConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FromStr for CommitmentConfig {
|
||||||
|
type Err = ParseCommitmentLevelError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
CommitmentLevel::from_str(s).map(|commitment| Self { commitment })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
/// An attribute of a slot. It describes how finalized a block is at some point in time. For example, a slot
|
/// An attribute of a slot. It describes how finalized a block is at some point in time. For example, a slot
|
||||||
@ -79,3 +90,37 @@ impl Default for CommitmentLevel {
|
|||||||
Self::Max
|
Self::Max
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FromStr for CommitmentLevel {
|
||||||
|
type Err = ParseCommitmentLevelError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s {
|
||||||
|
"max" => Ok(CommitmentLevel::Max),
|
||||||
|
"recent" => Ok(CommitmentLevel::Recent),
|
||||||
|
"root" => Ok(CommitmentLevel::Root),
|
||||||
|
"single" => Ok(CommitmentLevel::Single),
|
||||||
|
"singleGossip" => Ok(CommitmentLevel::SingleGossip),
|
||||||
|
_ => Err(ParseCommitmentLevelError::Invalid),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for CommitmentLevel {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
let s = match self {
|
||||||
|
CommitmentLevel::Max => "max",
|
||||||
|
CommitmentLevel::Recent => "recent",
|
||||||
|
CommitmentLevel::Root => "root",
|
||||||
|
CommitmentLevel::Single => "single",
|
||||||
|
CommitmentLevel::SingleGossip => "singleGossip",
|
||||||
|
};
|
||||||
|
write!(f, "{}", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum ParseCommitmentLevelError {
|
||||||
|
#[error("invalid variant")]
|
||||||
|
Invalid,
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user