nautilus_hyperliquid/
config.rs1use nautilus_network::websocket::TransportBackend;
19
20use crate::common::{
21 consts::{info_url, ws_url},
22 enums::HyperliquidEnvironment,
23};
24
25#[derive(Clone, Debug, bon::Builder)]
27#[cfg_attr(
28 feature = "python",
29 pyo3::pyclass(
30 module = "nautilus_trader.core.nautilus_pyo3.hyperliquid",
31 from_py_object
32 )
33)]
34#[cfg_attr(
35 feature = "python",
36 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.hyperliquid")
37)]
38pub struct HyperliquidDataClientConfig {
39 pub private_key: Option<String>,
41 pub base_url_ws: Option<String>,
43 pub base_url_http: Option<String>,
45 pub proxy_url: Option<String>,
47 #[builder(default)]
49 pub environment: HyperliquidEnvironment,
50 #[builder(default = 60)]
52 pub http_timeout_secs: u64,
53 #[builder(default = 30)]
55 pub ws_timeout_secs: u64,
56 #[builder(default = 60)]
58 pub update_instruments_interval_mins: u64,
59 #[builder(default)]
61 pub transport_backend: TransportBackend,
62}
63
64impl Default for HyperliquidDataClientConfig {
65 fn default() -> Self {
66 Self::builder().build()
67 }
68}
69
70impl HyperliquidDataClientConfig {
71 #[must_use]
73 pub fn new() -> Self {
74 Self::default()
75 }
76
77 #[must_use]
79 pub fn has_credentials(&self) -> bool {
80 self.private_key
81 .as_deref()
82 .is_some_and(|s| !s.trim().is_empty())
83 }
84
85 #[must_use]
87 pub fn ws_url(&self) -> String {
88 self.base_url_ws
89 .clone()
90 .unwrap_or_else(|| ws_url(self.environment).to_string())
91 }
92
93 #[must_use]
95 pub fn http_url(&self) -> String {
96 self.base_url_http
97 .clone()
98 .unwrap_or_else(|| info_url(self.environment).to_string())
99 }
100}
101
102#[derive(Clone, Debug, bon::Builder)]
104#[cfg_attr(
105 feature = "python",
106 pyo3::pyclass(
107 module = "nautilus_trader.core.nautilus_pyo3.hyperliquid",
108 from_py_object
109 )
110)]
111#[cfg_attr(
112 feature = "python",
113 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.hyperliquid")
114)]
115pub struct HyperliquidExecClientConfig {
116 pub private_key: Option<String>,
122 pub vault_address: Option<String>,
124 pub account_address: Option<String>,
128 pub base_url_ws: Option<String>,
130 pub base_url_http: Option<String>,
132 pub base_url_exchange: Option<String>,
134 pub proxy_url: Option<String>,
136 #[builder(default)]
138 pub environment: HyperliquidEnvironment,
139 #[builder(default = 60)]
141 pub http_timeout_secs: u64,
142 #[builder(default = 3)]
144 pub max_retries: u32,
145 #[builder(default = 100)]
147 pub retry_delay_initial_ms: u64,
148 #[builder(default = 5000)]
150 pub retry_delay_max_ms: u64,
151 #[builder(default = true)]
154 pub normalize_prices: bool,
155 #[builder(default = 50)]
159 pub market_order_slippage_bps: u32,
160 #[builder(default)]
162 pub transport_backend: TransportBackend,
163}
164
165impl Default for HyperliquidExecClientConfig {
166 fn default() -> Self {
167 Self::builder().build()
168 }
169}
170
171impl HyperliquidExecClientConfig {
172 #[must_use]
174 pub fn has_credentials(&self) -> bool {
175 self.private_key
176 .as_deref()
177 .is_some_and(|s| !s.trim().is_empty())
178 }
179
180 #[must_use]
182 pub fn ws_url(&self) -> String {
183 self.base_url_ws
184 .clone()
185 .unwrap_or_else(|| ws_url(self.environment).to_string())
186 }
187
188 #[must_use]
190 pub fn http_url(&self) -> String {
191 self.base_url_http
192 .clone()
193 .unwrap_or_else(|| info_url(self.environment).to_string())
194 }
195}
196
197#[cfg(test)]
198mod tests {
199 use rstest::rstest;
200
201 use super::*;
202
203 #[rstest]
204 fn test_exec_config_default_account_address_is_none() {
205 let config = HyperliquidExecClientConfig::default();
206 assert!(config.account_address.is_none());
207 }
208
209 #[rstest]
210 fn test_exec_config_with_account_address() {
211 let config = HyperliquidExecClientConfig {
212 account_address: Some("0x1234".to_string()),
213 ..HyperliquidExecClientConfig::default()
214 };
215 assert_eq!(config.account_address.as_deref(), Some("0x1234"));
216 }
217}