penumbra_sdk_txhash/
transaction_id.rs1use std::str::FromStr;
2
3use penumbra_sdk_proto::{penumbra::core::txhash::v1 as pb, DomainType};
4use serde::{Deserialize, Serialize};
5
6#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default)]
8#[serde(try_from = "pb::TransactionId", into = "pb::TransactionId")]
9pub struct TransactionId(pub [u8; 32]);
10
11impl AsRef<[u8]> for TransactionId {
12 fn as_ref(&self) -> &[u8] {
13 &self.0
14 }
15}
16
17impl std::fmt::Debug for TransactionId {
18 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 write!(f, "{}", hex::encode(self.0))
20 }
21}
22
23impl std::fmt::Display for TransactionId {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 write!(f, "{}", hex::encode(self.0))
26 }
27}
28
29impl FromStr for TransactionId {
30 type Err = anyhow::Error;
31
32 fn from_str(s: &str) -> Result<Self, Self::Err> {
33 let bytes = hex::decode(s)?;
34 if bytes.len() != 32 {
35 anyhow::bail!("invalid transaction ID length");
36 }
37 let mut id = [0u8; 32];
38 id.copy_from_slice(&bytes);
39 Ok(TransactionId(id))
40 }
41}
42
43impl DomainType for TransactionId {
44 type Proto = pb::TransactionId;
45}
46
47impl From<TransactionId> for pb::TransactionId {
48 fn from(id: TransactionId) -> pb::TransactionId {
49 pb::TransactionId {
50 inner: id.0.to_vec(),
51 }
52 }
53}
54
55impl TryFrom<pb::TransactionId> for TransactionId {
56 type Error = anyhow::Error;
57
58 fn try_from(proto: pb::TransactionId) -> anyhow::Result<TransactionId> {
59 let hash = proto.inner;
60 if hash.len() != 32 {
61 anyhow::bail!("invalid transaction ID length");
62 }
63 let mut id = [0u8; 32];
64 id.copy_from_slice(&hash);
65 Ok(TransactionId(id))
66 }
67}