Add base58-encoded addresses

This commit is contained in:
Greg Fitzgerald 2018-06-29 17:06:05 -06:00 committed by Greg Fitzgerald
parent 7b5b989cfe
commit a9881aee05
2 changed files with 49 additions and 48 deletions

View File

@ -74,3 +74,4 @@ tokio = "0.1"
tokio-codec = "0.1" tokio-codec = "0.1"
tokio-io = "0.1" tokio-io = "0.1"
itertools = "0.7.8" itertools = "0.7.8"
bs58 = "0.2.0"

View File

@ -1,16 +1,17 @@
extern crate atty; extern crate atty;
extern crate bincode; extern crate bincode;
extern crate bs58;
extern crate env_logger; extern crate env_logger;
extern crate getopts; extern crate getopts;
extern crate serde_json; extern crate serde_json;
extern crate solana; extern crate solana;
use bincode::serialize; use bincode::serialize;
use getopts::Options; use getopts::{Matches, Options};
use solana::crdt::{get_ip_addr, ReplicatedData}; use solana::crdt::{get_ip_addr, ReplicatedData};
use solana::drone::DroneRequest; use solana::drone::DroneRequest;
use solana::mint::Mint; use solana::mint::Mint;
use solana::signature::Signature; use solana::signature::{PublicKey, Signature};
use solana::thin_client::ThinClient; use solana::thin_client::ThinClient;
use std::env; use std::env;
use std::error; use std::error;
@ -26,8 +27,9 @@ use std::time::Duration;
enum WalletCommand { enum WalletCommand {
Balance, Balance,
AirDrop, AirDrop,
Pay, Address,
Confirm, Pay(i64, PublicKey),
Confirm(Signature),
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -58,7 +60,6 @@ struct WalletConfig {
client_addr: SocketAddr, client_addr: SocketAddr,
drone_addr: SocketAddr, drone_addr: SocketAddr,
command: WalletCommand, command: WalletCommand,
sig: Option<Signature>,
} }
impl Default for WalletConfig { impl Default for WalletConfig {
@ -70,7 +71,6 @@ impl Default for WalletConfig {
client_addr: default_addr.clone(), client_addr: default_addr.clone(),
drone_addr: default_addr.clone(), drone_addr: default_addr.clone(),
command: WalletCommand::Balance, command: WalletCommand::Balance,
sig: None,
} }
} }
} }
@ -82,14 +82,38 @@ fn print_usage(program: &str, opts: Options) {
brief += " Takes json formatted mint file to stdin."; brief += " Takes json formatted mint file to stdin.";
print!("{}", opts.usage(&brief)); print!("{}", opts.usage(&brief));
display_actions();
} }
fn parse_command(input: &str) -> Result<WalletCommand, WalletError> { fn parse_command(matches: &Matches) -> Result<WalletCommand, WalletError> {
match input { let input = &matches.free[0];
match input.as_ref() {
"address" => Ok(WalletCommand::Address),
"balance" => Ok(WalletCommand::Balance), "balance" => Ok(WalletCommand::Balance),
"airdrop" => Ok(WalletCommand::AirDrop), "airdrop" => Ok(WalletCommand::AirDrop),
"pay" => Ok(WalletCommand::Pay), "pay" => {
"confirm" => Ok(WalletCommand::Confirm), 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())), _ => Err(WalletError::CommandNotRecognized(input.to_string())),
} }
} }
@ -111,9 +135,7 @@ fn parse_args(args: Vec<String>) -> Result<WalletConfig, Box<error::Error>> {
}; };
if matches.opt_present("h") || matches.free.len() < 1 { if matches.opt_present("h") || matches.free.len() < 1 {
let program = args[0].clone(); print_usage(&args[0], opts);
print_usage(&program, opts);
display_actions();
return Ok(WalletConfig::default()); return Ok(WalletConfig::default());
} }
@ -144,15 +166,13 @@ fn parse_args(args: Vec<String>) -> Result<WalletConfig, Box<error::Error>> {
let mut drone_addr = leader.transactions_addr.clone(); let mut drone_addr = leader.transactions_addr.clone();
drone_addr.set_port(9900); drone_addr.set_port(9900);
let command = parse_command(&matches.free[0])?; let command = parse_command(&matches)?;
Ok(WalletConfig { Ok(WalletConfig {
leader, leader,
id, id,
client_addr, client_addr,
drone_addr, // TODO: Add an option for this. drone_addr, // TODO: Add an option for this.
command, command,
sig: None, // TODO: Add an option for this.
}) })
} }
@ -162,6 +182,9 @@ fn process_command(
) -> Result<(), Box<error::Error>> { ) -> Result<(), Box<error::Error>> {
match config.command { match config.command {
// Check client balance // Check client balance
WalletCommand::Address => {
println!("{}", bs58::encode(config.id.pubkey()).into_string());
}
WalletCommand::Balance => { WalletCommand::Balance => {
println!("Balance requested..."); println!("Balance requested...");
let balance = client.poll_get_balance(&config.id.pubkey()); 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 // 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 last_id = client.get_last_id();
let balance = client.poll_get_balance(&config.id.pubkey()); let sig = client.transfer(tokens, &config.id.keypair(), to, &last_id)?;
match balance { println!("{}", bs58::encode(sig).into_string());
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);
}
}
} }
// Confirm the last client transaction by signature // Confirm the last client transaction by signature
WalletCommand::Confirm => match config.sig { WalletCommand::Confirm(sig) => {
Some(sig) => { if client.check_signature(&sig) {
if client.check_signature(&sig) { println!("Confirmed");
println!("Signature found at bank id {:?}", config.id); } else {
} else { println!("Not found");
println!("Uh oh... Signature not found!");
}
} }
None => { }
println!("No recent signature. Make a payment to get started.");
}
},
} }
Ok(()) Ok(())
} }