Skip to main content

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}