#![allow(
clippy::missing_errors_doc,
reason = "errors documented on underlying Rust methods"
)]
pub mod config;
pub mod enums;
pub mod factories;
pub mod http;
pub mod urls;
pub mod websocket;
use nautilus_core::python::{to_pyruntime_err, to_pyvalue_err};
use nautilus_model::identifiers::ClientOrderId;
use nautilus_system::{
factories::{ClientConfig, DataClientFactory, ExecutionClientFactory},
get_global_pyo3_registry,
};
use pyo3::prelude::*;
use crate::{
common::{
consts::HYPERLIQUID_POST_ONLY_WOULD_MATCH,
enums::{
HyperliquidConditionalOrderType, HyperliquidProductType, HyperliquidTpSl,
HyperliquidTrailingOffsetType,
},
},
config::{HyperliquidDataClientConfig, HyperliquidExecClientConfig},
factories::{
HyperliquidDataClientFactory, HyperliquidExecFactoryConfig,
HyperliquidExecutionClientFactory,
},
http::{HyperliquidHttpClient, models::Cloid},
websocket::HyperliquidWebSocketClient,
};
#[pyfunction]
#[pyo3_stub_gen::derive::gen_stub_pyfunction(module = "nautilus_trader.hyperliquid")]
#[pyo3(name = "hyperliquid_cloid_from_client_order_id")]
fn py_hyperliquid_cloid_from_client_order_id(client_order_id: ClientOrderId) -> String {
Cloid::from_client_order_id(client_order_id).to_hex()
}
#[pyfunction]
#[pyo3_stub_gen::derive::gen_stub_pyfunction(module = "nautilus_trader.hyperliquid")]
#[pyo3(name = "hyperliquid_product_type_from_symbol")]
fn py_hyperliquid_product_type_from_symbol(symbol: &str) -> PyResult<HyperliquidProductType> {
HyperliquidProductType::from_symbol(symbol).map_err(to_pyvalue_err)
}
#[allow(clippy::needless_pass_by_value)]
fn extract_hyperliquid_data_factory(
py: Python<'_>,
factory: Py<PyAny>,
) -> PyResult<Box<dyn DataClientFactory>> {
match factory.extract::<HyperliquidDataClientFactory>(py) {
Ok(f) => Ok(Box::new(f)),
Err(e) => Err(to_pyvalue_err(format!(
"Failed to extract HyperliquidDataClientFactory: {e}"
))),
}
}
#[allow(clippy::needless_pass_by_value)]
fn extract_hyperliquid_exec_factory(
py: Python<'_>,
factory: Py<PyAny>,
) -> PyResult<Box<dyn ExecutionClientFactory>> {
match factory.extract::<HyperliquidExecutionClientFactory>(py) {
Ok(f) => Ok(Box::new(f)),
Err(e) => Err(to_pyvalue_err(format!(
"Failed to extract HyperliquidExecutionClientFactory: {e}"
))),
}
}
#[allow(clippy::needless_pass_by_value)]
fn extract_hyperliquid_data_config(
py: Python<'_>,
config: Py<PyAny>,
) -> PyResult<Box<dyn ClientConfig>> {
match config.extract::<HyperliquidDataClientConfig>(py) {
Ok(c) => Ok(Box::new(c)),
Err(e) => Err(to_pyvalue_err(format!(
"Failed to extract HyperliquidDataClientConfig: {e}"
))),
}
}
#[allow(clippy::needless_pass_by_value)]
fn extract_hyperliquid_exec_config(
py: Python<'_>,
config: Py<PyAny>,
) -> PyResult<Box<dyn ClientConfig>> {
match config.extract::<HyperliquidExecFactoryConfig>(py) {
Ok(c) => Ok(Box::new(c)),
Err(e) => Err(to_pyvalue_err(format!(
"Failed to extract HyperliquidExecFactoryConfig: {e}"
))),
}
}
#[pymodule]
pub fn hyperliquid(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add(
"HYPERLIQUID_POST_ONLY_WOULD_MATCH",
HYPERLIQUID_POST_ONLY_WOULD_MATCH,
)?;
m.add_class::<HyperliquidHttpClient>()?;
m.add_class::<HyperliquidWebSocketClient>()?;
m.add_class::<HyperliquidProductType>()?;
m.add_class::<HyperliquidTpSl>()?;
m.add_class::<HyperliquidConditionalOrderType>()?;
m.add_class::<HyperliquidTrailingOffsetType>()?;
m.add_function(wrap_pyfunction!(urls::py_get_hyperliquid_http_base_url, m)?)?;
m.add_function(wrap_pyfunction!(urls::py_get_hyperliquid_ws_url, m)?)?;
m.add_function(wrap_pyfunction!(
py_hyperliquid_product_type_from_symbol,
m
)?)?;
m.add_function(wrap_pyfunction!(
py_hyperliquid_cloid_from_client_order_id,
m
)?)?;
m.add_class::<HyperliquidDataClientConfig>()?;
m.add_class::<HyperliquidExecClientConfig>()?;
m.add_class::<HyperliquidExecFactoryConfig>()?;
m.add_class::<HyperliquidDataClientFactory>()?;
m.add_class::<HyperliquidExecutionClientFactory>()?;
let registry = get_global_pyo3_registry();
if let Err(e) = registry
.register_factory_extractor("HYPERLIQUID".to_string(), extract_hyperliquid_data_factory)
{
return Err(to_pyruntime_err(format!(
"Failed to register Hyperliquid data factory extractor: {e}"
)));
}
if let Err(e) = registry.register_exec_factory_extractor(
"HYPERLIQUID".to_string(),
extract_hyperliquid_exec_factory,
) {
return Err(to_pyruntime_err(format!(
"Failed to register Hyperliquid exec factory extractor: {e}"
)));
}
if let Err(e) = registry.register_config_extractor(
"HyperliquidDataClientConfig".to_string(),
extract_hyperliquid_data_config,
) {
return Err(to_pyruntime_err(format!(
"Failed to register Hyperliquid data config extractor: {e}"
)));
}
if let Err(e) = registry.register_config_extractor(
"HyperliquidExecFactoryConfig".to_string(),
extract_hyperliquid_exec_config,
) {
return Err(to_pyruntime_err(format!(
"Failed to register Hyperliquid exec config extractor: {e}"
)));
}
Ok(())
}