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