op_primitives/components/
layer_one.rs

1use std::fmt::Display;
2
3use enum_variants_strings::EnumVariantsStrings;
4use serde::{Deserialize, Serialize};
5use strum::EnumIter;
6
7/// L1 Client
8///
9/// The OP Stack L1 client is an L1 execution client.
10#[derive(
11    Default, Copy, Clone, PartialEq, EnumVariantsStrings, Deserialize, Serialize, EnumIter,
12)]
13#[serde(rename_all = "kebab-case")]
14#[enum_variants_strings_transform(transform = "kebab_case")]
15pub enum L1Client {
16    /// Geth
17    #[default]
18    Geth,
19    /// Erigon
20    Erigon,
21    /// Reth
22    Reth,
23}
24
25impl std::fmt::Debug for L1Client {
26    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27        write!(f, "{}", self.to_str())
28    }
29}
30
31impl std::str::FromStr for L1Client {
32    type Err = eyre::Report;
33
34    fn from_str(s: &str) -> Result<Self, Self::Err> {
35        if s == L1Client::Geth.to_str() {
36            return Ok(L1Client::Geth);
37        }
38        if s == L1Client::Erigon.to_str() {
39            return Ok(L1Client::Erigon);
40        }
41        if s == L1Client::Reth.to_str() {
42            return Ok(L1Client::Reth);
43        }
44        eyre::bail!("Invalid L1 client: {}", s)
45    }
46}
47
48impl Display for L1Client {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        write!(f, "{}", self.to_str())
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[test]
59    fn test_deserialize_string() {
60        assert_eq!(
61            serde_json::from_str::<L1Client>(r#""geth""#).unwrap(),
62            L1Client::Geth
63        );
64        assert_eq!(
65            serde_json::from_str::<L1Client>(r#""erigon""#).unwrap(),
66            L1Client::Erigon
67        );
68        assert_eq!(
69            serde_json::from_str::<L1Client>(r#""reth""#).unwrap(),
70            L1Client::Reth
71        );
72        assert!(serde_json::from_str::<L1Client>(r#""invalid""#).is_err());
73    }
74
75    #[test]
76    fn test_debug_string() {
77        assert_eq!(format!("{:?}", L1Client::Geth), "geth");
78        assert_eq!(format!("{:?}", L1Client::Erigon), "erigon");
79        assert_eq!(format!("{:?}", L1Client::Reth), "reth");
80    }
81
82    #[test]
83    fn test_l1_client_from_str() {
84        assert_eq!("geth".parse::<L1Client>().unwrap(), L1Client::Geth);
85        assert_eq!("erigon".parse::<L1Client>().unwrap(), L1Client::Erigon);
86        assert_eq!("reth".parse::<L1Client>().unwrap(), L1Client::Reth);
87        assert!("invalid".parse::<L1Client>().is_err());
88    }
89
90    #[test]
91    fn test_l1_client_to_str() {
92        assert_eq!(L1Client::Geth.to_str(), "geth");
93        assert_eq!(L1Client::Erigon.to_str(), "erigon");
94        assert_eq!(L1Client::Reth.to_str(), "reth");
95    }
96}