Skip to content

Commit

Permalink
fix: Chain serde
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes committed Nov 15, 2023
1 parent dc1cdc7 commit 9ef9256
Showing 1 changed file with 55 additions and 2 deletions.
57 changes: 55 additions & 2 deletions src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@ use strum::{EnumCount, IntoEnumIterator};

/// Either a known [`NamedChain`] or a EIP-155 chain ID.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Chain(ChainKind);

/// The kind of chain. Returned by [`Chain::kind`].
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ChainKind {
/// Known chain.
Named(NamedChain),
Expand Down Expand Up @@ -95,6 +93,45 @@ impl fmt::Display for Chain {
}
}

#[cfg(feature = "serde")]
impl serde::Serialize for Chain {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self.kind() {
ChainKind::Named(chain) => chain.serialize(serializer),
ChainKind::Id(id) => id.serialize(serializer),
}
}
}

#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for Chain {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct ChainVisitor;

impl<'de> serde::de::Visitor<'de> for ChainVisitor {
type Value = Chain;

fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("chain name or ID")
}

fn visit_u64<E: serde::de::Error>(self, value: u64) -> Result<Self::Value, E> {
Ok(Chain::from_id(value))
}

fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Self::Value, E> {
value.parse().map_err(serde::de::Error::custom)
}

fn visit_string<E: serde::de::Error>(self, v: String) -> Result<Self::Value, E> {
self.visit_str(&v)
}
}

deserializer.deserialize_any(ChainVisitor)
}
}

#[cfg(feature = "rlp")]
impl alloy_rlp::Encodable for Chain {
#[inline]
Expand Down Expand Up @@ -426,4 +463,20 @@ mod tests {
let chain = Chain::from_id(1234);
assert_eq!(chain.length(), 3);
}

#[cfg(feature = "serde")]
#[test]
fn test_serde() {
let chains = r#"["mainnet",1,80001,80002,"mumbai"]"#;
let re = r#"["mainnet","mainnet","mumbai",80002,"mumbai"]"#;
let expected = [
Chain::mainnet(),
Chain::mainnet(),
Chain::from_named(NamedChain::PolygonMumbai),
Chain::from_id(80002),
Chain::from_named(NamedChain::PolygonMumbai),
];
assert_eq!(serde_json::from_str::<Vec<Chain>>(chains).unwrap(), expected);
assert_eq!(serde_json::to_string(&expected).unwrap(), re);
}
}

0 comments on commit 9ef9256

Please sign in to comment.