diff --git a/crates/primitives/src/serde_helper/num.rs b/crates/primitives/src/serde_helper/num.rs index 312f287124..8201749851 100644 --- a/crates/primitives/src/serde_helper/num.rs +++ b/crates/primitives/src/serde_helper/num.rs @@ -88,6 +88,33 @@ pub mod u64_hex_or_decimal { U64HexOrNumber::from(*value).serialize(s) } } + +/// serde functions for handling primitive optional `u64` as [U64](crate::U64) +pub mod u64_hex_or_decimal_opt { + use crate::serde_helper::num::U64HexOrNumber; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + + /// Deserializes an `u64` accepting a hex quantity string with optional 0x prefix or + /// a number + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + match Option::::deserialize(deserializer)? { + Some(val) => Ok(Some(val.into())), + None => Ok(None), + } + } + + /// Serializes u64 as hex string + pub fn serialize(value: &Option, s: S) -> Result { + match value { + Some(val) => U64HexOrNumber::from(*val).serialize(s), + None => s.serialize_none(), + } + } +} + /// Deserializes the input into an `Option`, using [`from_int_or_hex`] to deserialize the /// inner value. pub fn from_int_or_hex_opt<'de, D>(deserializer: D) -> Result, D::Error> diff --git a/crates/rpc/rpc-types/src/eth/trace/filter.rs b/crates/rpc/rpc-types/src/eth/trace/filter.rs index bde828cab5..3121335dae 100644 --- a/crates/rpc/rpc-types/src/eth/trace/filter.rs +++ b/crates/rpc/rpc-types/src/eth/trace/filter.rs @@ -1,5 +1,5 @@ //! `trace_filter` types and support -use reth_primitives::{Address, BlockNumber}; +use reth_primitives::{serde_helper::num::u64_hex_or_decimal_opt, Address}; use serde::{Deserialize, Serialize}; /// Trace filter. @@ -8,15 +8,30 @@ use serde::{Deserialize, Serialize}; #[serde(rename_all = "camelCase")] pub struct TraceFilter { /// From block - pub from_block: Option, + #[serde(with = "u64_hex_or_decimal_opt")] + pub from_block: Option, /// To block - pub to_block: Option, + #[serde(with = "u64_hex_or_decimal_opt")] + pub to_block: Option, /// From address pub from_address: Option>, /// To address pub to_address: Option>, /// Output offset - pub after: Option, + pub after: Option, /// Output amount - pub count: Option, + pub count: Option, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse_filter() { + let s = r#"{"fromBlock": "0x3","toBlock": "0x5"}"#; + let filter: TraceFilter = serde_json::from_str(s).unwrap(); + assert_eq!(filter.from_block, Some(3)); + assert_eq!(filter.to_block, Some(5)); + } }