op_primitives/components/
layer_two.rs

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