1use eyre::Result;
2use kabu_broadcast_flashbots::client::RelayConfig;
3use serde::Deserialize;
4use std::collections::HashMap;
5use std::fs;
6use strum_macros::Display;
7
8#[derive(Clone, Debug, Deserialize)]
9pub struct BlockchainConfig {
10 pub chain_id: Option<i64>,
11}
12
13#[derive(Clone, Debug, Default, Deserialize, Display)]
14#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
15#[serde(rename_all = "lowercase")]
16pub enum NodeType {
17 #[default]
18 Geth,
19 Reth,
20}
21
22#[derive(Clone, Debug, Default, Deserialize, Display)]
23#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
24#[serde(rename_all = "lowercase")]
25pub enum TransportType {
26 #[default]
27 #[serde(rename = "ws")]
28 Ws,
29 #[serde(rename = "http")]
30 Http,
31 #[serde(rename = "ipc")]
32 Ipc,
33}
34
35#[derive(Clone, Debug, Default, Deserialize)]
36pub struct InfluxDbConfig {
37 pub url: String,
38 pub database: String,
39 pub tags: HashMap<String, String>,
40}
41
42#[derive(Clone, Debug, Default, Deserialize)]
43pub struct ClientConfig {
44 pub url: String,
45 pub node: NodeType,
46 pub transport: TransportType,
47 pub db_path: Option<String>,
48 pub exex: Option<String>,
49 }
53
54#[derive(Clone, Debug, Deserialize)]
93pub struct EnvSingerConfig {
94 #[serde(rename = "bc")]
95 pub blockchain: Option<String>,
96}
97
98#[derive(Clone, Debug, Deserialize)]
99#[serde(tag = "type")]
100pub enum SignersConfig {
101 #[serde(rename = "env")]
102 Env(EnvSingerConfig),
103}
104
105#[derive(Clone, Debug, Deserialize)]
106pub struct PreloaderConfig {
107 pub client: Option<String>,
108 #[serde(rename = "bc")]
109 pub blockchain: Option<String>,
110 pub encoder: Option<String>,
111 pub signers: Option<String>,
112}
113
114#[derive(Clone, Debug, Deserialize)]
115pub struct SwapStepEncoderConfig {
116 pub address: String,
117}
118
119#[derive(Clone, Debug, Deserialize)]
120#[serde(tag = "type")]
121pub enum EncoderConfig {
122 #[serde(rename = "swapstep")]
123 SwapStep(SwapStepEncoderConfig),
124}
125
126#[derive(Clone, Debug, Deserialize)]
127pub struct BlockchainClientConfig {
128 #[serde(rename = "bc")]
129 pub blockchain: Option<String>,
130 pub client: Option<String>,
131}
132#[derive(Clone, Debug, Deserialize)]
133pub struct ExExClientConfig {
134 #[serde(rename = "bc")]
135 pub blockchain: Option<String>,
136 pub url: Option<String>,
137}
138
139#[derive(Clone, Debug, Deserialize)]
140pub struct FlashbotsRelayConfig {
141 id: u16,
142 name: String,
143 url: String,
144 no_sign: Option<bool>,
145}
146
147impl From<FlashbotsRelayConfig> for RelayConfig {
148 fn from(config: FlashbotsRelayConfig) -> Self {
149 RelayConfig { id: config.id, name: config.name, url: config.url, no_sign: config.no_sign }
150 }
151}
152
153#[derive(Clone, Debug, Deserialize)]
154pub struct FlashbotsBroadcasterConfig {
155 #[serde(rename = "bc")]
156 pub blockchain: Option<String>,
157 pub client: Option<String>,
158 pub smart: Option<bool>,
159 pub relays: Option<Vec<FlashbotsRelayConfig>>,
160}
161
162impl FlashbotsBroadcasterConfig {
163 pub fn relays(&self) -> Vec<RelayConfig> {
164 self.relays.as_ref().map(|relays| relays.iter().map(|r| r.clone().into()).collect()).unwrap_or_default()
165 }
166}
167
168#[derive(Clone, Debug, Deserialize)]
169#[serde(tag = "type")]
170pub enum BroadcasterConfig {
171 #[serde(rename = "flashbots")]
172 Flashbots(FlashbotsBroadcasterConfig),
173}
174
175#[derive(Clone, Debug, Deserialize)]
176pub struct EvmEstimatorConfig {
177 pub client: Option<String>,
178 #[serde(rename = "bc")]
179 pub blockchain: Option<String>,
180 pub encoder: Option<String>,
181}
182
183#[derive(Clone, Debug, Deserialize)]
184pub struct GethEstimatorConfig {
185 pub client: Option<String>,
186 #[serde(rename = "bc")]
187 pub blockchain: Option<String>,
188 pub encoder: Option<String>,
189}
190
191#[derive(Clone, Debug, Deserialize)]
192#[serde(tag = "type")]
193pub enum EstimatorConfig {
194 #[serde(rename = "evm")]
195 Evm(EvmEstimatorConfig),
196 #[serde(rename = "geth")]
197 Geth(GethEstimatorConfig),
198}
199
200#[derive(Clone, Debug, Deserialize)]
201pub struct PoolsConfig {
202 #[serde(rename = "bc")]
203 pub blockchain: Option<String>,
204 pub client: Option<String>,
205 pub history: bool,
206 pub new: bool,
207 pub protocol: bool,
208}
209
210#[derive(Clone, Debug, Deserialize)]
211pub struct WebserverConfig {
212 pub host: String,
213}
214
215impl Default for WebserverConfig {
216 fn default() -> Self {
217 WebserverConfig { host: "127.0.0.1:3333".to_string() }
218 }
219}
220
221#[derive(Clone, Debug, Deserialize)]
222pub struct DatabaseConfig {
223 pub url: String,
224}
225
226#[derive(Debug, Clone, Deserialize)]
227pub struct ActorConfig {
228 pub broadcaster: Option<HashMap<String, BroadcasterConfig>>,
229 pub node: Option<HashMap<String, BlockchainClientConfig>>,
230 pub node_exex: Option<HashMap<String, ExExClientConfig>>,
231 pub mempool: Option<HashMap<String, BlockchainClientConfig>>,
232 pub price: Option<HashMap<String, BlockchainClientConfig>>,
233 pub pools: Option<HashMap<String, PoolsConfig>>,
234 pub noncebalance: Option<HashMap<String, BlockchainClientConfig>>,
235 pub estimator: Option<HashMap<String, EstimatorConfig>>,
236}
237
238#[derive(Debug, Clone, Deserialize)]
239pub struct TopologyConfig {
240 pub influxdb: Option<InfluxDbConfig>,
241 pub clients: HashMap<String, ClientConfig>,
242 pub blockchains: HashMap<String, BlockchainConfig>,
243 pub actors: ActorConfig,
244 pub signers: HashMap<String, SignersConfig>,
245 pub encoders: HashMap<String, EncoderConfig>,
246 pub preloaders: Option<HashMap<String, PreloaderConfig>>,
247 pub webserver: Option<WebserverConfig>,
248 pub database: Option<DatabaseConfig>,
249}
250
251impl TopologyConfig {
252 pub fn load_from_file(file_name: String) -> Result<TopologyConfig> {
253 let contents = fs::read_to_string(file_name)?;
254 let config: TopologyConfig = toml::from_str(&contents)?;
255 Ok(config)
256 }
257}
258
259#[cfg(test)]
260mod test {
261 use super::*;
262
263 #[test]
264 fn test_load() {
265 match TopologyConfig::load_from_file("../../config.toml".to_string()) {
266 Ok(c) => {
267 println!("{c:?}");
268 }
269 Err(e) => {
270 println!("Error:{e}")
271 }
272 }
273 }
274}