onemoney_protocol/api/chains.rs
1//! Chain-related API operations.
2
3use om_primitives_types::core::types::ChainId;
4use om_rest_types::responses::ChainIdResponse;
5
6use crate::{
7 client::{
8 Client,
9 config::{api_path, endpoints::chains::CHAIN_ID},
10 },
11 error::Result,
12};
13
14impl Client {
15 /// Get the predefined chain ID for this network.
16 ///
17 /// This method returns the predefined chain ID for the client's network
18 /// configuration without making any network requests. This is fast and
19 /// always available.
20 ///
21 /// # Returns
22 ///
23 /// The predefined chain ID for this network or None for custom chains.
24 ///
25 /// # Example
26 ///
27 /// ```rust
28 /// use onemoney_protocol::{Client, NamedChain};
29 ///
30 /// let client = Client::mainnet().unwrap();
31 /// let chain_id = client.chain_id();
32 /// assert_eq!(chain_id, NamedChain::MAINNET_CHAIN_ID);
33 /// ```
34 pub const fn chain_id(&self) -> Option<ChainId> {
35 self.network.chain_id()
36 }
37
38 /// Fetch the current chain ID from the network API.
39 ///
40 /// This method makes an HTTP request to fetch the chain ID from the
41 /// network. Use this to verify that the network is responding correctly
42 /// and matches the expected chain ID.
43 ///
44 /// # Returns
45 ///
46 /// The chain ID from the API response.
47 ///
48 /// # Example
49 ///
50 /// ```rust,no_run
51 /// use onemoney_protocol::Client;
52 ///
53 /// #[tokio::main]
54 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
55 /// let client = Client::mainnet()?;
56 ///
57 /// let api_chain_id = client.fetch_chain_id_from_network().await?;
58 /// let expected_chain_id = client.predefined_chain_id();
59 ///
60 /// assert_eq!(api_chain_id, expected_chain_id);
61 /// println!("Network chain ID matches expected: {}", api_chain_id);
62 ///
63 /// Ok(())
64 /// }
65 /// ```
66 pub async fn fetch_chain_id_from_network(&self) -> Result<u64> {
67 let response: ChainIdResponse = self.get(&api_path(CHAIN_ID)).await?;
68 Ok(response.chain_id)
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use om_primitives_types::core::chain::{ChainSpec, NamedChain};
75
76 use super::*;
77 use crate::client::Client;
78
79 #[test]
80 fn test_chain_id_response_structure() {
81 // Test that ChainIdResponse can be serialized/deserialized
82 let chain_id_response = ChainIdResponse {
83 chain_id: NamedChain::TESTNET_CHAIN_ID,
84 };
85
86 let json = serde_json::to_string(&chain_id_response).expect("Test data should be valid");
87 let deserialized: ChainIdResponse = serde_json::from_str(&json).expect("Test data should be valid");
88
89 assert_eq!(chain_id_response.chain_id, deserialized.chain_id);
90 }
91
92 #[test]
93 fn test_get_chain_id() {
94 // Test method for different client types
95 let mainnet_client = Client::mainnet().expect("Should create mainnet client");
96 let testnet_client = Client::testnet().expect("Should create testnet client");
97 let local_client = Client::local().expect("Should create local client");
98
99 assert_eq!(mainnet_client.chain_id(), Some(ChainSpec::MAINNET.chain_id()));
100 assert_eq!(testnet_client.chain_id(), Some(ChainSpec::TESTNET.chain_id()));
101 assert_eq!(local_client.chain_id(), Some(ChainSpec::TESTNET.chain_id()));
102 }
103}