kabu_core_node/
builder.rs

1//! Node builder for launching Kabu MEV bot with configured components
2
3use crate::context::KabuContext;
4use crate::node::ComponentSet;
5use crate::traits::ComponentBuilder;
6use alloy_network::Ethereum;
7use alloy_provider::Provider;
8use eyre::Result;
9use kabu_core_components::Component;
10use kabu_evm_db::{DatabaseKabuExt, KabuDBError};
11use kabu_node_debug_provider::DebugProviderExt;
12use kabu_types_entities::BlockHistoryState;
13use reth::revm::{Database, DatabaseCommit, DatabaseRef};
14use reth_ethereum_primitives::EthPrimitives;
15use reth_tasks::TaskExecutor;
16use std::marker::PhantomData;
17
18/// Type alias for a NodeBuilder with configured components
19type ConfiguredNodeBuilder<R, P, DB, Evm, N, E, S, M, B, Est, H, Mer, Mon, Sig> =
20    NodeBuilder<R, P, DB, Evm, ComponentSet<N, E, S, M, B, Est, H, Mer, Mon, Sig>>;
21
22/// Builder for creating and launching a Kabu node
23pub struct NodeBuilder<R, P, DB, Evm, Components = ()>
24where
25    R: Send + Sync + Clone + 'static,
26    P: Provider<Ethereum> + Send + Sync + Clone + 'static,
27    DB: DatabaseRef<Error = KabuDBError>
28        + Database<Error = KabuDBError>
29        + DatabaseCommit
30        + DatabaseKabuExt
31        + BlockHistoryState<EthPrimitives>
32        + Send
33        + Sync
34        + Clone
35        + Default
36        + 'static,
37    Evm: Clone + Send + Sync + 'static,
38{
39    context: Option<KabuContext<R, P, DB, Evm>>,
40    components: Components,
41    _phantom: PhantomData<(R, P, DB, Evm)>,
42}
43
44impl<R, P, DB, Evm> Default for NodeBuilder<R, P, DB, Evm, ()>
45where
46    R: Send + Sync + Clone + 'static,
47    P: Provider<Ethereum> + Send + Sync + Clone + 'static,
48    DB: DatabaseRef<Error = KabuDBError>
49        + Database<Error = KabuDBError>
50        + DatabaseCommit
51        + DatabaseKabuExt
52        + BlockHistoryState<EthPrimitives>
53        + Send
54        + Sync
55        + Clone
56        + Default
57        + 'static,
58    Evm: Clone + Send + Sync + 'static,
59{
60    fn default() -> Self {
61        Self::new()
62    }
63}
64
65impl<R, P, DB, Evm> NodeBuilder<R, P, DB, Evm, ()>
66where
67    R: Send + Sync + Clone + 'static,
68    P: Provider<Ethereum> + Send + Sync + Clone + 'static,
69    DB: DatabaseRef<Error = KabuDBError>
70        + Database<Error = KabuDBError>
71        + DatabaseCommit
72        + DatabaseKabuExt
73        + BlockHistoryState<EthPrimitives>
74        + Send
75        + Sync
76        + Clone
77        + Default
78        + 'static,
79    Evm: Clone + Send + Sync + 'static,
80{
81    /// Create a new node builder
82    pub fn new() -> Self {
83        Self { context: None, components: (), _phantom: PhantomData }
84    }
85
86    /// Set the context for the node
87    pub fn with_context(mut self, context: KabuContext<R, P, DB, Evm>) -> Self {
88        self.context = Some(context);
89        self
90    }
91
92    /// Set the components for the node
93    #[allow(clippy::type_complexity)]
94    pub fn with_components<N, E, S, M, B, Est, H, Mer, Mon, Sig>(
95        self,
96        components: ComponentSet<N, E, S, M, B, Est, H, Mer, Mon, Sig>,
97    ) -> ConfiguredNodeBuilder<R, P, DB, Evm, N, E, S, M, B, Est, H, Mer, Mon, Sig> {
98        NodeBuilder { context: self.context, components, _phantom: PhantomData }
99    }
100}
101
102impl<R, P, DB, Evm, N, E, S, M, B, Est, H, Mer, Mon, Sig> NodeBuilder<R, P, DB, Evm, ComponentSet<N, E, S, M, B, Est, H, Mer, Mon, Sig>>
103where
104    R: Send + Sync + Clone + 'static,
105    P: Provider<Ethereum> + DebugProviderExt<Ethereum> + Send + Sync + Clone + 'static,
106    DB: DatabaseRef<Error = KabuDBError>
107        + Database<Error = KabuDBError>
108        + DatabaseCommit
109        + DatabaseKabuExt
110        + BlockHistoryState<EthPrimitives>
111        + Send
112        + Sync
113        + Clone
114        + Default
115        + 'static,
116    Evm: Clone + Send + Sync + 'static,
117    N: ComponentBuilder<KabuContext<R, P, DB, Evm>>,
118    E: ComponentBuilder<KabuContext<R, P, DB, Evm>>,
119    S: ComponentBuilder<KabuContext<R, P, DB, Evm>>,
120    M: ComponentBuilder<KabuContext<R, P, DB, Evm>>,
121    B: ComponentBuilder<KabuContext<R, P, DB, Evm>>,
122    Est: ComponentBuilder<KabuContext<R, P, DB, Evm>>,
123    H: ComponentBuilder<KabuContext<R, P, DB, Evm>>,
124    Mer: ComponentBuilder<KabuContext<R, P, DB, Evm>>,
125    Mon: ComponentBuilder<KabuContext<R, P, DB, Evm>>,
126    Sig: ComponentBuilder<KabuContext<R, P, DB, Evm>>,
127{
128    /// Launch the node with all components
129    pub async fn launch(self, executor: TaskExecutor) -> Result<KabuHandle> {
130        let context = self.context.expect("Context must be set before launching");
131
132        // Build and spawn all components in dependency order
133
134        // Network component (block history)
135        let network = self.components.network.build(&context)?;
136        network.spawn(executor.clone())?;
137
138        // Market components (pools, price, etc.)
139        let market = self.components.market.build(&context)?;
140        market.spawn(executor.clone())?;
141
142        // Executor component (swap router)
143        let executor_component = self.components.executor.build(&context)?;
144        executor_component.spawn(executor.clone())?;
145
146        // Strategy component (arbitrage searcher)
147        let strategy = self.components.strategy.build(&context)?;
148        strategy.spawn(executor.clone())?;
149
150        // Estimator component (gas estimation)
151        let estimator = self.components.estimator.build(&context)?;
152        estimator.spawn(executor.clone())?;
153
154        // Signer bridge component (converts Ready to TxCompose)
155        let signer = self.components.signer.build(&context)?;
156        signer.spawn(executor.clone())?;
157
158        // Merger components (swap optimization)
159        let merger = self.components.merger.build(&context)?;
160        merger.spawn(executor.clone())?;
161
162        // Broadcaster component (transaction submission)
163        let broadcaster = self.components.broadcaster.build(&context)?;
164        broadcaster.spawn(executor.clone())?;
165
166        // Health monitoring
167        let health = self.components.health.build(&context)?;
168        health.spawn(executor.clone())?;
169
170        // Monitoring (metrics)
171        let monitoring = self.components.monitoring.build(&context)?;
172        monitoring.spawn(executor.clone())?;
173
174        Ok(KabuHandle { _phantom: PhantomData })
175    }
176}
177
178/// Handle to a running Kabu node
179pub struct KabuHandle {
180    _phantom: PhantomData<()>,
181}
182
183impl KabuHandle {
184    /// Wait for the node to finish (never returns in normal operation)
185    pub async fn wait_for_shutdown(self) -> eyre::Result<()> {
186        // In a real implementation, this would wait on shutdown signals
187        tokio::signal::ctrl_c().await?;
188        Ok(())
189    }
190}