1use anyhow::{Context, Result};
2use penumbra_sdk_proto::{util::tendermint_proxy::v1::GetTxRequest, DomainType};
3use penumbra_sdk_transaction::Transaction;
4use penumbra_sdk_view::{TransactionInfo, ViewClient};
5
6use crate::App;
7
8#[derive(Debug, clap::Args)]
10pub struct TxCmd {
11 hash: String,
13 #[clap(long)]
15 raw: bool,
16}
17
18impl TxCmd {
19 pub fn offline(&self) -> bool {
20 false
21 }
22 pub async fn exec(&self, app: &mut App) -> Result<()> {
23 let hash = self
24 .hash
25 .to_uppercase()
27 .parse()
28 .context("invalid transaction hash")?;
29
30 let tx_info = if let Ok(tx_info) = app.view().transaction_info_by_hash(hash).await {
32 tx_info
33 } else {
34 if !self.raw {
35 println!("Transaction not found in view service, fetching from fullnode...");
36 } else {
37 tracing::info!("Transaction not found in view service, fetching from fullnode...");
38 }
39 let mut client = app.tendermint_proxy_client().await?;
41 let rsp = client
42 .get_tx(GetTxRequest {
43 hash: hex::decode(self.hash.clone())?,
44 prove: false,
45 })
46 .await?;
47
48 let rsp = rsp.into_inner();
49 let tx = Transaction::decode(rsp.tx.as_slice())?;
50 let txp = Default::default();
51 let txv = tx.view_from_perspective(&txp);
52 let summary = txv.summary();
53
54 TransactionInfo {
55 height: rsp.height,
56 id: hash,
57 transaction: tx,
58 perspective: txp,
59 view: txv,
60 summary: summary,
61 }
62 };
63
64 if self.raw {
65 use colored_json::prelude::*;
66 println!(
67 "{}",
68 serde_json::to_string_pretty(&tx_info.view)?.to_colored_json_auto()?
69 );
70 } else {
71 use crate::transaction_view_ext::TransactionViewExt;
72 tx_info.view.render_terminal();
73 }
74
75 Ok(())
76 }
77}