kabu_defi_market/
protocol_pool_loader_component.rs1use std::sync::Arc;
2use tokio::sync::broadcast;
3
4use alloy_network::Network;
5use alloy_provider::Provider;
6use eyre::Result;
7use tracing::{error, info};
8
9use kabu_core_components::Component;
10use kabu_types_events::LoomTask;
11use kabu_types_market::{PoolClass, PoolId, PoolLoaders};
12use reth_tasks::TaskExecutor;
13
14#[derive(Clone)]
16pub struct ProtocolPoolLoaderComponent<P, PL, N>
17where
18 N: Network,
19 P: Provider<N> + Send + Sync + Clone + 'static,
20 PL: Provider<N> + Send + Sync + Clone + 'static,
21{
22 #[allow(dead_code)]
24 client: P,
25 #[allow(dead_code)]
27 pool_loaders: Arc<PoolLoaders<PL, N>>,
28 tasks_tx: Option<broadcast::Sender<LoomTask>>,
30}
31
32impl<P, PL, N> ProtocolPoolLoaderComponent<P, PL, N>
33where
34 N: Network + 'static,
35 P: Provider<N> + Send + Sync + Clone + 'static,
36 PL: Provider<N> + Send + Sync + Clone + 'static,
37{
38 pub fn new(client: P, pool_loaders: Arc<PoolLoaders<PL, N>>) -> Self {
39 Self { client, pool_loaders, tasks_tx: None }
40 }
41
42 pub fn with_task_channel(mut self, tasks_tx: broadcast::Sender<LoomTask>) -> Self {
43 self.tasks_tx = Some(tasks_tx);
44 self
45 }
46
47 async fn run(self) -> Result<()> {
48 info!("Starting protocol pool loader component");
49
50 let mut tasks = Vec::new();
52
53 let pool_classes = vec![PoolClass::UniswapV2, PoolClass::UniswapV3, PoolClass::Curve];
55
56 for pool_class in pool_classes {
57 let tasks_tx_clone = self.tasks_tx.clone();
58
59 let task = tokio::task::spawn(async move {
60 if let Err(e) = Self::process_protocol_loader(
61 pool_class,
62 Arc::new(()), tasks_tx_clone,
64 )
65 .await
66 {
67 error!("Protocol loader failed for {}: {}", pool_class, e);
68 }
69 });
70
71 tasks.push(task);
72 }
73
74 for task in tasks {
76 if let Err(e) = task.await {
77 error!("Protocol loader task failed: {}", e);
78 }
79 }
80
81 info!("Protocol pool loader component completed");
82 Ok(())
83 }
84
85 async fn process_protocol_loader(
86 pool_class: PoolClass,
87 _pool_loader: Arc<dyn Send + Sync>,
88 tasks_tx: Option<broadcast::Sender<LoomTask>>,
89 ) -> Result<()> {
90 info!("Protocol loader started for {}", pool_class);
91
92 if let Some(tx) = tasks_tx {
94 let example_pools = vec![
96 (PoolId::Address(alloy_primitives::Address::repeat_byte(0x01)), pool_class),
97 (PoolId::Address(alloy_primitives::Address::repeat_byte(0x02)), pool_class),
98 ];
99
100 let task = LoomTask::FetchAndAddPools(example_pools);
101
102 if let Err(e) = tx.send(task) {
103 error!("Failed to send protocol pool task for {}: {}", pool_class, e);
104 return Err(e.into());
105 }
106
107 info!("Sent protocol pool discovery task for {}", pool_class);
108 }
109
110 Ok(())
111 }
112}
113
114impl<P, PL, N> Component for ProtocolPoolLoaderComponent<P, PL, N>
115where
116 N: Network + 'static,
117 P: Provider<N> + Send + Sync + Clone + 'static,
118 PL: Provider<N> + Send + Sync + Clone + 'static,
119{
120 fn spawn(self, executor: TaskExecutor) -> Result<()> {
121 executor.spawn_critical(self.name(), async move {
122 if let Err(e) = self.run().await {
123 error!("Protocol pool loader component failed: {}", e);
124 }
125 });
126 Ok(())
127 }
128 fn name(&self) -> &'static str {
129 "ProtocolPoolLoaderComponent"
130 }
131}
132
133pub struct ProtocolPoolLoaderComponentBuilder {
135 }
137
138impl ProtocolPoolLoaderComponentBuilder {
139 pub fn new() -> Self {
140 Self {}
141 }
142
143 pub fn build<P, PL, N>(self, client: P, pool_loaders: Arc<PoolLoaders<PL, N>>) -> ProtocolPoolLoaderComponent<P, PL, N>
144 where
145 N: Network + 'static,
146 P: Provider<N> + Send + Sync + Clone + 'static,
147 PL: Provider<N> + Send + Sync + Clone + 'static,
148 {
149 ProtocolPoolLoaderComponent::new(client, pool_loaders)
150 }
151}
152
153impl Default for ProtocolPoolLoaderComponentBuilder {
154 fn default() -> Self {
155 Self::new()
156 }
157}