RpcClient now returns Signatures instead of Strings (#9129)

This commit is contained in:
Michael Vines
2020-03-27 15:46:00 -07:00
committed by GitHub
parent 74aed5cb58
commit 4a8b1d9b2c
5 changed files with 44 additions and 51 deletions

View File

@ -1153,7 +1153,7 @@ fn process_balance(
} }
fn process_confirm(rpc_client: &RpcClient, signature: &Signature) -> ProcessResult { 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) => { Ok(status) => {
if let Some(result) = status { if let Some(result) = status {
match result { match result {
@ -2165,7 +2165,7 @@ pub fn request_and_confirm_airdrop(
log_instruction_custom_error::<SystemError>(result) log_instruction_custom_error::<SystemError>(result)
} }
pub fn log_instruction_custom_error<E>(result: ClientResult<String>) -> ProcessResult pub fn log_instruction_custom_error<E>(result: ClientResult<Signature>) -> ProcessResult
where where
E: 'static + std::error::Error + DecodeError<E> + FromPrimitive, E: 'static + std::error::Error + DecodeError<E> + FromPrimitive,
{ {
@ -2182,7 +2182,7 @@ where
} }
Err(err.into()) Err(err.into())
} }
Ok(sig) => Ok(sig), Ok(sig) => Ok(sig.to_string()),
} }
} }

View File

