onemoney_protocol/api/
checkpoints.rs

1//! Checkpoint-related API operations.
2
3use crate::client::Client;
4use crate::client::config::api_path;
5use crate::client::config::endpoints::checkpoints::{BY_HASH, BY_NUMBER, NUMBER};
6use crate::{Checkpoint, CheckpointNumber, Result};
7
8impl Client {
9    /// Get a specific checkpoint by number.
10    ///
11    /// # Arguments
12    ///
13    /// * `number` - The checkpoint number
14    /// * `full` - Whether to include full transaction details
15    ///
16    /// # Returns
17    ///
18    /// The checkpoint information.
19    ///
20    /// # Example
21    ///
22    /// ```rust,no_run
23    /// use onemoney_protocol::Client;
24    ///
25    /// #[tokio::main]
26    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
27    ///     let client = Client::mainnet()?;
28    ///
29    ///     let checkpoint = client.get_checkpoint_by_number(456, false).await?;
30    ///     println!("Checkpoint number: {}", checkpoint.number);
31    ///
32    ///     Ok(())
33    /// }
34    /// ```
35    pub async fn get_checkpoint_by_number(&self, number: u64, full: bool) -> Result<Checkpoint> {
36        let path = api_path(&format!("{}?number={}&full={}", BY_NUMBER, number, full));
37        self.get(&path).await
38    }
39
40    /// Get a checkpoint by hash.
41    ///
42    /// # Arguments
43    ///
44    /// * `hash` - The checkpoint hash
45    /// * `full` - Whether to include full transaction details
46    ///
47    /// # Returns
48    ///
49    /// The checkpoint information.
50    ///
51    /// # Example
52    ///
53    /// ```rust,no_run
54    /// use onemoney_protocol::Client;
55    ///
56    /// #[tokio::main]
57    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
58    ///     let client = Client::mainnet()?;
59    ///
60    ///     let hash = "0x902006665c369834a0cf52eea2780f934a90b3c86a3918fb57371ac1fbbd7777";
61    ///     let checkpoint = client.get_checkpoint_by_hash(hash, false).await?;
62    ///     println!("Checkpoint number: {}", checkpoint.number);
63    ///
64    ///     Ok(())
65    /// }
66    /// ```
67    pub async fn get_checkpoint_by_hash(&self, hash: &str, full: bool) -> Result<Checkpoint> {
68        let path = api_path(&format!("{}?hash={}&full={}", BY_HASH, hash, full));
69        self.get(&path).await
70    }
71
72    /// Get the latest checkpoint number.
73    ///
74    /// # Returns
75    ///
76    /// The latest checkpoint number.
77    ///
78    /// # Example
79    ///
80    /// ```rust,no_run
81    /// use onemoney_protocol::Client;
82    ///
83    /// #[tokio::main]
84    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
85    ///     let client = Client::mainnet()?;
86    ///
87    ///     let checkpoint_number = client.get_checkpoint_number().await?;
88    ///     println!("Latest checkpoint number: {}", checkpoint_number.number);
89    ///
90    ///     Ok(())
91    /// }
92    /// ```
93    pub async fn get_checkpoint_number(&self) -> Result<CheckpointNumber> {
94        self.get(&api_path(NUMBER)).await
95    }
96}
97
98#[cfg(test)]
99mod tests {
100    use super::*;
101    use crate::CheckpointTransactions;
102    use crate::types::responses::transactions::Hash;
103    use alloy_primitives::B256;
104    use std::str::FromStr;
105
106    #[test]
107    fn test_checkpoint_structure() {
108        // Test that Checkpoint can be serialized/deserialized
109        let checkpoint = Checkpoint {
110            hash: Hash {
111                hash: B256::from_str(
112                    "0x902006665c369834a0cf52eea2780f934a90b3c86a3918fb57371ac1fbbd7777",
113                )
114                .expect("Test data should be valid"),
115            },
116            parent_hash: Hash {
117                hash: B256::from_str(
118                    "0x20e081da293ae3b81e30f864f38f6911663d7f2cf98337fca38db3cf5bbe7a8f",
119                )
120                .expect("Test data should be valid"),
121            },
122            state_root: Hash {
123                hash: B256::from_str(
124                    "0x18b2b9746b15451d1f9bc414f1c12bda8249c63d4a46926e661ae74c69defd9a",
125                )
126                .expect("Test data should be valid"),
127            },
128            transactions_root: Hash {
129                hash: B256::from_str(
130                    "0xa1e7ed47e548fa45c30232a7e7dfaad6495cff595a0ee1458aa470e574f3f6e4",
131                )
132                .expect("Test data should be valid"),
133            },
134            receipts_root: Hash {
135                hash: B256::from_str(
136                    "0x59ff04f73d9f934800687c60fb80e2de6e8233817b46d144aec724b569d80c3b",
137                )
138                .expect("Test data should be valid"),
139            },
140            number: 1500,
141            timestamp: 1739760890,
142            extra_data: String::new(),
143            transactions: CheckpointTransactions::Hashes(vec![]),
144            size: Some(1024),
145        };
146
147        let json = serde_json::to_string(&checkpoint).expect("Test data should be valid");
148        let deserialized: Checkpoint =
149            serde_json::from_str(&json).expect("Test data should be valid");
150
151        assert_eq!(checkpoint.number, deserialized.number);
152        assert_eq!(checkpoint.hash, deserialized.hash);
153        assert_eq!(checkpoint.timestamp, deserialized.timestamp);
154        assert_eq!(checkpoint.size, deserialized.size);
155    }
156
157    #[test]
158    fn test_checkpoint_number() {
159        let checkpoint_number = CheckpointNumber { number: 50 };
160
161        let json = serde_json::to_string(&checkpoint_number).expect("Test data should be valid");
162        let deserialized: CheckpointNumber =
163            serde_json::from_str(&json).expect("Test data should be valid");
164
165        assert_eq!(checkpoint_number.number, deserialized.number);
166    }
167}