solana/wallet/src/main.rs

240 lines
8.7 KiB
Rust
Raw Normal View History

#[macro_use]
extern crate clap;
use dirs;
2018-09-14 17:12:10 -07:00
#[macro_use]
2018-06-26 22:52:34 -07:00
extern crate solana;
2018-12-14 10:46:58 -08:00
#[macro_use]
extern crate serde_json;
mod wallet;
2018-12-14 10:46:58 -08:00
use crate::wallet::{parse_command, process_command, WalletConfig, WalletError};
use clap::{App, Arg, ArgMatches, SubCommand};
2018-07-27 21:37:53 -07:00
use solana::logger;
use solana_sdk::signature::{gen_keypair_file, read_keypair, KeypairUtil};
use std::error;
use std::net::SocketAddr;
pub fn parse_args(matches: &ArgMatches<'_>) -> Result<WalletConfig, Box<dyn error::Error>> {
2018-09-14 17:12:10 -07:00
let network = if let Some(addr) = matches.value_of("network") {
addr.parse().or_else(|_| {
Err(WalletError::BadParameter(
"Invalid network location".to_string(),
))
})?
} else {
2018-09-14 17:12:10 -07:00
socketaddr!("127.0.0.1:8001")
};
2018-09-14 17:12:36 -07:00
let timeout = if let Some(secs) = matches.value_of("timeout") {
Some(secs.to_string().parse().expect("integer"))
} else {
2018-09-14 17:12:36 -07:00
None
};
2018-11-09 14:10:44 -08:00
let proxy = matches.value_of("proxy").map(|proxy| proxy.to_string());
let mut path = dirs::home_dir().expect("home directory");
let id_path = if matches.is_present("keypair") {
matches.value_of("keypair").unwrap()
} else {
path.extend(&[".config", "solana", "id.json"]);
if !path.exists() {
gen_keypair_file(path.to_str().unwrap().to_string())?;
println!("New keypair generated at: {:?}", path.to_str().unwrap());
}
path.to_str().unwrap()
};
let id = read_keypair(id_path).or_else(|err| {
Err(WalletError::BadParameter(format!(
"{}: Unable to open keypair file: {}",
err, id_path
)))
})?;
let command = parse_command(id.pubkey(), &matches)?;
Ok(WalletConfig {
id,
command,
2018-11-09 14:10:44 -08:00
network,
timeout,
proxy,
2018-11-12 12:48:59 -08:00
drone_port: None,
})
}
fn main() -> Result<(), Box<dyn error::Error>> {
logger::setup();
let matches = App::new("solana-wallet")
.version(crate_version!())
.arg(
2018-09-14 17:12:10 -07:00
Arg::with_name("network")
.short("n")
.long("network")
.value_name("HOST:PORT")
.takes_value(true)
2018-09-14 17:12:10 -07:00
.help("Rendezvous with the network at this gossip entry point; defaults to 127.0.0.1:8001"),
2018-09-20 22:27:06 -07:00
).arg(
2018-07-12 15:02:14 -07:00
Arg::with_name("keypair")
.short("k")
.long("keypair")
.value_name("PATH")
.takes_value(true)
2018-07-12 15:02:14 -07:00
.help("/path/to/id.json"),
2018-09-20 22:27:06 -07:00
).arg(
Arg::with_name("timeout")
.long("timeout")
2018-09-14 15:32:57 -07:00
.value_name("SECS")
.takes_value(true)
2018-09-14 15:32:57 -07:00
.help("Max seconds to wait to get necessary gossip from the network"),
).arg(
Arg::with_name("proxy")
.long("proxy")
.takes_value(true)
.value_name("URL")
.help("Address of TLS proxy")
.conflicts_with("rpc-port")
).subcommand(SubCommand::with_name("address").about("Get your public key"))
.subcommand(
SubCommand::with_name("airdrop")
.about("Request a batch of tokens")
.arg(
Arg::with_name("tokens")
.index(1)
2018-09-14 15:32:57 -07:00
.value_name("NUM")
.takes_value(true)
.required(true)
.help("The number of tokens to request"),
),
).subcommand(SubCommand::with_name("balance").about("Get your balance"))
.subcommand(
SubCommand::with_name("cancel")
.about("Cancel a transfer")
.arg(
Arg::with_name("process-id")
.index(1)
.value_name("PROCESS_ID")
.takes_value(true)
.required(true)
.help("The process id of the transfer to cancel"),
),
).subcommand(
SubCommand::with_name("confirm")
.about("Confirm transaction by signature")
.arg(
Arg::with_name("signature")
.index(1)
.value_name("SIGNATURE")
.takes_value(true)
.required(true)
.help("The transaction signature to confirm"),
),
2018-10-22 21:21:33 -07:00
).subcommand(
SubCommand::with_name("deploy")
.about("Deploy a program")
.arg(
Arg::with_name("program-location")
.index(1)
.value_name("PATH")
.takes_value(true)
.required(true)
.help("/path/to/program.o"),
)
// TODO: Add "loader" argument; current default is bpf_loader
).subcommand(
SubCommand::with_name("get-transaction-count")
.about("Get current transaction count")
2018-09-14 16:25:14 -07:00
).subcommand(
SubCommand::with_name("pay")
.about("Send a payment")
.arg(
Arg::with_name("to")
.index(1)
.value_name("PUBKEY")
.takes_value(true)
.required(true)
.help("The pubkey of recipient"),
).arg(
Arg::with_name("tokens")
.index(2)
2018-09-14 15:32:57 -07:00
.value_name("NUM")
.takes_value(true)
.required(true)
.help("The number of tokens to send"),
2018-09-14 16:25:14 -07:00
).arg(
Arg::with_name("timestamp")
.long("after")
.value_name("DATETIME")
.takes_value(true)
.help("A timestamp after which transaction will execute"),
).arg(
Arg::with_name("timestamp-pubkey")
.long("require-timestamp-from")
.value_name("PUBKEY")
.takes_value(true)
.requires("timestamp")
.help("Require timestamp from this third party"),
).arg(
Arg::with_name("witness")
.long("require-signature-from")
.value_name("PUBKEY")
.takes_value(true)
.multiple(true)
.use_delimiter(true)
.help("Any third party signatures required to unlock the tokens"),
).arg(
2018-09-21 18:51:42 -07:00
Arg::with_name("cancelable")
.long("cancelable")
.takes_value(false),
),
2018-09-14 16:25:14 -07:00
).subcommand(
SubCommand::with_name("send-signature")
.about("Send a signature to authorize a transfer")
.arg(
2018-09-24 09:23:16 -07:00
Arg::with_name("to")
.index(1)
2018-09-24 09:23:16 -07:00
.value_name("PUBKEY")
.takes_value(true)
.required(true)
.help("The pubkey of recipient"),
).arg(
Arg::with_name("process-id")
.index(2)
.value_name("PROCESS_ID")
.takes_value(true)
.required(true)
.help("The process id of the transfer to authorize")
)
).subcommand(
SubCommand::with_name("send-timestamp")
.about("Send a timestamp to unlock a transfer")
.arg(
Arg::with_name("to")
.index(1)
.value_name("PUBKEY")
.takes_value(true)
.required(true)
.help("The pubkey of recipient"),
).arg(
Arg::with_name("process-id")
.index(2)
.value_name("PROCESS_ID")
.takes_value(true)
.required(true)
.help("The process id of the transfer to unlock")
).arg(
Arg::with_name("datetime")
.long("date")
.value_name("DATETIME")
.takes_value(true)
.help("Optional arbitrary timestamp to apply")
)
).get_matches();
2018-06-26 22:52:34 -07:00
let config = parse_args(&matches)?;
2018-09-20 22:27:06 -07:00
let result = process_command(&config)?;
println!("{}", result);
Ok(())
}