nautilus_okx/common/
urls.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 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
16use nautilus_core::env::get_env_var;
17
18/// OKX endpoint types for determining URL and authentication requirements.
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20#[cfg_attr(feature = "python", pyo3::pyclass)]
21pub enum OKXEndpointType {
22    Public,
23    Private,
24    Business,
25}
26
27/// Checks if endpoint requires authentication.
28pub fn requires_authentication(endpoint_type: OKXEndpointType) -> bool {
29    matches!(
30        endpoint_type,
31        OKXEndpointType::Private | OKXEndpointType::Business
32    )
33}
34
35/// Gets the HTTP base URL.
36pub fn get_http_base_url() -> String {
37    get_env_var("OKX_BASE_URL_HTTP").unwrap_or_else(|_| "https://www.okx.com".to_string())
38}
39
40/// Gets the WebSocket base URL for public data (market data).
41pub fn get_ws_base_url_public(is_demo: bool) -> String {
42    if is_demo {
43        get_env_var("OKX_DEMO_BASE_URL_WS_PUBLIC")
44            .unwrap_or_else(|_| "wss://wspap.okx.com:8443/ws/v5/public".to_string())
45    } else {
46        get_env_var("OKX_BASE_URL_WS_PUBLIC")
47            .unwrap_or_else(|_| "wss://ws.okx.com:8443/ws/v5/public".to_string())
48    }
49}
50
51/// Gets the WebSocket base URL for private data (account/order management).
52pub fn get_ws_base_url_private(is_demo: bool) -> String {
53    if is_demo {
54        get_env_var("OKX_DEMO_BASE_URL_WS_PRIVATE")
55            .unwrap_or_else(|_| "wss://wspap.okx.com:8443/ws/v5/private".to_string())
56    } else {
57        get_env_var("OKX_BASE_URL_WS_PRIVATE")
58            .unwrap_or_else(|_| "wss://ws.okx.com:8443/ws/v5/private".to_string())
59    }
60}
61
62/// Gets the WebSocket base URL for business data (bars/candlesticks).
63pub fn get_ws_base_url_business(is_demo: bool) -> String {
64    if is_demo {
65        get_env_var("OKX_DEMO_BASE_URL_WS_BUSINESS")
66            .unwrap_or_else(|_| "wss://wspap.okx.com:8443/ws/v5/business".to_string())
67    } else {
68        get_env_var("OKX_BASE_URL_WS_BUSINESS")
69            .unwrap_or_else(|_| "wss://ws.okx.com:8443/ws/v5/business".to_string())
70    }
71}
72
73/// Gets WebSocket URL by endpoint type.
74pub fn get_ws_url(endpoint_type: OKXEndpointType, is_demo: bool) -> String {
75    match endpoint_type {
76        OKXEndpointType::Public => get_ws_base_url_public(is_demo),
77        OKXEndpointType::Private => get_ws_base_url_private(is_demo),
78        OKXEndpointType::Business => get_ws_base_url_business(is_demo),
79    }
80}
81
82/// Gets the WebSocket base URL (backward compatibility - defaults to private).
83///
84/// .. deprecated::
85///     Use get_ws_base_url_public() or get_ws_base_url_private() instead.
86pub fn get_ws_base_url(is_demo: bool) -> String {
87    get_ws_base_url_private(is_demo)
88}
89
90#[cfg(test)]
91mod tests {
92    use rstest::rstest;
93
94    use super::*;
95
96    #[rstest]
97    fn test_endpoint_authentication() {
98        assert!(!requires_authentication(OKXEndpointType::Public));
99        assert!(requires_authentication(OKXEndpointType::Private));
100        assert!(requires_authentication(OKXEndpointType::Business));
101    }
102
103    #[rstest]
104    fn test_http_base_url() {
105        assert_eq!(get_http_base_url(), "https://www.okx.com");
106    }
107
108    #[rstest]
109    fn test_ws_urls_production() {
110        assert_eq!(
111            get_ws_base_url_public(false),
112            "wss://ws.okx.com:8443/ws/v5/public"
113        );
114        assert_eq!(
115            get_ws_base_url_private(false),
116            "wss://ws.okx.com:8443/ws/v5/private"
117        );
118        assert_eq!(
119            get_ws_base_url_business(false),
120            "wss://ws.okx.com:8443/ws/v5/business"
121        );
122    }
123
124    #[rstest]
125    fn test_ws_urls_demo() {
126        assert_eq!(
127            get_ws_base_url_public(true),
128            "wss://wspap.okx.com:8443/ws/v5/public"
129        );
130        assert_eq!(
131            get_ws_base_url_private(true),
132            "wss://wspap.okx.com:8443/ws/v5/private"
133        );
134        assert_eq!(
135            get_ws_base_url_business(true),
136            "wss://wspap.okx.com:8443/ws/v5/business"
137        );
138    }
139
140    #[rstest]
141    fn test_get_ws_url_by_type() {
142        assert_eq!(
143            get_ws_url(OKXEndpointType::Public, false),
144            get_ws_base_url_public(false)
145        );
146        assert_eq!(
147            get_ws_url(OKXEndpointType::Private, false),
148            get_ws_base_url_private(false)
149        );
150        assert_eq!(
151            get_ws_url(OKXEndpointType::Business, false),
152            get_ws_base_url_business(false)
153        );
154    }
155}