Skip to main content

onemoney_protocol/client/
config.rs

1//! Network configuration and API endpoints.
2
3use std::{borrow::Cow, time::Duration};
4
5use om_primitives_types::core::{chain::NamedChain, types::ChainId};
6
7/// Default mainnet API URL.
8pub const MAINNET_URL: &str = "https://api.mainnet.1money.network";
9
10/// Default testnet API URL.
11pub const TESTNET_URL: &str = "https://api.testnet.1money.network";
12
13/// Default local API URL.
14pub const LOCAL_URL: &str = "http://127.0.0.1:18555";
15
16/// Default request timeout.
17pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(30);
18
19/// API version prefix.
20pub const API_VERSION: &str = "/v1";
21
22/// Build an API path with version prefix.
23pub fn api_path(path: &str) -> String {
24    format!("{}{}", API_VERSION, path)
25}
26
27/// Network environment options.
28#[derive(Debug, Clone, PartialEq, Eq, Default)]
29pub enum Network {
30    /// Mainnet environment.
31    #[default]
32    Mainnet,
33    /// Testnet environment.
34    Testnet,
35    /// Local development environment.
36    Local,
37    /// Custom network environment.
38    Custom(Cow<'static, str>),
39}
40
41impl Network {
42    /// Get the base URL for this network.
43    pub fn url(&self) -> &str {
44        match self {
45            Network::Mainnet => MAINNET_URL,
46            Network::Testnet => TESTNET_URL,
47            Network::Local => LOCAL_URL,
48            Network::Custom(s) => s,
49        }
50    }
51
52    pub const fn chain_id(&self) -> Option<ChainId> {
53        match self {
54            Network::Mainnet => Some(NamedChain::MAINNET_CHAIN_ID),
55            Network::Testnet => Some(NamedChain::TESTNET_CHAIN_ID),
56            Network::Local => Some(NamedChain::TESTNET_CHAIN_ID),
57            Network::Custom(_) => {
58                // Custom network doesn't have a predefined chain ID.
59                // It must be fetched from the remote api instead.
60                None
61            }
62        }
63    }
64
65    /// Check if this is a production network.
66    pub fn is_production(&self) -> bool {
67        matches!(self, Network::Mainnet)
68    }
69
70    /// Check if this is a test network.
71    pub fn is_test(&self) -> bool {
72        !self.is_production()
73    }
74}
75
76/// API endpoint paths.
77pub mod endpoints {
78    /// Account-related endpoints.
79    pub mod accounts {
80        pub const NONCE: &str = "/accounts/nonce";
81        pub const BBNONCE: &str = "/accounts/bbnonce";
82        pub const TOKEN_ACCOUNT: &str = "/accounts/token_account";
83    }
84
85    /// Chain-related endpoints.
86    pub mod chains {
87        pub const CHAIN_ID: &str = "/chains/chain_id";
88    }
89
90    /// Checkpoint-related endpoints.
91    pub mod checkpoints {
92        pub const NUMBER: &str = "/checkpoints/number";
93        pub const BY_NUMBER: &str = "/checkpoints/by_number";
94        pub const BY_HASH: &str = "/checkpoints/by_hash";
95    }
96
97    /// Transaction-related endpoints.
98    pub mod transactions {
99        pub const PAYMENT: &str = "/transactions/payment";
100        pub const RAW: &str = "/transactions/raw";
101        pub const BY_HASH: &str = "/transactions/by_hash";
102        pub const RECEIPT_BY_HASH: &str = "/transactions/receipt/by_hash";
103        pub const ESTIMATE_FEE: &str = "/transactions/estimate_fee";
104
105        pub const FINALIZED_BY_HASH: &str = "/transactions/finalized/by_hash";
106    }
107
108    /// Token-related endpoints.
109    pub mod tokens {
110        pub const MINT: &str = "/tokens/mint";
111        pub const BURN: &str = "/tokens/burn";
112        pub const GRANT_AUTHORITY: &str = "/tokens/grant_authority";
113        pub const UPDATE_METADATA: &str = "/tokens/update_metadata";
114        pub const MANAGE_BLACKLIST: &str = "/tokens/manage_blacklist";
115        pub const MANAGE_WHITELIST: &str = "/tokens/manage_whitelist";
116        pub const PAUSE: &str = "/tokens/pause";
117        pub const TOKEN_METADATA: &str = "/tokens/token_metadata";
118    }
119
120    /// Governance-related endpoints.
121    pub mod governance {
122        pub const CURRENT_EPOCH: &str = "/governances/epoch";
123        pub const EPOCH_BY_ID: &str = "/governances/epoch/by_id";
124    }
125
126    /// Bridge-related endpoints.
127    #[cfg(feature = "bridge")]
128    pub mod bridge {
129        pub const BRIDGE_AND_MINT: &str = "/tokens/bridge_and_mint";
130        pub const BURN_AND_BRIDGE: &str = "/tokens/burn_and_bridge";
131    }
132}
133
134#[cfg(test)]
135mod tests {
136    use om_primitives_types::core::chain::ChainSpec;
137
138    use super::*;
139
140    #[test]
141    fn test_network_urls() {
142        assert_eq!(Network::Mainnet.url(), "https://api.mainnet.1money.network");
143        assert_eq!(Network::Testnet.url(), "https://api.testnet.1money.network");
144        assert_eq!(Network::Local.url(), "http://127.0.0.1:18555");
145    }
146
147    #[test]
148    fn test_network_properties() {
149        assert!(Network::Mainnet.is_production());
150        assert!(!Network::Testnet.is_production());
151        assert!(!Network::Local.is_production());
152
153        assert!(!Network::Mainnet.is_test());
154        assert!(Network::Testnet.is_test());
155        assert!(Network::Local.is_test());
156    }
157
158    #[test]
159    fn test_api_path_construction() {
160        // Test basic API path construction
161        let path = api_path("/test");
162        assert_eq!(path, "/v1/test");
163        assert!(path.contains("/v1/test"));
164
165        // Test with leading slash
166        let path_with_slash = api_path("/accounts/nonce");
167        assert_eq!(path_with_slash, "/v1/accounts/nonce");
168
169        // Test without leading slash
170        let path_without_slash = api_path("chains/chain_id");
171        assert_eq!(path_without_slash, "/v1chains/chain_id");
172    }
173
174    #[test]
175    fn test_endpoint_constants() {
176        // Test account endpoints
177        assert_eq!(endpoints::accounts::NONCE, "/accounts/nonce");
178        assert_eq!(endpoints::accounts::BBNONCE, "/accounts/bbnonce");
179        assert_eq!(endpoints::accounts::TOKEN_ACCOUNT, "/accounts/token_account");
180
181        // Test chain endpoints
182        assert_eq!(endpoints::chains::CHAIN_ID, "/chains/chain_id");
183
184        // Test checkpoint endpoints
185        assert_eq!(endpoints::checkpoints::NUMBER, "/checkpoints/number");
186        assert_eq!(endpoints::checkpoints::BY_NUMBER, "/checkpoints/by_number");
187        assert_eq!(endpoints::checkpoints::BY_HASH, "/checkpoints/by_hash");
188
189        // Test transaction endpoints
190        assert_eq!(endpoints::transactions::PAYMENT, "/transactions/payment");
191        assert_eq!(endpoints::transactions::RAW, "/transactions/raw");
192        assert_eq!(endpoints::transactions::BY_HASH, "/transactions/by_hash");
193        assert_eq!(
194            endpoints::transactions::RECEIPT_BY_HASH,
195            "/transactions/receipt/by_hash"
196        );
197        assert_eq!(endpoints::transactions::ESTIMATE_FEE, "/transactions/estimate_fee");
198
199        // Test token endpoints
200        assert_eq!(endpoints::tokens::MINT, "/tokens/mint");
201        assert_eq!(endpoints::tokens::BURN, "/tokens/burn");
202        assert_eq!(endpoints::tokens::GRANT_AUTHORITY, "/tokens/grant_authority");
203        assert_eq!(endpoints::tokens::UPDATE_METADATA, "/tokens/update_metadata");
204        assert_eq!(endpoints::tokens::MANAGE_BLACKLIST, "/tokens/manage_blacklist");
205        assert_eq!(endpoints::tokens::MANAGE_WHITELIST, "/tokens/manage_whitelist");
206        assert_eq!(endpoints::tokens::PAUSE, "/tokens/pause");
207        assert_eq!(endpoints::tokens::TOKEN_METADATA, "/tokens/token_metadata");
208
209        // Test governance endpoints
210        assert_eq!(endpoints::governance::CURRENT_EPOCH, "/governances/epoch");
211        assert_eq!(endpoints::governance::EPOCH_BY_ID, "/governances/epoch/by_id");
212    }
213
214    #[test]
215    fn test_network_default() {
216        let default_network = Network::default();
217        assert_eq!(default_network, Network::Mainnet);
218    }
219
220    #[test]
221    fn test_network_chain_ids() {
222        assert_eq!(Network::Mainnet.chain_id(), Some(ChainSpec::MAINNET.chain_id()));
223        assert_eq!(Network::Testnet.chain_id(), Some(ChainSpec::TESTNET.chain_id()));
224        assert_eq!(Network::Local.chain_id(), Some(ChainSpec::TESTNET.chain_id()));
225    }
226
227    #[test]
228    fn test_predefined_chain_id_panics_for_custom() {
229        let n = Network::Custom("http://localhost:18555".into());
230        assert_eq!(None, n.chain_id());
231    }
232
233    #[test]
234    fn test_constants() {
235        assert_eq!(API_VERSION, "/v1");
236        assert_eq!(DEFAULT_TIMEOUT, Duration::from_secs(30));
237
238        // Verify URL constants
239        assert!(MAINNET_URL.starts_with("https://"));
240        assert!(TESTNET_URL.starts_with("https://"));
241        assert!(LOCAL_URL.starts_with("http://"));
242    }
243}