mod account;
mod error;
mod transaction;
#[macro_use]
mod arg_handlers;
use self::account::account_cmd;
pub use self::arg_handlers::*;
pub use self::error::Error;
use self::transaction::transaction_cmd;
use super::emerald::keystore::{KdfDepthLevel, KeyFile};
use super::emerald::mnemonic::{gen_entropy, Language, Mnemonic, ENTROPY_BYTE_LENGTH};
use super::emerald::storage::{default_path, KeyfileStorage, StorageController};
use super::emerald::PrivateKey;
use super::emerald::{self, align_bytes, to_arr, to_even_str, trim_hex, Address, Transaction};
use clap::ArgMatches;
use rpc;
use std::net::SocketAddr;
use std::path::PathBuf;
use std::sync::Arc;
type ExecResult = Result<(), Error>;
const DEFAULT_CHAIN_NAME: &str = "mainnet";
const DEFAULT_UPSTREAM: &str = "127.0.0.1:8545";
pub fn execute(matches: &ArgMatches) -> ExecResult {
let env = EnvVars::parse();
let chain = matches.value_of("chain").unwrap_or(DEFAULT_CHAIN_NAME);
info!("Chain name: {}", DEFAULT_CHAIN_NAME);
let mut base_path = PathBuf::new();
if let Some(p) = matches
.value_of("base-path")
.or_else(|| env.emerald_base_path.as_ref().map(String::as_str))
{
base_path.push(&p)
} else {
base_path = default_path();
}
let storage_ctrl = Arc::new(Box::new(StorageController::new(base_path)?));
let keystore = storage_ctrl.get_keystore(chain)?;
match matches.subcommand() {
("server", Some(sub_m)) => server_cmd(sub_m, storage_ctrl.clone(), chain),
("account", Some(sub_m)) => account_cmd(sub_m, keystore, &env),
("transaction", Some(sub_m)) => transaction_cmd(sub_m, keystore, &env, chain),
("balance", Some(sub_m)) => balance_cmd(sub_m),
("mnemonic", Some(_)) => mnemonic_cmd(),
("nonce", Some(sub_m)) => nonce_cmd(sub_m),
_ => Err(Error::ExecError(
"No command selected. Use `-h` for help".to_string(),
)),
}
}
fn server_cmd(
matches: &ArgMatches,
storage_ctrl: Arc<Box<StorageController>>,
chain: &str,
) -> ExecResult {
info!("Starting Emerald Vault - v{}", emerald::version());
let host = matches.value_of("host").unwrap_or_default();
let port = matches.value_of("port").unwrap_or_default();
let addr = format!("{}:{}", host, port).parse::<SocketAddr>()?;
let sec_lvl = get_security_lvl(matches)?;
info!("Chain set to '{}'", chain);
info!("Security level set to '{}'", sec_lvl);
emerald::rpc::start(&addr, chain, storage_ctrl, Some(sec_lvl));
Ok(())
}
fn balance_cmd(matches: &ArgMatches) -> ExecResult {
match get_upstream(matches) {
Ok(ref rpc) => {
let addr = get_address(matches, "address").expect("Required account address");
let balance = rpc::request_balance(rpc, &addr)?;
info!("Balance for {} account", &addr);
println!("{}", balance);
Ok(())
}
Err(e) => Err(Error::ExecError(format!(
"Can't get balance: {}",
e.to_string()
))),
}
}
fn mnemonic_cmd() -> ExecResult {
let entropy = gen_entropy(ENTROPY_BYTE_LENGTH)?;
let mn = Mnemonic::new(Language::English, &entropy)?;
println!("{}", mn.sentence());
Ok(())
}
fn nonce_cmd(matches: &ArgMatches) -> ExecResult {
let addr = get_address(matches, "address").expect("Required account address");
let nonce = get_nonce(&matches, &addr)?;
info!("Nonce for {} account", &addr);
if matches.is_present("hex") {
println!("{:x}", nonce);
} else {
println!("{}", nonce);
}
Ok(())
}