nautilus_blockchain/
factories.rs1use std::{any::Any, cell::RefCell, rc::Rc, sync::Arc};
19
20use nautilus_common::{cache::Cache, clock::Clock};
21use posei_trader::client::DataClient;
22use nautilus_model::defi::chain::Chain;
23use nautilus_system::factories::{ClientConfig, DataClientFactory};
24
25use crate::{config::BlockchainAdapterConfig, data::BlockchainDataClient};
26
27#[derive(Debug, Clone)]
29pub struct BlockchainClientConfig {
30 pub adapter_config: BlockchainAdapterConfig,
32 pub chain: Arc<Chain>,
34}
35
36impl BlockchainClientConfig {
37 #[must_use]
39 pub const fn new(adapter_config: BlockchainAdapterConfig, chain: Arc<Chain>) -> Self {
40 Self {
41 adapter_config,
42 chain,
43 }
44 }
45}
46
47impl ClientConfig for BlockchainClientConfig {
48 fn as_any(&self) -> &dyn Any {
49 self
50 }
51}
52
53#[derive(Debug)]
58pub struct BlockchainDataClientFactory;
59
60impl BlockchainDataClientFactory {
61 #[must_use]
63 pub const fn new() -> Self {
64 Self
65 }
66}
67
68impl Default for BlockchainDataClientFactory {
69 fn default() -> Self {
70 Self::new()
71 }
72}
73
74impl DataClientFactory for BlockchainDataClientFactory {
75 fn create(
76 &self,
77 _name: &str,
78 config: &dyn ClientConfig,
79 _cache: Rc<RefCell<Cache>>,
80 _clock: Rc<RefCell<dyn Clock>>,
81 ) -> anyhow::Result<Box<dyn DataClient>> {
82 let blockchain_config = config
83 .as_any()
84 .downcast_ref::<BlockchainClientConfig>()
85 .ok_or_else(|| {
86 anyhow::anyhow!(
87 "Invalid config type for BlockchainDataClientFactory. Expected BlockchainClientConfig, got {:?}",
88 config
89 )
90 })?;
91
92 let client = BlockchainDataClient::new(
93 blockchain_config.chain.clone(),
94 blockchain_config.adapter_config.clone(),
95 );
96
97 Ok(Box::new(client))
98 }
99
100 fn name(&self) -> &'static str {
101 "BLOCKCHAIN"
102 }
103
104 fn config_type(&self) -> &'static str {
105 "BlockchainClientConfig"
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use std::sync::Arc;
112
113 use nautilus_model::defi::chain::{Blockchain, chains};
114 use nautilus_system::factories::DataClientFactory;
115 use rstest::rstest;
116
117 use crate::{
118 config::BlockchainAdapterConfig,
119 factories::{BlockchainClientConfig, BlockchainDataClientFactory},
120 };
121
122 #[rstest]
123 fn test_blockchain_client_config_creation() {
124 let adapter_config = BlockchainAdapterConfig::new(
125 "https://eth-mainnet.example.com".to_string(),
126 None,
127 None,
128 false,
129 );
130 let chain = Arc::new(chains::ETHEREUM.clone());
131
132 let config = BlockchainClientConfig::new(adapter_config, chain);
133
134 assert_eq!(config.chain.name, Blockchain::Ethereum);
135 assert_eq!(
136 config.adapter_config.http_rpc_url,
137 "https://eth-mainnet.example.com"
138 );
139 }
140
141 #[rstest]
142 fn test_factory_creation() {
143 let factory = BlockchainDataClientFactory::new();
144 assert_eq!(factory.name(), "BlockchainDataClientFactory");
145 assert_eq!(factory.config_type(), "BlockchainClientConfig");
146 }
147}