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()
}
})
}}
}
}