use std::str::FromStr as _; use indexer_service_protocol::{ HashType, PrivacyPreservingMessage, PrivacyPreservingTransaction, ProgramDeploymentMessage, ProgramDeploymentTransaction, PublicMessage, PublicTransaction, Transaction, WitnessSet, }; use itertools::{EitherOrBoth, Itertools as _}; use leptos::prelude::*; use leptos_router::{components::A, hooks::use_params_map}; use crate::api; /// Transaction page component #[component] pub fn TransactionPage() -> impl IntoView { let params = use_params_map(); let transaction_resource = Resource::new( move || { let s = params.read().get("hash")?; HashType::from_str(&s).ok() }, |hash_opt| async move { match hash_opt { Some(hash) => api::get_transaction(hash).await, None => Err(leptos::prelude::ServerFnError::ServerError( "Invalid transaction hash".to_owned(), )), } }, ); view! {
"Loading transaction..."
}> {move || { transaction_resource .get() .map(|result| match result { Ok(tx) => { let tx_hash = tx.hash().to_string(); let tx_type = match &tx { Transaction::Public(_) => "Public Transaction", Transaction::PrivacyPreserving(_) => "Privacy-Preserving Transaction", Transaction::ProgramDeployment(_) => "Program Deployment Transaction", }; view! {

"Transaction Information"

"Hash:" {tx_hash}
"Type:" {tx_type}
{ match tx { Transaction::Public(ptx) => { let PublicTransaction { hash: _, message, witness_set, } = ptx; let PublicMessage { program_id, account_ids, nonces, instruction_data, } = message; let WitnessSet { signatures_and_public_keys, proof, } = witness_set; let program_id_str = program_id.to_string(); let proof_len = proof.map_or(0, |p| p.0.len()); let signatures_count = signatures_and_public_keys.len(); view! {

"Public Transaction Details"

"Program ID:" {program_id_str}
"Instruction Data:" {format!("{} u32 values", instruction_data.len())}
"Proof Size:" {format!("{proof_len} bytes")}
"Signatures:" {signatures_count.to_string()}

"Accounts"

{account_ids .into_iter() .zip_longest(nonces.into_iter()) .map(|maybe_pair| { match maybe_pair { EitherOrBoth::Both(account_id, nonce) => { let account_id_str = account_id.to_string(); view! { } } EitherOrBoth::Left(account_id) => { let account_id_str = account_id.to_string(); view! { } } EitherOrBoth::Right(_) => { view! { } } } }) .collect::>()}
} .into_any() } Transaction::PrivacyPreserving(pptx) => { let PrivacyPreservingTransaction { hash: _, message, witness_set, } = pptx; let PrivacyPreservingMessage { public_account_ids, nonces, public_post_states: _, encrypted_private_post_states, new_commitments, new_nullifiers, block_validity_window, timestamp_validity_window, } = message; let WitnessSet { signatures_and_public_keys: _, proof, } = witness_set; let proof_len = proof.map_or(0, |p| p.0.len()); view! {

"Privacy-Preserving Transaction Details"

"Public Accounts:" {public_account_ids.len().to_string()}
"New Commitments:" {new_commitments.len().to_string()}
"Nullifiers:" {new_nullifiers.len().to_string()}
"Encrypted States:" {encrypted_private_post_states.len().to_string()}
"Proof Size:" {format!("{proof_len} bytes")}
"Block Validity Window:" {block_validity_window.to_string()}
"Timestamp Validity Window:" {timestamp_validity_window.to_string()}

"Public Accounts"

{public_account_ids .into_iter() .zip_longest(nonces.into_iter()) .map(|maybe_pair| { match maybe_pair { EitherOrBoth::Both(account_id, nonce) => { let account_id_str = account_id.to_string(); view! { } } EitherOrBoth::Left(account_id) => { let account_id_str = account_id.to_string(); view! { } } EitherOrBoth::Right(_) => { view! { } } } }) .collect::>()}
} .into_any() } Transaction::ProgramDeployment(pdtx) => { let ProgramDeploymentTransaction { hash: _, message, } = pdtx; let ProgramDeploymentMessage { bytecode } = message; let bytecode_len = bytecode.len(); view! {

"Program Deployment Transaction Details"

"Bytecode Size:" {format!("{bytecode_len} bytes")}
} .into_any() } }}
} .into_any() } Err(e) => { view! {

"Error"

{format!("Failed to load transaction: {e}")}

} .into_any() } }) }} } }