anvil_core/eth/serde_helpers.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
//! custom serde helper functions
#[allow(unused)]
pub mod sequence {
use serde::{
de::DeserializeOwned, ser::SerializeSeq, Deserialize, Deserializer, Serialize, Serializer,
};
#[allow(unused)]
pub fn serialize<S, T>(val: &T, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: Serialize,
{
let mut seq = s.serialize_seq(Some(1))?;
seq.serialize_element(val)?;
seq.end()
}
pub fn deserialize<'de, T, D>(d: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
T: DeserializeOwned,
{
let mut seq = Vec::<T>::deserialize(d)?;
if seq.len() != 1 {
return Err(serde::de::Error::custom(format!(
"expected params sequence with length 1 but got {}",
seq.len()
)))
}
Ok(seq.remove(0))
}
}
/// A module that deserializes `[]` optionally
pub mod empty_params {
use serde::{Deserialize, Deserializer};
pub fn deserialize<'de, D>(d: D) -> Result<(), D::Error>
where
D: Deserializer<'de>,
{
let seq = Option::<Vec<()>>::deserialize(d)?.unwrap_or_default();
if !seq.is_empty() {
return Err(serde::de::Error::custom(format!(
"expected params sequence with length 0 but got {}",
seq.len()
)))
}
Ok(())
}
}
/// A module that deserializes either a BlockNumberOrTag, or a simple number.
pub mod lenient_block_number {
use alloy_rpc_types::BlockNumberOrTag;
use serde::{Deserialize, Deserializer};
/// Following the spec the block parameter is either:
///
/// > HEX String - an integer block number
/// > String "earliest" for the earliest/genesis block
/// > String "latest" - for the latest mined block
/// > String "pending" - for the pending state/transactions
///
/// and with EIP-1898:
/// > blockNumber: QUANTITY - a block number
/// > blockHash: DATA - a block hash
///
/// <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1898.md>
///
/// EIP-1898 does not all calls that use `BlockNumber` like `eth_getBlockByNumber` and doesn't
/// list raw integers as supported.
///
/// However, there are dev node implementations that support integers, such as ganache: <https://github.com/foundry-rs/foundry/issues/1868>
///
/// N.B.: geth does not support ints in `eth_getBlockByNumber`
pub fn lenient_block_number<'de, D>(deserializer: D) -> Result<BlockNumberOrTag, D::Error>
where
D: Deserializer<'de>,
{
LenientBlockNumber::deserialize(deserializer).map(Into::into)
}
/// Same as `lenient_block_number` but requires to be `[num; 1]`
pub fn lenient_block_number_seq<'de, D>(deserializer: D) -> Result<BlockNumberOrTag, D::Error>
where
D: Deserializer<'de>,
{
let num = <[LenientBlockNumber; 1]>::deserialize(deserializer)?[0].into();
Ok(num)
}
/// Various block number representations, See [`lenient_block_number()`]
#[derive(Clone, Copy, Deserialize)]
#[serde(untagged)]
pub enum LenientBlockNumber {
BlockNumber(BlockNumberOrTag),
Num(u64),
}
impl From<LenientBlockNumber> for BlockNumberOrTag {
fn from(b: LenientBlockNumber) -> Self {
match b {
LenientBlockNumber::BlockNumber(b) => b,
LenientBlockNumber::Num(b) => b.into(),
}
}
}
}