alloy_serde/checksum.rs
1//! Serde functions for (de)serializing EIP-55 checksummed addresses.
2//!
3//! Can also be used for rejecting non checksummend addresses during deserialization.
4//!
5//! # Example
6//! ```
7//! use alloy_primitives::{address, Address};
8//! use alloy_serde;
9//! use serde::{Deserialize, Serialize};
10//!
11//! #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
12//! pub struct Container {
13//! #[serde(with = "alloy_serde::checksum")]
14//! value: Address,
15//! }
16//!
17//! let val = Container { value: address!("0xdadB0d80178819F2319190D340ce9A924f783711") };
18//! let s = serde_json::to_string(&val).unwrap();
19//! assert_eq!(s, "{\"value\":\"0xdadB0d80178819F2319190D340ce9A924f783711\"}");
20//!
21//! let deserialized: Container = serde_json::from_str(&s).unwrap();
22//! assert_eq!(val, deserialized);
23//!
24//! let invalid = "{\"value\":\"0xdadb0d80178819F2319190D340ce9A924f783711\"}";
25//! serde_json::from_str::<Container>(&invalid).unwrap_err();
26//! ```
27
28use crate::alloc::string::String;
29use alloy_primitives::Address;
30use serde::{Deserialize, Deserializer, Serializer};
31
32/// Serialize an [Address] with EIP-55 checksum.
33pub fn serialize<S>(value: &Address, serializer: S) -> Result<S::Ok, S::Error>
34where
35 S: Serializer,
36{
37 serializer.collect_str(&value.to_checksum(None))
38}
39
40/// Deserialize an [Address] only if it has EIP-55 checksum.
41pub fn deserialize<'de, D>(deserializer: D) -> Result<Address, D::Error>
42where
43 D: Deserializer<'de>,
44{
45 let str = String::deserialize(deserializer)?;
46 Address::parse_checksummed(str, None).map_err(serde::de::Error::custom)
47}