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