alloy_eips/
eip1898.rs

1//! [EIP-1898]: https://eips.ethereum.org/EIPS/eip-1898
2
3use alloy_primitives::{hex::FromHexError, ruint::ParseError, BlockHash, B256, U64};
4use alloy_rlp::{bytes, Decodable, Encodable, Error as RlpError};
5use core::{
6    fmt::{self, Formatter},
7    num::ParseIntError,
8    str::FromStr,
9};
10
11/// A helper struct to store the block number/hash and its parent hash.
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
14#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
15#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
16pub struct BlockWithParent {
17    /// Parent hash.
18    pub parent: B256,
19    /// Block number/hash.
20    pub block: BlockNumHash,
21}
22
23impl BlockWithParent {
24    /// Creates a new [`BlockWithParent`] instance.
25    pub const fn new(parent: B256, block: BlockNumHash) -> Self {
26        Self { parent, block }
27    }
28}
29
30/// A block hash which may have a boolean `requireCanonical` field.
31///
32/// - If false, a RPC call should raise if a block matching the hash is not found.
33/// - If true, a RPC call should additionally raise if the block is not in the canonical chain.
34///
35/// <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1898.md#specification>
36#[derive(Clone, Copy, PartialEq, Eq)]
37#[cfg_attr(feature = "serde", derive(serde::Serialize))]
38#[cfg_attr(feature = "serde", serde(rename = "camelCase"))]
39pub struct RpcBlockHash {
40    /// A block hash
41    pub block_hash: BlockHash,
42    /// Whether the block must be a canonical block
43    pub require_canonical: Option<bool>,
44}
45
46impl RpcBlockHash {
47    /// Returns a [`RpcBlockHash`] from a [`B256`].
48    #[doc(alias = "from_block_hash")]
49    pub const fn from_hash(block_hash: B256, require_canonical: Option<bool>) -> Self {
50        Self { block_hash, require_canonical }
51    }
52}
53
54impl From<B256> for RpcBlockHash {
55    fn from(value: B256) -> Self {
56        Self::from_hash(value, None)
57    }
58}
59
60impl From<RpcBlockHash> for B256 {
61    fn from(value: RpcBlockHash) -> Self {
62        value.block_hash
63    }
64}
65
66impl AsRef<B256> for RpcBlockHash {
67    fn as_ref(&self) -> &B256 {
68        &self.block_hash
69    }
70}
71
72impl fmt::Display for RpcBlockHash {
73    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
74        let Self { block_hash, require_canonical } = self;
75        if *require_canonical == Some(true) {
76            f.write_str("canonical ")?;
77        }
78        write!(f, "hash {block_hash}")
79    }
80}
81
82impl fmt::Debug for RpcBlockHash {
83    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
84        match self.require_canonical {
85            Some(require_canonical) => f
86                .debug_struct("RpcBlockHash")
87                .field("block_hash", &self.block_hash)
88                .field("require_canonical", &require_canonical)
89                .finish(),
90            None => fmt::Debug::fmt(&self.block_hash, f),
91        }
92    }
93}
94
95/// A block Number (or tag - "latest", "earliest", "pending")
96///
97/// This enum allows users to specify a block in a flexible manner.
98#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
99pub enum BlockNumberOrTag {
100    /// Latest block
101    #[default]
102    Latest,
103    /// Finalized block accepted as canonical
104    Finalized,
105    /// Safe head block
106    Safe,
107    /// Earliest block (genesis)
108    Earliest,
109    /// Pending block (not yet part of the blockchain)
110    Pending,
111    /// Block by number from canonical chain
112    Number(u64),
113}
114
115impl BlockNumberOrTag {
116    /// Returns the numeric block number if explicitly set
117    pub const fn as_number(&self) -> Option<u64> {
118        match *self {
119            Self::Number(num) => Some(num),
120            _ => None,
121        }
122    }
123
124    /// Returns `true` if a numeric block number is set
125    pub const fn is_number(&self) -> bool {
126        matches!(self, Self::Number(_))
127    }
128
129    /// Returns `true` if it's "latest"
130    pub const fn is_latest(&self) -> bool {
131        matches!(self, Self::Latest)
132    }
133
134    /// Returns `true` if it's "finalized"
135    pub const fn is_finalized(&self) -> bool {
136        matches!(self, Self::Finalized)
137    }
138
139    /// Returns `true` if it's "safe"
140    pub const fn is_safe(&self) -> bool {
141        matches!(self, Self::Safe)
142    }
143
144    /// Returns `true` if it's "pending"
145    pub const fn is_pending(&self) -> bool {
146        matches!(self, Self::Pending)
147    }
148
149    /// Returns `true` if it's "earliest"
150    pub const fn is_earliest(&self) -> bool {
151        matches!(self, Self::Earliest)
152    }
153}
154
155impl From<u64> for BlockNumberOrTag {
156    fn from(num: u64) -> Self {
157        Self::Number(num)
158    }
159}
160
161impl From<U64> for BlockNumberOrTag {
162    fn from(num: U64) -> Self {
163        num.to::<u64>().into()
164    }
165}
166
167#[cfg(feature = "serde")]
168impl serde::Serialize for BlockNumberOrTag {
169    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
170    where
171        S: serde::Serializer,
172    {
173        match *self {
174            Self::Number(x) => serializer.serialize_str(&format!("0x{x:x}")),
175            Self::Latest => serializer.serialize_str("latest"),
176            Self::Finalized => serializer.serialize_str("finalized"),
177            Self::Safe => serializer.serialize_str("safe"),
178            Self::Earliest => serializer.serialize_str("earliest"),
179            Self::Pending => serializer.serialize_str("pending"),
180        }
181    }
182}
183
184#[cfg(feature = "serde")]
185impl<'de> serde::Deserialize<'de> for BlockNumberOrTag {
186    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
187    where
188        D: serde::Deserializer<'de>,
189    {
190        let s = alloc::string::String::deserialize(deserializer)?;
191        s.parse().map_err(serde::de::Error::custom)
192    }
193}
194
195impl FromStr for BlockNumberOrTag {
196    type Err = ParseBlockNumberError;
197
198    fn from_str(s: &str) -> Result<Self, Self::Err> {
199        Ok(match s.to_lowercase().as_str() {
200            "latest" => Self::Latest,
201            "finalized" => Self::Finalized,
202            "safe" => Self::Safe,
203            "earliest" => Self::Earliest,
204            "pending" => Self::Pending,
205            s => {
206                if let Some(hex_val) = s.strip_prefix("0x") {
207                    u64::from_str_radix(hex_val, 16)?.into()
208                } else {
209                    return Err(HexStringMissingPrefixError::default().into());
210                }
211            }
212        })
213    }
214}
215
216impl fmt::Display for BlockNumberOrTag {
217    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218        match *self {
219            Self::Number(x) => write!(f, "0x{x:x}"),
220            Self::Latest => f.pad("latest"),
221            Self::Finalized => f.pad("finalized"),
222            Self::Safe => f.pad("safe"),
223            Self::Earliest => f.pad("earliest"),
224            Self::Pending => f.pad("pending"),
225        }
226    }
227}
228
229impl fmt::Debug for BlockNumberOrTag {
230    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
231        fmt::Display::fmt(self, f)
232    }
233}
234
235/// Error thrown when parsing a [BlockNumberOrTag] from a string.
236#[derive(Debug)]
237pub enum ParseBlockNumberError {
238    /// Failed to parse hex value
239    ParseIntErr(ParseIntError),
240    /// Failed to parse hex value
241    ParseErr(ParseError),
242    /// Block numbers should be 0x-prefixed
243    MissingPrefix(HexStringMissingPrefixError),
244}
245
246/// Error variants when parsing a [BlockNumberOrTag]
247impl core::error::Error for ParseBlockNumberError {
248    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
249        match self {
250            Self::ParseIntErr(err) => Some(err),
251            Self::MissingPrefix(err) => Some(err),
252            Self::ParseErr(_) => None,
253        }
254    }
255}
256
257impl fmt::Display for ParseBlockNumberError {
258    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
259        match self {
260            Self::ParseIntErr(err) => write!(f, "{err}"),
261            Self::ParseErr(err) => write!(f, "{err}"),
262            Self::MissingPrefix(err) => write!(f, "{err}"),
263        }
264    }
265}
266
267impl From<ParseIntError> for ParseBlockNumberError {
268    fn from(err: ParseIntError) -> Self {
269        Self::ParseIntErr(err)
270    }
271}
272
273impl From<ParseError> for ParseBlockNumberError {
274    fn from(err: ParseError) -> Self {
275        Self::ParseErr(err)
276    }
277}
278
279impl From<HexStringMissingPrefixError> for ParseBlockNumberError {
280    fn from(err: HexStringMissingPrefixError) -> Self {
281        Self::MissingPrefix(err)
282    }
283}
284
285/// Thrown when a 0x-prefixed hex string was expected
286#[derive(Clone, Copy, Debug, Default)]
287#[non_exhaustive]
288pub struct HexStringMissingPrefixError;
289
290impl fmt::Display for HexStringMissingPrefixError {
291    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
292        f.write_str("hex string without 0x prefix")
293    }
294}
295
296impl core::error::Error for HexStringMissingPrefixError {}
297
298/// A Block Identifier.
299/// <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1898.md>
300#[derive(Clone, Copy, PartialEq, Eq)]
301pub enum BlockId {
302    /// A block hash and an optional bool that defines if it's canonical
303    Hash(RpcBlockHash),
304    /// A block number
305    Number(BlockNumberOrTag),
306}
307
308impl BlockId {
309    /// Returns the block hash if it is [BlockId::Hash]
310    pub const fn as_block_hash(&self) -> Option<BlockHash> {
311        match self {
312            Self::Hash(hash) => Some(hash.block_hash),
313            Self::Number(_) => None,
314        }
315    }
316
317    /// Returns the block number if it is [`BlockId::Number`] and not a tag
318    pub const fn as_u64(&self) -> Option<u64> {
319        match self {
320            Self::Number(x) => x.as_number(),
321            _ => None,
322        }
323    }
324
325    /// Returns true if this is [BlockNumberOrTag::Latest]
326    pub const fn is_latest(&self) -> bool {
327        matches!(self, Self::Number(BlockNumberOrTag::Latest))
328    }
329
330    /// Returns true if this is [BlockNumberOrTag::Pending]
331    pub const fn is_pending(&self) -> bool {
332        matches!(self, Self::Number(BlockNumberOrTag::Pending))
333    }
334
335    /// Returns true if this is [BlockNumberOrTag::Safe]
336    pub const fn is_safe(&self) -> bool {
337        matches!(self, Self::Number(BlockNumberOrTag::Safe))
338    }
339
340    /// Returns true if this is [BlockNumberOrTag::Finalized]
341    pub const fn is_finalized(&self) -> bool {
342        matches!(self, Self::Number(BlockNumberOrTag::Finalized))
343    }
344
345    /// Returns true if this is [BlockNumberOrTag::Earliest]
346    pub const fn is_earliest(&self) -> bool {
347        matches!(self, Self::Number(BlockNumberOrTag::Earliest))
348    }
349
350    /// Returns true if this is [BlockNumberOrTag::Number]
351    pub const fn is_number(&self) -> bool {
352        matches!(self, Self::Number(BlockNumberOrTag::Number(_)))
353    }
354    /// Returns true if this is [BlockId::Hash]
355    pub const fn is_hash(&self) -> bool {
356        matches!(self, Self::Hash(_))
357    }
358
359    /// Creates a new "pending" tag instance.
360    pub const fn pending() -> Self {
361        Self::Number(BlockNumberOrTag::Pending)
362    }
363
364    /// Creates a new "latest" tag instance.
365    pub const fn latest() -> Self {
366        Self::Number(BlockNumberOrTag::Latest)
367    }
368
369    /// Creates a new "earliest" tag instance.
370    pub const fn earliest() -> Self {
371        Self::Number(BlockNumberOrTag::Earliest)
372    }
373
374    /// Creates a new "finalized" tag instance.
375    pub const fn finalized() -> Self {
376        Self::Number(BlockNumberOrTag::Finalized)
377    }
378
379    /// Creates a new "safe" tag instance.
380    pub const fn safe() -> Self {
381        Self::Number(BlockNumberOrTag::Safe)
382    }
383
384    /// Creates a new block number instance.
385    pub const fn number(num: u64) -> Self {
386        Self::Number(BlockNumberOrTag::Number(num))
387    }
388
389    /// Create a new block hash instance.
390    pub const fn hash(block_hash: BlockHash) -> Self {
391        Self::Hash(RpcBlockHash { block_hash, require_canonical: None })
392    }
393
394    /// Create a new block hash instance that requires the block to be canonical.
395    pub const fn hash_canonical(block_hash: BlockHash) -> Self {
396        Self::Hash(RpcBlockHash { block_hash, require_canonical: Some(true) })
397    }
398}
399
400impl Default for BlockId {
401    fn default() -> Self {
402        BlockNumberOrTag::Latest.into()
403    }
404}
405
406impl From<u64> for BlockId {
407    fn from(num: u64) -> Self {
408        BlockNumberOrTag::Number(num).into()
409    }
410}
411
412impl From<U64> for BlockId {
413    fn from(value: U64) -> Self {
414        value.to::<u64>().into()
415    }
416}
417
418impl From<BlockNumberOrTag> for BlockId {
419    fn from(num: BlockNumberOrTag) -> Self {
420        Self::Number(num)
421    }
422}
423
424impl From<HashOrNumber> for BlockId {
425    fn from(block: HashOrNumber) -> Self {
426        match block {
427            HashOrNumber::Hash(hash) => hash.into(),
428            HashOrNumber::Number(num) => num.into(),
429        }
430    }
431}
432
433impl From<B256> for BlockId {
434    fn from(block_hash: B256) -> Self {
435        RpcBlockHash { block_hash, require_canonical: None }.into()
436    }
437}
438
439impl From<(B256, Option<bool>)> for BlockId {
440    fn from(hash_can: (B256, Option<bool>)) -> Self {
441        RpcBlockHash { block_hash: hash_can.0, require_canonical: hash_can.1 }.into()
442    }
443}
444
445impl From<RpcBlockHash> for BlockId {
446    fn from(value: RpcBlockHash) -> Self {
447        Self::Hash(value)
448    }
449}
450
451#[cfg(feature = "serde")]
452impl serde::Serialize for BlockId {
453    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
454    where
455        S: serde::Serializer,
456    {
457        use serde::ser::SerializeStruct;
458
459        match self {
460            Self::Hash(RpcBlockHash { block_hash, require_canonical }) => {
461                let mut s = serializer.serialize_struct("BlockIdEip1898", 1)?;
462                s.serialize_field("blockHash", block_hash)?;
463                if let Some(require_canonical) = require_canonical {
464                    s.serialize_field("requireCanonical", require_canonical)?;
465                }
466                s.end()
467            }
468            Self::Number(num) => num.serialize(serializer),
469        }
470    }
471}
472
473#[cfg(feature = "serde")]
474impl<'de> serde::Deserialize<'de> for BlockId {
475    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
476    where
477        D: serde::Deserializer<'de>,
478    {
479        struct BlockIdVisitor;
480
481        impl<'de> serde::de::Visitor<'de> for BlockIdVisitor {
482            type Value = BlockId;
483
484            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
485                formatter.write_str("Block identifier following EIP-1898")
486            }
487
488            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
489            where
490                E: serde::de::Error,
491            {
492                // Since there is no way to clearly distinguish between a DATA parameter and a QUANTITY parameter. A str is therefor deserialized into a Block Number: <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1898.md>
493                // However, since the hex string should be a QUANTITY, we can safely assume that if the len is 66 bytes, it is in fact a hash, ref <https://github.com/ethereum/go-ethereum/blob/ee530c0d5aa70d2c00ab5691a89ab431b73f8165/rpc/types.go#L184-L184>
494                if v.len() == 66 {
495                    Ok(v.parse::<B256>().map_err(serde::de::Error::custom)?.into())
496                } else {
497                    // quantity hex string or tag
498                    Ok(BlockId::Number(v.parse().map_err(serde::de::Error::custom)?))
499                }
500            }
501
502            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
503            where
504                A: serde::de::MapAccess<'de>,
505            {
506                let mut number = None;
507                let mut block_hash = None;
508                let mut require_canonical = None;
509                while let Some(key) = map.next_key::<alloc::string::String>()? {
510                    match key.as_str() {
511                        "blockNumber" => {
512                            if number.is_some() || block_hash.is_some() {
513                                return Err(serde::de::Error::duplicate_field("blockNumber"));
514                            }
515                            if require_canonical.is_some() {
516                                return Err(serde::de::Error::custom(
517                                    "Non-valid require_canonical field",
518                                ));
519                            }
520                            number = Some(map.next_value::<BlockNumberOrTag>()?)
521                        }
522                        "blockHash" => {
523                            if number.is_some() || block_hash.is_some() {
524                                return Err(serde::de::Error::duplicate_field("blockHash"));
525                            }
526
527                            block_hash = Some(map.next_value::<B256>()?);
528                        }
529                        "requireCanonical" => {
530                            if number.is_some() || require_canonical.is_some() {
531                                return Err(serde::de::Error::duplicate_field("requireCanonical"));
532                            }
533
534                            require_canonical = Some(map.next_value::<bool>()?)
535                        }
536                        key => {
537                            return Err(serde::de::Error::unknown_field(
538                                key,
539                                &["blockNumber", "blockHash", "requireCanonical"],
540                            ))
541                        }
542                    }
543                }
544
545                #[expect(clippy::option_if_let_else)]
546                if let Some(number) = number {
547                    Ok(number.into())
548                } else if let Some(block_hash) = block_hash {
549                    Ok((block_hash, require_canonical).into())
550                } else {
551                    Err(serde::de::Error::custom(
552                        "Expected `blockNumber` or `blockHash` with `requireCanonical` optionally",
553                    ))
554                }
555            }
556        }
557
558        deserializer.deserialize_any(BlockIdVisitor)
559    }
560}
561
562impl fmt::Display for BlockId {
563    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
564        match self {
565            Self::Hash(hash) => hash.fmt(f),
566            Self::Number(num) => num.fmt(f),
567        }
568    }
569}
570
571impl fmt::Debug for BlockId {
572    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
573        match self {
574            Self::Hash(hash) => hash.fmt(f),
575            Self::Number(num) => num.fmt(f),
576        }
577    }
578}
579
580/// Error thrown when parsing a [BlockId] from a string.
581#[derive(Debug)]
582pub enum ParseBlockIdError {
583    /// Failed to parse a block id from a number.
584    ParseIntError(ParseIntError),
585    /// Failed to parse hex number
586    ParseError(ParseError),
587    /// Failed to parse a block id as a hex string.
588    FromHexError(FromHexError),
589}
590
591impl fmt::Display for ParseBlockIdError {
592    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
593        match self {
594            Self::ParseIntError(err) => write!(f, "{err}"),
595            Self::ParseError(err) => write!(f, "{err}"),
596            Self::FromHexError(err) => write!(f, "{err}"),
597        }
598    }
599}
600
601impl core::error::Error for ParseBlockIdError {
602    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
603        match self {
604            Self::ParseIntError(err) => Some(err),
605            Self::FromHexError(err) => Some(err),
606            Self::ParseError(_) => None,
607        }
608    }
609}
610
611impl From<ParseIntError> for ParseBlockIdError {
612    fn from(err: ParseIntError) -> Self {
613        Self::ParseIntError(err)
614    }
615}
616
617impl From<FromHexError> for ParseBlockIdError {
618    fn from(err: FromHexError) -> Self {
619        Self::FromHexError(err)
620    }
621}
622
623impl FromStr for BlockId {
624    type Err = ParseBlockIdError;
625    fn from_str(s: &str) -> Result<Self, Self::Err> {
626        if s.starts_with("0x") {
627            return match s.len() {
628                66 => B256::from_str(s).map(Into::into).map_err(ParseBlockIdError::FromHexError),
629                _ => U64::from_str(s).map(Into::into).map_err(ParseBlockIdError::ParseError),
630            };
631        }
632
633        match s {
634            "latest" | "finalized" | "safe" | "earliest" | "pending" => {
635                Ok(BlockNumberOrTag::from_str(s).unwrap().into())
636            }
637            _ => s.parse::<u64>().map_err(ParseBlockIdError::ParseIntError).map(Into::into),
638        }
639    }
640}
641
642/// A number and a hash.
643#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
644#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
645#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
646pub struct NumHash {
647    /// The number
648    pub number: u64,
649    /// The hash.
650    pub hash: B256,
651}
652
653/// Block number and hash of the forked block.
654pub type ForkBlock = NumHash;
655
656/// A block number and a hash
657pub type BlockNumHash = NumHash;
658
659impl NumHash {
660    /// Creates a new `NumHash` from a number and hash.
661    pub const fn new(number: u64, hash: B256) -> Self {
662        Self { number, hash }
663    }
664
665    /// Consumes `Self` and returns the number and hash
666    pub const fn into_components(self) -> (u64, B256) {
667        (self.number, self.hash)
668    }
669
670    /// Returns whether or not the block matches the given [HashOrNumber].
671    pub fn matches_block_or_num(&self, block: &HashOrNumber) -> bool {
672        match block {
673            HashOrNumber::Hash(hash) => self.hash == *hash,
674            HashOrNumber::Number(number) => self.number == *number,
675        }
676    }
677}
678
679impl From<(u64, B256)> for NumHash {
680    fn from(val: (u64, B256)) -> Self {
681        Self { number: val.0, hash: val.1 }
682    }
683}
684
685impl From<(B256, u64)> for NumHash {
686    fn from(val: (B256, u64)) -> Self {
687        Self { hash: val.0, number: val.1 }
688    }
689}
690
691/// Either a hash _or_ a block number
692#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
693#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
694#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
695pub enum HashOrNumber {
696    /// The hash
697    Hash(B256),
698    /// The number
699    Number(u64),
700}
701
702/// A block hash _or_ a block number
703pub type BlockHashOrNumber = HashOrNumber;
704
705// === impl HashOrNumber ===
706
707impl HashOrNumber {
708    /// Returns the block number if it is a [`HashOrNumber::Number`].
709    #[inline]
710    pub const fn as_number(self) -> Option<u64> {
711        match self {
712            Self::Hash(_) => None,
713            Self::Number(num) => Some(num),
714        }
715    }
716
717    /// Returns the block hash if it is a [`HashOrNumber::Hash`].
718    #[inline]
719    pub const fn as_hash(self) -> Option<B256> {
720        match self {
721            Self::Hash(hash) => Some(hash),
722            Self::Number(_) => None,
723        }
724    }
725}
726
727impl From<B256> for HashOrNumber {
728    fn from(value: B256) -> Self {
729        Self::Hash(value)
730    }
731}
732
733impl From<&B256> for HashOrNumber {
734    fn from(value: &B256) -> Self {
735        (*value).into()
736    }
737}
738
739impl From<u64> for HashOrNumber {
740    fn from(value: u64) -> Self {
741        Self::Number(value)
742    }
743}
744
745impl From<U64> for HashOrNumber {
746    fn from(value: U64) -> Self {
747        value.to::<u64>().into()
748    }
749}
750
751impl From<RpcBlockHash> for HashOrNumber {
752    fn from(value: RpcBlockHash) -> Self {
753        Self::Hash(value.into())
754    }
755}
756
757/// Allows for RLP encoding of either a hash or a number
758impl Encodable for HashOrNumber {
759    fn encode(&self, out: &mut dyn bytes::BufMut) {
760        match self {
761            Self::Hash(block_hash) => block_hash.encode(out),
762            Self::Number(block_number) => block_number.encode(out),
763        }
764    }
765    fn length(&self) -> usize {
766        match self {
767            Self::Hash(block_hash) => block_hash.length(),
768            Self::Number(block_number) => block_number.length(),
769        }
770    }
771}
772
773/// Allows for RLP decoding of a hash or number
774impl Decodable for HashOrNumber {
775    fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
776        let header: u8 = *buf.first().ok_or(RlpError::InputTooShort)?;
777        // if the byte string is exactly 32 bytes, decode it into a Hash
778        // 0xa0 = 0x80 (start of string) + 0x20 (32, length of string)
779        if header == 0xa0 {
780            // strip the first byte, parsing the rest of the string.
781            // If the rest of the string fails to decode into 32 bytes, we'll bubble up the
782            // decoding error.
783            Ok(B256::decode(buf)?.into())
784        } else {
785            // a block number when encoded as bytes ranges from 0 to any number of bytes - we're
786            // going to accept numbers which fit in less than 64 bytes.
787            // Any data larger than this which is not caught by the Hash decoding should error and
788            // is considered an invalid block number.
789            Ok(u64::decode(buf)?.into())
790        }
791    }
792}
793
794impl fmt::Display for HashOrNumber {
795    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
796        match self {
797            Self::Hash(hash) => write!(f, "{hash}"),
798            Self::Number(num) => write!(f, "{num}"),
799        }
800    }
801}
802
803/// Error thrown when parsing a [HashOrNumber] from a string.
804#[derive(Debug)]
805pub struct ParseBlockHashOrNumberError {
806    input: alloc::string::String,
807    parse_int_error: ParseIntError,
808    hex_error: alloy_primitives::hex::FromHexError,
809}
810
811impl fmt::Display for ParseBlockHashOrNumberError {
812    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
813        write!(
814            f,
815            "failed to parse {:?} as a number: {} or hash: {}",
816            self.input, self.parse_int_error, self.hex_error
817        )
818    }
819}
820
821impl core::error::Error for ParseBlockHashOrNumberError {}
822
823impl FromStr for HashOrNumber {
824    type Err = ParseBlockHashOrNumberError;
825
826    fn from_str(s: &str) -> Result<Self, Self::Err> {
827        use alloc::string::ToString;
828
829        match u64::from_str(s) {
830            Ok(val) => Ok(val.into()),
831            Err(parse_int_error) => match B256::from_str(s) {
832                Ok(val) => Ok(val.into()),
833                Err(hex_error) => Err(ParseBlockHashOrNumberError {
834                    input: s.to_string(),
835                    parse_int_error,
836                    hex_error,
837                }),
838            },
839        }
840    }
841}
842
843#[cfg(test)]
844mod tests {
845    use super::*;
846    use alloc::{string::ToString, vec::Vec};
847    use alloy_primitives::b256;
848
849    const HASH: B256 = b256!("1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9");
850
851    #[test]
852    fn block_id_from_str() {
853        assert_eq!("0x0".parse::<BlockId>().unwrap(), BlockId::number(0));
854        assert_eq!("0x24A931".parse::<BlockId>().unwrap(), BlockId::number(2402609));
855        assert_eq!(
856            "0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
857                .parse::<BlockId>()
858                .unwrap(),
859            HASH.into()
860        );
861    }
862
863    #[test]
864    #[cfg(feature = "serde")]
865    fn compact_block_number_serde() {
866        let num: BlockNumberOrTag = 1u64.into();
867        let serialized = serde_json::to_string(&num).unwrap();
868        assert_eq!(serialized, "\"0x1\"");
869    }
870
871    #[test]
872    fn block_id_as_u64() {
873        assert_eq!(BlockId::number(123).as_u64(), Some(123));
874        assert_eq!(BlockId::number(0).as_u64(), Some(0));
875        assert_eq!(BlockId::earliest().as_u64(), None);
876        assert_eq!(BlockId::latest().as_u64(), None);
877        assert_eq!(BlockId::pending().as_u64(), None);
878        assert_eq!(BlockId::safe().as_u64(), None);
879        assert_eq!(BlockId::hash(BlockHash::ZERO).as_u64(), None);
880        assert_eq!(BlockId::hash_canonical(BlockHash::ZERO).as_u64(), None);
881    }
882
883    #[test]
884    #[cfg(feature = "serde")]
885    fn can_parse_eip1898_block_ids() {
886        let num = serde_json::json!(
887            { "blockNumber": "0x0" }
888        );
889        let id = serde_json::from_value::<BlockId>(num).unwrap();
890        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Number(0u64)));
891
892        let num = serde_json::json!(
893            { "blockNumber": "pending" }
894        );
895        let id = serde_json::from_value::<BlockId>(num).unwrap();
896        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Pending));
897
898        let num = serde_json::json!(
899            { "blockNumber": "latest" }
900        );
901        let id = serde_json::from_value::<BlockId>(num).unwrap();
902        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Latest));
903
904        let num = serde_json::json!(
905            { "blockNumber": "finalized" }
906        );
907        let id = serde_json::from_value::<BlockId>(num).unwrap();
908        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Finalized));
909
910        let num = serde_json::json!(
911            { "blockNumber": "safe" }
912        );
913        let id = serde_json::from_value::<BlockId>(num).unwrap();
914        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Safe));
915
916        let num = serde_json::json!(
917            { "blockNumber": "earliest" }
918        );
919        let id = serde_json::from_value::<BlockId>(num).unwrap();
920        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Earliest));
921
922        let num = serde_json::json!("0x0");
923        let id = serde_json::from_value::<BlockId>(num).unwrap();
924        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Number(0u64)));
925
926        let num = serde_json::json!("pending");
927        let id = serde_json::from_value::<BlockId>(num).unwrap();
928        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Pending));
929
930        let num = serde_json::json!("latest");
931        let id = serde_json::from_value::<BlockId>(num).unwrap();
932        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Latest));
933
934        let num = serde_json::json!("finalized");
935        let id = serde_json::from_value::<BlockId>(num).unwrap();
936        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Finalized));
937
938        let num = serde_json::json!("safe");
939        let id = serde_json::from_value::<BlockId>(num).unwrap();
940        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Safe));
941
942        let num = serde_json::json!("earliest");
943        let id = serde_json::from_value::<BlockId>(num).unwrap();
944        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Earliest));
945
946        let num = serde_json::json!(
947            { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" }
948        );
949        let id = serde_json::from_value::<BlockId>(num).unwrap();
950        assert_eq!(
951            id,
952            BlockId::Hash(
953                "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
954                    .parse::<B256>()
955                    .unwrap()
956                    .into()
957            )
958        );
959    }
960
961    #[test]
962    fn display_rpc_block_hash() {
963        let hash = RpcBlockHash::from_hash(HASH, Some(true));
964
965        assert_eq!(
966            hash.to_string(),
967            "canonical hash 0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
968        );
969
970        let hash = RpcBlockHash::from_hash(HASH, None);
971
972        assert_eq!(
973            hash.to_string(),
974            "hash 0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
975        );
976    }
977
978    #[test]
979    fn display_block_id() {
980        let id = BlockId::hash(HASH);
981
982        assert_eq!(
983            id.to_string(),
984            "hash 0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
985        );
986
987        let id = BlockId::hash_canonical(HASH);
988
989        assert_eq!(
990            id.to_string(),
991            "canonical hash 0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
992        );
993
994        let id = BlockId::number(100000);
995
996        assert_eq!(id.to_string(), "0x186a0");
997
998        let id = BlockId::latest();
999
1000        assert_eq!(id.to_string(), "latest");
1001
1002        let id = BlockId::safe();
1003
1004        assert_eq!(id.to_string(), "safe");
1005
1006        let id = BlockId::finalized();
1007
1008        assert_eq!(id.to_string(), "finalized");
1009
1010        let id = BlockId::earliest();
1011
1012        assert_eq!(id.to_string(), "earliest");
1013
1014        let id = BlockId::pending();
1015
1016        assert_eq!(id.to_string(), "pending");
1017    }
1018
1019    #[test]
1020    fn test_block_number_or_tag() {
1021        // Test Latest variant
1022        let latest = BlockNumberOrTag::Latest;
1023        assert_eq!(latest.as_number(), None);
1024        assert!(latest.is_latest());
1025        assert!(!latest.is_number());
1026        assert!(!latest.is_finalized());
1027        assert!(!latest.is_safe());
1028        assert!(!latest.is_pending());
1029        assert!(!latest.is_earliest());
1030
1031        // Test Finalized variant
1032        let finalized = BlockNumberOrTag::Finalized;
1033        assert_eq!(finalized.as_number(), None);
1034        assert!(finalized.is_finalized());
1035        assert!(!finalized.is_latest());
1036        assert!(!finalized.is_number());
1037        assert!(!finalized.is_safe());
1038        assert!(!finalized.is_pending());
1039        assert!(!finalized.is_earliest());
1040
1041        // Test Safe variant
1042        let safe = BlockNumberOrTag::Safe;
1043        assert_eq!(safe.as_number(), None);
1044        assert!(safe.is_safe());
1045        assert!(!safe.is_latest());
1046        assert!(!safe.is_number());
1047        assert!(!safe.is_finalized());
1048        assert!(!safe.is_pending());
1049        assert!(!safe.is_earliest());
1050
1051        // Test Earliest variant
1052        let earliest = BlockNumberOrTag::Earliest;
1053        assert_eq!(earliest.as_number(), None);
1054        assert!(earliest.is_earliest());
1055        assert!(!earliest.is_latest());
1056        assert!(!earliest.is_number());
1057        assert!(!earliest.is_finalized());
1058        assert!(!earliest.is_safe());
1059        assert!(!earliest.is_pending());
1060
1061        // Test Pending variant
1062        let pending = BlockNumberOrTag::Pending;
1063        assert_eq!(pending.as_number(), None);
1064        assert!(pending.is_pending());
1065        assert!(!pending.is_latest());
1066        assert!(!pending.is_number());
1067        assert!(!pending.is_finalized());
1068        assert!(!pending.is_safe());
1069        assert!(!pending.is_earliest());
1070
1071        // Test Number variant
1072        let number = BlockNumberOrTag::Number(42);
1073        assert_eq!(number.as_number(), Some(42));
1074        assert!(number.is_number());
1075        assert!(!number.is_latest());
1076        assert!(!number.is_finalized());
1077        assert!(!number.is_safe());
1078        assert!(!number.is_pending());
1079        assert!(!number.is_earliest());
1080    }
1081
1082    #[test]
1083    fn test_block_number_or_tag_from() {
1084        // Test conversion from u64
1085        let num = 100u64;
1086        let block: BlockNumberOrTag = num.into();
1087        assert_eq!(block, BlockNumberOrTag::Number(100));
1088
1089        // Test conversion from U64
1090        let num = U64::from(200);
1091        let block: BlockNumberOrTag = num.into();
1092        assert_eq!(block, BlockNumberOrTag::Number(200));
1093    }
1094
1095    #[test]
1096    fn test_block_id() {
1097        let hash = BlockHash::random();
1098
1099        // Block hash
1100        let block_id_hash = BlockId::hash(hash);
1101        assert_eq!(block_id_hash.as_block_hash(), Some(hash));
1102        assert!(block_id_hash.is_hash());
1103        assert!(!block_id_hash.is_number());
1104        assert!(!block_id_hash.is_latest());
1105        assert!(!block_id_hash.is_pending());
1106        assert!(!block_id_hash.is_safe());
1107        assert!(!block_id_hash.is_finalized());
1108        assert!(!block_id_hash.is_earliest());
1109
1110        // Block number
1111        let block_id_number = BlockId::number(123);
1112        assert_eq!(block_id_number.as_u64(), Some(123));
1113        assert!(block_id_number.is_number());
1114        assert!(!block_id_number.is_hash());
1115        assert!(!block_id_number.is_latest());
1116        assert!(!block_id_number.is_pending());
1117        assert!(!block_id_number.is_safe());
1118        assert!(!block_id_number.is_finalized());
1119        assert!(!block_id_number.is_earliest());
1120
1121        // Latest block
1122        let block_latest = BlockId::latest();
1123        assert!(block_latest.is_latest());
1124        assert!(!block_latest.is_number());
1125        assert!(!block_latest.is_hash());
1126        assert!(!block_latest.is_pending());
1127        assert!(!block_latest.is_safe());
1128        assert!(!block_latest.is_finalized());
1129        assert!(!block_latest.is_earliest());
1130
1131        // Pending block
1132        let block_pending = BlockId::pending();
1133        assert!(block_pending.is_pending());
1134        assert!(!block_pending.is_latest());
1135        assert!(!block_pending.is_number());
1136        assert!(!block_pending.is_hash());
1137        assert!(!block_pending.is_safe());
1138        assert!(!block_pending.is_finalized());
1139        assert!(!block_pending.is_earliest());
1140
1141        // Safe block
1142        let block_safe = BlockId::safe();
1143        assert!(block_safe.is_safe());
1144        assert!(!block_safe.is_latest());
1145        assert!(!block_safe.is_number());
1146        assert!(!block_safe.is_hash());
1147        assert!(!block_safe.is_pending());
1148        assert!(!block_safe.is_finalized());
1149        assert!(!block_safe.is_earliest());
1150
1151        // Finalized block
1152        let block_finalized = BlockId::finalized();
1153        assert!(block_finalized.is_finalized());
1154        assert!(!block_finalized.is_latest());
1155        assert!(!block_finalized.is_number());
1156        assert!(!block_finalized.is_hash());
1157        assert!(!block_finalized.is_pending());
1158        assert!(!block_finalized.is_safe());
1159        assert!(!block_finalized.is_earliest());
1160
1161        // Earliest block
1162        let block_earliest = BlockId::earliest();
1163        assert!(block_earliest.is_earliest());
1164        assert!(!block_earliest.is_latest());
1165        assert!(!block_earliest.is_number());
1166        assert!(!block_earliest.is_hash());
1167        assert!(!block_earliest.is_pending());
1168        assert!(!block_earliest.is_safe());
1169        assert!(!block_earliest.is_finalized());
1170
1171        // Default block
1172        assert!(BlockId::default().is_latest());
1173        assert!(!BlockId::default().is_number());
1174        assert!(!BlockId::default().is_hash());
1175        assert!(!BlockId::default().is_pending());
1176        assert!(!BlockId::default().is_safe());
1177        assert!(!BlockId::default().is_finalized());
1178        assert!(!BlockId::default().is_earliest());
1179    }
1180
1181    #[test]
1182    fn test_u64_to_block_id() {
1183        // Simple u64
1184        let num: u64 = 123;
1185        let block_id: BlockId = num.into();
1186
1187        match block_id {
1188            BlockId::Number(BlockNumberOrTag::Number(n)) => assert_eq!(n, 123),
1189            _ => panic!("Expected BlockId::Number with 123"),
1190        }
1191
1192        // Big integer U64
1193        let num: U64 = U64::from(456);
1194        let block_id: BlockId = num.into();
1195
1196        match block_id {
1197            BlockId::Number(BlockNumberOrTag::Number(n)) => assert_eq!(n, 456),
1198            _ => panic!("Expected BlockId::Number with 456"),
1199        }
1200
1201        // u64 as HashOrNumber
1202        let num: u64 = 789;
1203        let block_id: BlockId = HashOrNumber::Number(num).into();
1204
1205        match block_id {
1206            BlockId::Number(BlockNumberOrTag::Number(n)) => assert_eq!(n, 789),
1207            _ => panic!("Expected BlockId::Number with 789"),
1208        }
1209    }
1210
1211    #[test]
1212    fn test_block_number_or_tag_to_block_id() {
1213        let block_number_or_tag = BlockNumberOrTag::Pending;
1214        let block_id: BlockId = block_number_or_tag.into();
1215
1216        match block_id {
1217            BlockId::Number(BlockNumberOrTag::Pending) => {}
1218            _ => panic!("Expected BlockId::Number with Pending"),
1219        }
1220    }
1221
1222    #[test]
1223    fn test_hash_or_number_to_block_id_hash() {
1224        // B256 wrapped in HashOrNumber
1225        let hash: B256 = B256::random();
1226        let block_id: BlockId = HashOrNumber::Hash(hash).into();
1227
1228        match block_id {
1229            BlockId::Hash(rpc_block_hash) => assert_eq!(rpc_block_hash.block_hash, hash),
1230            _ => panic!("Expected BlockId::Hash"),
1231        }
1232
1233        // Simple B256
1234        let hash: B256 = B256::random();
1235        let block_id: BlockId = hash.into();
1236
1237        match block_id {
1238            BlockId::Hash(rpc_block_hash) => assert_eq!(rpc_block_hash.block_hash, hash),
1239            _ => panic!("Expected BlockId::Hash"),
1240        }
1241
1242        // Tuple with B256 and canonical flag
1243        let hash: B256 = B256::random();
1244        let block_id: BlockId = (hash, Some(true)).into();
1245
1246        match block_id {
1247            BlockId::Hash(rpc_block_hash) => {
1248                assert_eq!(rpc_block_hash.block_hash, hash);
1249                assert_eq!(rpc_block_hash.require_canonical, Some(true));
1250            }
1251            _ => panic!("Expected BlockId::Hash with canonical flag"),
1252        }
1253    }
1254
1255    #[test]
1256    fn test_hash_or_number_as_number() {
1257        // Test with a number
1258        let hash_or_number = HashOrNumber::Number(123);
1259        assert_eq!(hash_or_number.as_number(), Some(123));
1260
1261        // Test with a hash
1262        let hash = B256::random();
1263        let hash_or_number = HashOrNumber::Hash(hash);
1264        assert_eq!(hash_or_number.as_number(), None);
1265    }
1266
1267    #[test]
1268    fn test_hash_or_number_as_hash() {
1269        // Test with a hash
1270        let hash = B256::random();
1271        let hash_or_number = HashOrNumber::Hash(hash);
1272        assert_eq!(hash_or_number.as_hash(), Some(hash));
1273
1274        // Test with a number
1275        let hash_or_number = HashOrNumber::Number(456);
1276        assert_eq!(hash_or_number.as_hash(), None);
1277    }
1278
1279    #[test]
1280    fn test_hash_or_number_conversions() {
1281        // Test conversion from B256
1282        let hash = B256::random();
1283        let hash_or_number: HashOrNumber = hash.into();
1284        assert_eq!(hash_or_number, HashOrNumber::Hash(hash));
1285
1286        // Test conversion from &B256
1287        let hash_ref: HashOrNumber = (&hash).into();
1288        assert_eq!(hash_ref, HashOrNumber::Hash(hash));
1289
1290        // Test conversion from u64
1291        let number: u64 = 123;
1292        let hash_or_number: HashOrNumber = number.into();
1293        assert_eq!(hash_or_number, HashOrNumber::Number(number));
1294
1295        // Test conversion from U64
1296        let u64_value = U64::from(456);
1297        let hash_or_number: HashOrNumber = u64_value.into();
1298        assert_eq!(hash_or_number, HashOrNumber::Number(u64_value.to::<u64>()));
1299
1300        // Test conversion from RpcBlockHash (assuming RpcBlockHash is convertible to B256)
1301        let rpc_block_hash = RpcBlockHash { block_hash: hash, require_canonical: Some(true) };
1302        let hash_or_number: HashOrNumber = rpc_block_hash.into();
1303        assert_eq!(hash_or_number, HashOrNumber::Hash(hash));
1304    }
1305
1306    #[test]
1307    fn test_hash_or_number_rlp_roundtrip_hash() {
1308        // Test case: encoding and decoding a B256 hash
1309        let original_hash = B256::random();
1310        let hash_or_number: HashOrNumber = HashOrNumber::Hash(original_hash);
1311
1312        // Encode the HashOrNumber
1313        let mut buf = Vec::new();
1314        hash_or_number.encode(&mut buf);
1315
1316        // Decode the encoded bytes
1317        let decoded: HashOrNumber = HashOrNumber::decode(&mut &buf[..]).expect("Decoding failed");
1318
1319        // Assert that the decoded value matches the original
1320        assert_eq!(decoded, hash_or_number);
1321    }
1322
1323    #[test]
1324    fn test_hash_or_number_rlp_roundtrip_u64() {
1325        // Test case: encoding and decoding a u64 number
1326        let original_number: u64 = 12345;
1327        let hash_or_number: HashOrNumber = HashOrNumber::Number(original_number);
1328
1329        // Encode the HashOrNumber
1330        let mut buf = Vec::new();
1331        hash_or_number.encode(&mut buf);
1332
1333        // Decode the encoded bytes
1334        let decoded: HashOrNumber = HashOrNumber::decode(&mut &buf[..]).expect("Decoding failed");
1335
1336        // Assert that the decoded value matches the original
1337        assert_eq!(decoded, hash_or_number);
1338    }
1339
1340    #[test]
1341    fn test_numhash() {
1342        let number: u64 = 42;
1343        let hash = B256::random();
1344
1345        let num_hash = NumHash::new(number, hash);
1346
1347        // Validate the initial values
1348        assert_eq!(num_hash.number, number);
1349        assert_eq!(num_hash.hash, hash);
1350
1351        // Test into_components
1352        assert_eq!(num_hash.into_components(), (number, hash));
1353    }
1354
1355    #[test]
1356    fn test_numhash_matches_block_or_num() {
1357        let number: u64 = 42;
1358        let hash = B256::random();
1359
1360        let num_hash = NumHash::new(number, hash);
1361
1362        // Test matching by hash
1363        let block_hash = HashOrNumber::Hash(hash);
1364        assert!(num_hash.matches_block_or_num(&block_hash));
1365
1366        // Test matching by number
1367        let block_number = HashOrNumber::Number(number);
1368        assert!(num_hash.matches_block_or_num(&block_number));
1369
1370        // Test non-matching by different hash
1371        let different_hash = B256::random();
1372        let non_matching_hash = HashOrNumber::Hash(different_hash);
1373        assert!(!num_hash.matches_block_or_num(&non_matching_hash));
1374
1375        // Test non-matching by different number
1376        let different_number: u64 = 43;
1377        let non_matching_number = HashOrNumber::Number(different_number);
1378        assert!(!num_hash.matches_block_or_num(&non_matching_number));
1379    }
1380
1381    #[test]
1382    fn test_numhash_conversions() {
1383        // From a tuple (u64, B256)
1384        let number: u64 = 42;
1385        let hash = B256::random();
1386
1387        let num_hash_from_tuple: NumHash = (number, hash).into();
1388
1389        assert_eq!(num_hash_from_tuple.number, number);
1390        assert_eq!(num_hash_from_tuple.hash, hash);
1391
1392        // From a reversed tuple (B256, u64)
1393        let number: u64 = 42;
1394        let hash = B256::random();
1395
1396        let num_hash_from_reversed_tuple: NumHash = (hash, number).into();
1397
1398        assert_eq!(num_hash_from_reversed_tuple.number, number);
1399        assert_eq!(num_hash_from_reversed_tuple.hash, hash);
1400    }
1401
1402    #[test]
1403    #[cfg(feature = "serde")]
1404    fn test_block_id_from_str() {
1405        // Valid hexadecimal block ID (with 0x prefix)
1406        let hex_id = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
1407        assert_eq!(
1408            BlockId::from_str(hex_id).unwrap(),
1409            BlockId::Hash(RpcBlockHash::from_hash(B256::from_str(hex_id).unwrap(), None))
1410        );
1411
1412        // Valid tag strings
1413        assert_eq!(BlockId::from_str("latest").unwrap(), BlockNumberOrTag::Latest.into());
1414        assert_eq!(BlockId::from_str("finalized").unwrap(), BlockNumberOrTag::Finalized.into());
1415        assert_eq!(BlockId::from_str("safe").unwrap(), BlockNumberOrTag::Safe.into());
1416        assert_eq!(BlockId::from_str("earliest").unwrap(), BlockNumberOrTag::Earliest.into());
1417        assert_eq!(BlockId::from_str("pending").unwrap(), BlockNumberOrTag::Pending.into());
1418
1419        // Valid numeric string without prefix
1420        let numeric_string = "12345";
1421        let parsed_numeric_string = BlockId::from_str(numeric_string);
1422        assert!(parsed_numeric_string.is_ok());
1423
1424        // Hex interpretation of numeric string
1425        assert_eq!(
1426            BlockId::from_str("0x12345").unwrap(),
1427            BlockId::Number(BlockNumberOrTag::Number(74565))
1428        );
1429
1430        // Invalid non-numeric string
1431        let invalid_string = "invalid_block_id";
1432        let parsed_invalid_string = BlockId::from_str(invalid_string);
1433        assert!(parsed_invalid_string.is_err());
1434    }
1435
1436    /// Check parsing according to EIP-1898.
1437    #[test]
1438    #[cfg(feature = "serde")]
1439    fn can_parse_blockid_u64() {
1440        let num = serde_json::json!(
1441            {"blockNumber": "0xaf"}
1442        );
1443
1444        let id = serde_json::from_value::<BlockId>(num);
1445        assert_eq!(id.unwrap(), BlockId::from(175));
1446    }
1447
1448    #[test]
1449    #[cfg(feature = "serde")]
1450    fn can_parse_block_hash() {
1451        let block_hash =
1452            B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
1453                .unwrap();
1454        let block_hash_json = serde_json::json!(
1455            { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}
1456        );
1457        let id = serde_json::from_value::<BlockId>(block_hash_json).unwrap();
1458        assert_eq!(id, BlockId::from(block_hash,));
1459    }
1460
1461    #[test]
1462    #[cfg(feature = "serde")]
1463    fn can_parse_block_hash_with_canonical() {
1464        let block_hash =
1465            B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
1466                .unwrap();
1467        let block_id = BlockId::Hash(RpcBlockHash::from_hash(block_hash, Some(true)));
1468        let block_hash_json = serde_json::json!(
1469            { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true }
1470        );
1471        let id = serde_json::from_value::<BlockId>(block_hash_json).unwrap();
1472        assert_eq!(id, block_id)
1473    }
1474    #[test]
1475    #[cfg(feature = "serde")]
1476    fn can_parse_blockid_tags() {
1477        let tags = [
1478            ("latest", BlockNumberOrTag::Latest),
1479            ("finalized", BlockNumberOrTag::Finalized),
1480            ("safe", BlockNumberOrTag::Safe),
1481            ("pending", BlockNumberOrTag::Pending),
1482        ];
1483        for (value, tag) in tags {
1484            let num = serde_json::json!({ "blockNumber": value });
1485            let id = serde_json::from_value::<BlockId>(num);
1486            assert_eq!(id.unwrap(), BlockId::from(tag))
1487        }
1488    }
1489    #[test]
1490    #[cfg(feature = "serde")]
1491    fn repeated_keys_is_err() {
1492        let num = serde_json::json!({"blockNumber": 1, "requireCanonical": true, "requireCanonical": false});
1493        assert!(serde_json::from_value::<BlockId>(num).is_err());
1494        let num =
1495            serde_json::json!({"blockNumber": 1, "requireCanonical": true, "blockNumber": 23});
1496        assert!(serde_json::from_value::<BlockId>(num).is_err());
1497    }
1498
1499    /// Serde tests
1500    #[test]
1501    #[cfg(feature = "serde")]
1502    fn serde_blockid_tags() {
1503        let block_ids = [
1504            BlockNumberOrTag::Latest,
1505            BlockNumberOrTag::Finalized,
1506            BlockNumberOrTag::Safe,
1507            BlockNumberOrTag::Pending,
1508        ]
1509        .map(BlockId::from);
1510        for block_id in &block_ids {
1511            let serialized = serde_json::to_string(&block_id).unwrap();
1512            let deserialized: BlockId = serde_json::from_str(&serialized).unwrap();
1513            assert_eq!(deserialized, *block_id)
1514        }
1515    }
1516
1517    #[test]
1518    #[cfg(feature = "serde")]
1519    fn serde_blockid_number() {
1520        let block_id = BlockId::from(100u64);
1521        let serialized = serde_json::to_string(&block_id).unwrap();
1522        let deserialized: BlockId = serde_json::from_str(&serialized).unwrap();
1523        assert_eq!(deserialized, block_id)
1524    }
1525
1526    #[test]
1527    #[cfg(feature = "serde")]
1528    fn serde_blockid_hash() {
1529        let block_id = BlockId::from(B256::default());
1530        let serialized = serde_json::to_string(&block_id).unwrap();
1531        let deserialized: BlockId = serde_json::from_str(&serialized).unwrap();
1532        assert_eq!(deserialized, block_id)
1533    }
1534
1535    #[test]
1536    #[cfg(feature = "serde")]
1537    fn serde_blockid_hash_from_str() {
1538        let val = "\"0x898753d8fdd8d92c1907ca21e68c7970abd290c647a202091181deec3f30a0b2\"";
1539        let block_hash: B256 = serde_json::from_str(val).unwrap();
1540        let block_id: BlockId = serde_json::from_str(val).unwrap();
1541        assert_eq!(block_id, BlockId::Hash(block_hash.into()));
1542    }
1543
1544    #[test]
1545    #[cfg(feature = "serde")]
1546    fn serde_rpc_payload_block_tag() {
1547        let payload = r#"{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},"latest"],"id":1,"jsonrpc":"2.0"}"#;
1548        let value: serde_json::Value = serde_json::from_str(payload).unwrap();
1549        let block_id_param = value.pointer("/params/1").unwrap();
1550        let block_id: BlockId = serde_json::from_value::<BlockId>(block_id_param.clone()).unwrap();
1551        assert_eq!(BlockId::Number(BlockNumberOrTag::Latest), block_id);
1552    }
1553
1554    #[test]
1555    #[cfg(feature = "serde")]
1556    fn serde_rpc_payload_block_object() {
1557        let example_payload = r#"{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},{"blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}],"id":1,"jsonrpc":"2.0"}"#;
1558        let value: serde_json::Value = serde_json::from_str(example_payload).unwrap();
1559        let block_id_param = value.pointer("/params/1").unwrap().to_string();
1560        let block_id: BlockId = serde_json::from_str::<BlockId>(&block_id_param).unwrap();
1561        let hash =
1562            B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
1563                .unwrap();
1564        assert_eq!(BlockId::from(hash), block_id);
1565        let serialized = serde_json::to_string(&BlockId::from(hash)).unwrap();
1566        assert_eq!("{\"blockHash\":\"0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3\"}", serialized)
1567    }
1568
1569    #[test]
1570    #[cfg(feature = "serde")]
1571    fn serde_rpc_payload_block_number() {
1572        let example_payload = r#"{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},{"blockNumber": "0x0"}],"id":1,"jsonrpc":"2.0"}"#;
1573        let value: serde_json::Value = serde_json::from_str(example_payload).unwrap();
1574        let block_id_param = value.pointer("/params/1").unwrap().to_string();
1575        let block_id: BlockId = serde_json::from_str::<BlockId>(&block_id_param).unwrap();
1576        assert_eq!(BlockId::from(0u64), block_id);
1577        let serialized = serde_json::to_string(&BlockId::from(0u64)).unwrap();
1578        assert_eq!("\"0x0\"", serialized)
1579    }
1580
1581    #[test]
1582    #[should_panic]
1583    #[cfg(feature = "serde")]
1584    fn serde_rpc_payload_block_number_duplicate_key() {
1585        let payload = r#"{"blockNumber": "0x132", "blockNumber": "0x133"}"#;
1586        let parsed_block_id = serde_json::from_str::<BlockId>(payload);
1587        parsed_block_id.unwrap();
1588    }
1589
1590    #[test]
1591    #[cfg(feature = "serde")]
1592    fn serde_rpc_payload_block_hash() {
1593        let payload = r#"{"blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}"#;
1594        let parsed = serde_json::from_str::<BlockId>(payload).unwrap();
1595        let expected = BlockId::from(
1596            B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
1597                .unwrap(),
1598        );
1599        assert_eq!(parsed, expected);
1600    }
1601
1602    #[test]
1603    #[cfg(feature = "serde")]
1604    fn serde_blocknumber_non_0xprefix() {
1605        let s = "\"2\"";
1606        let err = serde_json::from_str::<BlockNumberOrTag>(s).unwrap_err();
1607        assert_eq!(err.to_string(), HexStringMissingPrefixError::default().to_string());
1608    }
1609}