ccxt_exchanges/bitget/
builder.rs1use super::{Bitget, BitgetOptions};
7use ccxt_core::config::{ProxyConfig, RetryPolicy};
8use ccxt_core::types::default_type::{DefaultSubType, DefaultType};
9use ccxt_core::{ExchangeConfig, Result};
10use serde_json::Value;
11use std::collections::HashMap;
12use std::time::Duration;
13
14#[derive(Debug, Clone)]
34pub struct BitgetBuilder {
35 config: ExchangeConfig,
37 options: BitgetOptions,
39}
40
41impl Default for BitgetBuilder {
42 fn default() -> Self {
43 Self::new()
44 }
45}
46
47impl BitgetBuilder {
48 pub fn new() -> Self {
58 Self {
59 config: ExchangeConfig {
60 id: "bitget".to_string(),
61 name: "Bitget".to_string(),
62 ..Default::default()
63 },
64 options: BitgetOptions::default(),
65 }
66 }
67
68 pub fn api_key(mut self, key: impl Into<String>) -> Self {
74 self.config.api_key = Some(ccxt_core::SecretString::new(key));
75 self
76 }
77
78 pub fn secret(mut self, secret: impl Into<String>) -> Self {
84 self.config.secret = Some(ccxt_core::SecretString::new(secret));
85 self
86 }
87
88 pub fn passphrase(mut self, passphrase: impl Into<String>) -> Self {
96 self.config.password = Some(ccxt_core::SecretString::new(passphrase));
97 self
98 }
99
100 pub fn sandbox(mut self, enabled: bool) -> Self {
109 self.config.sandbox = enabled;
110 self.options.testnet = enabled;
111 self
112 }
113
114 pub fn product_type(mut self, product_type: impl Into<String>) -> Self {
125 self.options.product_type = product_type.into();
126 self
127 }
128
129 pub fn default_type(mut self, default_type: impl Into<DefaultType>) -> Self {
155 self.options.default_type = default_type.into();
156 self
157 }
158
159 pub fn default_sub_type(mut self, sub_type: DefaultSubType) -> Self {
184 self.options.default_sub_type = Some(sub_type);
185 self
186 }
187
188 pub fn timeout(mut self, timeout: Duration) -> Self {
190 self.config.timeout = timeout;
191 self
192 }
193
194 pub fn timeout_secs(mut self, seconds: u64) -> Self {
196 self.config.timeout = Duration::from_secs(seconds);
197 self
198 }
199
200 pub fn connect_timeout(mut self, timeout: Duration) -> Self {
206 self.config.connect_timeout = timeout;
207 self
208 }
209
210 pub fn connect_timeout_secs(mut self, seconds: u64) -> Self {
216 self.config.connect_timeout = Duration::from_secs(seconds);
217 self
218 }
219
220 pub fn retry_policy(mut self, policy: RetryPolicy) -> Self {
222 self.config.retry_policy = Some(policy);
223 self
224 }
225
226 pub fn recv_window(mut self, millis: u64) -> Self {
235 self.options.recv_window = millis;
236 self
237 }
238
239 pub fn enable_rate_limit(mut self, enabled: bool) -> Self {
245 self.config.enable_rate_limit = enabled;
246 self
247 }
248
249 pub fn proxy(mut self, proxy: ProxyConfig) -> Self {
251 self.config.proxy = Some(proxy);
252 self
253 }
254
255 pub fn proxy_url(mut self, url: impl Into<String>) -> Self {
257 self.config.proxy = Some(ProxyConfig::new(url));
258 self
259 }
260
261 pub fn verbose(mut self, enabled: bool) -> Self {
267 self.config.verbose = enabled;
268 self
269 }
270
271 pub fn option(mut self, key: impl Into<String>, value: Value) -> Self {
278 self.config.options.insert(key.into(), value);
279 self
280 }
281
282 pub fn options(mut self, options: HashMap<String, Value>) -> Self {
288 self.config.options.extend(options);
289 self
290 }
291
292 #[cfg(test)]
294 pub fn get_config(&self) -> &ExchangeConfig {
295 &self.config
296 }
297
298 #[cfg(test)]
300 pub fn get_options(&self) -> &BitgetOptions {
301 &self.options
302 }
303
304 pub fn build(self) -> Result<Bitget> {
314 Bitget::new_with_options(self.config, self.options)
315 }
316}
317
318#[cfg(test)]
319mod tests {
320 #![allow(clippy::disallowed_methods)]
321 use super::*;
322
323 #[test]
324 fn test_builder_default() {
325 let builder = BitgetBuilder::new();
326 assert_eq!(builder.config.id, "bitget");
327 assert_eq!(builder.config.name, "Bitget");
328 assert!(!builder.config.sandbox);
329 assert_eq!(builder.options.product_type, "spot");
330 }
331
332 #[test]
333 fn test_builder_api_key() {
334 let builder = BitgetBuilder::new().api_key("test-key");
335 assert_eq!(
336 builder.config.api_key.as_ref().map(|s| s.expose_secret()),
337 Some("test-key")
338 );
339 }
340
341 #[test]
342 fn test_builder_secret() {
343 let builder = BitgetBuilder::new().secret("test-secret");
344 assert_eq!(
345 builder.config.secret.as_ref().map(|s| s.expose_secret()),
346 Some("test-secret")
347 );
348 }
349
350 #[test]
351 fn test_builder_passphrase() {
352 let builder = BitgetBuilder::new().passphrase("test-passphrase");
353 assert_eq!(
354 builder.config.password.as_ref().map(|s| s.expose_secret()),
355 Some("test-passphrase")
356 );
357 }
358
359 #[test]
360 fn test_builder_sandbox() {
361 let builder = BitgetBuilder::new().sandbox(true);
362 assert!(builder.config.sandbox);
363 assert!(builder.options.testnet);
364 }
365
366 #[test]
367 fn test_builder_product_type() {
368 let builder = BitgetBuilder::new().product_type("umcbl");
369 assert_eq!(builder.options.product_type, "umcbl");
370 }
371
372 #[test]
373 fn test_builder_default_type() {
374 let builder = BitgetBuilder::new().default_type(DefaultType::Swap);
375 assert_eq!(builder.options.default_type, DefaultType::Swap);
376 }
377
378 #[test]
379 fn test_builder_default_type_from_string() {
380 let builder = BitgetBuilder::new().default_type("futures");
381 assert_eq!(builder.options.default_type, DefaultType::Futures);
382 }
383
384 #[test]
385 fn test_builder_default_sub_type() {
386 let builder = BitgetBuilder::new().default_sub_type(DefaultSubType::Inverse);
387 assert_eq!(
388 builder.options.default_sub_type,
389 Some(DefaultSubType::Inverse)
390 );
391 }
392
393 #[test]
394 fn test_builder_default_type_and_sub_type() {
395 let builder = BitgetBuilder::new()
396 .default_type(DefaultType::Swap)
397 .default_sub_type(DefaultSubType::Linear);
398 assert_eq!(builder.options.default_type, DefaultType::Swap);
399 assert_eq!(
400 builder.options.default_sub_type,
401 Some(DefaultSubType::Linear)
402 );
403 }
404
405 #[test]
406 fn test_builder_timeout() {
407 let builder = BitgetBuilder::new().timeout(Duration::from_secs(60));
408 assert_eq!(builder.config.timeout, Duration::from_secs(60));
409 }
410
411 #[test]
412 fn test_builder_connect_timeout() {
413 let builder = BitgetBuilder::new().connect_timeout(Duration::from_secs(15));
414 assert_eq!(builder.config.connect_timeout, Duration::from_secs(15));
415 }
416
417 #[test]
418 fn test_builder_connect_timeout_secs() {
419 let builder = BitgetBuilder::new().connect_timeout_secs(20);
420 assert_eq!(builder.config.connect_timeout, Duration::from_secs(20));
421 }
422
423 #[test]
424 fn test_builder_recv_window() {
425 let builder = BitgetBuilder::new().recv_window(10000);
426 assert_eq!(builder.options.recv_window, 10000);
427 }
428
429 #[test]
430 fn test_builder_chaining() {
431 let builder = BitgetBuilder::new()
432 .api_key("key")
433 .secret("secret")
434 .passphrase("pass")
435 .sandbox(true)
436 .timeout(Duration::from_secs(30))
437 .recv_window(5000)
438 .product_type("spot")
439 .default_type(DefaultType::Swap)
440 .default_sub_type(DefaultSubType::Linear);
441
442 assert_eq!(
443 builder.config.api_key.as_ref().map(|s| s.expose_secret()),
444 Some("key")
445 );
446 assert_eq!(
447 builder.config.secret.as_ref().map(|s| s.expose_secret()),
448 Some("secret")
449 );
450 assert_eq!(
451 builder.config.password.as_ref().map(|s| s.expose_secret()),
452 Some("pass")
453 );
454 assert!(builder.config.sandbox);
455 assert_eq!(builder.config.timeout, Duration::from_secs(30));
456 assert_eq!(builder.options.recv_window, 5000);
457 assert_eq!(builder.options.product_type, "spot");
458 assert_eq!(builder.options.default_type, DefaultType::Swap);
459 assert_eq!(
460 builder.options.default_sub_type,
461 Some(DefaultSubType::Linear)
462 );
463 }
464
465 #[test]
466 fn test_builder_build() {
467 let result = BitgetBuilder::new().build();
468 assert!(result.is_ok());
469
470 let bitget = result.unwrap();
471 assert_eq!(bitget.id(), "bitget");
472 assert_eq!(bitget.name(), "Bitget");
473 }
474
475 #[test]
476 fn test_builder_build_with_credentials() {
477 let result = BitgetBuilder::new()
478 .api_key("test-key")
479 .secret("test-secret")
480 .passphrase("test-passphrase")
481 .build();
482
483 assert!(result.is_ok());
484 }
485}