@ -266,8 +266,8 @@ pub fn process_claim_storage_reward(
&fee_calculator, &fee_calculator,
&tx.message, &tx.message,
)?; )?;
let signature_str = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &signers)?; let signature = rpc_client.send_and_confirm_transaction_with_spinner(&mut tx, &signers)?;
Ok(signature_str) Ok(signature.to_string())
} }
pub fn process_show_storage_account( pub fn process_show_storage_account(

View File

@ -28,7 +28,6 @@ use solana_vote_program::vote_state::MAX_LOCKOUT_HISTORY;
use std::{ use std::{
error, error,
net::SocketAddr, net::SocketAddr,
str::FromStr,
thread::sleep, thread::sleep,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
@ -67,7 +66,7 @@ impl RpcClient {
} }
} }
pub fn confirm_transaction(&self, signature: &str) -> ClientResult<bool> { pub fn confirm_transaction(&self, signature: &Signature) -> ClientResult<bool> {
Ok(self Ok(self
.confirm_transaction_with_commitment(signature, CommitmentConfig::default())? .confirm_transaction_with_commitment(signature, CommitmentConfig::default())?
.value) .value)
@ -75,14 +74,14 @@ impl RpcClient {
pub fn confirm_transaction_with_commitment( pub fn confirm_transaction_with_commitment(
&self, &self,
signature: &str, signature: &Signature,
commitment_config: CommitmentConfig, commitment_config: CommitmentConfig,
) -> RpcResult<bool> { ) -> RpcResult<bool> {
let response = self let response = self
.client .client
.send( .send(
&RpcRequest::ConfirmTransaction, &RpcRequest::ConfirmTransaction,
json!([signature, commitment_config]), json!([signature.to_string(), commitment_config]),
0, 0,
) )
.map_err(|err| err.into_with_command("ConfirmTransaction"))?; .map_err(|err| err.into_with_command("ConfirmTransaction"))?;
@ -91,28 +90,32 @@ impl RpcClient {
.map_err(|err| ClientError::new_with_command(err.into(), "ConfirmTransaction")) .map_err(|err| ClientError::new_with_command(err.into(), "ConfirmTransaction"))
} }
pub fn send_transaction(&self, transaction: &Transaction) -> ClientResult<String> { pub fn send_transaction(&self, transaction: &Transaction) -> ClientResult<Signature> {
let serialized_encoded = bs58::encode(serialize(transaction).unwrap()).into_string(); let serialized_encoded = bs58::encode(serialize(transaction).unwrap()).into_string();
let signature = let response =
self.client self.client
.send(&RpcRequest::SendTransaction, json!([serialized_encoded]), 5)?; .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()) match response.as_str() {
} else { None => {
Ok(signature.as_str().unwrap().to_string()) Err(RpcError::ForUser("Received result of an unexpected type".to_string()).into())
}
Some(signature_base58_str) => signature_base58_str
.parse::<Signature>()
.map_err(|err| RpcError::ParseError(err.to_string()).into()),
} }
} }
pub fn get_signature_status( pub fn get_signature_status(
&self, &self,
signature: &str, signature: &Signature,
) -> ClientResult<Option<transaction::Result<()>>> { ) -> ClientResult<Option<transaction::Result<()>>> {
self.get_signature_status_with_commitment(signature, CommitmentConfig::default()) self.get_signature_status_with_commitment(signature, CommitmentConfig::default())
} }
pub fn get_signature_status_with_commitment( pub fn get_signature_status_with_commitment(
&self, &self,
signature: &str, signature: &Signature,
commitment_config: CommitmentConfig, commitment_config: CommitmentConfig,
) -> ClientResult<Option<transaction::Result<()>>> { ) -> ClientResult<Option<transaction::Result<()>>> {
let signature_status = self.client.send( let signature_status = self.client.send(
@ -346,13 +349,13 @@ impl RpcClient {
&self, &self,
transaction: &mut Transaction, transaction: &mut Transaction,
signer_keys: &T, signer_keys: &T,
) -> ClientResult<String> { ) -> ClientResult<Signature> {
let mut send_retries = 20; let mut send_retries = 20;
loop { loop {
let mut status_retries = 15; let mut status_retries = 15;
let signature_str = self.send_transaction(transaction)?; let signature = self.send_transaction(transaction)?;
let status = loop { let status = loop {
let status = self.get_signature_status(&signature_str)?; let status = self.get_signature_status(&signature)?;
if status.is_none() { if status.is_none() {
status_retries -= 1; status_retries -= 1;
if status_retries == 0 { if status_retries == 0 {
@ -368,7 +371,7 @@ impl RpcClient {
}; };
send_retries = if let Some(result) = status.clone() { send_retries = if let Some(result) = status.clone() {
match result { match result {
Ok(_) => return Ok(signature_str), Ok(_) => return Ok(signature),
Err(TransactionError::AccountInUse) => { Err(TransactionError::AccountInUse) => {
// Fetch a new blockhash and re-sign the transaction before sending it again // Fetch a new blockhash and re-sign the transaction before sending it again
self.resign_transaction(transaction, signer_keys)?; self.resign_transaction(transaction, signer_keys)?;
@ -830,10 +833,9 @@ impl RpcClient {
) -> ClientResult<()> { ) -> ClientResult<()> {
let now = Instant::now(); let now = Instant::now();
loop { loop {
if let Ok(Some(_)) = self.get_signature_status_with_commitment( if let Ok(Some(_)) =
&signature.to_string(), self.get_signature_status_with_commitment(&signature, commitment_config.clone())
commitment_config.clone(), {
) {
break; break;
} }
if now.elapsed().as_secs() > 15 { if now.elapsed().as_secs() > 15 {
@ -971,7 +973,7 @@ impl RpcClient {
&self, &self,
transaction: &mut Transaction, transaction: &mut Transaction,
signer_keys: &T, signer_keys: &T,
) -> ClientResult<String> { ) -> ClientResult<Signature> {
let mut confirmations = 0; let mut confirmations = 0;
let progress_bar = new_spinner_progress_bar(); let progress_bar = new_spinner_progress_bar();
@ -982,23 +984,21 @@ impl RpcClient {
)); ));
let mut send_retries = 20; let mut send_retries = 20;
let signature_str = loop { let signature = loop {
let mut status_retries = 15; let mut status_retries = 15;
let (signature_str, status) = loop { let (signature, status) = loop {
let signature_str = self.send_transaction(transaction)?; let signature = self.send_transaction(transaction)?;
// Get recent commitment in order to count confirmations for successful transactions // Get recent commitment in order to count confirmations for successful transactions
let status = self.get_signature_status_with_commitment( let status = self
&signature_str, .get_signature_status_with_commitment(&signature, CommitmentConfig::recent())?;
CommitmentConfig::recent(),
)?;
if status.is_none() { if status.is_none() {
status_retries -= 1; status_retries -= 1;
if status_retries == 0 { if status_retries == 0 {
break (signature_str, status); break (signature, status);
} }
} else { } else {
break (signature_str, status); break (signature, status);
} }
if cfg!(not(test)) { if cfg!(not(test)) {
@ -1023,7 +1023,7 @@ impl RpcClient {
if let Some(result) = status { if let Some(result) = status {
match result { match result {
Ok(_) => { Ok(_) => {
break signature_str; break signature;
} }
Err(err) => { Err(err) => {
return Err(err.into()); 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 { loop {
// Return when default (max) commitment is reached // Return when default (max) commitment is reached
// Failed transactions have already been eliminated, `is_some` check is sufficient // 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.set_message("Transaction confirmed");
progress_bar.finish_and_clear(); progress_bar.finish_and_clear();
return Ok(signature_str); return Ok(signature);
} }
progress_bar.set_message(&format!( progress_bar.set_message(&format!(
"[{}/{}] Waiting for confirmations", "[{}/{}] Waiting for confirmations",
@ -1210,7 +1204,7 @@ mod tests {
let tx = system_transaction::transfer(&key, &to, 50, blockhash); let tx = system_transaction::transfer(&key, &to, 50, blockhash);
let signature = rpc_client.send_transaction(&tx); 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()); let rpc_client = RpcClient::new_mock("fails".to_string());
@ -1233,18 +1227,17 @@ mod tests {
#[test] #[test]
fn test_get_signature_status() { fn test_get_signature_status() {
let signature = Signature::default();
let rpc_client = RpcClient::new_mock("succeeds".to_string()); let rpc_client = RpcClient::new_mock("succeeds".to_string());
let signature = "good_signature";
let status = rpc_client.get_signature_status(&signature).unwrap(); let status = rpc_client.get_signature_status(&signature).unwrap();
assert_eq!(status, Some(Ok(()))); assert_eq!(status, Some(Ok(())));
let rpc_client = RpcClient::new_mock("sig_not_found".to_string()); 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(); let status = rpc_client.get_signature_status(&signature).unwrap();
assert_eq!(status, None); assert_eq!(status, None);
let rpc_client = RpcClient::new_mock("account_in_use".to_string()); 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(); let status = rpc_client.get_signature_status(&signature).unwrap();
assert_eq!(status, Some(Err(TransactionError::AccountInUse))); assert_eq!(status, Some(Err(TransactionError::AccountInUse)));
} }

View File

@ -471,7 +471,7 @@ impl SyncClient for ThinClient {
) -> TransportResult<Option<transaction::Result<()>>> { ) -> TransportResult<Option<transaction::Result<()>>> {
let status = self let status = self
.rpc_client() .rpc_client()
.get_signature_status(&signature.to_string()) .get_signature_status(&signature)
.map_err(|err| { .map_err(|err| {
io::Error::new( io::Error::new(
io::ErrorKind::Other, io::ErrorKind::Other,
@ -488,7 +488,7 @@ impl SyncClient for ThinClient {
) -> TransportResult<Option<transaction::Result<()>>> { ) -> TransportResult<Option<transaction::Result<()>>> {
let status = self let status = self
.rpc_client() .rpc_client()
.get_signature_status_with_commitment(&signature.to_string(), commitment_config) .get_signature_status_with_commitment(&signature, commitment_config)
.map_err(|err| { .map_err(|err| {
io::Error::new( io::Error::new(
io::ErrorKind::Other, io::ErrorKind::Other,

View File

@ -58,7 +58,7 @@ fn test_rpc_client() {
let now = Instant::now(); let now = Instant::now();
while now.elapsed().as_secs() <= 20 { while now.elapsed().as_secs() <= 20 {
let response = client let response = client
.confirm_transaction_with_commitment(signature.as_str(), CommitmentConfig::default()) .confirm_transaction_with_commitment(&signature, CommitmentConfig::default())
.unwrap(); .unwrap();
if response.value { if response.value {