eq_sdk/
types.rs

1use std::{error::Error, fmt::Display, str::FromStr};
2
3use base64::Engine;
4use celestia_types::{blob::Commitment, block::Height as BlockHeight, nmt::Namespace};
5use serde::{Deserialize, Serialize};
6
7#[derive(Serialize, Deserialize, Clone)]
8pub struct BlobId {
9    pub height: BlockHeight,
10    pub namespace: Namespace,
11    pub commitment: Commitment,
12}
13
14impl BlobId {
15    pub fn new(height: BlockHeight, namespace: Namespace, commitment: Commitment) -> Self {
16        Self {
17            height,
18            namespace,
19            commitment,
20        }
21    }
22}
23
24impl std::fmt::Debug for BlobId {
25    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26        let namespace_string;
27        if let Some(namespace) = &self.namespace.id_v0() {
28            namespace_string = base64::engine::general_purpose::STANDARD.encode(namespace);
29        } else {
30            namespace_string = "Invalid v0 ID".to_string()
31        }
32        let commitment_string =
33            base64::engine::general_purpose::STANDARD.encode(&self.commitment.hash());
34        f.debug_struct("Job")
35            .field("height", &self.height.value())
36            .field("namespace", &namespace_string)
37            .field("commitment", &commitment_string)
38            .finish()
39    }
40}
41
42/// Format = "height:namespace:commitment" using u64 for height, and base64 encoding for namespace and commitment
43impl Display for BlobId {
44    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45        let namespace_string;
46        if let Some(namespace) = &self.namespace.id_v0() {
47            namespace_string = base64::engine::general_purpose::STANDARD.encode(namespace);
48        } else {
49            namespace_string = "Invalid v0 ID".to_string()
50        }
51        let commitment_string =
52            base64::engine::general_purpose::STANDARD.encode(&self.commitment.hash());
53        write!(
54            f,
55            "{}:{}:{}",
56            self.height.value(),
57            &namespace_string,
58            &commitment_string
59        )
60    }
61}
62
63/// Format = "height:namespace:commitment" using u64 for height, and base64 encoding for namespace and commitment
64impl FromStr for BlobId {
65    type Err = Box<dyn Error>;
66
67    fn from_str(s: &str) -> Result<Self, Self::Err> {
68        let mut parts = s.splitn(3, ":");
69
70        let height = BlockHeight::from_str(parts.next().ok_or("Height missing (u64)")?)?;
71
72        let n_base64 = parts
73            .next()
74            .ok_or("Namespace missing (base64)")?
75            .to_string();
76        let n_bytes = base64::engine::general_purpose::STANDARD.decode(n_base64)?;
77        let namespace = Namespace::new_v0(&n_bytes)?;
78
79        let c_base64 = parts
80            .next()
81            .ok_or("Commitment missing (base64)")?
82            .to_string();
83        let c_bytes = base64::engine::general_purpose::STANDARD.decode(c_base64)?;
84        let c_hash: [u8; 32] = c_bytes
85            .try_into()
86            .map_err(|_| "Commitment must be 32 bytes!")?;
87        let commitment = Commitment::new(c_hash.into());
88
89        Ok(Self {
90            height,
91            namespace,
92            commitment,
93        })
94    }
95}