Port Wallet to jsonrpc and fix tests

This commit is contained in:
Tyera Eulberg
2018-09-20 23:27:06 -06:00
committed by Tyera Eulberg
parent 5ab38afa51
commit 9228fe11c9
4 changed files with 228 additions and 87 deletions

View File

@@ -5,9 +5,9 @@ extern crate dirs;
extern crate solana; extern crate solana;
use clap::{App, Arg, ArgMatches, SubCommand}; use clap::{App, Arg, ArgMatches, SubCommand};
use solana::client::mk_client;
use solana::drone::DRONE_PORT; use solana::drone::DRONE_PORT;
use solana::logger; use solana::logger;
use solana::rpc::RPC_PORT;
use solana::signature::{read_keypair, KeypairUtil}; use solana::signature::{read_keypair, KeypairUtil};
use solana::thin_client::poll_gossip_for_leader; use solana::thin_client::poll_gossip_for_leader;
use solana::wallet::{gen_keypair_file, parse_command, process_command, WalletConfig, WalletError}; use solana::wallet::{gen_keypair_file, parse_command, process_command, WalletConfig, WalletError};
@@ -54,12 +54,16 @@ pub fn parse_args(matches: &ArgMatches) -> Result<WalletConfig, Box<error::Error
let mut drone_addr = leader.contact_info.tpu; let mut drone_addr = leader.contact_info.tpu;
drone_addr.set_port(DRONE_PORT); drone_addr.set_port(DRONE_PORT);
let mut rpc_addr = leader.contact_info.tpu;
rpc_addr.set_port(RPC_PORT);
let command = parse_command(id.pubkey(), &matches)?; let command = parse_command(id.pubkey(), &matches)?;
Ok(WalletConfig { Ok(WalletConfig {
leader, leader,
id, id,
drone_addr, // TODO: Add an option for this. drone_addr, // TODO: Add an option for this.
rpc_addr, // TODO: Add an option for this.
command, command,
}) })
} }
@@ -75,16 +79,14 @@ fn main() -> Result<(), Box<error::Error>> {
.value_name("HOST:PORT") .value_name("HOST:PORT")
.takes_value(true) .takes_value(true)
.help("Rendezvous with the network at this gossip entry point; defaults to 127.0.0.1:8001"), .help("Rendezvous with the network at this gossip entry point; defaults to 127.0.0.1:8001"),
) ).arg(
.arg(
Arg::with_name("keypair") Arg::with_name("keypair")
.short("k") .short("k")
.long("keypair") .long("keypair")
.value_name("PATH") .value_name("PATH")
.takes_value(true) .takes_value(true)
.help("/path/to/id.json"), .help("/path/to/id.json"),
) ).arg(
.arg(
Arg::with_name("timeout") Arg::with_name("timeout")
.long("timeout") .long("timeout")
.value_name("SECS") .value_name("SECS")
@@ -133,8 +135,7 @@ fn main() -> Result<(), Box<error::Error>> {
.get_matches(); .get_matches();
let config = parse_args(&matches)?; let config = parse_args(&matches)?;
let mut client = mk_client(&config.leader); let result = process_command(&config)?;
let result = process_command(&config, &mut client)?;
println!("{}", result); println!("{}", result);
Ok(()) Ok(())
} }

View File

@@ -27,6 +27,11 @@ impl fmt::Display for Hash {
} }
} }
impl Hash {
pub fn new(hash_slice: &[u8]) -> Self {
Hash(GenericArray::clone_from_slice(&hash_slice))
}
}
/// Return a Sha256 hash for the given data. /// Return a Sha256 hash for the given data.
pub fn hashv(vals: &[&[u8]]) -> Hash { pub fn hashv(vals: &[&[u8]]) -> Hash {
let mut hasher = Sha256::default(); let mut hasher = Sha256::default();

View File

@@ -90,6 +90,9 @@ build_rpc_trait! {
#[rpc(meta, name = "confirmTransaction")] #[rpc(meta, name = "confirmTransaction")]
fn confirm_transaction(&self, Self::Metadata, String) -> Result<bool>; fn confirm_transaction(&self, Self::Metadata, String) -> Result<bool>;
#[rpc(meta, name = "getAccountInfo")]
fn get_account_info(&self, Self::Metadata, String) -> Result<Account>;
#[rpc(meta, name = "getBalance")] #[rpc(meta, name = "getBalance")]
fn get_balance(&self, Self::Metadata, String) -> Result<i64>; fn get_balance(&self, Self::Metadata, String) -> Result<i64>;
@@ -102,9 +105,6 @@ build_rpc_trait! {
#[rpc(meta, name = "getTransactionCount")] #[rpc(meta, name = "getTransactionCount")]
fn get_transaction_count(&self, Self::Metadata) -> Result<u64>; fn get_transaction_count(&self, Self::Metadata) -> Result<u64>;
#[rpc(meta, name = "getAccountInfo")]
fn get_account_info(&self, Self::Metadata, String) -> Result<Account>;
#[rpc(meta, name= "requestAirdrop")] #[rpc(meta, name= "requestAirdrop")]
fn request_airdrop(&self, Self::Metadata, String, u64) -> Result<String>; fn request_airdrop(&self, Self::Metadata, String, u64) -> Result<String>;
@@ -127,6 +127,16 @@ impl RpcSol for RpcSolImpl {
let signature = Signature::new(&signature_vec); let signature = Signature::new(&signature_vec);
meta.request_processor.get_signature_status(signature) meta.request_processor.get_signature_status(signature)
} }
fn get_account_info(&self, meta: Self::Metadata, id: String) -> Result<Account> {
let pubkey_vec = bs58::decode(id)
.into_vec()
.map_err(|_| Error::invalid_request())?;
if pubkey_vec.len() != mem::size_of::<Pubkey>() {
return Err(Error::invalid_request());
}
let pubkey = Pubkey::new(&pubkey_vec);
meta.request_processor.get_account_info(pubkey)
}
fn get_balance(&self, meta: Self::Metadata, id: String) -> Result<i64> { fn get_balance(&self, meta: Self::Metadata, id: String) -> Result<i64> {
let pubkey_vec = bs58::decode(id) let pubkey_vec = bs58::decode(id)
.into_vec() .into_vec()
@@ -146,16 +156,6 @@ impl RpcSol for RpcSolImpl {
fn get_transaction_count(&self, meta: Self::Metadata) -> Result<u64> { fn get_transaction_count(&self, meta: Self::Metadata) -> Result<u64> {
meta.request_processor.get_transaction_count() meta.request_processor.get_transaction_count()
} }
fn get_account_info(&self, meta: Self::Metadata, id: String) -> Result<Account> {
let pubkey_vec = bs58::decode(id)
.into_vec()
.map_err(|_| Error::invalid_request())?;
if pubkey_vec.len() != mem::size_of::<Pubkey>() {
return Err(Error::invalid_request());
}
let pubkey = Pubkey::new(&pubkey_vec);
meta.request_processor.get_account_info(pubkey)
}
fn request_airdrop(&self, meta: Self::Metadata, id: String, tokens: u64) -> Result<String> { fn request_airdrop(&self, meta: Self::Metadata, id: String, tokens: u64) -> Result<String> {
let pubkey_vec = bs58::decode(id) let pubkey_vec = bs58::decode(id)
.into_vec() .into_vec()
@@ -208,6 +208,11 @@ impl JsonRpcRequestProcessor {
} }
/// Process JSON-RPC request items sent via JSON-RPC. /// Process JSON-RPC request items sent via JSON-RPC.
fn get_account_info(&self, pubkey: Pubkey) -> Result<Account> {
self.bank
.get_account(&pubkey)
.ok_or(Error::invalid_request())
}
fn get_balance(&self, pubkey: Pubkey) -> Result<i64> { fn get_balance(&self, pubkey: Pubkey) -> Result<i64> {
let val = self.bank.get_balance(&pubkey); let val = self.bank.get_balance(&pubkey);
Ok(val) Ok(val)
@@ -225,11 +230,6 @@ impl JsonRpcRequestProcessor {
fn get_transaction_count(&self) -> Result<u64> { fn get_transaction_count(&self) -> Result<u64> {
Ok(self.bank.transaction_count() as u64) Ok(self.bank.transaction_count() as u64)
} }
fn get_account_info(&self, pubkey: Pubkey) -> Result<Account> {
self.bank
.get_account(&pubkey)
.ok_or(Error::invalid_request())
}
} }
#[cfg(test)] #[cfg(test)]

View File

@@ -4,9 +4,12 @@ use clap::ArgMatches;
use crdt::NodeInfo; use crdt::NodeInfo;
use drone::DroneRequest; use drone::DroneRequest;
use fullnode::Config; use fullnode::Config;
use hash::Hash;
use reqwest;
use reqwest::header::CONTENT_TYPE;
use ring::rand::SystemRandom; use ring::rand::SystemRandom;
use ring::signature::Ed25519KeyPair; use ring::signature::Ed25519KeyPair;
use serde_json; use serde_json::{self, Value};
use signature::{Keypair, KeypairUtil, Pubkey, Signature}; use signature::{Keypair, KeypairUtil, Pubkey, Signature};
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::prelude::*; use std::io::prelude::*;
@@ -17,7 +20,7 @@ use std::path::Path;
use std::thread::sleep; use std::thread::sleep;
use std::time::Duration; use std::time::Duration;
use std::{error, fmt, mem}; use std::{error, fmt, mem};
use thin_client::ThinClient; use transaction::Transaction;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum WalletCommand { pub enum WalletCommand {
@@ -32,6 +35,7 @@ pub enum WalletCommand {
pub enum WalletError { pub enum WalletError {
CommandNotRecognized(String), CommandNotRecognized(String),
BadParameter(String), BadParameter(String),
RpcRequestError(String),
} }
impl fmt::Display for WalletError { impl fmt::Display for WalletError {
@@ -55,6 +59,7 @@ pub struct WalletConfig {
pub leader: NodeInfo, pub leader: NodeInfo,
pub id: Keypair, pub id: Keypair,
pub drone_addr: SocketAddr, pub drone_addr: SocketAddr,
pub rpc_addr: SocketAddr,
pub command: WalletCommand, pub command: WalletCommand,
} }
@@ -65,6 +70,7 @@ impl Default for WalletConfig {
leader: NodeInfo::new_with_socketaddr(&default_addr), leader: NodeInfo::new_with_socketaddr(&default_addr),
id: Keypair::new(), id: Keypair::new(),
drone_addr: default_addr, drone_addr: default_addr,
rpc_addr: default_addr,
command: WalletCommand::Balance, command: WalletCommand::Balance,
} }
} }
@@ -75,10 +81,25 @@ pub fn parse_command(
matches: &ArgMatches, matches: &ArgMatches,
) -> Result<WalletCommand, Box<error::Error>> { ) -> Result<WalletCommand, Box<error::Error>> {
let response = match matches.subcommand() { let response = match matches.subcommand() {
("address", Some(_address_matches)) => Ok(WalletCommand::Address),
("airdrop", Some(airdrop_matches)) => { ("airdrop", Some(airdrop_matches)) => {
let tokens = airdrop_matches.value_of("tokens").unwrap().parse()?; let tokens = airdrop_matches.value_of("tokens").unwrap().parse()?;
Ok(WalletCommand::AirDrop(tokens)) Ok(WalletCommand::AirDrop(tokens))
} }
("balance", Some(_balance_matches)) => Ok(WalletCommand::Balance),
("confirm", Some(confirm_matches)) => {
let signatures = bs58::decode(confirm_matches.value_of("signature").unwrap())
.into_vec()
.expect("base58-encoded signature");
if signatures.len() == mem::size_of::<Signature>() {
let signature = Signature::new(&signatures);
Ok(WalletCommand::Confirm(signature))
} else {
eprintln!("{}", confirm_matches.usage());
Err(WalletError::BadParameter("Invalid signature".to_string()))
}
}
("pay", Some(pay_matches)) => { ("pay", Some(pay_matches)) => {
let to = if pay_matches.is_present("to") { let to = if pay_matches.is_present("to") {
let pubkey_vec = bs58::decode(pay_matches.value_of("to").unwrap()) let pubkey_vec = bs58::decode(pay_matches.value_of("to").unwrap())
@@ -98,22 +119,6 @@ pub fn parse_command(
Ok(WalletCommand::Pay(tokens, to)) Ok(WalletCommand::Pay(tokens, to))
} }
("confirm", Some(confirm_matches)) => {
println!("{:?}", confirm_matches.value_of("signature").unwrap());
let signatures = bs58::decode(confirm_matches.value_of("signature").unwrap())
.into_vec()
.expect("base58-encoded signature");
if signatures.len() == mem::size_of::<Signature>() {
let signature = Signature::new(&signatures);
Ok(WalletCommand::Confirm(signature))
} else {
eprintln!("{}", confirm_matches.usage());
Err(WalletError::BadParameter("Invalid signature".to_string()))
}
}
("balance", Some(_balance_matches)) => Ok(WalletCommand::Balance),
("address", Some(_address_matches)) => Ok(WalletCommand::Address),
("", None) => { ("", None) => {
println!("{}", matches.usage()); println!("{}", matches.usage());
Err(WalletError::CommandNotRecognized( Err(WalletError::CommandNotRecognized(
@@ -125,24 +130,10 @@ pub fn parse_command(
Ok(response) Ok(response)
} }
pub fn process_command( pub fn process_command(config: &WalletConfig) -> Result<String, Box<error::Error>> {
config: &WalletConfig,
client: &mut ThinClient,
) -> Result<String, Box<error::Error>> {
match config.command { match config.command {
// Check client balance // Get address of this client
WalletCommand::Address => Ok(format!("{}", config.id.pubkey())), WalletCommand::Address => Ok(format!("{}", config.id.pubkey())),
WalletCommand::Balance => {
println!("Balance requested...");
let balance = client.poll_get_balance(&config.id.pubkey());
match balance {
Ok(balance) => Ok(format!("Your balance is: {:?}", balance)),
Err(ref e) if e.kind() == ErrorKind::Other => {
Ok("No account found! Request an airdrop to get started.".to_string())
}
Err(error) => Err(error)?,
}
}
// Request an airdrop from Solana Drone; // Request an airdrop from Solana Drone;
// Request amount is set in request_airdrop function // Request amount is set in request_airdrop function
WalletCommand::AirDrop(tokens) => { WalletCommand::AirDrop(tokens) => {
@@ -150,7 +141,11 @@ pub fn process_command(
"Requesting airdrop of {:?} tokens from {}", "Requesting airdrop of {:?} tokens from {}",
tokens, config.drone_addr tokens, config.drone_addr
); );
let previous_balance = client.poll_get_balance(&config.id.pubkey()).unwrap_or(0); let params = format!("[\"{}\"]", config.id.pubkey());
let previous_balance = WalletRpcRequest::GetBalance
.make_rpc_request(&config.rpc_addr, 1, Some(params))?
.as_i64()
.unwrap_or(0);
request_airdrop(&config.drone_addr, &config.id.pubkey(), tokens as u64)?; request_airdrop(&config.drone_addr, &config.id.pubkey(), tokens as u64)?;
// TODO: return airdrop Result from Drone instead of polling the // TODO: return airdrop Result from Drone instead of polling the
@@ -158,8 +153,10 @@ pub fn process_command(
let mut current_balance = previous_balance; let mut current_balance = previous_balance;
for _ in 0..20 { for _ in 0..20 {
sleep(Duration::from_millis(500)); sleep(Duration::from_millis(500));
current_balance = client let params = format!("[\"{}\"]", config.id.pubkey());
.poll_get_balance(&config.id.pubkey()) current_balance = WalletRpcRequest::GetBalance
.make_rpc_request(&config.rpc_addr, 1, Some(params))?
.as_i64()
.unwrap_or(previous_balance); .unwrap_or(previous_balance);
if previous_balance != current_balance { if previous_balance != current_balance {
@@ -172,20 +169,70 @@ pub fn process_command(
} }
Ok(format!("Your balance is: {:?}", current_balance)) Ok(format!("Your balance is: {:?}", current_balance))
} }
// If client has positive balance, spend tokens in {balance} number of transactions WalletCommand::Balance => {
WalletCommand::Pay(tokens, to) => { println!("Balance requested...");
let last_id = client.get_last_id(); let params = format!("[\"{}\"]", config.id.pubkey());
let signature = client.transfer(tokens, &config.id, to, &last_id)?; let balance = WalletRpcRequest::GetBalance
Ok(format!("{}", signature)) .make_rpc_request(&config.rpc_addr, 1, Some(params))?
.as_i64();
match balance {
Some(0) => Ok("No account found! Request an airdrop to get started.".to_string()),
Some(tokens) => Ok(format!("Your balance is: {:?}", tokens)),
None => Err(WalletError::RpcRequestError(
"Received result of an unexpected type".to_string(),
))?,
}
} }
// Confirm the last client transaction by signature // Confirm the last client transaction by signature
WalletCommand::Confirm(signature) => { WalletCommand::Confirm(signature) => {
if client.check_signature(&signature) { let params = format!("[\"{}\"]", signature);
Ok("Confirmed".to_string()) let confirmation = WalletRpcRequest::ConfirmTransaction
} else { .make_rpc_request(&config.rpc_addr, 1, Some(params))?
Ok("Not found".to_string()) .as_bool();
match confirmation {
Some(b) => {
if b {
Ok("Confirmed".to_string())
} else {
Ok("Not found".to_string())
}
}
None => Err(WalletError::RpcRequestError(
"Received result of an unexpected type".to_string(),
))?,
} }
} }
// If client has positive balance, spend tokens in {balance} number of transactions
WalletCommand::Pay(tokens, to) => {
let result = WalletRpcRequest::GetLastId.make_rpc_request(&config.rpc_addr, 1, None)?;
if result.as_str().is_none() {
Err(WalletError::RpcRequestError(
"Received bad last_id".to_string(),
))?
}
let last_id_str = result.as_str().unwrap();
let last_id_vec = bs58::decode(last_id_str)
.into_vec()
.map_err(|_| WalletError::RpcRequestError("Received bad last_id".to_string()))?;
let last_id = Hash::new(&last_id_vec);
let tx = Transaction::new(&config.id, to, tokens, last_id);
let serialized = serialize(&tx).unwrap();
let params = format!("[{}]", serde_json::to_string(&serialized)?);
let signature = WalletRpcRequest::SendTransaction.make_rpc_request(
&config.rpc_addr,
2,
Some(params.to_string()),
)?;
if signature.as_str().is_none() {
Err(WalletError::RpcRequestError(
"Received result of an unexpected type".to_string(),
))?
}
let signature_str = signature.as_str().unwrap();
Ok(format!("{}", signature_str))
}
} }
} }
@@ -247,17 +294,71 @@ pub fn gen_keypair_file(outfile: String) -> Result<String, Box<error::Error>> {
Ok(serialized) Ok(serialized)
} }
pub enum WalletRpcRequest {
ConfirmTransaction,
GetAccountInfo,
GetBalance,
GetFinality,
GetLastId,
GetTransactionCount,
RequestAirdrop,
SendTransaction,
}
impl WalletRpcRequest {
fn make_rpc_request(
&self,
rpc_addr: &SocketAddr,
id: u64,
params: Option<String>,
) -> Result<Value, Box<error::Error>> {
let rpc_string = format!("http://{}", rpc_addr.to_string());
let jsonrpc = "2.0";
let method = match self {
WalletRpcRequest::ConfirmTransaction => "confirmTransaction",
WalletRpcRequest::GetAccountInfo => "getAccountInfo",
WalletRpcRequest::GetBalance => "getBalance",
WalletRpcRequest::GetFinality => "getFinality",
WalletRpcRequest::GetLastId => "getLastId",
WalletRpcRequest::GetTransactionCount => "getTransactionCount",
WalletRpcRequest::RequestAirdrop => "requestAirdrop",
WalletRpcRequest::SendTransaction => "sendTransaction",
};
let client = reqwest::Client::new();
let mut request: String = format!(
"{{\"jsonrpc\":\"{}\",\"id\":{},\"method\":\"{}\"",
jsonrpc, id, method
);
if let Some(param_string) = params {
request.push_str(&format!(",\"params\":{}", param_string));
}
request.push_str(&"}".to_string());
let mut response = client
.post(&rpc_string)
.header(CONTENT_TYPE, "application/json")
.body(request)
.send()?;
let json: Value = serde_json::from_str(&response.text()?)?;
if json["error"].is_object() {
Err(WalletError::RpcRequestError(format!(
"RPC Error response: {}",
serde_json::to_string(&json["error"]).unwrap()
)))?
}
Ok(json["result"].clone())
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use bank::Bank; use bank::Bank;
use clap::{App, Arg, SubCommand}; use clap::{App, Arg, SubCommand};
use client::mk_client;
use crdt::Node; use crdt::Node;
use drone::run_local_drone; use drone::run_local_drone;
use fullnode::Fullnode; use fullnode::Fullnode;
use ledger::LedgerWriter; use ledger::LedgerWriter;
use mint::Mint; use mint::Mint;
use rpc::RPC_PORT;
use signature::{read_keypair, read_pkcs8, Keypair, KeypairUtil}; use signature::{read_keypair, read_pkcs8, Keypair, KeypairUtil};
use std::net::UdpSocket; use std::net::UdpSocket;
use std::sync::mpsc::channel; use std::sync::mpsc::channel;
@@ -396,28 +497,31 @@ mod tests {
config.drone_addr = receiver.recv().unwrap(); config.drone_addr = receiver.recv().unwrap();
config.leader = leader_data1; config.leader = leader_data1;
let mut rpc_addr = leader_data.contact_info.ncp;
rpc_addr.set_port(RPC_PORT);
config.rpc_addr = rpc_addr;
let tokens = 50; let tokens = 50;
config.command = WalletCommand::AirDrop(tokens); config.command = WalletCommand::AirDrop(tokens);
let mut client = mk_client(&config.leader);
assert_eq!( assert_eq!(
process_command(&config, &mut client).unwrap(), process_command(&config).unwrap(),
format!("Your balance is: {:?}", tokens) format!("Your balance is: {:?}", tokens)
); );
config.command = WalletCommand::Balance; config.command = WalletCommand::Balance;
assert_eq!( assert_eq!(
process_command(&config, &mut client).unwrap(), process_command(&config).unwrap(),
format!("Your balance is: {:?}", tokens) format!("Your balance is: {:?}", tokens)
); );
config.command = WalletCommand::Address; config.command = WalletCommand::Address;
assert_eq!( assert_eq!(
process_command(&config, &mut client).unwrap(), process_command(&config).unwrap(),
format!("{}", config.id.pubkey()) format!("{}", config.id.pubkey())
); );
config.command = WalletCommand::Pay(10, bob_pubkey); config.command = WalletCommand::Pay(10, bob_pubkey);
let sig_response = process_command(&config, &mut client); let sig_response = process_command(&config);
assert!(sig_response.is_ok()); assert!(sig_response.is_ok());
sleep(Duration::from_millis(100)); sleep(Duration::from_millis(100));
@@ -426,11 +530,11 @@ mod tests {
.expect("base58-encoded signature"); .expect("base58-encoded signature");
let signature = Signature::new(&signatures); let signature = Signature::new(&signatures);
config.command = WalletCommand::Confirm(signature); config.command = WalletCommand::Confirm(signature);
assert_eq!(process_command(&config, &mut client).unwrap(), "Confirmed"); assert_eq!(process_command(&config).unwrap(), "Confirmed");
config.command = WalletCommand::Balance; config.command = WalletCommand::Balance;
assert_eq!( assert_eq!(
process_command(&config, &mut client).unwrap(), process_command(&config).unwrap(),
format!("Your balance is: {:?}", tokens - 10) format!("Your balance is: {:?}", tokens - 10)
); );
} }
@@ -461,20 +565,22 @@ mod tests {
let requests_socket = UdpSocket::bind("0.0.0.0:0").unwrap(); let requests_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
let transactions_socket = UdpSocket::bind("0.0.0.0:0").unwrap(); let transactions_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
let mut client = ThinClient::new(
leader_data.contact_info.rpu,
requests_socket,
leader_data.contact_info.tpu,
transactions_socket,
);
let (sender, receiver) = channel(); let (sender, receiver) = channel();
run_local_drone(alice.keypair(), leader_data.contact_info.ncp, sender); run_local_drone(alice.keypair(), leader_data.contact_info.ncp, sender);
let drone_addr = receiver.recv().unwrap(); let drone_addr = receiver.recv().unwrap();
let mut rpc_addr = leader_data.contact_info.ncp;
rpc_addr.set_port(RPC_PORT);
let signature = request_airdrop(&drone_addr, &bob_pubkey, 50); let signature = request_airdrop(&drone_addr, &bob_pubkey, 50);
assert!(signature.is_ok()); assert!(signature.is_ok());
assert!(client.check_signature(&signature.unwrap())); let params = format!("[\"{}\"]", signature.unwrap());
let confirmation = WalletRpcRequest::ConfirmTransaction
.make_rpc_request(&rpc_addr, 1, Some(params))
.unwrap()
.as_bool()
.unwrap();
assert!(confirmation);
} }
#[test] #[test]
fn test_gen_keypair_file() { fn test_gen_keypair_file() {
@@ -491,4 +597,33 @@ mod tests {
fs::remove_file(outfile).unwrap(); fs::remove_file(outfile).unwrap();
assert!(!Path::new(outfile).exists()); assert!(!Path::new(outfile).exists());
} }
#[test]
fn test_make_rpc_request() {
// let leader_keypair = Keypair::new();
// let leader = Node::new_localhost_with_pubkey(leader_keypair.pubkey());
//
// let alice = Mint::new(10_000_000);
// let bank = Bank::new(&alice);
// let bob_pubkey = Keypair::new().pubkey();
// let leader_data = leader.info.clone();
// let leader_data1 = leader.info.clone();
// let ledger_path = tmp_ledger("thin_client", &alice);
//
// let mut config = WalletConfig::default();
//
// let _server = Fullnode::new_with_bank(
// leader_keypair,
// bank,
// 0,
// &[],
// leader,
// None,
// &ledger_path,
// false,
// None,
// );
// sleep(Duration::from_millis(200));
assert!(true);
}
} }