1use nautilus_core::string::secret::SecretString;
19use nautilus_model::identifiers::{AccountId, Venue};
20use nautilus_network::websocket::TransportBackend;
21use pyo3::pymethods;
22
23use crate::{
24 common::enums::{LighterDeployment, LighterEnvironment},
25 config::{LighterDataClientConfig, LighterExecutionClientConfig},
26};
27
28#[pymethods]
29#[pyo3_stub_gen::derive::gen_stub_pymethods]
30impl LighterDataClientConfig {
31 #[new]
33 #[pyo3(signature = (
34 base_url_http = None,
35 base_url_ws = None,
36 proxy_url = None,
37 environment = None,
38 account_index = None,
39 api_key_index = None,
40 private_key = None,
41 http_timeout_secs = None,
42 ws_timeout_secs = None,
43 update_instruments_interval_mins = None,
44 rest_quota_per_min = None,
45 transport_backend = None,
46 deployment = None,
47 venue = None,
48 book_snapshot_timeout_secs = None,
49 ))]
50 #[expect(clippy::too_many_arguments)]
51 fn py_new(
52 base_url_http: Option<String>,
53 base_url_ws: Option<String>,
54 proxy_url: Option<String>,
55 environment: Option<LighterEnvironment>,
56 account_index: Option<u64>,
57 api_key_index: Option<u8>,
58 private_key: Option<String>,
59 http_timeout_secs: Option<u64>,
60 ws_timeout_secs: Option<u64>,
61 update_instruments_interval_mins: Option<u64>,
62 rest_quota_per_min: Option<u32>,
63 transport_backend: Option<TransportBackend>,
64 deployment: Option<LighterDeployment>,
65 venue: Option<Venue>,
66 book_snapshot_timeout_secs: Option<u64>,
67 ) -> Self {
68 let defaults = Self::default();
69 Self {
70 environment: environment.unwrap_or(defaults.environment),
71 deployment: deployment.unwrap_or(defaults.deployment),
72 venue,
73 account_index,
74 api_key_index,
75 private_key: private_key.map(SecretString::from),
76 base_url_http,
77 base_url_ws,
78 proxy_url: proxy_url.map(SecretString::from),
79 http_timeout_secs: http_timeout_secs.unwrap_or(defaults.http_timeout_secs),
80 ws_timeout_secs: ws_timeout_secs.unwrap_or(defaults.ws_timeout_secs),
81 update_instruments_interval_mins: update_instruments_interval_mins
82 .unwrap_or(defaults.update_instruments_interval_mins),
83 book_snapshot_timeout_secs: book_snapshot_timeout_secs
84 .unwrap_or(defaults.book_snapshot_timeout_secs),
85 rest_quota_per_min,
86 transport_backend: transport_backend.unwrap_or(defaults.transport_backend),
87 }
88 }
89
90 #[getter]
91 const fn has_proxy_url(&self) -> bool {
92 self.proxy_url.is_some()
93 }
94
95 fn __repr__(&self) -> String {
96 stringify!(LighterDataClientConfig).to_string()
97 }
98}
99
100#[pymethods]
101#[pyo3_stub_gen::derive::gen_stub_pymethods]
102impl LighterExecutionClientConfig {
103 #[new]
105 #[pyo3(signature = (
106 account_id,
107 account_index = None,
108 api_key_index = None,
109 private_key = None,
110 base_url_http = None,
111 base_url_ws = None,
112 proxy_url = None,
113 environment = None,
114 http_timeout_secs = None,
115 ws_timeout_secs = None,
116 market_order_slippage_bps = None,
117 rest_quota_per_min = None,
118 sendtx_quota_per_min = None,
119 transport_backend = None,
120 deployment = None,
121 venue = None,
122 use_gtd = true,
123 ))]
124 #[expect(clippy::too_many_arguments)]
125 fn py_new(
126 account_id: AccountId,
127 account_index: Option<u64>,
128 api_key_index: Option<u8>,
129 private_key: Option<String>,
130 base_url_http: Option<String>,
131 base_url_ws: Option<String>,
132 proxy_url: Option<String>,
133 environment: Option<LighterEnvironment>,
134 http_timeout_secs: Option<u64>,
135 ws_timeout_secs: Option<u64>,
136 market_order_slippage_bps: Option<u32>,
137 rest_quota_per_min: Option<u32>,
138 sendtx_quota_per_min: Option<u32>,
139 transport_backend: Option<TransportBackend>,
140 deployment: Option<LighterDeployment>,
141 venue: Option<Venue>,
142 use_gtd: bool,
143 ) -> Self {
144 let defaults = Self::default();
145 Self {
146 environment: environment.unwrap_or(defaults.environment),
147 deployment: deployment.unwrap_or(defaults.deployment),
148 venue,
149 account_id,
150 account_index,
151 api_key_index,
152 private_key: private_key.map(SecretString::from),
153 base_url_http,
154 base_url_ws,
155 proxy_url: proxy_url.map(SecretString::from),
156 http_timeout_secs: http_timeout_secs.unwrap_or(defaults.http_timeout_secs),
157 ws_timeout_secs: ws_timeout_secs.unwrap_or(defaults.ws_timeout_secs),
158 market_order_slippage_bps: market_order_slippage_bps
159 .unwrap_or(defaults.market_order_slippage_bps),
160 rest_quota_per_min,
161 sendtx_quota_per_min,
162 transport_backend: transport_backend.unwrap_or(defaults.transport_backend),
163 use_gtd,
164 }
165 }
166
167 #[getter]
168 const fn has_proxy_url(&self) -> bool {
169 self.proxy_url.is_some()
170 }
171
172 fn __repr__(&self) -> String {
173 stringify!(LighterExecutionClientConfig).to_string()
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use rstest::rstest;
180
181 use super::*;
182
183 #[rstest]
184 fn test_data_config_py_new_book_timeout() {
185 let config = LighterDataClientConfig::py_new(
186 None,
187 None,
188 None,
189 None,
190 None,
191 None,
192 None,
193 None,
194 None,
195 None,
196 Some(7),
197 None,
198 None,
199 None,
200 Some(42),
201 );
202
203 assert_eq!(config.rest_quota_per_min, Some(7));
204 assert_eq!(config.book_snapshot_timeout_secs, 42);
205 }
206
207 #[rstest]
208 fn test_data_config_py_new_book_timeout_default() {
209 let config = LighterDataClientConfig::py_new(
210 None, None, None, None, None, None, None, None, None, None, None, None, None, None,
211 None,
212 );
213
214 assert_eq!(config.book_snapshot_timeout_secs, 10);
215 }
216}