Use optimistic confirmation in getSignatureStatuses, and various downstream client methods (#14430)
* Add optimistically_confirmed field to TransactionStatus * Update docs * Convert new field to confirmation_status * Update docs to confirmationStatus * Update variants * Update docs * Just Confirmed
This commit is contained in:
@ -20,7 +20,7 @@ use solana_account_decoder::parse_token::UiTokenAmount;
|
||||
pub use solana_runtime::bank::RewardType;
|
||||
use solana_sdk::{
|
||||
clock::{Slot, UnixTimestamp},
|
||||
commitment_config::CommitmentConfig,
|
||||
commitment_config::{CommitmentConfig, CommitmentLevel},
|
||||
deserialize_utils::default_on_eof,
|
||||
instruction::CompiledInstruction,
|
||||
message::{Message, MessageHeader},
|
||||
@ -260,6 +260,14 @@ impl From<TransactionStatusMeta> for UiTransactionStatusMeta {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum TransactionConfirmationStatus {
|
||||
Processed,
|
||||
Confirmed,
|
||||
Finalized,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TransactionStatus {
|
||||
@ -267,12 +275,28 @@ pub struct TransactionStatus {
|
||||
pub confirmations: Option<usize>, // None = rooted
|
||||
pub status: Result<()>, // legacy field
|
||||
pub err: Option<TransactionError>,
|
||||
pub confirmation_status: Option<TransactionConfirmationStatus>,
|
||||
}
|
||||
|
||||
impl TransactionStatus {
|
||||
pub fn satisfies_commitment(&self, commitment_config: CommitmentConfig) -> bool {
|
||||
(commitment_config == CommitmentConfig::default() && self.confirmations.is_none())
|
||||
|| commitment_config == CommitmentConfig::recent()
|
||||
match commitment_config.commitment {
|
||||
CommitmentLevel::Max | CommitmentLevel::Root => self.confirmations.is_none(),
|
||||
CommitmentLevel::SingleGossip => {
|
||||
if let Some(status) = &self.confirmation_status {
|
||||
*status != TransactionConfirmationStatus::Processed
|
||||
} else {
|
||||
// These fallback cases handle TransactionStatus RPC responses from older software
|
||||
self.confirmations.is_some() && self.confirmations.unwrap() > 1
|
||||
|| self.confirmations.is_none()
|
||||
}
|
||||
}
|
||||
CommitmentLevel::Single => match self.confirmations {
|
||||
Some(confirmations) => confirmations >= 1,
|
||||
None => true,
|
||||
},
|
||||
CommitmentLevel::Recent => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -545,9 +569,13 @@ mod test {
|
||||
confirmations: None,
|
||||
status: Ok(()),
|
||||
err: None,
|
||||
confirmation_status: Some(TransactionConfirmationStatus::Finalized),
|
||||
};
|
||||
|
||||
assert!(status.satisfies_commitment(CommitmentConfig::default()));
|
||||
assert!(status.satisfies_commitment(CommitmentConfig::root()));
|
||||
assert!(status.satisfies_commitment(CommitmentConfig::single()));
|
||||
assert!(status.satisfies_commitment(CommitmentConfig::single_gossip()));
|
||||
assert!(status.satisfies_commitment(CommitmentConfig::recent()));
|
||||
|
||||
let status = TransactionStatus {
|
||||
@ -555,9 +583,69 @@ mod test {
|
||||
confirmations: Some(10),
|
||||
status: Ok(()),
|
||||
err: None,
|
||||
confirmation_status: Some(TransactionConfirmationStatus::Confirmed),
|
||||
};
|
||||
|
||||
assert!(!status.satisfies_commitment(CommitmentConfig::default()));
|
||||
assert!(!status.satisfies_commitment(CommitmentConfig::root()));
|
||||
assert!(status.satisfies_commitment(CommitmentConfig::single()));
|
||||
assert!(status.satisfies_commitment(CommitmentConfig::single_gossip()));
|
||||
assert!(status.satisfies_commitment(CommitmentConfig::recent()));
|
||||
|
||||
let status = TransactionStatus {
|
||||
slot: 0,
|
||||
confirmations: Some(1),
|
||||
status: Ok(()),
|
||||
err: None,
|
||||
confirmation_status: Some(TransactionConfirmationStatus::Processed),
|
||||
};
|
||||
|
||||
assert!(!status.satisfies_commitment(CommitmentConfig::default()));
|
||||
assert!(!status.satisfies_commitment(CommitmentConfig::root()));
|
||||
assert!(status.satisfies_commitment(CommitmentConfig::single()));
|
||||
assert!(!status.satisfies_commitment(CommitmentConfig::single_gossip()));
|
||||
assert!(status.satisfies_commitment(CommitmentConfig::recent()));
|
||||
|
||||
let status = TransactionStatus {
|
||||
slot: 0,
|
||||
confirmations: Some(0),
|
||||
status: Ok(()),
|
||||
err: None,
|
||||
confirmation_status: None,
|
||||
};
|
||||
|
||||
assert!(!status.satisfies_commitment(CommitmentConfig::default()));
|
||||
assert!(!status.satisfies_commitment(CommitmentConfig::root()));
|
||||
assert!(!status.satisfies_commitment(CommitmentConfig::single()));
|
||||
assert!(!status.satisfies_commitment(CommitmentConfig::single_gossip()));
|
||||
assert!(status.satisfies_commitment(CommitmentConfig::recent()));
|
||||
|
||||
// Test single_gossip fallback cases
|
||||
let status = TransactionStatus {
|
||||
slot: 0,
|
||||
confirmations: Some(1),
|
||||
status: Ok(()),
|
||||
err: None,
|
||||
confirmation_status: None,
|
||||
};
|
||||
assert!(!status.satisfies_commitment(CommitmentConfig::single_gossip()));
|
||||
|
||||
let status = TransactionStatus {
|
||||
slot: 0,
|
||||
confirmations: Some(2),
|
||||
status: Ok(()),
|
||||
err: None,
|
||||
confirmation_status: None,
|
||||
};
|
||||
assert!(status.satisfies_commitment(CommitmentConfig::single_gossip()));
|
||||
|
||||
let status = TransactionStatus {
|
||||
slot: 0,
|
||||
confirmations: None,
|
||||
status: Ok(()),
|
||||
err: None,
|
||||
confirmation_status: None,
|
||||
};
|
||||
assert!(status.satisfies_commitment(CommitmentConfig::single_gossip()));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user