1use crate::common::enums::{OKXEnvironment, OKXRegion};
19
20const OKX_HTTP_URL: &str = "https://www.okx.com";
22const OKX_WS_PUBLIC_URL: &str = "wss://ws.okx.com:8443/ws/v5/public";
23const OKX_WS_PRIVATE_URL: &str = "wss://ws.okx.com:8443/ws/v5/private";
24const OKX_WS_BUSINESS_URL: &str = "wss://ws.okx.com:8443/ws/v5/business";
25const OKX_DEMO_WS_PUBLIC_URL: &str = "wss://wspap.okx.com:8443/ws/v5/public";
26const OKX_DEMO_WS_PRIVATE_URL: &str = "wss://wspap.okx.com:8443/ws/v5/private";
27const OKX_DEMO_WS_BUSINESS_URL: &str = "wss://wspap.okx.com:8443/ws/v5/business";
28
29const OKX_EEA_HTTP_URL: &str = "https://eea.okx.com";
31const OKX_EEA_WS_PUBLIC_URL: &str = "wss://wseea.okx.com:8443/ws/v5/public";
32const OKX_EEA_WS_PRIVATE_URL: &str = "wss://wseea.okx.com:8443/ws/v5/private";
33const OKX_EEA_WS_BUSINESS_URL: &str = "wss://wseea.okx.com:8443/ws/v5/business";
34const OKX_EEA_DEMO_WS_PUBLIC_URL: &str = "wss://wseeapap.okx.com:8443/ws/v5/public";
35const OKX_EEA_DEMO_WS_PRIVATE_URL: &str = "wss://wseeapap.okx.com:8443/ws/v5/private";
36const OKX_EEA_DEMO_WS_BUSINESS_URL: &str = "wss://wseeapap.okx.com:8443/ws/v5/business";
37
38const OKX_US_HTTP_URL: &str = "https://us.okx.com";
40const OKX_US_WS_PUBLIC_URL: &str = "wss://wsus.okx.com:8443/ws/v5/public";
41const OKX_US_WS_PRIVATE_URL: &str = "wss://wsus.okx.com:8443/ws/v5/private";
42const OKX_US_WS_BUSINESS_URL: &str = "wss://wsus.okx.com:8443/ws/v5/business";
43const OKX_US_DEMO_WS_PUBLIC_URL: &str = "wss://wsuspap.okx.com:8443/ws/v5/public";
44const OKX_US_DEMO_WS_PRIVATE_URL: &str = "wss://wsuspap.okx.com:8443/ws/v5/private";
45const OKX_US_DEMO_WS_BUSINESS_URL: &str = "wss://wsuspap.okx.com:8443/ws/v5/business";
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49#[cfg_attr(feature = "python", pyo3::pyclass(from_py_object))]
50#[cfg_attr(
51 feature = "python",
52 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.okx")
53)]
54pub enum OKXEndpointType {
55 Public,
56 Private,
57 Business,
58}
59
60pub fn requires_authentication(endpoint_type: OKXEndpointType) -> bool {
62 matches!(
63 endpoint_type,
64 OKXEndpointType::Private | OKXEndpointType::Business
65 )
66}
67
68#[must_use]
73pub const fn get_http_base_url(region: OKXRegion) -> &'static str {
74 match region {
75 OKXRegion::Global => OKX_HTTP_URL,
76 OKXRegion::Eea => OKX_EEA_HTTP_URL,
77 OKXRegion::Us => OKX_US_HTTP_URL,
78 }
79}
80
81#[must_use]
83pub fn get_ws_base_url_public(region: OKXRegion, environment: OKXEnvironment) -> &'static str {
84 match (region, environment) {
85 (OKXRegion::Global, OKXEnvironment::Live) => OKX_WS_PUBLIC_URL,
86 (OKXRegion::Global, OKXEnvironment::Demo) => OKX_DEMO_WS_PUBLIC_URL,
87 (OKXRegion::Eea, OKXEnvironment::Live) => OKX_EEA_WS_PUBLIC_URL,
88 (OKXRegion::Eea, OKXEnvironment::Demo) => OKX_EEA_DEMO_WS_PUBLIC_URL,
89 (OKXRegion::Us, OKXEnvironment::Live) => OKX_US_WS_PUBLIC_URL,
90 (OKXRegion::Us, OKXEnvironment::Demo) => OKX_US_DEMO_WS_PUBLIC_URL,
91 }
92}
93
94#[must_use]
96pub fn get_ws_base_url_private(region: OKXRegion, environment: OKXEnvironment) -> &'static str {
97 match (region, environment) {
98 (OKXRegion::Global, OKXEnvironment::Live) => OKX_WS_PRIVATE_URL,
99 (OKXRegion::Global, OKXEnvironment::Demo) => OKX_DEMO_WS_PRIVATE_URL,
100 (OKXRegion::Eea, OKXEnvironment::Live) => OKX_EEA_WS_PRIVATE_URL,
101 (OKXRegion::Eea, OKXEnvironment::Demo) => OKX_EEA_DEMO_WS_PRIVATE_URL,
102 (OKXRegion::Us, OKXEnvironment::Live) => OKX_US_WS_PRIVATE_URL,
103 (OKXRegion::Us, OKXEnvironment::Demo) => OKX_US_DEMO_WS_PRIVATE_URL,
104 }
105}
106
107#[must_use]
109pub fn get_ws_base_url_business(region: OKXRegion, environment: OKXEnvironment) -> &'static str {
110 match (region, environment) {
111 (OKXRegion::Global, OKXEnvironment::Live) => OKX_WS_BUSINESS_URL,
112 (OKXRegion::Global, OKXEnvironment::Demo) => OKX_DEMO_WS_BUSINESS_URL,
113 (OKXRegion::Eea, OKXEnvironment::Live) => OKX_EEA_WS_BUSINESS_URL,
114 (OKXRegion::Eea, OKXEnvironment::Demo) => OKX_EEA_DEMO_WS_BUSINESS_URL,
115 (OKXRegion::Us, OKXEnvironment::Live) => OKX_US_WS_BUSINESS_URL,
116 (OKXRegion::Us, OKXEnvironment::Demo) => OKX_US_DEMO_WS_BUSINESS_URL,
117 }
118}
119
120#[must_use]
126pub fn derive_ws_url(base_url: &str, channel: &str) -> String {
127 let url = base_url.trim_end_matches('/');
128 for suffix in ["/public", "/private", "/business"] {
129 if let Some(base) = url.strip_suffix(suffix) {
130 return format!("{base}/{channel}");
131 }
132 }
133 format!("{url}/{channel}")
134}
135
136#[must_use]
138pub fn get_ws_url(
139 endpoint_type: OKXEndpointType,
140 region: OKXRegion,
141 environment: OKXEnvironment,
142) -> &'static str {
143 match endpoint_type {
144 OKXEndpointType::Public => get_ws_base_url_public(region, environment),
145 OKXEndpointType::Private => get_ws_base_url_private(region, environment),
146 OKXEndpointType::Business => get_ws_base_url_business(region, environment),
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use rstest::rstest;
153
154 use super::*;
155
156 #[rstest]
157 fn test_endpoint_authentication() {
158 assert!(!requires_authentication(OKXEndpointType::Public));
159 assert!(requires_authentication(OKXEndpointType::Private));
160 assert!(requires_authentication(OKXEndpointType::Business));
161 }
162
163 #[rstest]
164 #[case(OKXRegion::Global, "https://www.okx.com")]
165 #[case(OKXRegion::Eea, "https://eea.okx.com")]
166 #[case(OKXRegion::Us, "https://us.okx.com")]
167 fn test_http_base_url(#[case] region: OKXRegion, #[case] expected: &str) {
168 assert_eq!(get_http_base_url(region), expected);
169 }
170
171 #[rstest]
172 #[case(
173 OKXRegion::Global,
174 "wss://ws.okx.com:8443/ws/v5/public",
175 "wss://ws.okx.com:8443/ws/v5/private",
176 "wss://ws.okx.com:8443/ws/v5/business"
177 )]
178 #[case(
179 OKXRegion::Eea,
180 "wss://wseea.okx.com:8443/ws/v5/public",
181 "wss://wseea.okx.com:8443/ws/v5/private",
182 "wss://wseea.okx.com:8443/ws/v5/business"
183 )]
184 #[case(
185 OKXRegion::Us,
186 "wss://wsus.okx.com:8443/ws/v5/public",
187 "wss://wsus.okx.com:8443/ws/v5/private",
188 "wss://wsus.okx.com:8443/ws/v5/business"
189 )]
190 fn test_ws_urls_live(
191 #[case] region: OKXRegion,
192 #[case] public: &str,
193 #[case] private: &str,
194 #[case] business: &str,
195 ) {
196 assert_eq!(get_ws_base_url_public(region, OKXEnvironment::Live), public);
197 assert_eq!(
198 get_ws_base_url_private(region, OKXEnvironment::Live),
199 private
200 );
201 assert_eq!(
202 get_ws_base_url_business(region, OKXEnvironment::Live),
203 business
204 );
205 }
206
207 #[rstest]
208 #[case(
209 OKXRegion::Global,
210 "wss://wspap.okx.com:8443/ws/v5/public",
211 "wss://wspap.okx.com:8443/ws/v5/private",
212 "wss://wspap.okx.com:8443/ws/v5/business"
213 )]
214 #[case(
215 OKXRegion::Eea,
216 "wss://wseeapap.okx.com:8443/ws/v5/public",
217 "wss://wseeapap.okx.com:8443/ws/v5/private",
218 "wss://wseeapap.okx.com:8443/ws/v5/business"
219 )]
220 #[case(
221 OKXRegion::Us,
222 "wss://wsuspap.okx.com:8443/ws/v5/public",
223 "wss://wsuspap.okx.com:8443/ws/v5/private",
224 "wss://wsuspap.okx.com:8443/ws/v5/business"
225 )]
226 fn test_ws_urls_demo(
227 #[case] region: OKXRegion,
228 #[case] public: &str,
229 #[case] private: &str,
230 #[case] business: &str,
231 ) {
232 assert_eq!(get_ws_base_url_public(region, OKXEnvironment::Demo), public);
233 assert_eq!(
234 get_ws_base_url_private(region, OKXEnvironment::Demo),
235 private
236 );
237 assert_eq!(
238 get_ws_base_url_business(region, OKXEnvironment::Demo),
239 business
240 );
241 }
242
243 #[rstest]
244 #[case(
245 "wss://ws.okx.com:8443/ws/v5/public",
246 "business",
247 "wss://ws.okx.com:8443/ws/v5/business"
248 )]
249 #[case(
250 "wss://wseea.okx.com:8443/ws/v5/public",
251 "private",
252 "wss://wseea.okx.com:8443/ws/v5/private"
253 )]
254 #[case(
255 "wss://wseea.okx.com:8443/ws/v5/private",
256 "business",
257 "wss://wseea.okx.com:8443/ws/v5/business"
258 )]
259 #[case(
260 "wss://wseea.okx.com:8443/ws/v5/private/",
261 "business",
262 "wss://wseea.okx.com:8443/ws/v5/business"
263 )]
264 #[case(
265 "wss://custom.proxy:8443/ws/v5",
266 "business",
267 "wss://custom.proxy:8443/ws/v5/business"
268 )]
269 fn test_derive_ws_url(#[case] base_url: &str, #[case] channel: &str, #[case] expected: &str) {
270 assert_eq!(derive_ws_url(base_url, channel), expected);
271 }
272
273 #[rstest]
274 #[case(OKXRegion::Global)]
275 #[case(OKXRegion::Eea)]
276 #[case(OKXRegion::Us)]
277 fn test_get_ws_url_by_type(#[case] region: OKXRegion) {
278 assert_eq!(
279 get_ws_url(OKXEndpointType::Public, region, OKXEnvironment::Live),
280 get_ws_base_url_public(region, OKXEnvironment::Live)
281 );
282 assert_eq!(
283 get_ws_url(OKXEndpointType::Private, region, OKXEnvironment::Live),
284 get_ws_base_url_private(region, OKXEnvironment::Live)
285 );
286 assert_eq!(
287 get_ws_url(OKXEndpointType::Business, region, OKXEnvironment::Live),
288 get_ws_base_url_business(region, OKXEnvironment::Live)
289 );
290 }
291}