diff --git a/cli/src/cli.rs b/cli/src/cli.rs index 3550b30332..ec3d6cec8f 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -1153,7 +1153,7 @@ fn process_balance( } fn process_confirm(rpc_client: &RpcClient, signature: &Signature) -> ProcessResult { - match rpc_client.get_signature_status(&signature.to_string()) { + match rpc_client.get_signature_status(&signature) { Ok(status) => { if let Some(result) = status { match result { @@ -2165,7 +2165,7 @@ pub fn request_and_confirm_airdrop( log_instruction_custom_error::(result) } -pub fn log_instruction_custom_error(result: ClientResult) -> ProcessResult +pub fn log_instruction_custom_error(result: ClientResult) -> ProcessResult where E: 'static + std::error::Error + DecodeError + FromPrimitive, { @@ -2182,7 +2182,7 @@ where } Err(err.into()) } - Ok(sig) => Ok(sig), + Ok(sig) => Ok(sig.to_string()), } } diff --git a/cli/src/storage.rs b/cli/src/storage.rs index 816d7d0700..6be99dcfbd 100644 --- a/cli/src/storage.rs +++ b/cli/src/storage.rs @@ -266,8 +266,8 @@ pub fn process_claim_storage_reward( &fee_calculator, &tx.message, )?; - let signature_str = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &signers)?; - Ok(signature_str) + let signature = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &signers)?; + Ok(signature.to_string()) } pub fn process_show_storage_account( diff --git a/client/src/rpc_client.rs b/client/src/rpc_client.rs index 71b1522a7f..addf4d2f16 100644 --- a/client/src/rpc_client.rs +++ b/client/src/rpc_client.rs @@ -28,7 +28,6 @@ use solana_vote_program::vote_state::MAX_LOCKOUT_HISTORY; use std::{ error, net::SocketAddr, - str::FromStr, thread::sleep, time::{Duration, Instant}, }; @@ -67,7 +66,7 @@ impl RpcClient { } } - pub fn confirm_transaction(&self, signature: &str) -> ClientResult { + pub fn confirm_transaction(&self, signature: &Signature) -> ClientResult { Ok(self .confirm_transaction_with_commitment(signature, CommitmentConfig::default())? .value) @@ -75,14 +74,14 @@ impl RpcClient { pub fn confirm_transaction_with_commitment( &self, - signature: &str, + signature: &Signature, commitment_config: CommitmentConfig, ) -> RpcResult { let response = self .client .send( &RpcRequest::ConfirmTransaction, - json!([signature, commitment_config]), + json!([signature.to_string(), commitment_config]), 0, ) .map_err(|err| err.into_with_command("ConfirmTransaction"))?; @@ -91,28 +90,32 @@ impl RpcClient { .map_err(|err| ClientError::new_with_command(err.into(), "ConfirmTransaction")) } - pub fn send_transaction(&self, transaction: &Transaction) -> ClientResult { + pub fn send_transaction(&self, transaction: &Transaction) -> ClientResult { let serialized_encoded = bs58::encode(serialize(transaction).unwrap()).into_string(); - let signature = + let response = self.client .send(&RpcRequest::SendTransaction, json!([serialized_encoded]), 5)?; - if signature.as_str().is_none() { - Err(RpcError::ForUser("Received result of an unexpected type".to_string()).into()) - } else { - Ok(signature.as_str().unwrap().to_string()) + + match response.as_str() { + None => { + Err(RpcError::ForUser("Received result of an unexpected type".to_string()).into()) + } + Some(signature_base58_str) => signature_base58_str + .parse::() + .map_err(|err| RpcError::ParseError(err.to_string()).into()), } } pub fn get_signature_status( &self, - signature: &str, + signature: &Signature, ) -> ClientResult>> { self.get_signature_status_with_commitment(signature, CommitmentConfig::default()) } pub fn get_signature_status_with_commitment( &self, - signature: &str, + signature: &Signature, commitment_config: CommitmentConfig, ) -> ClientResult>> { let signature_status = self.client.send( @@ -346,13 +349,13 @@ impl RpcClient { &self, transaction: &mut Transaction, signer_keys: &T, - ) -> ClientResult { + ) -> ClientResult { let mut send_retries = 20; loop { let mut status_retries = 15; - let signature_str = self.send_transaction(transaction)?; + let signature = self.send_transaction(transaction)?; let status = loop { - let status = self.get_signature_status(&signature_str)?; + let status = self.get_signature_status(&signature)?; if status.is_none() { status_retries -= 1; if status_retries == 0 { @@ -368,7 +371,7 @@ impl RpcClient { }; send_retries = if let Some(result) = status.clone() { match result { - Ok(_) => return Ok(signature_str), + Ok(_) => return Ok(signature), Err(TransactionError::AccountInUse) => { // Fetch a new blockhash and re-sign the transaction before sending it again self.resign_transaction(transaction, signer_keys)?; @@ -830,10 +833,9 @@ impl RpcClient { ) -> ClientResult<()> { let now = Instant::now(); loop { - if let Ok(Some(_)) = self.get_signature_status_with_commitment( - &signature.to_string(), - commitment_config.clone(), - ) { + if let Ok(Some(_)) = + self.get_signature_status_with_commitment(&signature, commitment_config.clone()) + { break; } if now.elapsed().as_secs() > 15 { @@ -971,7 +973,7 @@ impl RpcClient { &self, transaction: &mut Transaction, signer_keys: &T, - ) -> ClientResult { + ) -> ClientResult { let mut confirmations = 0; let progress_bar = new_spinner_progress_bar(); @@ -982,23 +984,21 @@ impl RpcClient { )); let mut send_retries = 20; - let signature_str = loop { + let signature = loop { let mut status_retries = 15; - let (signature_str, status) = loop { - let signature_str = self.send_transaction(transaction)?; + let (signature, status) = loop { + let signature = self.send_transaction(transaction)?; // Get recent commitment in order to count confirmations for successful transactions - let status = self.get_signature_status_with_commitment( - &signature_str, - CommitmentConfig::recent(), - )?; + let status = self + .get_signature_status_with_commitment(&signature, CommitmentConfig::recent())?; if status.is_none() { status_retries -= 1; if status_retries == 0 { - break (signature_str, status); + break (signature, status); } } else { - break (signature_str, status); + break (signature, status); } if cfg!(not(test)) { @@ -1023,7 +1023,7 @@ impl RpcClient { if let Some(result) = status { match result { Ok(_) => { - break signature_str; + break signature; } Err(err) => { return Err(err.into()); @@ -1036,19 +1036,13 @@ impl RpcClient { } } }; - let signature = Signature::from_str(&signature_str).map_err(|_| { - ClientError::from(ClientErrorKind::Custom(format!( - "Returned string {} cannot be parsed as a signature", - signature_str - ))) - })?; loop { // Return when default (max) commitment is reached // Failed transactions have already been eliminated, `is_some` check is sufficient - if self.get_signature_status(&signature_str)?.is_some() { + if self.get_signature_status(&signature)?.is_some() { progress_bar.set_message("Transaction confirmed"); progress_bar.finish_and_clear(); - return Ok(signature_str); + return Ok(signature); } progress_bar.set_message(&format!( "[{}/{}] Waiting for confirmations", @@ -1210,7 +1204,7 @@ mod tests { let tx = system_transaction::transfer(&key, &to, 50, blockhash); let signature = rpc_client.send_transaction(&tx); - assert_eq!(signature.unwrap(), SIGNATURE.to_string()); + assert_eq!(signature.unwrap(), SIGNATURE.parse().unwrap()); let rpc_client = RpcClient::new_mock("fails".to_string()); @@ -1233,18 +1227,17 @@ mod tests { #[test] fn test_get_signature_status() { + let signature = Signature::default(); + let rpc_client = RpcClient::new_mock("succeeds".to_string()); - let signature = "good_signature"; let status = rpc_client.get_signature_status(&signature).unwrap(); assert_eq!(status, Some(Ok(()))); let rpc_client = RpcClient::new_mock("sig_not_found".to_string()); - let signature = "sig_not_found"; let status = rpc_client.get_signature_status(&signature).unwrap(); assert_eq!(status, None); let rpc_client = RpcClient::new_mock("account_in_use".to_string()); - let signature = "account_in_use"; let status = rpc_client.get_signature_status(&signature).unwrap(); assert_eq!(status, Some(Err(TransactionError::AccountInUse))); } diff --git a/client/src/thin_client.rs b/client/src/thin_client.rs index e3c601bddc..2384a66a35 100644 --- a/client/src/thin_client.rs +++ b/client/src/thin_client.rs @@ -471,7 +471,7 @@ impl SyncClient for ThinClient { ) -> TransportResult>> { let status = self .rpc_client() - .get_signature_status(&signature.to_string()) + .get_signature_status(&signature) .map_err(|err| { io::Error::new( io::ErrorKind::Other, @@ -488,7 +488,7 @@ impl SyncClient for ThinClient { ) -> TransportResult>> { let status = self .rpc_client() - .get_signature_status_with_commitment(&signature.to_string(), commitment_config) + .get_signature_status_with_commitment(&signature, commitment_config) .map_err(|err| { io::Error::new( io::ErrorKind::Other, diff --git a/core/tests/client.rs b/core/tests/client.rs index be06e84217..73cb9e201b 100644 --- a/core/tests/client.rs +++ b/core/tests/client.rs @@ -58,7 +58,7 @@ fn test_rpc_client() { let now = Instant::now(); while now.elapsed().as_secs() <= 20 { let response = client - .confirm_transaction_with_commitment(signature.as_str(), CommitmentConfig::default()) + .confirm_transaction_with_commitment(&signature, CommitmentConfig::default()) .unwrap(); if response.value {