From 25e6034429163f7f15b51b39114ff1715a422497 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 29 Jun 2018 16:04:35 -0600 Subject: [PATCH 1/3] Print usage is a command is not provided --- src/bin/wallet.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/bin/wallet.rs b/src/bin/wallet.rs index 3ed1e49d844d0e..161d3220415886 100644 --- a/src/bin/wallet.rs +++ b/src/bin/wallet.rs @@ -77,7 +77,7 @@ impl Default for WalletConfig { fn print_usage(program: &str, opts: Options) { let mut brief = format!("Usage: {} [options]\n\n", program); - brief += " solana-wallet allows you to perform basic actions, including\n"; + brief += " solana-wallet allows you to perform basic actions, including"; brief += " requesting an airdrop, checking your balance, and spending tokens."; brief += " Takes json formatted mint file to stdin."; @@ -110,7 +110,7 @@ fn parse_args(args: Vec) -> Result> { } }; - if matches.opt_present("h") { + if matches.opt_present("h") || matches.free.len() < 1 { let program = args[0].clone(); print_usage(&program, opts); display_actions(); @@ -232,10 +232,11 @@ fn process_command( fn display_actions() { println!(""); - println!(" `balance` - Get your account balance"); - println!(" `airdrop` - Request a batch of tokens"); - println!(" `pay` - Spend your tokens as fast as possible"); - println!(" `confirm` - Confirm your last payment by signature"); + println!("Commands:"); + println!(" balance Get your account balance"); + println!(" airdrop Request a batch of tokens"); + println!(" pay Spend your tokens as fast as possible"); + println!(" confirm Confirm your last payment by signature"); println!(""); } From 95370623d58976fc3a46864afc6fd60032573fb6 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 29 Jun 2018 17:06:05 -0600 Subject: [PATCH 2/3] Add base58-encoded addresses --- Cargo.toml | 1 + src/bin/wallet.rs | 96 +++++++++++++++++++++++------------------------ 2 files changed, 49 insertions(+), 48 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d7a21a4ff832b6..d0bd0461e6db90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,3 +74,4 @@ tokio = "0.1" tokio-codec = "0.1" tokio-io = "0.1" itertools = "0.7.8" +bs58 = "0.2.0" diff --git a/src/bin/wallet.rs b/src/bin/wallet.rs index 161d3220415886..2053e12886c743 100644 --- a/src/bin/wallet.rs +++ b/src/bin/wallet.rs @@ -1,16 +1,17 @@ extern crate atty; extern crate bincode; +extern crate bs58; extern crate env_logger; extern crate getopts; extern crate serde_json; extern crate solana; use bincode::serialize; -use getopts::Options; +use getopts::{Matches, Options}; use solana::crdt::{get_ip_addr, ReplicatedData}; use solana::drone::DroneRequest; use solana::mint::Mint; -use solana::signature::Signature; +use solana::signature::{PublicKey, Signature}; use solana::thin_client::ThinClient; use std::env; use std::error; @@ -26,8 +27,9 @@ use std::time::Duration; enum WalletCommand { Balance, AirDrop, - Pay, - Confirm, + Address, + Pay(i64, PublicKey), + Confirm(Signature), } #[derive(Debug, Clone)] @@ -58,7 +60,6 @@ struct WalletConfig { client_addr: SocketAddr, drone_addr: SocketAddr, command: WalletCommand, - sig: Option, } impl Default for WalletConfig { @@ -70,7 +71,6 @@ impl Default for WalletConfig { client_addr: default_addr.clone(), drone_addr: default_addr.clone(), command: WalletCommand::Balance, - sig: None, } } } @@ -82,14 +82,38 @@ fn print_usage(program: &str, opts: Options) { brief += " Takes json formatted mint file to stdin."; print!("{}", opts.usage(&brief)); + display_actions(); } -fn parse_command(input: &str) -> Result { - match input { +fn parse_command(matches: &Matches) -> Result { + let input = &matches.free[0]; + match input.as_ref() { + "address" => Ok(WalletCommand::Address), "balance" => Ok(WalletCommand::Balance), "airdrop" => Ok(WalletCommand::AirDrop), - "pay" => Ok(WalletCommand::Pay), - "confirm" => Ok(WalletCommand::Confirm), + "pay" => { + if matches.free.len() < 3 { + eprintln!("No tokens and public key provided"); + exit(1); + } + let tokens = matches.free[1].parse().expect("parse integer"); + let pubkey_vec = bs58::decode(&matches.free[2]) + .into_vec() + .expect("base58-encoded public key"); + let to = PublicKey::clone_from_slice(&pubkey_vec); + Ok(WalletCommand::Pay(tokens, to)) + } + "confirm" => { + if matches.free.len() < 2 { + eprintln!("No signature provided"); + exit(1); + } + let sig_vec = bs58::decode(&matches.free[1]) + .into_vec() + .expect("base58-encoded signature"); + let sig = Signature::clone_from_slice(&sig_vec); + Ok(WalletCommand::Confirm(sig)) + } _ => Err(WalletError::CommandNotRecognized(input.to_string())), } } @@ -111,9 +135,7 @@ fn parse_args(args: Vec) -> Result> { }; if matches.opt_present("h") || matches.free.len() < 1 { - let program = args[0].clone(); - print_usage(&program, opts); - display_actions(); + print_usage(&args[0], opts); return Ok(WalletConfig::default()); } @@ -144,15 +166,13 @@ fn parse_args(args: Vec) -> Result> { let mut drone_addr = leader.transactions_addr.clone(); drone_addr.set_port(9900); - let command = parse_command(&matches.free[0])?; - + let command = parse_command(&matches)?; Ok(WalletConfig { leader, id, client_addr, drone_addr, // TODO: Add an option for this. command, - sig: None, // TODO: Add an option for this. }) } @@ -162,6 +182,9 @@ fn process_command( ) -> Result<(), Box> { match config.command { // Check client balance + WalletCommand::Address => { + println!("{}", bs58::encode(config.id.pubkey()).into_string()); + } WalletCommand::Balance => { println!("Balance requested..."); let balance = client.poll_get_balance(&config.id.pubkey()); @@ -190,42 +213,19 @@ fn process_command( ); } // If client has positive balance, spend tokens in {balance} number of transactions - WalletCommand::Pay => { + WalletCommand::Pay(tokens, to) => { let last_id = client.get_last_id(); - let balance = client.poll_get_balance(&config.id.pubkey()); - match balance { - Ok(0) => { - println!("You don't have any tokens!"); - } - Ok(balance) => { - println!("Sending {:?} tokens to self...", balance); - let sig = client - .transfer(balance, &config.id.keypair(), config.id.pubkey(), &last_id) - .expect("transfer return signature"); - println!("Transaction sent!"); - println!("Signature: {:?}", sig); - } - Err(ref e) if e.kind() == std::io::ErrorKind::Other => { - println!("No account found! Request an airdrop to get started."); - } - Err(error) => { - println!("An error occurred: {:?}", error); - } - } + let sig = client.transfer(tokens, &config.id.keypair(), to, &last_id)?; + println!("{}", bs58::encode(sig).into_string()); } // Confirm the last client transaction by signature - WalletCommand::Confirm => match config.sig { - Some(sig) => { - if client.check_signature(&sig) { - println!("Signature found at bank id {:?}", config.id); - } else { - println!("Uh oh... Signature not found!"); - } + WalletCommand::Confirm(sig) => { + if client.check_signature(&sig) { + println!("Confirmed"); + } else { + println!("Not found"); } - None => { - println!("No recent signature. Make a payment to get started."); - } - }, + } } Ok(()) } From cb4ee5bfba505a8fdbe23961e9fac9faa68adcfe Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 29 Jun 2018 17:08:55 -0600 Subject: [PATCH 3/3] Add doc --- src/bin/wallet.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bin/wallet.rs b/src/bin/wallet.rs index 2053e12886c743..19ce3493a30c83 100644 --- a/src/bin/wallet.rs +++ b/src/bin/wallet.rs @@ -25,9 +25,9 @@ use std::thread::sleep; use std::time::Duration; enum WalletCommand { + Address, Balance, AirDrop, - Address, Pay(i64, PublicKey), Confirm(Signature), } @@ -233,6 +233,7 @@ fn process_command( fn display_actions() { println!(""); println!("Commands:"); + println!(" address Get your public key"); println!(" balance Get your account balance"); println!(" airdrop Request a batch of tokens"); println!(" pay Spend your tokens as fast as possible");