kabu_core_config/
kabu_config.rs1use crate::config_loader::{ConfigLoader, ConfigLoaderSync, LoadConfigError, load_from_file, load_from_file_sync};
2use alloy_primitives::Address;
3use async_trait::async_trait;
4use eyre::Result;
5use serde::Deserialize;
6use std::collections::HashMap;
7use strum_macros::Display;
8
9#[derive(Clone, Debug, Default, Deserialize, Display)]
11#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
12#[serde(rename_all = "lowercase")]
13pub enum NodeType {
14 #[default]
15 Geth,
16 Reth,
17}
18
19#[derive(Clone, Debug, Deserialize)]
21pub struct RemoteNodeConfig {
22 pub ws_url: String,
24 pub http_url: String,
26 pub node: NodeType,
28}
29
30impl RemoteNodeConfig {
31 pub fn ws_url(&self) -> &str {
33 &self.ws_url
34 }
35
36 pub fn http_url(&self) -> &str {
38 &self.http_url
39 }
40}
41
42#[derive(Clone, Debug, Deserialize)]
44pub struct SignerConfig {
45 pub private_key: String,
46}
47
48#[derive(Clone, Debug, Deserialize)]
50pub struct BuilderConfig {
51 pub id: u8,
52 pub name: String,
53 pub url: String,
54 #[serde(default)]
55 pub no_sign: bool,
56}
57
58#[derive(Clone, Debug, Default, Deserialize)]
60pub struct InfluxDbConfig {
61 pub url: String,
62 pub database: String,
63 pub tags: HashMap<String, String>,
64}
65
66#[derive(Clone, Debug, Deserialize)]
68pub struct WebserverConfig {
69 pub host: String,
70}
71
72impl Default for WebserverConfig {
73 fn default() -> Self {
74 WebserverConfig { host: "127.0.0.1:3333".to_string() }
75 }
76}
77
78#[derive(Clone, Debug, Deserialize)]
80pub struct DatabaseConfig {
81 pub url: String,
82}
83
84#[derive(Clone, Debug, Deserialize)]
86pub struct KabuConfig {
87 pub remote_node: Option<RemoteNodeConfig>,
89
90 pub signers: Vec<SignerConfig>,
92
93 #[serde(default)]
95 pub builders: Vec<BuilderConfig>,
96
97 pub multicaller_address: Address,
99
100 pub influxdb: Option<InfluxDbConfig>,
102
103 pub webserver: Option<WebserverConfig>,
105
106 pub database: Option<DatabaseConfig>,
108}
109
110impl KabuConfig {
111 pub fn load_from_file(file_name: String) -> Result<KabuConfig> {
113 let config = load_from_file_sync(file_name)?;
114 Ok(config)
115 }
116
117 pub async fn load_from_file_async(file_name: String) -> Result<KabuConfig> {
119 let config = load_from_file(file_name).await?;
120 Ok(config)
121 }
122}
123
124#[async_trait]
125impl ConfigLoader for KabuConfig {
126 type SectionType = KabuConfig;
127
128 async fn load_from_file(file_name: String) -> Result<Self::SectionType, LoadConfigError> {
129 load_from_file(file_name).await
130 }
131}
132
133impl ConfigLoaderSync for KabuConfig {
134 type SectionType = KabuConfig;
135
136 fn load_from_file_sync(file_name: String) -> Result<Self::SectionType, LoadConfigError> {
137 load_from_file_sync(file_name)
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144
145 #[test]
146 fn test_node_type_display() {
147 assert_eq!(NodeType::Geth.to_string(), "geth");
148 assert_eq!(NodeType::Reth.to_string(), "reth");
149 }
150
151 #[test]
152 fn test_remote_node_config() {
153 let config = RemoteNodeConfig {
154 ws_url: "ws://localhost:8545".to_string(),
155 http_url: "http://localhost:8545".to_string(),
156 node: NodeType::Reth,
157 };
158
159 assert_eq!(config.ws_url(), "ws://localhost:8545");
160 assert_eq!(config.http_url(), "http://localhost:8545");
161 }
162
163 #[test]
164 fn test_config_parsing_with_remote_node() {
165 let toml_str = r#"
166 signers = []
167 builders = []
168 multicaller_address = "0x0000000000000000000000000000000000000000"
169
170 [remote_node]
171 ws_url = "ws://localhost:8545"
172 http_url = "http://localhost:8545"
173 node = "reth"
174 "#;
175
176 let config: KabuConfig = toml::from_str(toml_str).unwrap();
177 assert!(config.remote_node.is_some());
178 let remote = config.remote_node.unwrap();
179 assert_eq!(remote.ws_url, "ws://localhost:8545");
180 assert_eq!(remote.http_url, "http://localhost:8545");
181 }
182
183 #[test]
184 fn test_config_parsing_without_remote_node() {
185 let toml_str = r#"
186 signers = []
187 builders = []
188 multicaller_address = "0x0000000000000000000000000000000000000000"
189 "#;
190
191 let config: KabuConfig = toml::from_str(toml_str).unwrap();
192 assert!(config.remote_node.is_none());
193 }
194}