1use hopr_primitive_types::prelude::*;
2pub use hopr_strategy::StrategyConfig;
3use hopr_transport::config::SessionGlobalConfig;
4pub use hopr_transport::config::{
5 HostConfig, HostType, NetworkConfig, ProbeConfig, ProtocolConfig, TransportConfig, validate_external_host,
6};
7use serde::{Deserialize, Serialize};
8use serde_with::{DisplayFromStr, serde_as};
9use validator::{Validate, ValidationError};
10
11pub const DEFAULT_SAFE_TRANSACTION_SERVICE_PROVIDER: &str = "https://safe-transaction.prod.hoprtech.net/";
12pub const DEFAULT_HOST: &str = "0.0.0.0";
13pub const DEFAULT_PORT: u16 = 9091;
14
15fn validate_announced(v: &bool) -> Result<(), ValidationError> {
16 if *v {
17 Ok(())
18 } else {
19 Err(ValidationError::new(
20 "Announce option should be turned ON in 2.*, only public nodes are supported",
21 ))
22 }
23}
24
25#[inline]
26fn default_network() -> String {
27 "anvil-localhost".to_owned()
28}
29
30#[inline]
31fn just_true() -> bool {
32 true
33}
34
35#[derive(Debug, Clone, PartialEq, smart_default::SmartDefault, Serialize, Deserialize, Validate)]
36#[serde(deny_unknown_fields)]
37pub struct Chain {
38 #[validate(custom(function = "validate_announced"))]
39 #[serde(default = "just_true")]
40 #[default = true]
41 pub announce: bool,
42 #[serde(default = "default_network")]
43 #[default(default_network())]
44 pub network: String,
45 #[serde(default)]
46 pub provider: Option<String>,
47 #[serde(default)]
48 pub max_rpc_requests_per_sec: Option<u32>,
49 #[serde(default)]
50 pub protocols: hopr_chain_api::config::ProtocolsConfig,
51 #[serde(default = "just_true")]
52 #[default = true]
53 pub keep_logs: bool,
54 #[serde(default = "just_true")]
55 #[default = true]
56 pub fast_sync: bool,
57}
58
59#[inline]
60fn default_invalid_address() -> Address {
61 Address::default()
62}
63
64#[inline]
65fn default_safe_transaction_service_provider() -> String {
66 DEFAULT_SAFE_TRANSACTION_SERVICE_PROVIDER.to_owned()
67}
68
69#[serde_as]
70#[derive(Debug, Clone, PartialEq, smart_default::SmartDefault, Serialize, Deserialize, Validate)]
71#[serde(deny_unknown_fields)]
72pub struct SafeModule {
73 #[validate(url)]
74 #[serde(default = "default_safe_transaction_service_provider")]
75 #[default(default_safe_transaction_service_provider())]
76 pub safe_transaction_service_provider: String,
77 #[serde_as(as = "DisplayFromStr")]
78 #[serde(default = "default_invalid_address")]
79 #[default(default_invalid_address())]
80 pub safe_address: Address,
81 #[serde_as(as = "DisplayFromStr")]
82 #[serde(default = "default_invalid_address")]
83 #[default(default_invalid_address())]
84 pub module_address: Address,
85}
86
87#[allow(dead_code)]
88fn validate_directory_exists(s: &str) -> Result<(), ValidationError> {
89 if std::path::Path::new(s).is_dir() {
90 Ok(())
91 } else {
92 Err(ValidationError::new("Invalid directory path specified"))
93 }
94}
95
96#[derive(Debug, Clone, PartialEq, smart_default::SmartDefault, Serialize, Deserialize, Validate)]
97#[serde(deny_unknown_fields)]
98pub struct Db {
99 #[serde(default)]
101 pub data: String,
102 #[serde(default = "just_true")]
103 #[default = true]
104 pub initialize: bool,
105 #[serde(default)]
106 pub force_initialize: bool,
107}
108
109#[derive(Debug, Clone, PartialEq, smart_default::SmartDefault, Serialize, Deserialize, Validate)]
110pub struct HoprLibConfig {
111 #[validate(nested)]
113 #[validate(custom(function = "validate_external_host"))]
114 #[serde(default = "default_host")]
115 #[default(default_host())]
116 pub host: HostConfig,
117 #[validate(nested)]
119 #[serde(default)]
120 pub db: Db,
121 #[validate(nested)]
126 #[serde(default = "hopr_strategy::hopr_default_strategies")]
127 #[default(hopr_strategy::hopr_default_strategies())]
128 pub strategy: StrategyConfig,
129 #[validate(nested)]
131 #[serde(default)]
132 pub probe: ProbeConfig,
133 #[validate(nested)]
135 #[serde(default)]
136 pub network_options: NetworkConfig,
137 #[validate(nested)]
139 #[serde(default)]
140 pub transport: TransportConfig,
141 #[validate(nested)]
143 #[serde(default)]
144 pub protocol: ProtocolConfig,
145 #[validate(nested)]
147 #[serde(default)]
148 pub session: SessionGlobalConfig,
149 #[validate(nested)]
151 #[serde(default)]
152 pub chain: Chain,
153 #[validate(nested)]
155 #[serde(default)]
156 pub safe_module: SafeModule,
157}
158
159#[inline]
162fn default_host() -> HostConfig {
163 HostConfig {
164 address: HostType::IPv4(DEFAULT_HOST.to_owned()),
165 port: DEFAULT_PORT,
166 }
167}
168
169#[cfg(test)]
170mod tests {
171 use super::*;
172
173 #[test]
174 fn test_config_should_be_serializable_using_serde() -> Result<(), Box<dyn std::error::Error>> {
175 let cfg = HoprLibConfig::default();
176
177 let yaml = serde_yaml::to_string(&cfg)?;
178 let cfg_after_serde: HoprLibConfig = serde_yaml::from_str(&yaml)?;
179 assert_eq!(cfg, cfg_after_serde);
180
181 Ok(())
182 }
183}