Get everything off RpcSignatureStatus
This commit is contained in:
committed by
Tyera Eulberg
parent
90c1300bb6
commit
f349c1f0dc
@ -1,6 +1,7 @@
|
||||
use crate::generic_rpc_client_request::GenericRpcClientRequest;
|
||||
use crate::rpc_request::RpcRequest;
|
||||
use serde_json::{Number, Value};
|
||||
use solana_sdk::transaction::{self, TransactionError};
|
||||
|
||||
pub const PUBKEY: &str = "7RoSF9fUmdphVCpabEoefH81WwrW7orsWonXWqTXkKV8";
|
||||
pub const SIGNATURE: &str =
|
||||
@ -44,14 +45,14 @@ impl GenericRpcClientRequest for MockRpcClientRequest {
|
||||
}
|
||||
RpcRequest::GetRecentBlockhash => Value::String(PUBKEY.to_string()),
|
||||
RpcRequest::GetSignatureStatus => {
|
||||
let str = if self.url == "account_in_use" {
|
||||
"AccountInUse"
|
||||
} else if self.url == "bad_sig_status" {
|
||||
"SignatureNotFound"
|
||||
let response: Option<transaction::Result<()>> = if self.url == "account_in_use" {
|
||||
Some(Err(TransactionError::AccountInUse))
|
||||
} else if self.url == "sig_not_found" {
|
||||
None
|
||||
} else {
|
||||
"Confirmed"
|
||||
Some(Ok(()))
|
||||
};
|
||||
Value::String(str.to_string())
|
||||
serde_json::to_value(response).unwrap()
|
||||
}
|
||||
RpcRequest::GetTransactionCount => Value::Number(Number::from(1234)),
|
||||
RpcRequest::SendTransaction => Value::String(SIGNATURE.to_string()),
|
||||
|
@ -2,7 +2,6 @@ use crate::generic_rpc_client_request::GenericRpcClientRequest;
|
||||
use crate::mock_rpc_client_request::MockRpcClientRequest;
|
||||
use crate::rpc_client_request::RpcClientRequest;
|
||||
use crate::rpc_request::RpcRequest;
|
||||
use crate::rpc_signature_status::RpcSignatureStatus;
|
||||
use bincode::serialize;
|
||||
use bs58;
|
||||
use log::*;
|
||||
@ -12,11 +11,10 @@ use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||
use solana_sdk::timing::{DEFAULT_TICKS_PER_SLOT, NUM_TICKS_PER_SECOND};
|
||||
use solana_sdk::transaction::Transaction;
|
||||
use solana_sdk::transaction::{self, Transaction, TransactionError};
|
||||
use std::error;
|
||||
use std::io;
|
||||
use std::net::SocketAddr;
|
||||
use std::str::FromStr;
|
||||
use std::thread::sleep;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
@ -69,25 +67,14 @@ impl RpcClient {
|
||||
pub fn get_signature_status(
|
||||
&self,
|
||||
signature: &str,
|
||||
) -> Result<RpcSignatureStatus, Box<dyn error::Error>> {
|
||||
) -> Result<Option<transaction::Result<()>>, Box<dyn error::Error>> {
|
||||
let params = json!([signature.to_string()]);
|
||||
let signature_status =
|
||||
self.client
|
||||
.send(&RpcRequest::GetSignatureStatus, Some(params), 5)?;
|
||||
if let Some(status) = signature_status.as_str() {
|
||||
let rpc_status = RpcSignatureStatus::from_str(status).map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("Unable to parse signature status: {:?}", err),
|
||||
)
|
||||
})?;
|
||||
Ok(rpc_status)
|
||||
} else {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Received result of an unexpected type",
|
||||
))?
|
||||
}
|
||||
let result: Option<transaction::Result<()>> =
|
||||
serde_json::from_value(signature_status).unwrap();
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn send_and_confirm_transaction<T: KeypairUtil>(
|
||||
@ -101,7 +88,7 @@ impl RpcClient {
|
||||
let signature_str = self.send_transaction(transaction)?;
|
||||
let status = loop {
|
||||
let status = self.get_signature_status(&signature_str)?;
|
||||
if status == RpcSignatureStatus::SignatureNotFound {
|
||||
if status.is_none() {
|
||||
status_retries -= 1;
|
||||
if status_retries == 0 {
|
||||
break status;
|
||||
@ -116,19 +103,19 @@ impl RpcClient {
|
||||
));
|
||||
}
|
||||
};
|
||||
match status {
|
||||
RpcSignatureStatus::AccountInUse | RpcSignatureStatus::SignatureNotFound => {
|
||||
// Fetch a new blockhash and re-sign the transaction before sending it again
|
||||
self.resign_transaction(transaction, signer)?;
|
||||
send_retries -= 1;
|
||||
send_retries = if let Some(result) = status.clone() {
|
||||
match result {
|
||||
Ok(_) => return Ok(signature_str),
|
||||
Err(TransactionError::AccountInUse) => {
|
||||
// Fetch a new blockhash and re-sign the transaction before sending it again
|
||||
self.resign_transaction(transaction, signer)?;
|
||||
send_retries - 1
|
||||
}
|
||||
Err(_) => 0,
|
||||
}
|
||||
RpcSignatureStatus::Confirmed => {
|
||||
return Ok(signature_str);
|
||||
}
|
||||
_ => {
|
||||
send_retries = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
send_retries - 1
|
||||
};
|
||||
if send_retries == 0 {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@ -177,7 +164,10 @@ impl RpcClient {
|
||||
.filter(|(_transaction, signature)| {
|
||||
if let Some(signature) = signature {
|
||||
if let Ok(status) = self.get_signature_status(&signature) {
|
||||
return status != RpcSignatureStatus::Confirmed;
|
||||
if status.is_none() {
|
||||
return false;
|
||||
}
|
||||
return status.unwrap().is_err();
|
||||
}
|
||||
}
|
||||
true
|
||||
@ -557,6 +547,7 @@ mod tests {
|
||||
use solana_logger;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::system_transaction;
|
||||
use solana_sdk::transaction::TransactionError;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::thread;
|
||||
|
||||
@ -692,18 +683,18 @@ mod tests {
|
||||
fn test_get_signature_status() {
|
||||
let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||
let signature = "good_signature";
|
||||
let status = rpc_client.get_signature_status(&signature);
|
||||
assert_eq!(status.unwrap(), RpcSignatureStatus::Confirmed);
|
||||
let status = rpc_client.get_signature_status(&signature).unwrap();
|
||||
assert_eq!(status, Some(Ok(())));
|
||||
|
||||
let rpc_client = RpcClient::new_mock("bad_sig_status".to_string());
|
||||
let signature = "bad_status";
|
||||
let status = dbg!(rpc_client.get_signature_status(&signature));
|
||||
assert_eq!(status.unwrap(), RpcSignatureStatus::SignatureNotFound);
|
||||
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("fails".to_string());
|
||||
let signature = "bad_status_fmt";
|
||||
let status = rpc_client.get_signature_status(&signature);
|
||||
assert!(status.is_err());
|
||||
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)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Reference in New Issue
Block a user