diff --git a/ethers-core/src/types/block.rs b/ethers-core/src/types/block.rs index 13fede2b..8d090465 100644 --- a/ethers-core/src/types/block.rs +++ b/ethers-core/src/types/block.rs @@ -1,6 +1,7 @@ // Taken from https://github.com/tomusdrw/rust-web3/blob/master/src/types/block.rs use crate::types::{Address, Bloom, Bytes, H256, U256, U64}; -use serde::{ser::SerializeStruct, Deserialize, Serialize, Serializer}; +use serde::{ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializer}; +use std::str::FromStr; /// The block type returned from RPC calls. /// This is generic over a `TX` type which will be either the hash or the @@ -192,12 +193,46 @@ impl Serialize for BlockNumber { } } +impl<'de> Deserialize<'de> for BlockNumber { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?.to_lowercase(); + Ok(match s.as_str() { + "latest" => Self::Latest, + "earliest" => Self::Earliest, + "pending" => Self::Pending, + n => BlockNumber::Number(U64::from_str(n).map_err(serde::de::Error::custom)?), + }) + } +} + #[cfg(test)] #[cfg(not(feature = "celo"))] mod tests { use super::*; use crate::types::{Transaction, TxHash}; + #[test] + fn serde_block_number() { + for b in vec![ + BlockNumber::Latest, + BlockNumber::Earliest, + BlockNumber::Pending, + ] { + let b_ser = serde_json::to_string(&b).unwrap(); + let b_de: BlockNumber = serde_json::from_str(&b_ser).unwrap(); + assert_eq!(b_de, b); + } + + let b = BlockNumber::Number(1042u64.into()); + let b_ser = serde_json::to_string(&b).unwrap(); + let b_de: BlockNumber = serde_json::from_str(&b_ser).unwrap(); + assert_eq!(b_ser, "\"0x412\""); + assert_eq!(b_de, b); + } + #[test] fn deserialize_blk_no_txs() { let block = r#"{"number":"0x3","hash":"0xda53da08ef6a3cbde84c33e51c04f68c3853b6a3731f10baa2324968eee63972","parentHash":"0x689c70c080ca22bc0e681694fa803c1aba16a69c8b6368fed5311d279eb9de90","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x7270c1c4440180f2bd5215809ee3d545df042b67329499e1ab97eb759d31610d","stateRoot":"0x29f32984517a7d25607da485b23cefabfd443751422ca7e603395e1de9bc8a4b","receiptsRoot":"0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2","miner":"0x0000000000000000000000000000000000000000","difficulty":"0x0","totalDifficulty":"0x0","extraData":"0x","size":"0x3e8","gasLimit":"0x6691b7","gasUsed":"0x5208","timestamp":"0x5ecedbb9","transactions":["0xc3c5f700243de37ae986082fd2af88d2a7c2752a0c0f7b9d6ac47c729d45e067"],"uncles":[]}"#;