From e87cac06da50c48487de902fda9441e13fee006a Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Fri, 21 Sep 2018 15:27:03 -0600 Subject: [PATCH] Request/reqwest improvements - Use json macro to simplify request builds - Add proxy option for reqwest to use TLS - Add rpc port options for configured nodes --- src/bin/wallet.rs | 29 +++++++++++++++++++++--- src/lib.rs | 1 + src/wallet.rs | 58 +++++++++++++++++++++++++---------------------- 3 files changed, 58 insertions(+), 30 deletions(-) diff --git a/src/bin/wallet.rs b/src/bin/wallet.rs index 83fb1cf41e..55f63ec9c1 100644 --- a/src/bin/wallet.rs +++ b/src/bin/wallet.rs @@ -54,8 +54,18 @@ pub fn parse_args(matches: &ArgMatches) -> Result Result Result<(), Box> { .value_name("SECS") .takes_value(true) .help("Max seconds to wait to get necessary gossip from the network"), + ).arg( + Arg::with_name("rpc-port") + .long("port") + .takes_value(true) + .value_name("NUM") + .help("Optional rpc-port configuration to connect to non-default nodes") + ).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("airdrop") .about("Request a batch of tokens") diff --git a/src/lib.rs b/src/lib.rs index d7bed5c68c..d0da09ce1a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,6 +94,7 @@ extern crate ring; extern crate serde; #[macro_use] extern crate serde_derive; +#[macro_use] extern crate serde_json; extern crate sha2; extern crate socket2; diff --git a/src/wallet.rs b/src/wallet.rs index 39ba8a304a..acaccbdd6e 100644 --- a/src/wallet.rs +++ b/src/wallet.rs @@ -59,7 +59,7 @@ pub struct WalletConfig { pub leader: NodeInfo, pub id: Keypair, pub drone_addr: SocketAddr, - pub rpc_addr: SocketAddr, + pub rpc_addr: String, pub command: WalletCommand, } @@ -70,7 +70,7 @@ impl Default for WalletConfig { leader: NodeInfo::new_with_socketaddr(&default_addr), id: Keypair::new(), drone_addr: default_addr, - rpc_addr: default_addr, + rpc_addr: default_addr.to_string(), command: WalletCommand::Balance, } } @@ -135,17 +135,21 @@ pub fn process_command(config: &WalletConfig) -> Result Ok(format!("{}", config.id.pubkey())), // Request an airdrop from Solana Drone; - // Request amount is set in request_airdrop function WalletCommand::AirDrop(tokens) => { println!( "Requesting airdrop of {:?} tokens from {}", tokens, config.drone_addr ); - let params = format!("[\"{}\"]", config.id.pubkey()); - let previous_balance = WalletRpcRequest::GetBalance + let params = json!(format!("{}", config.id.pubkey())); + let previous_balance = match WalletRpcRequest::GetBalance .make_rpc_request(&config.rpc_addr, 1, Some(params))? .as_i64() - .unwrap_or(0); + { + Some(tokens) => tokens, + None => Err(WalletError::RpcRequestError( + "Received result of an unexpected type".to_string(), + ))?, + }; request_airdrop(&config.drone_addr, &config.id.pubkey(), tokens as u64)?; // TODO: return airdrop Result from Drone instead of polling the @@ -153,7 +157,7 @@ pub fn process_command(config: &WalletConfig) -> Result Result { println!("Balance requested..."); - let params = format!("[\"{}\"]", config.id.pubkey()); + let params = json!(format!("{}", config.id.pubkey())); let balance = WalletRpcRequest::GetBalance .make_rpc_request(&config.rpc_addr, 1, Some(params))? .as_i64(); @@ -185,7 +189,7 @@ pub fn process_command(config: &WalletConfig) -> Result { - let params = format!("[\"{}\"]", signature); + let params = json!(format!("{}", signature)); let confirmation = WalletRpcRequest::ConfirmTransaction .make_rpc_request(&config.rpc_addr, 1, Some(params))? .as_bool(); @@ -202,7 +206,7 @@ pub fn process_command(config: &WalletConfig) -> Result { let result = WalletRpcRequest::GetLastId.make_rpc_request(&config.rpc_addr, 1, None)?; if result.as_str().is_none() { @@ -218,11 +222,11 @@ pub fn process_command(config: &WalletConfig) -> Result, + params: Option, ) -> Result> { - let rpc_string = format!("http://{}", rpc_addr.to_string()); let jsonrpc = "2.0"; let method = match self { WalletRpcRequest::ConfirmTransaction => "confirmTransaction", @@ -324,18 +327,18 @@ impl WalletRpcRequest { WalletRpcRequest::SendTransaction => "sendTransaction", }; let client = reqwest::Client::new(); - let mut request: String = format!( - "{{\"jsonrpc\":\"{}\",\"id\":{},\"method\":\"{}\"", - jsonrpc, id, method - ); + let mut request = json!({ + "jsonrpc": jsonrpc, + "id": id, + "method": method, + }); if let Some(param_string) = params { - request.push_str(&format!(",\"params\":{}", param_string)); + request["params"] = json!(vec![param_string]); } - request.push_str(&"}".to_string()); let mut response = client - .post(&rpc_string) + .post(rpc_addr) .header(CONTENT_TYPE, "application/json") - .body(request) + .body(request.to_string()) .send()?; let json: Value = serde_json::from_str(&response.text()?)?; if json["error"].is_object() { @@ -499,7 +502,7 @@ mod tests { let mut rpc_addr = leader_data.contact_info.ncp; rpc_addr.set_port(rpc_port); - config.rpc_addr = rpc_addr; + config.rpc_addr = format!("http://{}", rpc_addr.to_string()); let tokens = 50; config.command = WalletCommand::AirDrop(tokens); @@ -569,12 +572,13 @@ mod tests { run_local_drone(alice.keypair(), leader_data.contact_info.ncp, sender); let drone_addr = receiver.recv().unwrap(); - let mut rpc_addr = leader_data.contact_info.ncp; - rpc_addr.set_port(rpc_port); + let mut addr = leader_data.contact_info.ncp; + addr.set_port(rpc_port); + let rpc_addr = format!("http://{}", addr.to_string()); let signature = request_airdrop(&drone_addr, &bob_pubkey, 50); assert!(signature.is_ok()); - let params = format!("[\"{}\"]", signature.unwrap()); + let params = json!(format!("{}", signature.unwrap())); let confirmation = WalletRpcRequest::ConfirmTransaction .make_rpc_request(&rpc_addr, 1, Some(params)) .unwrap()