binance_sdk/common/
config.rs

1use derive_builder::Builder;
2use reqwest::{Client, ClientBuilder};
3use std::fmt;
4use std::sync::Arc;
5use tokio_tungstenite::Connector;
6
7use super::models::{ConfigBuildError, TimeUnit, WebsocketMode};
8use super::utils::{SignatureGenerator, build_client};
9
10#[derive(Clone)]
11pub struct AgentConnector(pub Connector);
12
13impl fmt::Debug for AgentConnector {
14    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15        write!(f, "Connector(…)")
16    }
17}
18
19#[derive(Clone)]
20pub struct HttpAgent(pub Arc<dyn Fn(ClientBuilder) -> ClientBuilder + Send + Sync>);
21
22impl fmt::Debug for HttpAgent {
23    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24        write!(f, "HttpAgent(<custom agent fn>)")
25    }
26}
27
28#[derive(Debug, Clone)]
29pub struct ProxyAuth {
30    pub username: String,
31    pub password: String,
32}
33
34#[derive(Debug, Clone)]
35pub struct ProxyConfig {
36    pub host: String,
37    pub port: u16,
38    pub protocol: Option<String>,
39    pub auth: Option<ProxyAuth>,
40}
41
42#[derive(Debug, Clone)]
43pub enum PrivateKey {
44    File(String),
45    Raw(Vec<u8>),
46}
47
48#[derive(Debug, Clone, Builder)]
49#[builder(
50    pattern = "owned",
51    build_fn(name = "try_build", error = "ConfigBuildError")
52)]
53pub struct ConfigurationRestApi {
54    #[builder(setter(into, strip_option), default)]
55    pub api_key: Option<String>,
56
57    #[builder(setter(into, strip_option), default)]
58    pub api_secret: Option<String>,
59
60    #[builder(setter(into, strip_option), default)]
61    pub base_path: Option<String>,
62
63    #[builder(default = "1000")]
64    pub timeout: u64,
65
66    #[builder(default = "true")]
67    pub keep_alive: bool,
68
69    #[builder(default = "true")]
70    pub compression: bool,
71
72    #[builder(default = "3")]
73    pub retries: u32,
74
75    #[builder(default = "1000")]
76    pub backoff: u64,
77
78    #[builder(setter(strip_option), default)]
79    pub proxy: Option<ProxyConfig>,
80
81    #[builder(setter(strip_option), default)]
82    pub agent: Option<HttpAgent>,
83
84    #[builder(setter(strip_option), default)]
85    pub private_key: Option<PrivateKey>,
86
87    #[builder(setter(strip_option), default)]
88    pub private_key_passphrase: Option<String>,
89
90    #[builder(setter(strip_option), default)]
91    pub time_unit: Option<TimeUnit>,
92
93    #[builder(setter(skip))]
94    pub(crate) client: Client,
95
96    #[builder(setter(skip))]
97    pub(crate) user_agent: String,
98
99    #[builder(setter(skip))]
100    pub(crate) signature_gen: SignatureGenerator,
101}
102
103impl ConfigurationRestApi {
104    #[must_use]
105    pub fn builder() -> ConfigurationRestApiBuilder {
106        ConfigurationRestApiBuilder::default()
107    }
108}
109
110impl ConfigurationRestApiBuilder {
111    /// Builds a `ConfigurationRestApi` instance with configured HTTP client and signature generator.
112    ///
113    /// # Returns
114    ///
115    /// A `Result` containing the fully configured `ConfigurationRestApi` or a `ConfigBuildError` if configuration fails.
116    ///
117    /// # Errors
118    ///
119    /// Returns a `ConfigBuildError` if the initial configuration build fails or if client setup encounters issues.
120    pub fn build(self) -> Result<ConfigurationRestApi, ConfigBuildError> {
121        let mut cfg = self.try_build()?;
122        cfg.client = build_client(
123            cfg.timeout,
124            cfg.keep_alive,
125            cfg.proxy.as_ref(),
126            cfg.agent.clone(),
127        );
128        cfg.signature_gen = SignatureGenerator::new(
129            cfg.api_secret.clone(),
130            cfg.private_key.clone(),
131            cfg.private_key_passphrase.clone(),
132        );
133
134        Ok(cfg)
135    }
136}
137
138#[derive(Debug, Clone, Builder)]
139#[builder(
140    pattern = "owned",
141    build_fn(name = "try_build", error = "ConfigBuildError")
142)]
143pub struct ConfigurationWebsocketApi {
144    #[builder(setter(into, strip_option), default)]
145    pub api_key: Option<String>,
146
147    #[builder(setter(into, strip_option), default)]
148    pub api_secret: Option<String>,
149
150    #[builder(setter(into, strip_option), default)]
151    pub ws_url: Option<String>,
152
153    #[builder(default = "5000")]
154    pub timeout: u64,
155
156    #[builder(default = "5000")]
157    pub reconnect_delay: u64,
158
159    #[builder(default = "WebsocketMode::Single")]
160    pub mode: WebsocketMode,
161
162    #[builder(setter(strip_option), default)]
163    pub agent: Option<AgentConnector>,
164
165    #[builder(setter(strip_option), default)]
166    pub private_key: Option<PrivateKey>,
167
168    #[builder(setter(strip_option), default)]
169    pub private_key_passphrase: Option<String>,
170
171    #[builder(setter(strip_option), default)]
172    pub time_unit: Option<TimeUnit>,
173
174    #[builder(setter(skip))]
175    pub(crate) user_agent: String,
176
177    #[builder(setter(skip))]
178    pub(crate) signature_gen: SignatureGenerator,
179}
180
181impl ConfigurationWebsocketApi {
182    /// Creates a builder for `ConfigurationWebsocketApi` with the specified API key.
183    ///
184    /// # Arguments
185    ///
186    /// * `api_key` - The API key to be used for the WebSocket API configuration
187    ///
188    /// # Returns
189    ///
190    /// A `ConfigurationWebsocketApiBuilder` initialized with the provided API key
191    #[must_use]
192    pub fn builder() -> ConfigurationWebsocketApiBuilder {
193        ConfigurationWebsocketApiBuilder::default()
194    }
195}
196
197impl ConfigurationWebsocketApiBuilder {
198    /// Builds the `ConfigurationWebsocketApi` with a generated signature generator.
199    ///
200    /// This method attempts to build the configuration using the builder's settings
201    /// and then initializes the signature generator with the API secret, private key,
202    /// and private key passphrase.
203    ///
204    /// # Returns
205    ///
206    /// A `Result` containing the fully configured `ConfigurationWebsocketApi` or a
207    /// `ConfigBuildError` if the build process fails.
208    ///
209    /// # Errors
210    ///
211    /// Returns a `ConfigBuildError` if the initial configuration build fails or if signature generation fails.
212    ///
213    pub fn build(self) -> Result<ConfigurationWebsocketApi, ConfigBuildError> {
214        let mut cfg = self.try_build()?;
215        cfg.signature_gen = SignatureGenerator::new(
216            cfg.api_secret.clone(),
217            cfg.private_key.clone(),
218            cfg.private_key_passphrase.clone(),
219        );
220
221        Ok(cfg)
222    }
223}
224
225#[derive(Debug, Clone, Builder)]
226#[builder(pattern = "owned", build_fn(error = "ConfigBuildError"))]
227pub struct ConfigurationWebsocketStreams {
228    #[builder(setter(into, strip_option), default)]
229    pub ws_url: Option<String>,
230
231    #[builder(default = "5000")]
232    pub reconnect_delay: u64,
233
234    #[builder(default = "WebsocketMode::Single")]
235    pub mode: WebsocketMode,
236
237    #[builder(setter(strip_option), default)]
238    pub agent: Option<AgentConnector>,
239
240    #[builder(setter(strip_option), default)]
241    pub time_unit: Option<TimeUnit>,
242
243    #[builder(setter(skip))]
244    pub(crate) user_agent: String,
245}
246
247impl ConfigurationWebsocketStreams {
248    #[must_use]
249    /// Creates a builder for `ConfigurationWebsocketStreams` with default settings.
250    ///
251    /// # Returns
252    ///
253    /// A `ConfigurationWebsocketStreamsBuilder` initialized with default values
254    pub fn builder() -> ConfigurationWebsocketStreamsBuilder {
255        ConfigurationWebsocketStreamsBuilder::default()
256    }
257}