use crate::common::enums::{OKXEnvironment, OKXRegion};
const OKX_HTTP_URL: &str = "https://www.okx.com";
const OKX_WS_PUBLIC_URL: &str = "wss://ws.okx.com:8443/ws/v5/public";
const OKX_WS_PRIVATE_URL: &str = "wss://ws.okx.com:8443/ws/v5/private";
const OKX_WS_BUSINESS_URL: &str = "wss://ws.okx.com:8443/ws/v5/business";
const OKX_DEMO_WS_PUBLIC_URL: &str = "wss://wspap.okx.com:8443/ws/v5/public";
const OKX_DEMO_WS_PRIVATE_URL: &str = "wss://wspap.okx.com:8443/ws/v5/private";
const OKX_DEMO_WS_BUSINESS_URL: &str = "wss://wspap.okx.com:8443/ws/v5/business";
const OKX_EEA_HTTP_URL: &str = "https://eea.okx.com";
const OKX_EEA_WS_PUBLIC_URL: &str = "wss://wseea.okx.com:8443/ws/v5/public";
const OKX_EEA_WS_PRIVATE_URL: &str = "wss://wseea.okx.com:8443/ws/v5/private";
const OKX_EEA_WS_BUSINESS_URL: &str = "wss://wseea.okx.com:8443/ws/v5/business";
const OKX_EEA_DEMO_WS_PUBLIC_URL: &str = "wss://wseeapap.okx.com:8443/ws/v5/public";
const OKX_EEA_DEMO_WS_PRIVATE_URL: &str = "wss://wseeapap.okx.com:8443/ws/v5/private";
const OKX_EEA_DEMO_WS_BUSINESS_URL: &str = "wss://wseeapap.okx.com:8443/ws/v5/business";
const OKX_US_HTTP_URL: &str = "https://us.okx.com";
const OKX_US_WS_PUBLIC_URL: &str = "wss://wsus.okx.com:8443/ws/v5/public";
const OKX_US_WS_PRIVATE_URL: &str = "wss://wsus.okx.com:8443/ws/v5/private";
const OKX_US_WS_BUSINESS_URL: &str = "wss://wsus.okx.com:8443/ws/v5/business";
const OKX_US_DEMO_WS_PUBLIC_URL: &str = "wss://wsuspap.okx.com:8443/ws/v5/public";
const OKX_US_DEMO_WS_PRIVATE_URL: &str = "wss://wsuspap.okx.com:8443/ws/v5/private";
const OKX_US_DEMO_WS_BUSINESS_URL: &str = "wss://wsuspap.okx.com:8443/ws/v5/business";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "python", pyo3::pyclass(from_py_object))]
#[cfg_attr(
feature = "python",
pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.okx")
)]
pub enum OKXEndpointType {
Public,
Private,
Business,
}
pub fn requires_authentication(endpoint_type: OKXEndpointType) -> bool {
matches!(
endpoint_type,
OKXEndpointType::Private | OKXEndpointType::Business
)
}
#[must_use]
pub const fn get_http_base_url(region: OKXRegion) -> &'static str {
match region {
OKXRegion::Global => OKX_HTTP_URL,
OKXRegion::Eea => OKX_EEA_HTTP_URL,
OKXRegion::Us => OKX_US_HTTP_URL,
}
}
#[must_use]
pub fn get_ws_base_url_public(region: OKXRegion, environment: OKXEnvironment) -> &'static str {
match (region, environment) {
(OKXRegion::Global, OKXEnvironment::Live) => OKX_WS_PUBLIC_URL,
(OKXRegion::Global, OKXEnvironment::Demo) => OKX_DEMO_WS_PUBLIC_URL,
(OKXRegion::Eea, OKXEnvironment::Live) => OKX_EEA_WS_PUBLIC_URL,
(OKXRegion::Eea, OKXEnvironment::Demo) => OKX_EEA_DEMO_WS_PUBLIC_URL,
(OKXRegion::Us, OKXEnvironment::Live) => OKX_US_WS_PUBLIC_URL,
(OKXRegion::Us, OKXEnvironment::Demo) => OKX_US_DEMO_WS_PUBLIC_URL,
}
}
#[must_use]
pub fn get_ws_base_url_private(region: OKXRegion, environment: OKXEnvironment) -> &'static str {
match (region, environment) {
(OKXRegion::Global, OKXEnvironment::Live) => OKX_WS_PRIVATE_URL,
(OKXRegion::Global, OKXEnvironment::Demo) => OKX_DEMO_WS_PRIVATE_URL,
(OKXRegion::Eea, OKXEnvironment::Live) => OKX_EEA_WS_PRIVATE_URL,
(OKXRegion::Eea, OKXEnvironment::Demo) => OKX_EEA_DEMO_WS_PRIVATE_URL,
(OKXRegion::Us, OKXEnvironment::Live) => OKX_US_WS_PRIVATE_URL,
(OKXRegion::Us, OKXEnvironment::Demo) => OKX_US_DEMO_WS_PRIVATE_URL,
}
}
#[must_use]
pub fn get_ws_base_url_business(region: OKXRegion, environment: OKXEnvironment) -> &'static str {
match (region, environment) {
(OKXRegion::Global, OKXEnvironment::Live) => OKX_WS_BUSINESS_URL,
(OKXRegion::Global, OKXEnvironment::Demo) => OKX_DEMO_WS_BUSINESS_URL,
(OKXRegion::Eea, OKXEnvironment::Live) => OKX_EEA_WS_BUSINESS_URL,
(OKXRegion::Eea, OKXEnvironment::Demo) => OKX_EEA_DEMO_WS_BUSINESS_URL,
(OKXRegion::Us, OKXEnvironment::Live) => OKX_US_WS_BUSINESS_URL,
(OKXRegion::Us, OKXEnvironment::Demo) => OKX_US_DEMO_WS_BUSINESS_URL,
}
}
#[must_use]
pub fn derive_ws_url(base_url: &str, channel: &str) -> String {
let url = base_url.trim_end_matches('/');
for suffix in ["/public", "/private", "/business"] {
if let Some(base) = url.strip_suffix(suffix) {
return format!("{base}/{channel}");
}
}
format!("{url}/{channel}")
}
#[must_use]
pub fn get_ws_url(
endpoint_type: OKXEndpointType,
region: OKXRegion,
environment: OKXEnvironment,
) -> &'static str {
match endpoint_type {
OKXEndpointType::Public => get_ws_base_url_public(region, environment),
OKXEndpointType::Private => get_ws_base_url_private(region, environment),
OKXEndpointType::Business => get_ws_base_url_business(region, environment),
}
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use super::*;
#[rstest]
fn test_endpoint_authentication() {
assert!(!requires_authentication(OKXEndpointType::Public));
assert!(requires_authentication(OKXEndpointType::Private));
assert!(requires_authentication(OKXEndpointType::Business));
}
#[rstest]
#[case(OKXRegion::Global, "https://www.okx.com")]
#[case(OKXRegion::Eea, "https://eea.okx.com")]
#[case(OKXRegion::Us, "https://us.okx.com")]
fn test_http_base_url(#[case] region: OKXRegion, #[case] expected: &str) {
assert_eq!(get_http_base_url(region), expected);
}
#[rstest]
#[case(
OKXRegion::Global,
"wss://ws.okx.com:8443/ws/v5/public",
"wss://ws.okx.com:8443/ws/v5/private",
"wss://ws.okx.com:8443/ws/v5/business"
)]
#[case(
OKXRegion::Eea,
"wss://wseea.okx.com:8443/ws/v5/public",
"wss://wseea.okx.com:8443/ws/v5/private",
"wss://wseea.okx.com:8443/ws/v5/business"
)]
#[case(
OKXRegion::Us,
"wss://wsus.okx.com:8443/ws/v5/public",
"wss://wsus.okx.com:8443/ws/v5/private",
"wss://wsus.okx.com:8443/ws/v5/business"
)]
fn test_ws_urls_live(
#[case] region: OKXRegion,
#[case] public: &str,
#[case] private: &str,
#[case] business: &str,
) {
assert_eq!(get_ws_base_url_public(region, OKXEnvironment::Live), public);
assert_eq!(
get_ws_base_url_private(region, OKXEnvironment::Live),
private
);
assert_eq!(
get_ws_base_url_business(region, OKXEnvironment::Live),
business
);
}
#[rstest]
#[case(
OKXRegion::Global,
"wss://wspap.okx.com:8443/ws/v5/public",
"wss://wspap.okx.com:8443/ws/v5/private",
"wss://wspap.okx.com:8443/ws/v5/business"
)]
#[case(
OKXRegion::Eea,
"wss://wseeapap.okx.com:8443/ws/v5/public",
"wss://wseeapap.okx.com:8443/ws/v5/private",
"wss://wseeapap.okx.com:8443/ws/v5/business"
)]
#[case(
OKXRegion::Us,
"wss://wsuspap.okx.com:8443/ws/v5/public",
"wss://wsuspap.okx.com:8443/ws/v5/private",
"wss://wsuspap.okx.com:8443/ws/v5/business"
)]
fn test_ws_urls_demo(
#[case] region: OKXRegion,
#[case] public: &str,
#[case] private: &str,
#[case] business: &str,
) {
assert_eq!(get_ws_base_url_public(region, OKXEnvironment::Demo), public);
assert_eq!(
get_ws_base_url_private(region, OKXEnvironment::Demo),
private
);
assert_eq!(
get_ws_base_url_business(region, OKXEnvironment::Demo),
business
);
}
#[rstest]
#[case(
"wss://ws.okx.com:8443/ws/v5/public",
"business",
"wss://ws.okx.com:8443/ws/v5/business"
)]
#[case(
"wss://wseea.okx.com:8443/ws/v5/public",
"private",
"wss://wseea.okx.com:8443/ws/v5/private"
)]
#[case(
"wss://wseea.okx.com:8443/ws/v5/private",
"business",
"wss://wseea.okx.com:8443/ws/v5/business"
)]
#[case(
"wss://wseea.okx.com:8443/ws/v5/private/",
"business",
"wss://wseea.okx.com:8443/ws/v5/business"
)]
#[case(
"wss://custom.proxy:8443/ws/v5",
"business",
"wss://custom.proxy:8443/ws/v5/business"
)]
fn test_derive_ws_url(#[case] base_url: &str, #[case] channel: &str, #[case] expected: &str) {
assert_eq!(derive_ws_url(base_url, channel), expected);
}
#[rstest]
#[case(OKXRegion::Global)]
#[case(OKXRegion::Eea)]
#[case(OKXRegion::Us)]
fn test_get_ws_url_by_type(#[case] region: OKXRegion) {
assert_eq!(
get_ws_url(OKXEndpointType::Public, region, OKXEnvironment::Live),
get_ws_base_url_public(region, OKXEnvironment::Live)
);
assert_eq!(
get_ws_url(OKXEndpointType::Private, region, OKXEnvironment::Live),
get_ws_base_url_private(region, OKXEnvironment::Live)
);
assert_eq!(
get_ws_url(OKXEndpointType::Business, region, OKXEnvironment::Live),
get_ws_base_url_business(region, OKXEnvironment::Live)
);
}
}