ccxt_core/base_exchange/
config.rs

1//! Exchange configuration structures and builders
2
3use crate::config::{ProxyConfig, RetryPolicy};
4use crate::credentials::SecretString;
5use serde_json::Value;
6use std::collections::HashMap;
7use std::time::Duration;
8
9/// Exchange configuration
10#[derive(Debug, Clone)]
11pub struct ExchangeConfig {
12    /// Exchange identifier
13    pub id: String,
14    /// Exchange display name
15    pub name: String,
16    /// API key for authentication (automatically zeroed on drop)
17    pub api_key: Option<SecretString>,
18    /// API secret for authentication (automatically zeroed on drop)
19    pub secret: Option<SecretString>,
20    /// Password (required by some exchanges, automatically zeroed on drop)
21    pub password: Option<SecretString>,
22    /// User ID (required by some exchanges)
23    pub uid: Option<String>,
24    /// Account ID
25    pub account_id: Option<String>,
26    /// Enable rate limiting
27    pub enable_rate_limit: bool,
28    /// Rate limit in requests per second
29    pub rate_limit: u32,
30    /// Request timeout (default: 30 seconds)
31    pub timeout: Duration,
32    /// TCP connection timeout (default: 10 seconds)
33    pub connect_timeout: Duration,
34    /// Retry policy
35    pub retry_policy: Option<RetryPolicy>,
36    /// Enable sandbox/testnet mode
37    pub sandbox: bool,
38    /// Custom user agent string
39    pub user_agent: Option<String>,
40    /// HTTP proxy configuration
41    pub proxy: Option<ProxyConfig>,
42    /// Enable verbose logging
43    pub verbose: bool,
44    /// Custom exchange-specific options
45    pub options: HashMap<String, Value>,
46    /// URL overrides for mocking/testing
47    pub url_overrides: HashMap<String, String>,
48}
49
50impl Default for ExchangeConfig {
51    fn default() -> Self {
52        Self {
53            id: String::new(),
54            name: String::new(),
55            api_key: None,
56            secret: None,
57            password: None,
58            uid: None,
59            account_id: None,
60            enable_rate_limit: true,
61            rate_limit: 10,
62            timeout: Duration::from_secs(30),
63            connect_timeout: Duration::from_secs(10),
64            retry_policy: None,
65            sandbox: false,
66            user_agent: Some(format!("ccxt-rust/{}", env!("CARGO_PKG_VERSION"))),
67            proxy: None,
68            verbose: false,
69            options: HashMap::new(),
70            url_overrides: HashMap::new(),
71        }
72    }
73}
74
75impl ExchangeConfig {
76    /// Create a new configuration builder
77    ///
78    /// # Example
79    ///
80    /// ```rust
81    /// use ccxt_core::base_exchange::ExchangeConfig;
82    ///
83    /// let config = ExchangeConfig::builder()
84    ///     .id("binance")
85    ///     .name("Binance")
86    ///     .api_key("your-api-key")
87    ///     .secret("your-secret")
88    ///     .sandbox(true)
89    ///     .build();
90    /// ```
91    pub fn builder() -> ExchangeConfigBuilder {
92        ExchangeConfigBuilder::default()
93    }
94}
95
96/// Builder for `ExchangeConfig`
97///
98/// Provides a fluent API for constructing exchange configurations.
99///
100/// # Example
101///
102/// ```rust
103/// use ccxt_core::base_exchange::ExchangeConfigBuilder;
104/// use std::time::Duration;
105///
106/// let config = ExchangeConfigBuilder::new()
107///     .id("binance")
108///     .name("Binance")
109///     .api_key("your-api-key")
110///     .secret("your-secret")
111///     .timeout(Duration::from_secs(60))
112///     .build();
113/// ```
114#[derive(Debug, Clone, Default)]
115pub struct ExchangeConfigBuilder {
116    config: ExchangeConfig,
117}
118
119impl ExchangeConfigBuilder {
120    /// Create a new builder with default configuration
121    pub fn new() -> Self {
122        Self::default()
123    }
124
125    /// Set the exchange identifier
126    pub fn id(mut self, id: impl Into<String>) -> Self {
127        self.config.id = id.into();
128        self
129    }
130
131    /// Set the exchange display name
132    pub fn name(mut self, name: impl Into<String>) -> Self {
133        self.config.name = name.into();
134        self
135    }
136
137    /// Set the API key for authentication
138    pub fn api_key(mut self, key: impl Into<String>) -> Self {
139        self.config.api_key = Some(SecretString::new(key));
140        self
141    }
142
143    /// Set the API secret for authentication
144    pub fn secret(mut self, secret: impl Into<String>) -> Self {
145        self.config.secret = Some(SecretString::new(secret));
146        self
147    }
148
149    /// Set the password (required by some exchanges)
150    pub fn password(mut self, password: impl Into<String>) -> Self {
151        self.config.password = Some(SecretString::new(password));
152        self
153    }
154
155    /// Set the user ID (required by some exchanges)
156    pub fn uid(mut self, uid: impl Into<String>) -> Self {
157        self.config.uid = Some(uid.into());
158        self
159    }
160
161    /// Set the account ID
162    pub fn account_id(mut self, account_id: impl Into<String>) -> Self {
163        self.config.account_id = Some(account_id.into());
164        self
165    }
166
167    /// Enable or disable rate limiting
168    pub fn enable_rate_limit(mut self, enabled: bool) -> Self {
169        self.config.enable_rate_limit = enabled;
170        self
171    }
172
173    /// Set the rate limit in requests per second
174    pub fn rate_limit(mut self, rate_limit: u32) -> Self {
175        self.config.rate_limit = rate_limit;
176        self
177    }
178
179    /// Set the request timeout
180    pub fn timeout(mut self, timeout: Duration) -> Self {
181        self.config.timeout = timeout;
182        self
183    }
184
185    /// Set the TCP connection timeout
186    pub fn connect_timeout(mut self, timeout: Duration) -> Self {
187        self.config.connect_timeout = timeout;
188        self
189    }
190
191    /// Set the TCP connection timeout in seconds (convenience method)
192    pub fn connect_timeout_secs(mut self, seconds: u64) -> Self {
193        self.config.connect_timeout = Duration::from_secs(seconds);
194        self
195    }
196
197    /// Set the retry policy
198    pub fn retry_policy(mut self, policy: RetryPolicy) -> Self {
199        self.config.retry_policy = Some(policy);
200        self
201    }
202
203    /// Enable or disable sandbox/testnet mode
204    pub fn sandbox(mut self, enabled: bool) -> Self {
205        self.config.sandbox = enabled;
206        self
207    }
208
209    /// Set a custom user agent string
210    pub fn user_agent(mut self, user_agent: impl Into<String>) -> Self {
211        self.config.user_agent = Some(user_agent.into());
212        self
213    }
214
215    /// Set the HTTP proxy configuration
216    pub fn proxy(mut self, proxy: ProxyConfig) -> Self {
217        self.config.proxy = Some(proxy);
218        self
219    }
220
221    /// Set the HTTP proxy URL (convenience method)
222    pub fn proxy_url(mut self, url: impl Into<String>) -> Self {
223        self.config.proxy = Some(ProxyConfig::new(url));
224        self
225    }
226
227    /// Enable or disable verbose logging
228    pub fn verbose(mut self, enabled: bool) -> Self {
229        self.config.verbose = enabled;
230        self
231    }
232
233    /// Set a custom option
234    pub fn option(mut self, key: impl Into<String>, value: Value) -> Self {
235        self.config.options.insert(key.into(), value);
236        self
237    }
238
239    /// Set multiple custom options
240    pub fn options(mut self, options: HashMap<String, Value>) -> Self {
241        self.config.options.extend(options);
242        self
243    }
244
245    /// Set a URL override for a specific key (e.g., "public", "private")
246    pub fn url_override(mut self, key: impl Into<String>, url: impl Into<String>) -> Self {
247        self.config.url_overrides.insert(key.into(), url.into());
248        self
249    }
250
251    /// Build the configuration
252    pub fn build(self) -> ExchangeConfig {
253        self.config
254    }
255}