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}