Skip to main content

nautilus_deribit/
config.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Configuration structures for the Deribit adapter.
17
18use nautilus_model::identifiers::{AccountId, TraderId};
19use nautilus_network::websocket::TransportBackend;
20
21use crate::{
22    common::{
23        credential::credential_env_vars,
24        enums::DeribitEnvironment,
25        urls::{get_http_base_url, get_ws_url},
26    },
27    http::models::DeribitProductType,
28};
29
30/// Configuration for the Deribit data client.
31#[derive(Clone, Debug, bon::Builder)]
32#[cfg_attr(
33    feature = "python",
34    pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.deribit", from_py_object)
35)]
36#[cfg_attr(
37    feature = "python",
38    pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.deribit")
39)]
40pub struct DeribitDataClientConfig {
41    /// Optional API key for authenticated endpoints.
42    pub api_key: Option<String>,
43    /// Optional API secret for authenticated endpoints.
44    pub api_secret: Option<String>,
45    /// Product types to load (e.g., Future, Option, Spot).
46    #[builder(default = vec![DeribitProductType::Future])]
47    pub product_types: Vec<DeribitProductType>,
48    /// Optional override for the HTTP base URL.
49    pub base_url_http: Option<String>,
50    /// Optional override for the WebSocket URL.
51    pub base_url_ws: Option<String>,
52    /// Optional proxy URL for HTTP and WebSocket transports.
53    pub proxy_url: Option<String>,
54    /// The Deribit environment (mainnet or testnet).
55    #[builder(default)]
56    pub environment: DeribitEnvironment,
57    /// HTTP timeout in seconds.
58    #[builder(default = 60)]
59    pub http_timeout_secs: u64,
60    /// Maximum retry attempts for requests.
61    #[builder(default = 3)]
62    pub max_retries: u32,
63    /// Initial retry delay in milliseconds.
64    #[builder(default = 1_000)]
65    pub retry_delay_initial_ms: u64,
66    /// Maximum retry delay in milliseconds.
67    #[builder(default = 10_000)]
68    pub retry_delay_max_ms: u64,
69    /// Heartbeat interval in seconds for WebSocket connection.
70    #[builder(default = 30)]
71    pub heartbeat_interval_secs: u64,
72    /// Interval for refreshing instruments (in minutes).
73    #[builder(default = 60)]
74    pub update_instruments_interval_mins: u64,
75    /// WebSocket transport backend (defaults to `Tungstenite`).
76    #[builder(default)]
77    pub transport_backend: TransportBackend,
78}
79
80impl Default for DeribitDataClientConfig {
81    fn default() -> Self {
82        Self::builder().build()
83    }
84}
85
86impl DeribitDataClientConfig {
87    /// Creates a new configuration with default settings.
88    #[must_use]
89    pub fn new() -> Self {
90        Self::default()
91    }
92
93    /// Returns `true` when API credentials are available (in config or env vars).
94    #[must_use]
95    pub fn has_api_credentials(&self) -> bool {
96        let (key_env, secret_env) = credential_env_vars(self.environment);
97        let has_key = self.api_key.is_some() || std::env::var(key_env).is_ok();
98        let has_secret = self.api_secret.is_some() || std::env::var(secret_env).is_ok();
99        has_key && has_secret
100    }
101
102    /// Returns the HTTP base URL, falling back to the default when unset.
103    #[must_use]
104    pub fn http_base_url(&self) -> String {
105        self.base_url_http
106            .clone()
107            .unwrap_or_else(|| get_http_base_url(self.environment).to_string())
108    }
109
110    /// Returns the WebSocket URL, respecting the environment and overrides.
111    #[must_use]
112    pub fn ws_url(&self) -> String {
113        self.base_url_ws
114            .clone()
115            .unwrap_or_else(|| get_ws_url(self.environment).to_string())
116    }
117}
118
119/// Configuration for the Deribit execution client.
120#[derive(Clone, Debug, bon::Builder)]
121#[cfg_attr(
122    feature = "python",
123    pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.deribit", from_py_object)
124)]
125#[cfg_attr(
126    feature = "python",
127    pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.deribit")
128)]
129pub struct DeribitExecClientConfig {
130    /// The trader ID for this client.
131    #[builder(default)]
132    pub trader_id: TraderId,
133    /// The account ID for this client.
134    #[builder(default = AccountId::from("DERIBIT-001"))]
135    pub account_id: AccountId,
136    /// Optional API key for authenticated endpoints.
137    pub api_key: Option<String>,
138    /// Optional API secret for authenticated endpoints.
139    pub api_secret: Option<String>,
140    /// Product types to load (e.g., Future, Option, Spot).
141    #[builder(default = vec![DeribitProductType::Future])]
142    pub product_types: Vec<DeribitProductType>,
143    /// Optional override for the HTTP base URL.
144    pub base_url_http: Option<String>,
145    /// Optional override for the WebSocket URL.
146    pub base_url_ws: Option<String>,
147    /// Optional proxy URL for HTTP and WebSocket transports.
148    pub proxy_url: Option<String>,
149    /// The Deribit environment (mainnet or testnet).
150    #[builder(default)]
151    pub environment: DeribitEnvironment,
152    /// HTTP timeout in seconds.
153    #[builder(default = 60)]
154    pub http_timeout_secs: u64,
155    /// Maximum retry attempts for requests.
156    #[builder(default = 3)]
157    pub max_retries: u32,
158    /// Initial retry delay in milliseconds.
159    #[builder(default = 1_000)]
160    pub retry_delay_initial_ms: u64,
161    /// Maximum retry delay in milliseconds.
162    #[builder(default = 10_000)]
163    pub retry_delay_max_ms: u64,
164    /// WebSocket transport backend (defaults to `Tungstenite`).
165    #[builder(default)]
166    pub transport_backend: TransportBackend,
167}
168
169impl Default for DeribitExecClientConfig {
170    fn default() -> Self {
171        Self::builder().build()
172    }
173}
174
175impl DeribitExecClientConfig {
176    /// Returns `true` when API credentials are available (in config or env vars).
177    #[must_use]
178    pub fn has_api_credentials(&self) -> bool {
179        let (key_env, secret_env) = credential_env_vars(self.environment);
180        let has_key = self.api_key.is_some() || std::env::var(key_env).is_ok();
181        let has_secret = self.api_secret.is_some() || std::env::var(secret_env).is_ok();
182        has_key && has_secret
183    }
184
185    /// Returns the HTTP base URL, falling back to the default when unset.
186    #[must_use]
187    pub fn http_base_url(&self) -> String {
188        self.base_url_http
189            .clone()
190            .unwrap_or_else(|| get_http_base_url(self.environment).to_string())
191    }
192
193    /// Returns the WebSocket URL, respecting the environment and overrides.
194    #[must_use]
195    pub fn ws_url(&self) -> String {
196        self.base_url_ws
197            .clone()
198            .unwrap_or_else(|| get_ws_url(self.environment).to_string())
199    }
200}
201
202#[cfg(test)]
203mod tests {
204    use rstest::rstest;
205
206    use super::*;
207
208    #[rstest]
209    fn test_default_config() {
210        let config = DeribitDataClientConfig::default();
211        assert_eq!(config.environment, DeribitEnvironment::Mainnet);
212        assert_eq!(config.product_types.len(), 1);
213        assert_eq!(config.http_timeout_secs, 60);
214    }
215
216    #[rstest]
217    fn test_http_base_url_default() {
218        let config = DeribitDataClientConfig::default();
219        assert_eq!(config.http_base_url(), "https://www.deribit.com");
220    }
221
222    #[rstest]
223    fn test_http_base_url_testnet() {
224        let config = DeribitDataClientConfig {
225            environment: DeribitEnvironment::Testnet,
226            ..Default::default()
227        };
228        assert_eq!(config.http_base_url(), "https://test.deribit.com");
229    }
230
231    #[rstest]
232    fn test_ws_url_default() {
233        let config = DeribitDataClientConfig::default();
234        assert_eq!(config.ws_url(), "wss://www.deribit.com/ws/api/v2");
235    }
236
237    #[rstest]
238    fn test_ws_url_testnet() {
239        let config = DeribitDataClientConfig {
240            environment: DeribitEnvironment::Testnet,
241            ..Default::default()
242        };
243        assert_eq!(config.ws_url(), "wss://test.deribit.com/ws/api/v2");
244    }
245
246    #[rstest]
247    fn test_has_api_credentials_in_config() {
248        let config = DeribitDataClientConfig {
249            api_key: Some("test_key".to_string()),
250            api_secret: Some("test_secret".to_string()),
251            ..Default::default()
252        };
253        assert!(config.has_api_credentials());
254    }
255}