nautilus_blockchain/python/
mod.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//! Python bindings from [PyO3](https://pyo3.rs).
17
18pub mod config;
19
20#[cfg(feature = "hypersync")]
21pub mod factories;
22
23#[cfg(feature = "hypersync")]
24use nautilus_system::{
25    factories::{ClientConfig, DataClientFactory},
26    get_global_pyo3_registry,
27};
28use pyo3::prelude::*;
29
30/// Extractor function for `BlockchainDataClientFactory`.
31#[cfg(feature = "hypersync")]
32fn extract_blockchain_factory(
33    py: Python<'_>,
34    factory: PyObject,
35) -> PyResult<Box<dyn DataClientFactory>> {
36    match factory.extract::<crate::factories::BlockchainDataClientFactory>(py) {
37        Ok(concrete_factory) => Ok(Box::new(concrete_factory)),
38        Err(e) => Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(format!(
39            "Failed to extract BlockchainDataClientFactory: {e}"
40        ))),
41    }
42}
43
44/// Extractor function for `BlockchainDataClientConfig`.
45#[cfg(feature = "hypersync")]
46fn extract_blockchain_config(py: Python<'_>, config: PyObject) -> PyResult<Box<dyn ClientConfig>> {
47    match config.extract::<crate::config::BlockchainDataClientConfig>(py) {
48        Ok(concrete_config) => Ok(Box::new(concrete_config)),
49        Err(e) => Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(format!(
50            "Failed to extract BlockchainDataClientConfig: {e}"
51        ))),
52    }
53}
54
55/// Loaded as `nautilus_pyo3.blockchain`.
56///
57/// # Errors
58///
59/// Returns a `PyErr` if registering any module components fails.
60#[pymodule]
61pub fn blockchain(_: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
62    m.add_class::<crate::config::BlockchainDataClientConfig>()?;
63    m.add_class::<crate::config::DexPoolFilters>()?;
64    #[cfg(feature = "hypersync")]
65    m.add_class::<crate::factories::BlockchainDataClientFactory>()?;
66
67    // Register extractors with the global registry
68    #[cfg(feature = "hypersync")]
69    {
70        let registry = get_global_pyo3_registry();
71
72        if let Err(e) = registry
73            .register_factory_extractor("BLOCKCHAIN".to_string(), extract_blockchain_factory)
74        {
75            return Err(PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(format!(
76                "Failed to register blockchain factory extractor: {e}"
77            )));
78        }
79
80        if let Err(e) = registry.register_config_extractor(
81            "BlockchainDataClientConfig".to_string(),
82            extract_blockchain_config,
83        ) {
84            return Err(PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(format!(
85                "Failed to register blockchain config extractor: {e}"
86            )));
87        }
88    }
89
90    Ok(())
91}