1use alloy_primitives::U256;
4use serde::{de::Error, Deserialize, Deserializer};
5use serde_json::Value;
6
7pub fn deserialize_json_ttd_opt<'de, D>(deserializer: D) -> Result<Option<U256>, D::Error>
10where
11 D: Deserializer<'de>,
12{
13 Option::<Value>::deserialize(deserializer)?.map(ttd_from_value::<D>).transpose()
14}
15
16fn ttd_from_value<'de, D>(val: Value) -> Result<U256, D::Error>
18where
19 D: Deserializer<'de>,
20{
21 let val = match val {
22 Value::Number(num) => num,
23 Value::String(raw) => return raw.parse().map_err(D::Error::custom),
24 _ => return Err(Error::custom("TTD must be a number or string")),
25 };
26
27 let num = if let Some(val) = val.as_u64() {
28 U256::from(val)
29 } else if let Some(value) = val.as_f64() {
30 if value == 5.875e22 {
48 U256::from(58750000000000000000000u128)
49 } else {
50 return Err(Error::custom("Deserializing a large non-mainnet TTD is not supported"));
53 }
54 } else {
55 return Err(Error::custom("Negative TTD values are invalid and will not be deserialized"));
57 };
58
59 Ok(num)
60}
61
62#[cfg(test)]
63mod tests {
64 #[cfg(not(feature = "std"))]
65 use alloc::{vec, vec::Vec};
66 use alloy_primitives::U256;
67 use serde::{Deserialize, Serialize};
68 use serde_json::json;
69
70 #[test]
71 fn jsonu256_deserialize() {
72 let deserialized: Vec<U256> =
73 serde_json::from_str(r#"["","0", "0x","10",10,"0x10"]"#).unwrap();
74 assert_eq!(
75 deserialized,
76 vec![
77 U256::ZERO,
78 U256::ZERO,
79 U256::ZERO,
80 U256::from(10),
81 U256::from(10),
82 U256::from(16),
83 ]
84 );
85 }
86
87 #[test]
88 fn jsonu256_serialize() {
89 let data = U256::from(16);
90 let serialized = serde_json::to_string(&data).unwrap();
91
92 assert_eq!(serialized, r#""0x10""#);
93 }
94
95 #[test]
96 fn deserialize_ttd() {
97 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
98 struct Ttd(#[serde(deserialize_with = "super::deserialize_json_ttd_opt")] Option<U256>);
99
100 let deserialized: Vec<Ttd> = serde_json::from_str(
101 r#"["",0,"0","0x0","58750000000000000000000",58750000000000000000000]"#,
102 )
103 .unwrap();
104 assert_eq!(
105 deserialized,
106 vec![
107 Ttd(Some(U256::ZERO)),
108 Ttd(Some(U256::ZERO)),
109 Ttd(Some(U256::ZERO)),
110 Ttd(Some(U256::ZERO)),
111 Ttd(Some(U256::from(58750000000000000000000u128))),
112 Ttd(Some(U256::from(58750000000000000000000u128))),
113 ]
114 );
115 }
116
117 #[test]
118 fn deserialize_ttd_none() {
119 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
120 struct Ttd(#[serde(deserialize_with = "super::deserialize_json_ttd_opt")] Option<U256>);
121
122 let deserialized: Ttd = serde_json::from_value(json!(null)).unwrap();
124 assert_eq!(deserialized, Ttd(None));
125 }
126
127 #[test]
128 fn deserialize_ttd_invalid_string() {
129 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
130 struct Ttd(#[serde(deserialize_with = "super::deserialize_json_ttd_opt")] Option<U256>);
131
132 let result: Result<Ttd, _> = serde_json::from_value(json!("invalid_string"));
134 assert!(result.is_err());
135 }
136
137 #[test]
138 fn deserialize_ttd_large_non_mainnet() {
139 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
140 struct Ttd(#[serde(deserialize_with = "super::deserialize_json_ttd_opt")] Option<U256>);
141
142 let result: Result<Ttd, _> = serde_json::from_value(json!(6.0e22));
144 assert!(result.is_err());
145 }
146
147 #[test]
148 fn deserialize_ttd_negative_number() {
149 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
150 struct Ttd(#[serde(deserialize_with = "super::deserialize_json_ttd_opt")] Option<U256>);
151
152 let result: Result<Ttd, _> = serde_json::from_value(json!(-1));
154 assert!(result.is_err());
155 }
156
157 #[test]
158 fn deserialize_ttd_as_string() {
159 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
160 struct Ttd(#[serde(deserialize_with = "super::deserialize_json_ttd_opt")] Option<U256>);
161
162 let deserialized: Ttd = serde_json::from_value(json!("0x12345")).unwrap();
164 assert_eq!(deserialized, Ttd(Some(U256::from(0x12345))));
165 }
166}