Skip to content
This repository has been archived by the owner on Jan 8, 2020. It is now read-only.

Commit

Permalink
Add command (#61)
Browse files Browse the repository at this point in the history
* Update AppVeyor badge

* Update version
Use emerald-rs v0.18 to add BIP39  mnemonic functionality to RPC
endppoint

* Update error message

* Add mnemonic generation command

* Fix merge commit

* Refactor error handling

* Fix `bats` tests
  • Loading branch information
r8d8 authored Dec 18, 2017
1 parent de20baf commit af4088a
Show file tree
Hide file tree
Showing 10 changed files with 64 additions and 99 deletions.
5 changes: 2 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,11 @@ before_install:
- if [ $TRAVIS_OS_NAME = linux ]; then sudo apt-get -qq update; else brew update; fi
- if [ $TRAVIS_OS_NAME = linux ]; then sudo apt-get install -y libusb-1.0-0-dev bats; else brew install libusb bats; fi
- travis_wait cargo install rustfmt --force || true
- travis_wait cargo install rustfmt --force || true

before_script:
- export PATH="$PATH":~/.cargo/bin
- echo "\$ rustfmt --version"
- cargo fmt --all -- --version
- cargo fmt --all -- --version --force

script:
# Install Janus
Expand All @@ -40,7 +39,7 @@ script:
- export PATH=$PATH:$PWD/janusbin
- export APP_VERSION="$(janus version -format 'v%M.%m.%C-%S')"
- export RUST_BACKTRACE=1
- cargo fmt --all -- --verbose --write-mode=diff
- cargo fmt --all -- --verbose --force --write-mode=diff
- cargo test --all --verbose
- cargo build --all --verbose --release
- cp ./target/release/emerald "$HOME/.cargo/bin/"
Expand Down
2 changes: 1 addition & 1 deletion cli.bats
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bats

: ${EMERALD_CLI:=$HOME/.cargo/bin/emerald} # FIXME emerald or emerald-cli?
: ${EMERALD_CLI:=$HOME/.cargo/bin/emerald}


# Setup and teardown are called surrounding EACH @test.
Expand Down
5 changes: 1 addition & 4 deletions src/cmd/arg_handlers.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
//! # Helpers for command execution


use super::Error;
use super::{CmdExecutor, Address, PrivateKey, KeyFile, trim_hex, to_arr, align_bytes, to_even_str};
use super::{align_bytes, to_arr, to_even_str, trim_hex, Address, CmdExecutor, KeyFile, PrivateKey};
use std::path::{Path, PathBuf};
use std::io::Read;
use std::fs::File;
Expand All @@ -15,7 +14,6 @@ use std::io::Write;
use rpassword;
use emerald::Transaction;


/// Environment variables used to change default variables
#[derive(Default, Debug)]
pub struct EnvVars {
Expand Down Expand Up @@ -128,7 +126,6 @@ pub fn parse_pk(s: &str) -> Result<PrivateKey, Error> {
Ok(pk)
}


/// Parse transaction value
pub fn parse_value(s: &str) -> Result<[u8; 32], Error> {
let value_str = parse_arg(s)?;
Expand Down
80 changes: 21 additions & 59 deletions src/cmd/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,78 +9,40 @@ use reqwest;
use std::num;
use hex;

macro_rules! from_err {
( $x:ty ) => {
impl From<$x> for Error {
fn from(err: $x) -> Self {
Error::ExecError(err.to_string())
}
}
};
}

///
#[derive(Debug)]
pub enum Error {
/// Command execution error
ExecError(String),
}

impl From<io::Error> for Error {
fn from(err: io::Error) -> Self {
Error::ExecError(err.to_string())
}
}

impl From<KeyStorageError> for Error {
fn from(err: KeyStorageError) -> Self {
Error::ExecError(err.to_string())
}
}

impl From<string::ParseError> for Error {
fn from(err: string::ParseError) -> Self {
Error::ExecError(err.to_string())
}
}

impl From<emerald::Error> for Error {
fn from(err: emerald::Error) -> Self {
Error::ExecError(err.to_string())
}
}

impl From<AddrParseError> for Error {
fn from(err: AddrParseError) -> Self {
Error::ExecError(format!("Can't parse host/port args: {}", err.to_string()))
}
}

impl From<keystore::Error> for Error {
fn from(err: keystore::Error) -> Self {
Error::ExecError(err.to_string())
}
}

impl From<keystore::SerializeError> for Error {
fn from(err: keystore::SerializeError) -> Self {
Error::ExecError(err.to_string())
}
}

impl From<json::EncoderError> for Error {
fn from(err: json::EncoderError) -> Self {
Error::ExecError(err.to_string())
}
}

impl From<reqwest::Error> for Error {
fn from(err: reqwest::Error) -> Self {
Error::ExecError(err.to_string())
}
}

impl From<num::ParseIntError> for Error {
fn from(err: num::ParseIntError) -> Self {
Error::ExecError(err.to_string())
}
}

impl From<hex::FromHexError> for Error {
fn from(err: hex::FromHexError) -> Self {
Error::ExecError(err.to_string())
}
}
from_err!(io::Error);
from_err!(KeyStorageError);
from_err!(string::ParseError);
from_err!(emerald::Error);
from_err!(keystore::Error);
from_err!(keystore::SerializeError);
from_err!(json::EncoderError);
from_err!(reqwest::Error);
from_err!(num::ParseIntError);
from_err!(hex::FromHexError);
from_err!(emerald::mnemonic::Error);

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand Down
27 changes: 19 additions & 8 deletions src/cmd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ mod error;
mod arg_handlers;

pub use self::error::Error;
use super::emerald::keystore::{KeyFile, KdfDepthLevel};
use super::emerald::{self, Address, Transaction, to_arr, to_chain_id, trim_hex, align_bytes,
to_even_str};
use super::emerald::keystore::{KdfDepthLevel, KeyFile};
use super::emerald::{self, align_bytes, to_arr, to_chain_id, to_even_str, trim_hex, Address,
Transaction};
use super::emerald::PrivateKey;
use super::emerald::mnemonic::{gen_entropy, Language, Mnemonic, ENTROPY_BYTE_LENGTH};
use super::emerald::storage::{default_path, StorageController};
use std::net::SocketAddr;
use std::str::FromStr;
Expand All @@ -19,7 +20,6 @@ use hex::ToHex;
use std::path::PathBuf;
use std::sync::Arc;


#[derive(Debug, Deserialize, Clone)]
pub struct Args {
pub arg_address: String,
Expand Down Expand Up @@ -50,6 +50,7 @@ pub struct Args {
pub cmd_server: bool,
pub cmd_list: bool,
pub cmd_new: bool,
pub cmd_mnemonic: bool,
pub cmd_balance: bool,
pub cmd_hide: bool,
pub cmd_unhide: bool,
Expand Down Expand Up @@ -78,7 +79,7 @@ impl CmdExecutor {

let chain = match arg_or_default(&args.flag_chain, &env.emerald_chain) {
Ok(c) => c,
Err(e) => {
Err(_) => {
info!("Missed `--chain` argument. Use default: `mainnet`");
"mainnet".to_string()
}
Expand All @@ -87,7 +88,7 @@ impl CmdExecutor {
let sec_level_str = arg_or_default(&args.flag_security_level, &env.emerald_security_level)?;
let sec_level = match KdfDepthLevel::from_str(&sec_level_str) {
Ok(sec) => sec,
Err(e) => {
Err(_) => {
info!("Missed `--security-level` argument. Use default: `ultra`");
KdfDepthLevel::default()
}
Expand All @@ -108,7 +109,6 @@ impl CmdExecutor {
Err(_) => None,
};


Ok(CmdExecutor {
args: args.clone(),
chain: chain,
Expand All @@ -127,6 +127,8 @@ impl CmdExecutor {
self.list()
} else if self.args.cmd_new {
self.new_account()
} else if self.args.cmd_mnemonic {
self.new_mnemonic()
} else if self.args.cmd_balance {
self.balance()
} else if self.args.cmd_hide {
Expand Down Expand Up @@ -216,6 +218,14 @@ impl CmdExecutor {
Ok(())
}

/// Creates new BIP32 mnemonic phrase
fn new_mnemonic(&self) -> ExecResult<Error> {
let entropy = gen_entropy(ENTROPY_BYTE_LENGTH)?;
let mn = Mnemonic::new(Language::English, &entropy)?;
println!("{}", mn.sentence());
Ok(())
}

/// Show user balance
fn balance(&self) -> ExecResult<Error> {
match self.connector {
Expand Down Expand Up @@ -334,6 +344,7 @@ impl CmdExecutor {
}
}

/// Send transaction into network through provided node
fn send_transaction(&self, raw: &[u8]) -> ExecResult<Error> {
match self.connector {
Some(ref conn) => {
Expand All @@ -343,7 +354,7 @@ impl CmdExecutor {
Ok(())
}

None => Err(Error::ExecError("Invalid chain name".to_string())),
None => Err(Error::ExecError("Can't connect to node".to_string())),
}
}
}
27 changes: 13 additions & 14 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
//! # CLI wrapper for `emerald-rs`

#![cfg(feature = "cli")]

#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]

#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate serde_derive;
extern crate text_io;
extern crate serde;
extern crate docopt;
extern crate env_logger;
extern crate emerald_rs as emerald;
extern crate rustc_serialize;
extern crate serde_json;
extern crate jsonrpc_core;
extern crate env_logger;
extern crate hex;
extern crate hyper;
extern crate jsonrpc_core;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate reqwest;
extern crate hex;
extern crate rpassword;
extern crate rustc_serialize;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate text_io;

mod cmd;
mod rpc;
Expand Down
2 changes: 0 additions & 2 deletions src/rpc/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ use reqwest::Client;
use serde_json::Value;
use cmd::Error;


lazy_static! {
static ref CLIENT: Client = Client::new().expect("Expect to create an HTTP client");
}


/// RPC methods
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum ClientMethod {
Expand Down
7 changes: 3 additions & 4 deletions src/rpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
mod http;
mod serialize;

pub use self::http::{RpcConnector, MethodParams, ClientMethod};
use jsonrpc_core::{Value, Params};
pub use self::http::{ClientMethod, MethodParams, RpcConnector};
use jsonrpc_core::{Params, Value};
use cmd::Error;
use hex::ToHex;
use emerald::{Address, trim_hex};
use emerald::{trim_hex, Address};

/// Get nonce for address from remote node
///
Expand All @@ -31,7 +31,6 @@ pub fn get_nonce(rpc: &RpcConnector, addr: &Address) -> Result<u64, Error> {
}
}


/// Send signed raw transaction to the remote client
///
/// # Arguments:
Expand Down
1 change: 0 additions & 1 deletion src/rpc/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use jsonrpc_core::Params;


lazy_static! {
static ref REQ_ID: Arc<AtomicUsize> = Arc::new(AtomicUsize::new(1));
}
Expand Down
7 changes: 4 additions & 3 deletions usage.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ Emerald offline wallet command line interface.

Usage:
emerald server [--port=<port>] [--host=<host>] [--base-path=<path>] [-v | --verbose] [-q | --quite]
emerald mnemonic
emerald new [--chain=<chain>] ([[--security-level=<level>] [--name=<name>] [--description=<description>]] | --raw <key>)
emerald list [--chain=<chain>] [--show-hidden]
emerald hide [--chain=<chain>] <address>
Expand Down Expand Up @@ -36,6 +37,6 @@ Options:
--security-level=<normal|high|ultra> Level of security for cryptographic operations [default: ultra]
--show-hidden Include hidden keyfiles
--upstream=<upstream> URL to ethereum node [default: 127.0.0.1:8545]
--gas=<gas> Gas limit for transaction
--gas-price=<price> Gas price for transaction execution
--nonce=<nonce> Transaction count of sender
--gas=<gas> Gas limit for transaction, hex-encoded value in `wei`
--gas-price=<price> Gas price for transaction, hex-encoded value in `wei`
--nonce=<nonce> Transaction count of sender

0 comments on commit af4088a

Please sign in to comment.