nautilus_blockchain/
factories.rs1use std::{any::Any, cell::RefCell, rc::Rc};
19
20use nautilus_common::{cache::Cache, clock::Clock};
21use nautilus_data::client::DataClient;
22use nautilus_system::factories::{ClientConfig, DataClientFactory};
23
24use crate::{config::BlockchainDataClientConfig, data::client::BlockchainDataClient};
25
26impl ClientConfig for BlockchainDataClientConfig {
27 fn as_any(&self) -> &dyn Any {
28 self
29 }
30}
31
32#[derive(Debug, Clone)]
37#[cfg_attr(
38 feature = "python",
39 pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.blockchain")
40)]
41#[cfg_attr(
42 feature = "python",
43 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.adapters.blockchain")
44)]
45pub struct BlockchainDataClientFactory;
46
47impl BlockchainDataClientFactory {
48 #[must_use]
50 pub const fn new() -> Self {
51 Self
52 }
53}
54
55impl Default for BlockchainDataClientFactory {
56 fn default() -> Self {
57 Self::new()
58 }
59}
60
61impl DataClientFactory for BlockchainDataClientFactory {
62 fn create(
63 &self,
64 _name: &str,
65 config: &dyn ClientConfig,
66 _cache: Rc<RefCell<Cache>>,
67 _clock: Rc<RefCell<dyn Clock>>,
68 ) -> anyhow::Result<Box<dyn DataClient>> {
69 let blockchain_config = config
70 .as_any()
71 .downcast_ref::<BlockchainDataClientConfig>()
72 .ok_or_else(|| {
73 anyhow::anyhow!(
74 "Invalid config type for BlockchainDataClientFactory. Expected `BlockchainDataClientConfig`, was {config:?}"
75 )
76 })?;
77
78 let client = BlockchainDataClient::new(blockchain_config.clone());
79
80 Ok(Box::new(client))
81 }
82
83 fn name(&self) -> &'static str {
84 "BLOCKCHAIN"
85 }
86
87 fn config_type(&self) -> &'static str {
88 "BlockchainDataClientConfig"
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use std::sync::Arc;
95
96 use nautilus_model::defi::chain::{Blockchain, chains};
97 use nautilus_system::factories::DataClientFactory;
98 use rstest::rstest;
99
100 use crate::{config::BlockchainDataClientConfig, factories::BlockchainDataClientFactory};
101
102 #[rstest]
103 fn test_blockchain_data_client_config_creation() {
104 let chain = Arc::new(chains::ETHEREUM.clone());
105 let config = BlockchainDataClientConfig::new(
106 chain,
107 vec![],
108 "https://eth-mainnet.example.com".to_string(),
109 None,
110 None,
111 None,
112 false,
113 None,
114 None,
115 None,
116 );
117
118 assert_eq!(config.chain.name, Blockchain::Ethereum);
119 assert_eq!(config.http_rpc_url, "https://eth-mainnet.example.com");
120 }
121
122 #[rstest]
123 fn test_factory_creation() {
124 let factory = BlockchainDataClientFactory::new();
125 assert_eq!(factory.name(), "BLOCKCHAIN");
126 assert_eq!(factory.config_type(), "BlockchainDataClientConfig");
127 }
128}