hopr_lib/
config.rs

1use hopr_primitive_types::prelude::*;
2pub use hopr_transport::config::{
3    HoprPacketPipelineConfig, HoprProtocolConfig, HostConfig, HostType, ProbeConfig, SessionGlobalConfig,
4    TransportConfig, looks_like_domain,
5};
6use validator::{Validate, ValidationError};
7
8pub const DEFAULT_SAFE_TRANSACTION_SERVICE_PROVIDER: &str = "https://safe-transaction.prod.hoprtech.net/";
9pub const DEFAULT_HOST: &str = "0.0.0.0";
10pub const DEFAULT_PORT: u16 = 9091;
11
12#[inline]
13fn default_invalid_address() -> Address {
14    Address::default()
15}
16
17#[inline]
18fn default_safe_transaction_service_provider() -> String {
19    DEFAULT_SAFE_TRANSACTION_SERVICE_PROVIDER.to_owned()
20}
21
22#[cfg_attr(feature = "serde", cfg_eval::cfg_eval, serde_with::serde_as)]
23#[derive(Debug, Clone, PartialEq, smart_default::SmartDefault, Validate)]
24#[cfg_attr(
25    feature = "serde",
26    derive(serde::Serialize, serde::Deserialize),
27    serde(deny_unknown_fields)
28)]
29pub struct SafeModule {
30    #[validate(url)]
31    #[cfg_attr(feature = "serde", serde(default = "default_safe_transaction_service_provider"))]
32    #[default(default_safe_transaction_service_provider())]
33    pub safe_transaction_service_provider: String,
34    #[cfg_attr(
35        feature = "serde",
36        serde_as(as = "serde_with::DisplayFromStr"),
37        serde(default = "default_invalid_address")
38    )]
39    #[default(default_invalid_address())]
40    pub safe_address: Address,
41    #[cfg_attr(
42        feature = "serde",
43        serde_as(as = "serde_with::DisplayFromStr"),
44        serde(default = "default_invalid_address")
45    )]
46    #[default(default_invalid_address())]
47    pub module_address: Address,
48}
49
50#[allow(dead_code)]
51fn validate_directory_exists(s: &str) -> Result<(), ValidationError> {
52    if std::path::Path::new(s).is_dir() {
53        Ok(())
54    } else {
55        Err(ValidationError::new("Invalid directory path specified"))
56    }
57}
58
59#[derive(Debug, Clone, PartialEq, smart_default::SmartDefault, Validate)]
60#[cfg_attr(
61    feature = "serde",
62    derive(serde::Serialize, serde::Deserialize),
63    serde(deny_unknown_fields)
64)]
65pub struct HoprLibConfig {
66    /// Configuration related to host specifics
67    #[validate(nested)]
68    #[default(default_host())]
69    #[cfg_attr(feature = "serde", serde(default = "default_host"))]
70    pub host: HostConfig,
71    /// Determines whether the node should be advertised publicly on-chain.
72    #[cfg_attr(feature = "serde", serde(default))]
73    pub publish: bool,
74    /// Configuration of the HOPR protocol.
75    #[validate(nested)]
76    #[cfg_attr(feature = "serde", serde(default))]
77    pub protocol: HoprProtocolConfig,
78    /// Configuration of the node Safe and Module.
79    #[validate(nested)]
80    #[cfg_attr(feature = "serde", serde(default))]
81    pub safe_module: SafeModule,
82}
83
84// NOTE: this intentionally does not validate (0.0.0.0) to force user to specify
85// their external IP.
86#[inline]
87fn default_host() -> HostConfig {
88    HostConfig {
89        address: HostType::IPv4(DEFAULT_HOST.to_owned()),
90        port: DEFAULT_PORT,
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    #[cfg(feature = "serde")]
97    #[test]
98    fn test_config_should_be_serializable_using_serde() -> Result<(), Box<dyn std::error::Error>> {
99        let cfg = super::HoprLibConfig::default();
100
101        let yaml = serde_yaml::to_string(&cfg)?;
102        let cfg_after_serde: super::HoprLibConfig = serde_yaml::from_str(&yaml)?;
103        assert_eq!(cfg, cfg_after_serde);
104
105        Ok(())
106    }
107}