diff --git a/client/src/rpc_client.rs b/client/src/rpc_client.rs index 0ad8a04d3..cff5ed38e 100644 --- a/client/src/rpc_client.rs +++ b/client/src/rpc_client.rs @@ -55,6 +55,33 @@ impl RpcClient { } } + pub fn confirm_transaction(&self, signature: &str) -> Result { + self.confirm_transaction_with_commitment(signature, CommitmentConfig::default()) + } + + pub fn confirm_transaction_with_commitment( + &self, + signature: &str, + commitment_config: CommitmentConfig, + ) -> Result { + let params = json!(signature); + let response = self.client.send( + &RpcRequest::ConfirmTransaction, + Some(params), + 0, + Some(commitment_config), + )?; + if response.as_bool().is_none() { + Err(io::Error::new( + io::ErrorKind::Other, + "Received result of an unexpected type", + ) + .into()) + } else { + Ok(response.as_bool().unwrap()) + } + } + pub fn send_transaction(&self, transaction: &Transaction) -> Result { let serialized = serialize(transaction).unwrap(); let params = json!(serialized); @@ -437,8 +464,27 @@ impl RpcClient { pubkey: &Pubkey, commitment_config: CommitmentConfig, ) -> io::Result { - self.get_account_with_commitment(pubkey, commitment_config) - .map(|account| account.lamports) + let params = json!(pubkey.to_string()); + let balance_json = self + .client + .send( + &RpcRequest::GetBalance, + Some(params), + 0, + Some(commitment_config), + ) + .map_err(|err| { + io::Error::new( + io::ErrorKind::Other, + format!("GetBalance request failure: {:?}", err), + ) + })?; + serde_json::from_value(balance_json).map_err(|err| { + io::Error::new( + io::ErrorKind::Other, + format!("GetBalance parse failure: {:?}", err), + ) + }) } pub fn get_program_accounts(&self, pubkey: &Pubkey) -> io::Result> { diff --git a/core/tests/client.rs b/core/tests/client.rs new file mode 100644 index 000000000..e548faa74 --- /dev/null +++ b/core/tests/client.rs @@ -0,0 +1,57 @@ +use solana_client::rpc_client::RpcClient; +use solana_core::validator::new_validator_for_tests; +use solana_sdk::pubkey::Pubkey; +use solana_sdk::signature::KeypairUtil; +use solana_sdk::system_transaction; +use std::fs::remove_dir_all; +use std::thread::sleep; +use std::time::{Duration, Instant}; + +#[test] +fn test_rpc_client() { + solana_logger::setup(); + + let (server, leader_data, alice, ledger_path) = new_validator_for_tests(); + let bob_pubkey = Pubkey::new_rand(); + + let client = RpcClient::new_socket(leader_data.rpc); + + assert_eq!( + client.get_version().unwrap(), + format!("{{\"solana-core\":\"{}\"}}", env!("CARGO_PKG_VERSION")) + ); + + assert_eq!(client.get_balance(&bob_pubkey).unwrap(), 0); + + assert_eq!(client.get_balance(&alice.pubkey()).unwrap(), 10000); + + let (blockhash, _fee_calculator) = client.get_recent_blockhash().unwrap(); + + let tx = system_transaction::transfer(&alice, &bob_pubkey, 20, blockhash); + let signature = client.send_transaction(&tx).unwrap(); + + let mut confirmed_tx = false; + + let now = Instant::now(); + while now.elapsed().as_secs() <= 20 { + let response = client.confirm_transaction(signature.as_str()); + + match response { + Ok(true) => { + confirmed_tx = true; + break; + } + _ => (), + } + + sleep(Duration::from_millis(500)); + } + + assert!(confirmed_tx); + + assert_eq!(client.get_balance(&bob_pubkey).unwrap(), 20); + assert_eq!(client.get_balance(&alice.pubkey()).unwrap(), 9980); + + server.close().unwrap(); + remove_dir_all(ledger_path).unwrap(); +}