electrum_client/
config.rs

1use std::time::Duration;
2
3/// Configuration for an electrum client
4///
5/// Refer to [`Client::from_config`] and [`ClientType::from_config`].
6///
7/// [`Client::from_config`]: crate::Client::from_config
8/// [`ClientType::from_config`]: crate::ClientType::from_config
9#[derive(Debug, Clone)]
10pub struct Config {
11    /// Proxy socks5 configuration, default None
12    socks5: Option<Socks5Config>,
13    /// timeout in seconds, default None (depends on TcpStream default)
14    timeout: Option<Duration>,
15    /// number of retry if any error, default 1
16    retry: u8,
17    /// when ssl, validate the domain, default true
18    validate_domain: bool,
19}
20
21/// Configuration for Socks5
22#[derive(Debug, Clone)]
23pub struct Socks5Config {
24    /// The address of the socks5 service
25    pub addr: String,
26    /// Optional credential for the service
27    pub credentials: Option<Socks5Credential>,
28}
29
30/// Credential for the proxy
31#[derive(Debug, Clone)]
32pub struct Socks5Credential {
33    pub username: String,
34    pub password: String,
35}
36
37/// [Config] Builder
38pub struct ConfigBuilder {
39    config: Config,
40}
41
42impl ConfigBuilder {
43    /// Create a builder with a default config, equivalent to [ConfigBuilder::default()]
44    pub fn new() -> Self {
45        ConfigBuilder {
46            config: Config::default(),
47        }
48    }
49
50    /// Set the socks5 config if Some, it accept an `Option` because it's easier for the caller to use
51    /// in a method chain
52    pub fn socks5(mut self, socks5_config: Option<Socks5Config>) -> Self {
53        self.config.socks5 = socks5_config;
54        self
55    }
56
57    /// Sets the timeout
58    pub fn timeout(mut self, timeout: Option<u8>) -> Self {
59        self.config.timeout = timeout.map(|t| Duration::from_secs(t as u64));
60        self
61    }
62
63    /// Sets the retry attempts number
64    pub fn retry(mut self, retry: u8) -> Self {
65        self.config.retry = retry;
66        self
67    }
68
69    /// Sets if the domain has to be validated
70    pub fn validate_domain(mut self, validate_domain: bool) -> Self {
71        self.config.validate_domain = validate_domain;
72        self
73    }
74
75    /// Return the config and consume the builder
76    pub fn build(self) -> Config {
77        self.config
78    }
79}
80
81impl Default for ConfigBuilder {
82    fn default() -> Self {
83        Self::new()
84    }
85}
86
87impl Socks5Config {
88    /// Socks5Config constructor without credentials
89    pub fn new(addr: impl ToString) -> Self {
90        let addr = addr.to_string().replacen("socks5://", "", 1);
91        Socks5Config {
92            addr,
93            credentials: None,
94        }
95    }
96
97    /// Socks5Config constructor if we have credentials
98    pub fn with_credentials(addr: impl ToString, username: String, password: String) -> Self {
99        let mut config = Socks5Config::new(addr);
100        config.credentials = Some(Socks5Credential { username, password });
101        config
102    }
103}
104
105impl Config {
106    /// Get the configuration for `socks5`
107    ///
108    /// Set this with [`ConfigBuilder::socks5`]
109    pub fn socks5(&self) -> &Option<Socks5Config> {
110        &self.socks5
111    }
112
113    /// Get the configuration for `retry`
114    ///
115    /// Set this with [`ConfigBuilder::retry`]
116    pub fn retry(&self) -> u8 {
117        self.retry
118    }
119
120    /// Get the configuration for `timeout`
121    ///
122    /// Set this with [`ConfigBuilder::timeout`]
123    pub fn timeout(&self) -> Option<Duration> {
124        self.timeout
125    }
126
127    /// Get the configuration for `validate_domain`
128    ///
129    /// Set this with [`ConfigBuilder::validate_domain`]
130    pub fn validate_domain(&self) -> bool {
131        self.validate_domain
132    }
133
134    /// Convenience method for calling [`ConfigBuilder::new`]
135    pub fn builder() -> ConfigBuilder {
136        ConfigBuilder::new()
137    }
138}
139
140impl Default for Config {
141    fn default() -> Self {
142        Config {
143            socks5: None,
144            timeout: None,
145            retry: 1,
146            validate_domain: true,
147        }
148    }
149}