alloy_rpc_types_engine/
identification.rs

1//! Client identification: <https://github.com/ethereum/execution-apis/blob/main/src/engine/identification.md>
2
3use alloc::string::String;
4
5/// This enum defines a standard for specifying a client with just two letters. Clients teams which
6/// have a code reserved in this list MUST use this code when identifying themselves.
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
9#[derive(strum::IntoStaticStr)] // Into<&'static str>, AsRef<str>, fmt::Display and serde::Serialize
10#[derive(strum::EnumString)] // FromStr, TryFrom<&str>
11#[non_exhaustive]
12pub enum ClientCode {
13    /// Besu
14    BU,
15    /// EthereumJS
16    EJ,
17    /// Erigon
18    EG,
19    /// Geth, go-ethereum
20    GE,
21    /// Grandine
22    GR,
23    /// Lighthouse
24    LH,
25    /// Lodestar
26    LS,
27    /// Nethermind
28    NM,
29    /// Nimbus
30    NB,
31    /// Trin Execution
32    TE,
33    /// Teku
34    TK,
35    /// Prysm
36    PM,
37    /// Reth
38    RH,
39}
40
41impl ClientCode {
42    /// Returns the client identifier as str.
43    pub fn as_str(&self) -> &'static str {
44        (*self).into()
45    }
46
47    /// Returns the human readable client name for the given code.
48    pub const fn client_name(&self) -> &'static str {
49        match self {
50            Self::BU => "Besu",
51            Self::EJ => "EthereumJS",
52            Self::EG => "Erigon",
53            Self::GE => "Geth",
54            Self::GR => "Grandine",
55            Self::LH => "Lighthouse",
56            Self::LS => "Lodestar",
57            Self::NM => "Nethermind",
58            Self::NB => "Nimbus",
59            Self::TE => "Trin Execution",
60            Self::TK => "Teku",
61            Self::PM => "Prysm",
62            Self::RH => "Reth",
63        }
64    }
65}
66
67#[cfg(feature = "serde")]
68impl serde::Serialize for ClientCode {
69    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
70        serializer.serialize_str(self.as_str())
71    }
72}
73
74impl core::fmt::Display for ClientCode {
75    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
76        self.as_str().fmt(f)
77    }
78}
79
80/// Contains information which identifies a client implementation.
81#[derive(Clone, Debug, PartialEq, Eq)]
82#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
83#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
84pub struct ClientVersionV1 {
85    /// Client code, e.g. GE for Geth
86    pub code: ClientCode,
87    /// Human-readable name of the client, e.g. Lighthouse or go-ethereum
88    pub name: String,
89    /// The version string of the current implementation e.g. v4.6.0 or 1.0.0-alpha.1 or
90    /// 1.0.0+20130313144700
91    pub version: String,
92    /// first four bytes of the latest commit hash of this build e.g: `fa4ff922`
93    pub commit: String,
94}
95
96#[cfg(test)]
97mod tests {
98    use super::*;
99    use similar_asserts::assert_eq;
100
101    #[test]
102    #[cfg(feature = "serde")]
103    fn client_id_serde() {
104        let s = r#"{"code":"RH","name":"Reth","version":"v1.10.8","commit":"fa4ff922"}"#;
105        let v: ClientVersionV1 = serde_json::from_str(s).unwrap();
106        assert_eq!(v.code, ClientCode::RH);
107        assert_eq!(v.name, "Reth");
108        assert_eq!(serde_json::to_string(&v).unwrap(), s);
109    }
110}