Clap v3 update: keygen (#24479)
* update clap to v3: keygen * use clap-v3-utils * update Cargo.lock * address PR comments * get rid of unnecessary generic for clap validator
This commit is contained in:
parent
0d51596224
commit
a22101489c
|
@ -5038,10 +5038,10 @@ name = "solana-keygen"
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bs58",
|
"bs58",
|
||||||
"clap 2.33.3",
|
"clap 3.1.8",
|
||||||
"dirs-next",
|
"dirs-next",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"solana-clap-utils",
|
"solana-clap-v3-utils",
|
||||||
"solana-cli-config",
|
"solana-cli-config",
|
||||||
"solana-remote-wallet",
|
"solana-remote-wallet",
|
||||||
"solana-sdk 1.11.0",
|
"solana-sdk 1.11.0",
|
||||||
|
|
|
@ -25,12 +25,12 @@ where
|
||||||
|
|
||||||
// Return an error if string cannot be parsed as type T.
|
// Return an error if string cannot be parsed as type T.
|
||||||
// Takes a String to avoid second type parameter when used as a clap validator
|
// Takes a String to avoid second type parameter when used as a clap validator
|
||||||
pub fn is_parsable<T>(string: String) -> Result<(), String>
|
pub fn is_parsable<T>(string: &str) -> Result<(), String>
|
||||||
where
|
where
|
||||||
T: FromStr,
|
T: FromStr,
|
||||||
T::Err: Display,
|
T::Err: Display,
|
||||||
{
|
{
|
||||||
is_parsable_generic::<T, String>(string)
|
is_parsable_generic::<T, &str>(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return an error if string cannot be parsed as numeric type T, and value not within specified
|
// Return an error if string cannot be parsed as numeric type T, and value not within specified
|
||||||
|
@ -57,10 +57,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return an error if a pubkey cannot be parsed.
|
// Return an error if a pubkey cannot be parsed.
|
||||||
pub fn is_pubkey<T>(string: T) -> Result<(), String>
|
pub fn is_pubkey(string: &str) -> Result<(), String> {
|
||||||
where
|
|
||||||
T: AsRef<str> + Display,
|
|
||||||
{
|
|
||||||
is_parsable_generic::<Pubkey, _>(string)
|
is_parsable_generic::<Pubkey, _>(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,14 +93,11 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return an error if a `SignerSourceKind::Prompt` cannot be parsed
|
// Return an error if a `SignerSourceKind::Prompt` cannot be parsed
|
||||||
pub fn is_prompt_signer_source<T>(string: T) -> Result<(), String>
|
pub fn is_prompt_signer_source(string: &str) -> Result<(), String> {
|
||||||
where
|
if string == ASK_KEYWORD {
|
||||||
T: AsRef<str> + Display,
|
|
||||||
{
|
|
||||||
if string.as_ref() == ASK_KEYWORD {
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
match parse_signer_source(string.as_ref())
|
match parse_signer_source(string)
|
||||||
.map_err(|err| format!("{}", err))?
|
.map_err(|err| format!("{}", err))?
|
||||||
.kind
|
.kind
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,10 +11,10 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bs58 = "0.4.0"
|
bs58 = "0.4.0"
|
||||||
clap = "2.33"
|
clap = { version = "3.1.5", features = ["cargo"] }
|
||||||
dirs-next = "2.0.0"
|
dirs-next = "2.0.0"
|
||||||
num_cpus = "1.13.1"
|
num_cpus = "1.13.1"
|
||||||
solana-clap-utils = { path = "../clap-utils", version = "=1.11.0" }
|
solana-clap-v3-utils = { path = "../clap-v3-utils", version = "=1.11.0" }
|
||||||
solana-cli-config = { path = "../cli-config", version = "=1.11.0" }
|
solana-cli-config = { path = "../cli-config", version = "=1.11.0" }
|
||||||
solana-remote-wallet = { path = "../remote-wallet", version = "=1.11.0" }
|
solana-remote-wallet = { path = "../remote-wallet", version = "=1.11.0" }
|
||||||
solana-sdk = { path = "../sdk", version = "=1.11.0" }
|
solana-sdk = { path = "../sdk", version = "=1.11.0" }
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
#![allow(clippy::integer_arithmetic)]
|
#![allow(clippy::integer_arithmetic)]
|
||||||
use {
|
use {
|
||||||
bip39::{Language, Mnemonic, MnemonicType, Seed},
|
bip39::{Language, Mnemonic, MnemonicType, Seed},
|
||||||
clap::{
|
clap::{crate_description, crate_name, Arg, ArgMatches, Command},
|
||||||
crate_description, crate_name, value_t, value_t_or_exit, values_t_or_exit, App,
|
solana_clap_v3_utils::{
|
||||||
AppSettings, Arg, ArgMatches, SubCommand,
|
|
||||||
},
|
|
||||||
solana_clap_utils::{
|
|
||||||
input_parsers::STDOUT_OUTFILE_TOKEN,
|
input_parsers::STDOUT_OUTFILE_TOKEN,
|
||||||
input_validators::{is_parsable, is_prompt_signer_source},
|
input_validators::{is_parsable, is_prompt_signer_source},
|
||||||
keypair::{
|
keypair::{
|
||||||
|
@ -68,8 +65,8 @@ const NO_OUTFILE_ARG: ArgConstant<'static> = ArgConstant {
|
||||||
help: "Only print a seed phrase and pubkey. Do not output a keypair file",
|
help: "Only print a seed phrase and pubkey. Do not output a keypair file",
|
||||||
};
|
};
|
||||||
|
|
||||||
fn word_count_arg<'a, 'b>() -> Arg<'a, 'b> {
|
fn word_count_arg<'a>() -> Arg<'a> {
|
||||||
Arg::with_name(WORD_COUNT_ARG.name)
|
Arg::new(WORD_COUNT_ARG.name)
|
||||||
.long(WORD_COUNT_ARG.long)
|
.long(WORD_COUNT_ARG.long)
|
||||||
.possible_values(&["12", "15", "18", "21", "24"])
|
.possible_values(&["12", "15", "18", "21", "24"])
|
||||||
.default_value("12")
|
.default_value("12")
|
||||||
|
@ -78,8 +75,8 @@ fn word_count_arg<'a, 'b>() -> Arg<'a, 'b> {
|
||||||
.help(WORD_COUNT_ARG.help)
|
.help(WORD_COUNT_ARG.help)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn language_arg<'a, 'b>() -> Arg<'a, 'b> {
|
fn language_arg<'a>() -> Arg<'a> {
|
||||||
Arg::with_name(LANGUAGE_ARG.name)
|
Arg::new(LANGUAGE_ARG.name)
|
||||||
.long(LANGUAGE_ARG.long)
|
.long(LANGUAGE_ARG.long)
|
||||||
.possible_values(&[
|
.possible_values(&[
|
||||||
"english",
|
"english",
|
||||||
|
@ -97,15 +94,15 @@ fn language_arg<'a, 'b>() -> Arg<'a, 'b> {
|
||||||
.help(LANGUAGE_ARG.help)
|
.help(LANGUAGE_ARG.help)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn no_passphrase_arg<'a, 'b>() -> Arg<'a, 'b> {
|
fn no_passphrase_arg<'a>() -> Arg<'a> {
|
||||||
Arg::with_name(NO_PASSPHRASE_ARG.name)
|
Arg::new(NO_PASSPHRASE_ARG.name)
|
||||||
.long(NO_PASSPHRASE_ARG.long)
|
.long(NO_PASSPHRASE_ARG.long)
|
||||||
.alias("no-passphrase")
|
.alias("no-passphrase")
|
||||||
.help(NO_PASSPHRASE_ARG.help)
|
.help(NO_PASSPHRASE_ARG.help)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn no_outfile_arg<'a, 'b>() -> Arg<'a, 'b> {
|
fn no_outfile_arg<'a>() -> Arg<'a> {
|
||||||
Arg::with_name(NO_OUTFILE_ARG.name)
|
Arg::new(NO_OUTFILE_ARG.name)
|
||||||
.long(NO_OUTFILE_ARG.long)
|
.long(NO_OUTFILE_ARG.long)
|
||||||
.conflicts_with_all(&["outfile", "silent"])
|
.conflicts_with_all(&["outfile", "silent"])
|
||||||
.help(NO_OUTFILE_ARG.help)
|
.help(NO_OUTFILE_ARG.help)
|
||||||
|
@ -115,7 +112,7 @@ trait KeyGenerationCommonArgs {
|
||||||
fn key_generation_common_args(self) -> Self;
|
fn key_generation_common_args(self) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KeyGenerationCommonArgs for App<'_, '_> {
|
impl KeyGenerationCommonArgs for Command<'_> {
|
||||||
fn key_generation_common_args(self) -> Self {
|
fn key_generation_common_args(self) -> Self {
|
||||||
self.arg(word_count_arg())
|
self.arg(word_count_arg())
|
||||||
.arg(language_arg())
|
.arg(language_arg())
|
||||||
|
@ -163,7 +160,7 @@ fn output_keypair(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn grind_validator_starts_with(v: String) -> Result<(), String> {
|
fn grind_validator_starts_with(v: &str) -> Result<(), String> {
|
||||||
if v.matches(':').count() != 1 || (v.starts_with(':') || v.ends_with(':')) {
|
if v.matches(':').count() != 1 || (v.starts_with(':') || v.ends_with(':')) {
|
||||||
return Err(String::from("Expected : between PREFIX and COUNT"));
|
return Err(String::from("Expected : between PREFIX and COUNT"));
|
||||||
}
|
}
|
||||||
|
@ -178,7 +175,7 @@ fn grind_validator_starts_with(v: String) -> Result<(), String> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn grind_validator_ends_with(v: String) -> Result<(), String> {
|
fn grind_validator_ends_with(v: &str) -> Result<(), String> {
|
||||||
if v.matches(':').count() != 1 || (v.starts_with(':') || v.ends_with(':')) {
|
if v.matches(':').count() != 1 || (v.starts_with(':') || v.ends_with(':')) {
|
||||||
return Err(String::from("Expected : between SUFFIX and COUNT"));
|
return Err(String::from("Expected : between SUFFIX and COUNT"));
|
||||||
}
|
}
|
||||||
|
@ -193,7 +190,7 @@ fn grind_validator_ends_with(v: String) -> Result<(), String> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn grind_validator_starts_and_ends_with(v: String) -> Result<(), String> {
|
fn grind_validator_starts_and_ends_with(v: &str) -> Result<(), String> {
|
||||||
if v.matches(':').count() != 2 || (v.starts_with(':') || v.ends_with(':')) {
|
if v.matches(':').count() != 2 || (v.starts_with(':') || v.ends_with(':')) {
|
||||||
return Err(String::from(
|
return Err(String::from(
|
||||||
"Expected : between PREFIX and SUFFIX and COUNT",
|
"Expected : between PREFIX and SUFFIX and COUNT",
|
||||||
|
@ -213,7 +210,7 @@ fn grind_validator_starts_and_ends_with(v: String) -> Result<(), String> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn acquire_language(matches: &ArgMatches<'_>) -> Language {
|
fn acquire_language(matches: &ArgMatches) -> Language {
|
||||||
match matches.value_of(LANGUAGE_ARG.name).unwrap() {
|
match matches.value_of(LANGUAGE_ARG.name).unwrap() {
|
||||||
"english" => Language::English,
|
"english" => Language::English,
|
||||||
"chinese-simplified" => Language::ChineseSimplified,
|
"chinese-simplified" => Language::ChineseSimplified,
|
||||||
|
@ -232,7 +229,7 @@ fn no_passphrase_and_message() -> (String, String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn acquire_passphrase_and_message(
|
fn acquire_passphrase_and_message(
|
||||||
matches: &ArgMatches<'_>,
|
matches: &ArgMatches,
|
||||||
) -> Result<(String, String), Box<dyn error::Error>> {
|
) -> Result<(String, String), Box<dyn error::Error>> {
|
||||||
if matches.is_present(NO_PASSPHRASE_ARG.name) {
|
if matches.is_present(NO_PASSPHRASE_ARG.name) {
|
||||||
Ok(no_passphrase_and_message())
|
Ok(no_passphrase_and_message())
|
||||||
|
@ -331,13 +328,14 @@ fn grind_parse_args(
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn error::Error>> {
|
fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
let default_num_threads = num_cpus::get().to_string();
|
let default_num_threads = num_cpus::get().to_string();
|
||||||
let matches = App::new(crate_name!())
|
let matches = Command::new(crate_name!())
|
||||||
.about(crate_description!())
|
.about(crate_description!())
|
||||||
.version(solana_version::version!())
|
.version(solana_version::version!())
|
||||||
.setting(AppSettings::SubcommandRequiredElseHelp)
|
.subcommand_required(true)
|
||||||
|
.arg_required_else_help(true)
|
||||||
.arg({
|
.arg({
|
||||||
let arg = Arg::with_name("config_file")
|
let arg = Arg::new("config_file")
|
||||||
.short("C")
|
.short('C')
|
||||||
.long("config")
|
.long("config")
|
||||||
.value_name("FILEPATH")
|
.value_name("FILEPATH")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
|
@ -350,10 +348,10 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("verify")
|
Command::new("verify")
|
||||||
.about("Verify a keypair can sign and verify a message.")
|
.about("Verify a keypair can sign and verify a message.")
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("pubkey")
|
Arg::new("pubkey")
|
||||||
.index(1)
|
.index(1)
|
||||||
.value_name("PUBKEY")
|
.value_name("PUBKEY")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
|
@ -361,7 +359,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
.help("Public key"),
|
.help("Public key"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("keypair")
|
Arg::new("keypair")
|
||||||
.index(2)
|
.index(2)
|
||||||
.value_name("KEYPAIR")
|
.value_name("KEYPAIR")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
|
@ -369,26 +367,26 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("new")
|
Command::new("new")
|
||||||
.about("Generate new keypair file from a random seed phrase and optional BIP39 passphrase")
|
.about("Generate new keypair file from a random seed phrase and optional BIP39 passphrase")
|
||||||
.setting(AppSettings::DisableVersion)
|
.disable_version_flag(true)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("outfile")
|
Arg::new("outfile")
|
||||||
.short("o")
|
.short('o')
|
||||||
.long("outfile")
|
.long("outfile")
|
||||||
.value_name("FILEPATH")
|
.value_name("FILEPATH")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("Path to generated file"),
|
.help("Path to generated file"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("force")
|
Arg::new("force")
|
||||||
.short("f")
|
.short('f')
|
||||||
.long("force")
|
.long("force")
|
||||||
.help("Overwrite the output file if it exists"),
|
.help("Overwrite the output file if it exists"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("silent")
|
Arg::new("silent")
|
||||||
.short("s")
|
.short('s')
|
||||||
.long("silent")
|
.long("silent")
|
||||||
.help("Do not display seed phrase. Useful when piping output to other programs that prompt for user input, like gpg"),
|
.help("Do not display seed phrase. Useful when piping output to other programs that prompt for user input, like gpg"),
|
||||||
)
|
)
|
||||||
|
@ -396,46 +394,49 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
.arg(no_outfile_arg())
|
.arg(no_outfile_arg())
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("grind")
|
Command::new("grind")
|
||||||
.about("Grind for vanity keypairs")
|
.about("Grind for vanity keypairs")
|
||||||
.setting(AppSettings::DisableVersion)
|
.disable_version_flag(true)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("ignore_case")
|
Arg::new("ignore_case")
|
||||||
.long("ignore-case")
|
.long("ignore-case")
|
||||||
.help("Performs case insensitive matches"),
|
.help("Performs case insensitive matches"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("starts_with")
|
Arg::new("starts_with")
|
||||||
.long("starts-with")
|
.long("starts-with")
|
||||||
.value_name("PREFIX:COUNT")
|
.value_name("PREFIX:COUNT")
|
||||||
.number_of_values(1)
|
.number_of_values(1)
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.multiple(true)
|
.multiple_occurrences(true)
|
||||||
|
.multiple_values(true)
|
||||||
.validator(grind_validator_starts_with)
|
.validator(grind_validator_starts_with)
|
||||||
.help("Saves specified number of keypairs whos public key starts with the indicated prefix\nExample: --starts-with sol:4\nPREFIX type is Base58\nCOUNT type is u64"),
|
.help("Saves specified number of keypairs whos public key starts with the indicated prefix\nExample: --starts-with sol:4\nPREFIX type is Base58\nCOUNT type is u64"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("ends_with")
|
Arg::new("ends_with")
|
||||||
.long("ends-with")
|
.long("ends-with")
|
||||||
.value_name("SUFFIX:COUNT")
|
.value_name("SUFFIX:COUNT")
|
||||||
.number_of_values(1)
|
.number_of_values(1)
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.multiple(true)
|
.multiple_occurrences(true)
|
||||||
|
.multiple_values(true)
|
||||||
.validator(grind_validator_ends_with)
|
.validator(grind_validator_ends_with)
|
||||||
.help("Saves specified number of keypairs whos public key ends with the indicated suffix\nExample: --ends-with ana:4\nSUFFIX type is Base58\nCOUNT type is u64"),
|
.help("Saves specified number of keypairs whos public key ends with the indicated suffix\nExample: --ends-with ana:4\nSUFFIX type is Base58\nCOUNT type is u64"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("starts_and_ends_with")
|
Arg::new("starts_and_ends_with")
|
||||||
.long("starts-and-ends-with")
|
.long("starts-and-ends-with")
|
||||||
.value_name("PREFIX:SUFFIX:COUNT")
|
.value_name("PREFIX:SUFFIX:COUNT")
|
||||||
.number_of_values(1)
|
.number_of_values(1)
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.multiple(true)
|
.multiple_occurrences(true)
|
||||||
|
.multiple_values(true)
|
||||||
.validator(grind_validator_starts_and_ends_with)
|
.validator(grind_validator_starts_and_ends_with)
|
||||||
.help("Saves specified number of keypairs whos public key starts and ends with the indicated perfix and suffix\nExample: --starts-and-ends-with sol:ana:4\nPREFIX and SUFFIX type is Base58\nCOUNT type is u64"),
|
.help("Saves specified number of keypairs whos public key starts and ends with the indicated perfix and suffix\nExample: --starts-and-ends-with sol:ana:4\nPREFIX and SUFFIX type is Base58\nCOUNT type is u64"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("num_threads")
|
Arg::new("num_threads")
|
||||||
.long("num-threads")
|
.long("num-threads")
|
||||||
.value_name("NUMBER")
|
.value_name("NUMBER")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
|
@ -444,7 +445,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
.help("Specify the number of grind threads"),
|
.help("Specify the number of grind threads"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("use_mnemonic")
|
Arg::new("use_mnemonic")
|
||||||
.long("use-mnemonic")
|
.long("use-mnemonic")
|
||||||
.help("Generate using a mnemonic key phrase. Expect a significant slowdown in this mode"),
|
.help("Generate using a mnemonic key phrase. Expect a significant slowdown in this mode"),
|
||||||
)
|
)
|
||||||
|
@ -457,42 +458,42 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("pubkey")
|
Command::new("pubkey")
|
||||||
.about("Display the pubkey from a keypair file")
|
.about("Display the pubkey from a keypair file")
|
||||||
.setting(AppSettings::DisableVersion)
|
.disable_version_flag(true)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("keypair")
|
Arg::new("keypair")
|
||||||
.index(1)
|
.index(1)
|
||||||
.value_name("KEYPAIR")
|
.value_name("KEYPAIR")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("Filepath or URL to a keypair"),
|
.help("Filepath or URL to a keypair"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(SKIP_SEED_PHRASE_VALIDATION_ARG.name)
|
Arg::new(SKIP_SEED_PHRASE_VALIDATION_ARG.name)
|
||||||
.long(SKIP_SEED_PHRASE_VALIDATION_ARG.long)
|
.long(SKIP_SEED_PHRASE_VALIDATION_ARG.long)
|
||||||
.help(SKIP_SEED_PHRASE_VALIDATION_ARG.help),
|
.help(SKIP_SEED_PHRASE_VALIDATION_ARG.help),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("outfile")
|
Arg::new("outfile")
|
||||||
.short("o")
|
.short('o')
|
||||||
.long("outfile")
|
.long("outfile")
|
||||||
.value_name("FILEPATH")
|
.value_name("FILEPATH")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("Path to generated file"),
|
.help("Path to generated file"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("force")
|
Arg::new("force")
|
||||||
.short("f")
|
.short('f')
|
||||||
.long("force")
|
.long("force")
|
||||||
.help("Overwrite the output file if it exists"),
|
.help("Overwrite the output file if it exists"),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("recover")
|
Command::new("recover")
|
||||||
.about("Recover keypair from seed phrase and optional BIP39 passphrase")
|
.about("Recover keypair from seed phrase and optional BIP39 passphrase")
|
||||||
.setting(AppSettings::DisableVersion)
|
.disable_version_flag(true)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("prompt_signer")
|
Arg::new("prompt_signer")
|
||||||
.index(1)
|
.index(1)
|
||||||
.value_name("KEYPAIR")
|
.value_name("KEYPAIR")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
|
@ -500,21 +501,21 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
.help("`prompt:` URI scheme or `ASK` keyword"),
|
.help("`prompt:` URI scheme or `ASK` keyword"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("outfile")
|
Arg::new("outfile")
|
||||||
.short("o")
|
.short('o')
|
||||||
.long("outfile")
|
.long("outfile")
|
||||||
.value_name("FILEPATH")
|
.value_name("FILEPATH")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("Path to generated file"),
|
.help("Path to generated file"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("force")
|
Arg::new("force")
|
||||||
.short("f")
|
.short('f')
|
||||||
.long("force")
|
.long("force")
|
||||||
.help("Overwrite the output file if it exists"),
|
.help("Overwrite the output file if it exists"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(SKIP_SEED_PHRASE_VALIDATION_ARG.name)
|
Arg::new(SKIP_SEED_PHRASE_VALIDATION_ARG.name)
|
||||||
.long(SKIP_SEED_PHRASE_VALIDATION_ARG.long)
|
.long(SKIP_SEED_PHRASE_VALIDATION_ARG.long)
|
||||||
.help(SKIP_SEED_PHRASE_VALIDATION_ARG.help),
|
.help(SKIP_SEED_PHRASE_VALIDATION_ARG.help),
|
||||||
),
|
),
|
||||||
|
@ -525,7 +526,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
do_main(&matches).map_err(|err| DisplayError::new_as_boxed(err).into())
|
do_main(&matches).map_err(|err| DisplayError::new_as_boxed(err).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_main(matches: &ArgMatches<'_>) -> Result<(), Box<dyn error::Error>> {
|
fn do_main(matches: &ArgMatches) -> Result<(), Box<dyn error::Error>> {
|
||||||
let config = if let Some(config_file) = matches.value_of("config_file") {
|
let config = if let Some(config_file) = matches.value_of("config_file") {
|
||||||
Config::load(config_file).unwrap_or_default()
|
Config::load(config_file).unwrap_or_default()
|
||||||
} else {
|
} else {
|
||||||
|
@ -534,8 +535,10 @@ fn do_main(matches: &ArgMatches<'_>) -> Result<(), Box<dyn error::Error>> {
|
||||||
|
|
||||||
let mut wallet_manager = None;
|
let mut wallet_manager = None;
|
||||||
|
|
||||||
match matches.subcommand() {
|
let subcommand = matches.subcommand().unwrap();
|
||||||
("pubkey", Some(matches)) => {
|
|
||||||
|
match subcommand {
|
||||||
|
("pubkey", matches) => {
|
||||||
let pubkey =
|
let pubkey =
|
||||||
get_keypair_from_matches(matches, config, &mut wallet_manager)?.try_pubkey()?;
|
get_keypair_from_matches(matches, config, &mut wallet_manager)?.try_pubkey()?;
|
||||||
|
|
||||||
|
@ -547,7 +550,7 @@ fn do_main(matches: &ArgMatches<'_>) -> Result<(), Box<dyn error::Error>> {
|
||||||
println!("{}", pubkey);
|
println!("{}", pubkey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
("new", Some(matches)) => {
|
("new", matches) => {
|
||||||
let mut path = dirs_next::home_dir().expect("home directory");
|
let mut path = dirs_next::home_dir().expect("home directory");
|
||||||
let outfile = if matches.is_present("outfile") {
|
let outfile = if matches.is_present("outfile") {
|
||||||
matches.value_of("outfile")
|
matches.value_of("outfile")
|
||||||
|
@ -564,7 +567,7 @@ fn do_main(matches: &ArgMatches<'_>) -> Result<(), Box<dyn error::Error>> {
|
||||||
None => (),
|
None => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
let word_count = value_t!(matches.value_of(WORD_COUNT_ARG.name), usize).unwrap();
|
let word_count: usize = matches.value_of_t(WORD_COUNT_ARG.name).unwrap();
|
||||||
let mnemonic_type = MnemonicType::for_word_count(word_count)?;
|
let mnemonic_type = MnemonicType::for_word_count(word_count)?;
|
||||||
let language = acquire_language(matches);
|
let language = acquire_language(matches);
|
||||||
|
|
||||||
|
@ -592,7 +595,7 @@ fn do_main(matches: &ArgMatches<'_>) -> Result<(), Box<dyn error::Error>> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
("recover", Some(matches)) => {
|
("recover", matches) => {
|
||||||
let mut path = dirs_next::home_dir().expect("home directory");
|
let mut path = dirs_next::home_dir().expect("home directory");
|
||||||
let outfile = if matches.is_present("outfile") {
|
let outfile = if matches.is_present("outfile") {
|
||||||
matches.value_of("outfile").unwrap()
|
matches.value_of("outfile").unwrap()
|
||||||
|
@ -614,11 +617,12 @@ fn do_main(matches: &ArgMatches<'_>) -> Result<(), Box<dyn error::Error>> {
|
||||||
};
|
};
|
||||||
output_keypair(&keypair, outfile, "recovered")?;
|
output_keypair(&keypair, outfile, "recovered")?;
|
||||||
}
|
}
|
||||||
("grind", Some(matches)) => {
|
("grind", matches) => {
|
||||||
let ignore_case = matches.is_present("ignore_case");
|
let ignore_case = matches.is_present("ignore_case");
|
||||||
|
|
||||||
let starts_with_args = if matches.is_present("starts_with") {
|
let starts_with_args = if matches.is_present("starts_with") {
|
||||||
values_t_or_exit!(matches, "starts_with", String)
|
matches
|
||||||
|
.values_of_t_or_exit::<String>("starts_with")
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|s| if ignore_case { s.to_lowercase() } else { s })
|
.map(|s| if ignore_case { s.to_lowercase() } else { s })
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -626,7 +630,8 @@ fn do_main(matches: &ArgMatches<'_>) -> Result<(), Box<dyn error::Error>> {
|
||||||
HashSet::new()
|
HashSet::new()
|
||||||
};
|
};
|
||||||
let ends_with_args = if matches.is_present("ends_with") {
|
let ends_with_args = if matches.is_present("ends_with") {
|
||||||
values_t_or_exit!(matches, "ends_with", String)
|
matches
|
||||||
|
.values_of_t_or_exit::<String>("ends_with")
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|s| if ignore_case { s.to_lowercase() } else { s })
|
.map(|s| if ignore_case { s.to_lowercase() } else { s })
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -634,7 +639,8 @@ fn do_main(matches: &ArgMatches<'_>) -> Result<(), Box<dyn error::Error>> {
|
||||||
HashSet::new()
|
HashSet::new()
|
||||||
};
|
};
|
||||||
let starts_and_ends_with_args = if matches.is_present("starts_and_ends_with") {
|
let starts_and_ends_with_args = if matches.is_present("starts_and_ends_with") {
|
||||||
values_t_or_exit!(matches, "starts_and_ends_with", String)
|
matches
|
||||||
|
.values_of_t_or_exit::<String>("starts_and_ends_with")
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|s| if ignore_case { s.to_lowercase() } else { s })
|
.map(|s| if ignore_case { s.to_lowercase() } else { s })
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -652,7 +658,7 @@ fn do_main(matches: &ArgMatches<'_>) -> Result<(), Box<dyn error::Error>> {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let num_threads = value_t_or_exit!(matches.value_of("num_threads"), usize);
|
let num_threads: usize = matches.value_of_t_or_exit("num_threads");
|
||||||
|
|
||||||
let grind_matches = grind_parse_args(
|
let grind_matches = grind_parse_args(
|
||||||
ignore_case,
|
ignore_case,
|
||||||
|
@ -664,7 +670,7 @@ fn do_main(matches: &ArgMatches<'_>) -> Result<(), Box<dyn error::Error>> {
|
||||||
|
|
||||||
let use_mnemonic = matches.is_present("use_mnemonic");
|
let use_mnemonic = matches.is_present("use_mnemonic");
|
||||||
|
|
||||||
let word_count = value_t!(matches.value_of(WORD_COUNT_ARG.name), usize).unwrap();
|
let word_count: usize = matches.value_of_t(WORD_COUNT_ARG.name).unwrap();
|
||||||
let mnemonic_type = MnemonicType::for_word_count(word_count)?;
|
let mnemonic_type = MnemonicType::for_word_count(word_count)?;
|
||||||
let language = acquire_language(matches);
|
let language = acquire_language(matches);
|
||||||
|
|
||||||
|
@ -766,7 +772,7 @@ fn do_main(matches: &ArgMatches<'_>) -> Result<(), Box<dyn error::Error>> {
|
||||||
thread_handle.join().unwrap();
|
thread_handle.join().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
("verify", Some(matches)) => {
|
("verify", matches) => {
|
||||||
let keypair = get_keypair_from_matches(matches, config, &mut wallet_manager)?;
|
let keypair = get_keypair_from_matches(matches, config, &mut wallet_manager)?;
|
||||||
let simple_message = Message::new(
|
let simple_message = Message::new(
|
||||||
&[Instruction::new_with_bincode(
|
&[Instruction::new_with_bincode(
|
||||||
|
|
Loading…
Reference in New Issue