1use derive_builder::Builder;
2use reqwest::{Client, ClientBuilder};
3use std::collections::HashMap;
4use std::fmt;
5use std::sync::Arc;
6use tokio_tungstenite::Connector;
7
8use super::models::{ConfigBuildError, TimeUnit, WebsocketMode};
9use super::utils::{SignatureGenerator, build_client};
10
11#[derive(Clone)]
12pub struct AgentConnector(pub Connector);
13
14impl fmt::Debug for AgentConnector {
15 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16 write!(f, "Connector(…)")
17 }
18}
19
20#[derive(Clone)]
21pub struct HttpAgent(pub Arc<dyn Fn(ClientBuilder) -> ClientBuilder + Send + Sync>);
22
23impl fmt::Debug for HttpAgent {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 write!(f, "HttpAgent(<custom agent fn>)")
26 }
27}
28
29#[derive(Clone)]
30pub struct ProxyAuth {
31 pub username: String,
32 pub password: String,
33}
34
35#[derive(Debug, Clone)]
36pub struct ProxyConfig {
37 pub host: String,
38 pub port: u16,
39 pub protocol: Option<String>,
40 pub auth: Option<ProxyAuth>,
41}
42
43impl fmt::Debug for ProxyAuth {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 f.debug_struct("ProxyAuth")
46 .field("username", &self.username)
47 .field("password", &"[REDACTED]")
48 .finish()
49 }
50}
51
52#[derive(Clone)]
53pub enum PrivateKey {
54 File(String),
55 Raw(Vec<u8>),
56}
57
58impl fmt::Debug for PrivateKey {
59 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60 match self {
61 PrivateKey::File(_) => write!(f, "PrivateKey::File([REDACTED])"),
62 PrivateKey::Raw(_) => write!(f, "PrivateKey::Raw([REDACTED])"),
63 }
64 }
65}
66
67#[derive(Clone, Builder)]
68#[builder(
69 pattern = "owned",
70 build_fn(name = "try_build", error = "ConfigBuildError")
71)]
72pub struct ConfigurationRestApi {
73 #[builder(setter(into, strip_option), default)]
74 pub api_key: Option<String>,
75
76 #[builder(setter(into, strip_option), default)]
77 pub api_secret: Option<String>,
78
79 #[builder(setter(into, strip_option), default)]
80 pub base_path: Option<String>,
81
82 #[builder(default = "1000")]
83 pub timeout: u64,
84
85 #[builder(default = "true")]
86 pub keep_alive: bool,
87
88 #[builder(default = "true")]
89 pub compression: bool,
90
91 #[builder(default = "3")]
92 pub retries: u32,
93
94 #[builder(default = "1000")]
95 pub backoff: u64,
96
97 #[builder(setter(strip_option), default)]
98 pub proxy: Option<ProxyConfig>,
99
100 #[builder(setter(strip_option, into), default)]
101 pub custom_headers: Option<HashMap<String, String>>,
102
103 #[builder(setter(strip_option), default)]
104 pub agent: Option<HttpAgent>,
105
106 #[builder(setter(strip_option), default)]
107 pub private_key: Option<PrivateKey>,
108
109 #[builder(setter(strip_option), default)]
110 pub private_key_passphrase: Option<String>,
111
112 #[builder(setter(strip_option), default)]
113 pub time_unit: Option<TimeUnit>,
114
115 #[builder(setter(skip))]
116 pub(crate) client: Client,
117
118 #[builder(setter(skip))]
119 pub(crate) user_agent: String,
120
121 #[builder(setter(skip))]
122 pub(crate) signature_gen: SignatureGenerator,
123}
124
125impl fmt::Debug for ConfigurationRestApi {
126 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127 f.debug_struct("ConfigurationRestApi")
128 .field("api_key", &self.api_key.as_ref().map(|_| "[REDACTED]"))
129 .field(
130 "api_secret",
131 &self.api_secret.as_ref().map(|_| "[REDACTED]"),
132 )
133 .field("base_path", &self.base_path)
134 .field("timeout", &self.timeout)
135 .field("keep_alive", &self.keep_alive)
136 .field("compression", &self.compression)
137 .field("retries", &self.retries)
138 .field("backoff", &self.backoff)
139 .field("proxy", &self.proxy)
140 .field("custom_headers", &self.custom_headers)
141 .field("agent", &self.agent)
142 .field(
143 "private_key",
144 &self.private_key.as_ref().map(|_| "[REDACTED]"),
145 )
146 .field(
147 "private_key_passphrase",
148 &self.private_key_passphrase.as_ref().map(|_| "[REDACTED]"),
149 )
150 .field("time_unit", &self.time_unit)
151 .field("client", &"<reqwest::Client>")
152 .field("user_agent", &self.user_agent)
153 .field("signature_gen", &self.signature_gen)
154 .finish()
155 }
156}
157
158impl ConfigurationRestApi {
159 #[must_use]
160 pub fn builder() -> ConfigurationRestApiBuilder {
161 ConfigurationRestApiBuilder::default()
162 }
163}
164
165impl ConfigurationRestApiBuilder {
166 pub fn build(self) -> Result<ConfigurationRestApi, ConfigBuildError> {
176 let mut cfg = self.try_build()?;
177 cfg.client = build_client(
178 cfg.timeout,
179 cfg.keep_alive,
180 cfg.proxy.as_ref(),
181 cfg.agent.clone(),
182 );
183 cfg.signature_gen = SignatureGenerator::new(
184 cfg.api_secret.clone(),
185 cfg.private_key.clone(),
186 cfg.private_key_passphrase.clone(),
187 );
188
189 Ok(cfg)
190 }
191}
192
193#[derive(Clone, Builder)]
194#[builder(
195 pattern = "owned",
196 build_fn(name = "try_build", error = "ConfigBuildError")
197)]
198pub struct ConfigurationWebsocketApi {
199 #[builder(setter(into, strip_option), default)]
200 pub api_key: Option<String>,
201
202 #[builder(setter(into, strip_option), default)]
203 pub api_secret: Option<String>,
204
205 #[builder(setter(into, strip_option), default)]
206 pub ws_url: Option<String>,
207
208 #[builder(default = "5000")]
209 pub timeout: u64,
210
211 #[builder(default = "5000")]
212 pub reconnect_delay: u64,
213
214 #[builder(default = "WebsocketMode::Single")]
215 pub mode: WebsocketMode,
216
217 #[builder(setter(strip_option), default)]
218 pub agent: Option<AgentConnector>,
219
220 #[builder(setter(strip_option), default)]
221 pub private_key: Option<PrivateKey>,
222
223 #[builder(setter(strip_option), default)]
224 pub private_key_passphrase: Option<String>,
225
226 #[builder(setter(strip_option), default)]
227 pub time_unit: Option<TimeUnit>,
228
229 #[builder(default = "true")]
230 pub auto_session_relogon: bool,
231
232 #[builder(setter(skip))]
233 pub(crate) user_agent: String,
234
235 #[builder(setter(skip))]
236 pub(crate) signature_gen: SignatureGenerator,
237}
238
239impl fmt::Debug for ConfigurationWebsocketApi {
240 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
241 f.debug_struct("ConfigurationWebsocketApi")
242 .field("api_key", &self.api_key.as_ref().map(|_| "[REDACTED]"))
243 .field(
244 "api_secret",
245 &self.api_secret.as_ref().map(|_| "[REDACTED]"),
246 )
247 .field("ws_url", &self.ws_url)
248 .field("timeout", &self.timeout)
249 .field("reconnect_delay", &self.reconnect_delay)
250 .field("mode", &self.mode)
251 .field("agent", &self.agent)
252 .field(
253 "private_key",
254 &self.private_key.as_ref().map(|_| "[REDACTED]"),
255 )
256 .field(
257 "private_key_passphrase",
258 &self.private_key_passphrase.as_ref().map(|_| "[REDACTED]"),
259 )
260 .field("time_unit", &self.time_unit)
261 .field("auto_session_relogon", &self.auto_session_relogon)
262 .field("user_agent", &self.user_agent)
263 .field("signature_gen", &self.signature_gen)
264 .finish()
265 }
266}
267
268impl ConfigurationWebsocketApi {
269 #[must_use]
279 pub fn builder() -> ConfigurationWebsocketApiBuilder {
280 ConfigurationWebsocketApiBuilder::default()
281 }
282}
283
284impl ConfigurationWebsocketApiBuilder {
285 pub fn build(self) -> Result<ConfigurationWebsocketApi, ConfigBuildError> {
301 let mut cfg = self.try_build()?;
302 cfg.signature_gen = SignatureGenerator::new(
303 cfg.api_secret.clone(),
304 cfg.private_key.clone(),
305 cfg.private_key_passphrase.clone(),
306 );
307
308 Ok(cfg)
309 }
310}
311
312#[derive(Debug, Clone, Builder)]
313#[builder(pattern = "owned", build_fn(error = "ConfigBuildError"))]
314pub struct ConfigurationWebsocketStreams {
315 #[builder(setter(into, strip_option), default)]
316 pub ws_url: Option<String>,
317
318 #[builder(default = "5000")]
319 pub reconnect_delay: u64,
320
321 #[builder(default = "WebsocketMode::Single")]
322 pub mode: WebsocketMode,
323
324 #[builder(setter(strip_option), default)]
325 pub agent: Option<AgentConnector>,
326
327 #[builder(setter(strip_option), default)]
328 pub time_unit: Option<TimeUnit>,
329
330 #[builder(setter(skip))]
331 pub(crate) user_agent: String,
332}
333
334impl ConfigurationWebsocketStreams {
335 #[must_use]
336 pub fn builder() -> ConfigurationWebsocketStreamsBuilder {
342 ConfigurationWebsocketStreamsBuilder::default()
343 }
344}