Skip to main content

onemoney_protocol/api/
checkpoints.rs

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