Cli: support json output for transaction-history (#30376)
* Add cli-output structs for transaction-history * Support json output for transaction history * Use pre-existing CliTransactionConfirmation
This commit is contained in:
parent
d984fbb735
commit
a095f5f229
|
@ -758,6 +758,111 @@ impl CliValidator {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CliHistorySignatureVec(Vec<CliHistorySignature>);
|
||||
|
||||
impl CliHistorySignatureVec {
|
||||
pub fn new(list: Vec<CliHistorySignature>) -> Self {
|
||||
Self(list)
|
||||
}
|
||||
}
|
||||
|
||||
impl QuietDisplay for CliHistorySignatureVec {}
|
||||
impl VerboseDisplay for CliHistorySignatureVec {
|
||||
fn write_str(&self, w: &mut dyn std::fmt::Write) -> std::fmt::Result {
|
||||
for signature in &self.0 {
|
||||
VerboseDisplay::write_str(signature, w)?;
|
||||
}
|
||||
writeln!(w, "{} transactions found", self.0.len())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CliHistorySignatureVec {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
for signature in &self.0 {
|
||||
write!(f, "{signature}")?;
|
||||
}
|
||||
writeln!(f, "{} transactions found", self.0.len())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CliHistorySignature {
|
||||
pub signature: String,
|
||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
||||
pub verbose: Option<CliHistoryVerbose>,
|
||||
}
|
||||
|
||||
impl QuietDisplay for CliHistorySignature {}
|
||||
impl VerboseDisplay for CliHistorySignature {
|
||||
fn write_str(&self, w: &mut dyn std::fmt::Write) -> std::fmt::Result {
|
||||
let verbose = self
|
||||
.verbose
|
||||
.as_ref()
|
||||
.expect("should have verbose.is_some()");
|
||||
writeln!(
|
||||
w,
|
||||
"{} [slot={} {}status={}] {}",
|
||||
self.signature,
|
||||
verbose.slot,
|
||||
match verbose.block_time {
|
||||
None => "".to_string(),
|
||||
Some(block_time) => format!("timestamp={} ", unix_timestamp_to_string(block_time)),
|
||||
},
|
||||
if let Some(err) = &verbose.err {
|
||||
format!("Failed: {err:?}")
|
||||
} else {
|
||||
match &verbose.confirmation_status {
|
||||
None => "Finalized".to_string(),
|
||||
Some(status) => format!("{status:?}"),
|
||||
}
|
||||
},
|
||||
verbose.memo.clone().unwrap_or_default(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CliHistorySignature {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln!(f, "{}", self.signature)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CliHistoryVerbose {
|
||||
pub slot: Slot,
|
||||
pub block_time: Option<UnixTimestamp>,
|
||||
pub err: Option<TransactionError>,
|
||||
pub confirmation_status: Option<TransactionConfirmationStatus>,
|
||||
pub memo: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CliHistoryTransactionVec(Vec<CliTransactionConfirmation>);
|
||||
|
||||
impl CliHistoryTransactionVec {
|
||||
pub fn new(list: Vec<CliTransactionConfirmation>) -> Self {
|
||||
Self(list)
|
||||
}
|
||||
}
|
||||
|
||||
impl QuietDisplay for CliHistoryTransactionVec {}
|
||||
impl VerboseDisplay for CliHistoryTransactionVec {}
|
||||
|
||||
impl fmt::Display for CliHistoryTransactionVec {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
for transaction in &self.0 {
|
||||
VerboseDisplay::write_str(transaction, f)?;
|
||||
writeln!(f)?;
|
||||
}
|
||||
writeln!(f, "{} transactions found", self.0.len())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CliNonceAccount {
|
||||
|
|
|
@ -19,7 +19,7 @@ use {
|
|||
cli_version::CliVersion,
|
||||
display::{
|
||||
build_balance_message, format_labeled_address, new_spinner_progress_bar,
|
||||
println_transaction, unix_timestamp_to_string, writeln_name_value,
|
||||
writeln_name_value,
|
||||
},
|
||||
*,
|
||||
},
|
||||
|
@ -61,7 +61,9 @@ use {
|
|||
},
|
||||
transaction::Transaction,
|
||||
},
|
||||
solana_transaction_status::UiTransactionEncoding,
|
||||
solana_transaction_status::{
|
||||
EncodableWithMeta, EncodedConfirmedTransactionWithStatusMeta, UiTransactionEncoding,
|
||||
},
|
||||
solana_vote_program::vote_state::VoteState,
|
||||
std::{
|
||||
collections::{BTreeMap, HashMap, VecDeque},
|
||||
|
@ -2032,35 +2034,35 @@ pub fn process_transaction_history(
|
|||
},
|
||||
)?;
|
||||
|
||||
let transactions_found = format!("{} transactions found", results.len());
|
||||
|
||||
for result in results {
|
||||
if config.verbose {
|
||||
println!(
|
||||
"{} [slot={} {}status={}] {}",
|
||||
result.signature,
|
||||
result.slot,
|
||||
match result.block_time {
|
||||
None => "".to_string(),
|
||||
Some(block_time) =>
|
||||
format!("timestamp={} ", unix_timestamp_to_string(block_time)),
|
||||
},
|
||||
if let Some(err) = result.err {
|
||||
format!("Failed: {err:?}")
|
||||
} else {
|
||||
match result.confirmation_status {
|
||||
None => "Finalized".to_string(),
|
||||
Some(status) => format!("{status:?}"),
|
||||
}
|
||||
},
|
||||
result.memo.unwrap_or_default(),
|
||||
);
|
||||
} else {
|
||||
println!("{}", result.signature);
|
||||
}
|
||||
|
||||
if show_transactions {
|
||||
if !show_transactions {
|
||||
let cli_signatures: Vec<_> = results
|
||||
.into_iter()
|
||||
.map(|result| {
|
||||
let mut signature = CliHistorySignature {
|
||||
signature: result.signature,
|
||||
..CliHistorySignature::default()
|
||||
};
|
||||
if config.verbose {
|
||||
signature.verbose = Some(CliHistoryVerbose {
|
||||
slot: result.slot,
|
||||
block_time: result.block_time,
|
||||
err: result.err,
|
||||
confirmation_status: result.confirmation_status,
|
||||
memo: result.memo,
|
||||
});
|
||||
}
|
||||
signature
|
||||
})
|
||||
.collect();
|
||||
Ok(config
|
||||
.output_format
|
||||
.formatted_string(&CliHistorySignatureVec::new(cli_signatures)))
|
||||
} else {
|
||||
let mut cli_transactions = vec![];
|
||||
for result in results {
|
||||
if let Ok(signature) = result.signature.parse::<Signature>() {
|
||||
let mut transaction = None;
|
||||
let mut get_transaction_error = None;
|
||||
match rpc_client.get_transaction_with_config(
|
||||
&signature,
|
||||
RpcTransactionConfig {
|
||||
|
@ -2070,25 +2072,42 @@ pub fn process_transaction_history(
|
|||
},
|
||||
) {
|
||||
Ok(confirmed_transaction) => {
|
||||
println_transaction(
|
||||
&confirmed_transaction
|
||||
.transaction
|
||||
.transaction
|
||||
.decode()
|
||||
.expect("Successful decode"),
|
||||
confirmed_transaction.transaction.meta.as_ref(),
|
||||
" ",
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let EncodedConfirmedTransactionWithStatusMeta {
|
||||
block_time,
|
||||
slot,
|
||||
transaction: transaction_with_meta,
|
||||
} = confirmed_transaction;
|
||||
|
||||
let decoded_transaction =
|
||||
transaction_with_meta.transaction.decode().unwrap();
|
||||
let json_transaction = decoded_transaction.json_encode();
|
||||
|
||||
transaction = Some(CliTransaction {
|
||||
transaction: json_transaction,
|
||||
meta: transaction_with_meta.meta,
|
||||
block_time,
|
||||
slot: Some(slot),
|
||||
decoded_transaction,
|
||||
prefix: " ".to_string(),
|
||||
sigverify_status: vec![],
|
||||
});
|
||||
}
|
||||
Err(err) => println!(" Unable to get confirmed transaction details: {err}"),
|
||||
}
|
||||
Err(err) => {
|
||||
get_transaction_error = Some(format!("{err:?}"));
|
||||
}
|
||||
};
|
||||
cli_transactions.push(CliTransactionConfirmation {
|
||||
confirmation_status: result.confirmation_status,
|
||||
transaction,
|
||||
get_transaction_error,
|
||||
err: result.err,
|
||||
});
|
||||
}
|
||||
println!();
|
||||
}
|
||||
Ok(config
|
||||
.output_format
|
||||
.formatted_string(&CliHistoryTransactionVec::new(cli_transactions)))
|
||||
}
|
||||
Ok(transactions_found)
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
|
|
Loading…
Reference in New Issue