1use 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#[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 pub parent: B256,
19 pub block: BlockNumHash,
21}
22
23impl BlockWithParent {
24 pub const fn new(parent: B256, block: BlockNumHash) -> Self {
26 Self { parent, block }
27 }
28}
29
30#[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 pub block_hash: BlockHash,
42 pub require_canonical: Option<bool>,
44}
45
46impl RpcBlockHash {
47 #[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#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
99pub enum BlockNumberOrTag {
100 #[default]
102 Latest,
103 Finalized,
105 Safe,
107 Earliest,
109 Pending,
111 Number(u64),
113}
114
115impl BlockNumberOrTag {
116 pub const fn as_number(&self) -> Option<u64> {
118 match *self {
119 Self::Number(num) => Some(num),
120 _ => None,
121 }
122 }
123
124 pub const fn is_number(&self) -> bool {
126 matches!(self, Self::Number(_))
127 }
128
129 pub const fn is_latest(&self) -> bool {
131 matches!(self, Self::Latest)
132 }
133
134 pub const fn is_finalized(&self) -> bool {
136 matches!(self, Self::Finalized)
137 }
138
139 pub const fn is_safe(&self) -> bool {
141 matches!(self, Self::Safe)
142 }
143
144 pub const fn is_pending(&self) -> bool {
146 matches!(self, Self::Pending)
147 }
148
149 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#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
242pub struct LenientBlockNumberOrTag(BlockNumberOrTag);
243
244impl LenientBlockNumberOrTag {
245 pub const fn new(block_number_or_tag: BlockNumberOrTag) -> Self {
247 Self(block_number_or_tag)
248 }
249
250 pub const fn into_inner(self) -> BlockNumberOrTag {
252 self.0
253 }
254}
255
256impl From<LenientBlockNumberOrTag> for BlockNumberOrTag {
257 fn from(value: LenientBlockNumberOrTag) -> Self {
258 value.0
259 }
260}
261
262#[cfg(feature = "serde")]
264pub mod lenient_block_number_or_tag {
265 use super::{BlockNumberOrTag, LenientBlockNumberOrTag};
266 use core::fmt;
267 use serde::{
268 de::{self, Visitor},
269 Deserialize, Deserializer,
270 };
271
272 pub fn deserialize<'de, D>(deserializer: D) -> Result<BlockNumberOrTag, D::Error>
291 where
292 D: Deserializer<'de>,
293 {
294 LenientBlockNumberOrTag::deserialize(deserializer).map(Into::into)
295 }
296
297 impl<'de> Deserialize<'de> for LenientBlockNumberOrTag {
298 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
299 where
300 D: Deserializer<'de>,
301 {
302 struct LenientBlockNumberVisitor;
303
304 impl<'de> Visitor<'de> for LenientBlockNumberVisitor {
305 type Value = LenientBlockNumberOrTag;
306
307 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
308 formatter.write_str("a block number or tag, or a u64")
309 }
310
311 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
312 where
313 E: de::Error,
314 {
315 Ok(LenientBlockNumberOrTag(v.into()))
316 }
317
318 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
319 where
320 E: de::Error,
321 {
322 if let Ok(num) = v.parse::<u64>() {
324 return Ok(LenientBlockNumberOrTag(BlockNumberOrTag::Number(num)));
325 }
326
327 BlockNumberOrTag::deserialize(de::value::StrDeserializer::<E>::new(v))
328 .map(LenientBlockNumberOrTag)
329 .map_err(de::Error::custom)
330 }
331 }
332
333 deserializer.deserialize_any(LenientBlockNumberVisitor)
334 }
335 }
336}
337
338#[derive(Debug)]
340pub enum ParseBlockNumberError {
341 ParseIntErr(ParseIntError),
343 ParseErr(ParseError),
345 MissingPrefix(HexStringMissingPrefixError),
347}
348
349impl core::error::Error for ParseBlockNumberError {
351 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
352 match self {
353 Self::ParseIntErr(err) => Some(err),
354 Self::MissingPrefix(err) => Some(err),
355 Self::ParseErr(_) => None,
356 }
357 }
358}
359
360impl fmt::Display for ParseBlockNumberError {
361 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
362 match self {
363 Self::ParseIntErr(err) => write!(f, "{err}"),
364 Self::ParseErr(err) => write!(f, "{err}"),
365 Self::MissingPrefix(err) => write!(f, "{err}"),
366 }
367 }
368}
369
370impl From<ParseIntError> for ParseBlockNumberError {
371 fn from(err: ParseIntError) -> Self {
372 Self::ParseIntErr(err)
373 }
374}
375
376impl From<ParseError> for ParseBlockNumberError {
377 fn from(err: ParseError) -> Self {
378 Self::ParseErr(err)
379 }
380}
381
382impl From<HexStringMissingPrefixError> for ParseBlockNumberError {
383 fn from(err: HexStringMissingPrefixError) -> Self {
384 Self::MissingPrefix(err)
385 }
386}
387
388#[derive(Clone, Copy, Debug, Default)]
390#[non_exhaustive]
391pub struct HexStringMissingPrefixError;
392
393impl fmt::Display for HexStringMissingPrefixError {
394 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
395 f.write_str("hex string without 0x prefix")
396 }
397}
398
399impl core::error::Error for HexStringMissingPrefixError {}
400
401#[derive(Clone, Copy, PartialEq, Eq)]
404pub enum BlockId {
405 Hash(RpcBlockHash),
407 Number(BlockNumberOrTag),
409}
410
411impl BlockId {
412 pub const fn as_block_hash(&self) -> Option<BlockHash> {
414 match self {
415 Self::Hash(hash) => Some(hash.block_hash),
416 Self::Number(_) => None,
417 }
418 }
419
420 pub const fn as_u64(&self) -> Option<u64> {
422 match self {
423 Self::Number(x) => x.as_number(),
424 _ => None,
425 }
426 }
427
428 pub const fn is_latest(&self) -> bool {
430 matches!(self, Self::Number(BlockNumberOrTag::Latest))
431 }
432
433 pub const fn is_pending(&self) -> bool {
435 matches!(self, Self::Number(BlockNumberOrTag::Pending))
436 }
437
438 pub const fn is_safe(&self) -> bool {
440 matches!(self, Self::Number(BlockNumberOrTag::Safe))
441 }
442
443 pub const fn is_finalized(&self) -> bool {
445 matches!(self, Self::Number(BlockNumberOrTag::Finalized))
446 }
447
448 pub const fn is_earliest(&self) -> bool {
450 matches!(self, Self::Number(BlockNumberOrTag::Earliest))
451 }
452
453 pub const fn is_number(&self) -> bool {
455 matches!(self, Self::Number(BlockNumberOrTag::Number(_)))
456 }
457 pub const fn is_hash(&self) -> bool {
459 matches!(self, Self::Hash(_))
460 }
461
462 pub const fn pending() -> Self {
464 Self::Number(BlockNumberOrTag::Pending)
465 }
466
467 pub const fn latest() -> Self {
469 Self::Number(BlockNumberOrTag::Latest)
470 }
471
472 pub const fn earliest() -> Self {
474 Self::Number(BlockNumberOrTag::Earliest)
475 }
476
477 pub const fn finalized() -> Self {
479 Self::Number(BlockNumberOrTag::Finalized)
480 }
481
482 pub const fn safe() -> Self {
484 Self::Number(BlockNumberOrTag::Safe)
485 }
486
487 pub const fn number(num: u64) -> Self {
489 Self::Number(BlockNumberOrTag::Number(num))
490 }
491
492 pub const fn hash(block_hash: BlockHash) -> Self {
494 Self::Hash(RpcBlockHash { block_hash, require_canonical: None })
495 }
496
497 pub const fn hash_canonical(block_hash: BlockHash) -> Self {
499 Self::Hash(RpcBlockHash { block_hash, require_canonical: Some(true) })
500 }
501}
502
503impl Default for BlockId {
504 fn default() -> Self {
505 BlockNumberOrTag::Latest.into()
506 }
507}
508
509impl From<u64> for BlockId {
510 fn from(num: u64) -> Self {
511 BlockNumberOrTag::Number(num).into()
512 }
513}
514
515impl From<U64> for BlockId {
516 fn from(value: U64) -> Self {
517 value.to::<u64>().into()
518 }
519}
520
521impl From<BlockNumberOrTag> for BlockId {
522 fn from(num: BlockNumberOrTag) -> Self {
523 Self::Number(num)
524 }
525}
526
527impl From<HashOrNumber> for BlockId {
528 fn from(block: HashOrNumber) -> Self {
529 match block {
530 HashOrNumber::Hash(hash) => hash.into(),
531 HashOrNumber::Number(num) => num.into(),
532 }
533 }
534}
535
536impl From<B256> for BlockId {
537 fn from(block_hash: B256) -> Self {
538 RpcBlockHash { block_hash, require_canonical: None }.into()
539 }
540}
541
542impl From<(B256, Option<bool>)> for BlockId {
543 fn from(hash_can: (B256, Option<bool>)) -> Self {
544 RpcBlockHash { block_hash: hash_can.0, require_canonical: hash_can.1 }.into()
545 }
546}
547
548impl From<RpcBlockHash> for BlockId {
549 fn from(value: RpcBlockHash) -> Self {
550 Self::Hash(value)
551 }
552}
553
554#[cfg(feature = "serde")]
555impl serde::Serialize for BlockId {
556 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
557 where
558 S: serde::Serializer,
559 {
560 use serde::ser::SerializeStruct;
561
562 match self {
563 Self::Hash(RpcBlockHash { block_hash, require_canonical }) => {
564 let mut s = serializer.serialize_struct("BlockIdEip1898", 1)?;
565 s.serialize_field("blockHash", block_hash)?;
566 if let Some(require_canonical) = require_canonical {
567 s.serialize_field("requireCanonical", require_canonical)?;
568 }
569 s.end()
570 }
571 Self::Number(num) => num.serialize(serializer),
572 }
573 }
574}
575
576#[cfg(feature = "serde")]
577impl<'de> serde::Deserialize<'de> for BlockId {
578 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
579 where
580 D: serde::Deserializer<'de>,
581 {
582 struct BlockIdVisitor;
583
584 impl<'de> serde::de::Visitor<'de> for BlockIdVisitor {
585 type Value = BlockId;
586
587 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
588 formatter.write_str("Block identifier following EIP-1898")
589 }
590
591 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
592 where
593 E: serde::de::Error,
594 {
595 if v.len() == 66 {
598 Ok(v.parse::<B256>().map_err(serde::de::Error::custom)?.into())
599 } else {
600 Ok(BlockId::Number(v.parse().map_err(serde::de::Error::custom)?))
602 }
603 }
604
605 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
606 where
607 A: serde::de::MapAccess<'de>,
608 {
609 let mut number = None;
610 let mut block_hash = None;
611 let mut require_canonical = None;
612 while let Some(key) = map.next_key::<alloc::string::String>()? {
613 match key.as_str() {
614 "blockNumber" => {
615 if number.is_some() || block_hash.is_some() {
616 return Err(serde::de::Error::duplicate_field("blockNumber"));
617 }
618 if require_canonical.is_some() {
619 return Err(serde::de::Error::custom(
620 "Non-valid require_canonical field",
621 ));
622 }
623 number = Some(map.next_value::<BlockNumberOrTag>()?)
624 }
625 "blockHash" => {
626 if number.is_some() || block_hash.is_some() {
627 return Err(serde::de::Error::duplicate_field("blockHash"));
628 }
629
630 block_hash = Some(map.next_value::<B256>()?);
631 }
632 "requireCanonical" => {
633 if number.is_some() || require_canonical.is_some() {
634 return Err(serde::de::Error::duplicate_field("requireCanonical"));
635 }
636
637 require_canonical = Some(map.next_value::<bool>()?)
638 }
639 key => {
640 return Err(serde::de::Error::unknown_field(
641 key,
642 &["blockNumber", "blockHash", "requireCanonical"],
643 ))
644 }
645 }
646 }
647
648 #[expect(clippy::option_if_let_else)]
649 if let Some(number) = number {
650 Ok(number.into())
651 } else if let Some(block_hash) = block_hash {
652 Ok((block_hash, require_canonical).into())
653 } else {
654 Err(serde::de::Error::custom(
655 "Expected `blockNumber` or `blockHash` with `requireCanonical` optionally",
656 ))
657 }
658 }
659 }
660
661 deserializer.deserialize_any(BlockIdVisitor)
662 }
663}
664
665impl fmt::Display for BlockId {
666 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
667 match self {
668 Self::Hash(hash) => hash.fmt(f),
669 Self::Number(num) => num.fmt(f),
670 }
671 }
672}
673
674impl fmt::Debug for BlockId {
675 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
676 match self {
677 Self::Hash(hash) => hash.fmt(f),
678 Self::Number(num) => num.fmt(f),
679 }
680 }
681}
682
683#[derive(Debug)]
685pub enum ParseBlockIdError {
686 ParseIntError(ParseIntError),
688 ParseError(ParseError),
690 FromHexError(FromHexError),
692}
693
694impl fmt::Display for ParseBlockIdError {
695 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
696 match self {
697 Self::ParseIntError(err) => write!(f, "{err}"),
698 Self::ParseError(err) => write!(f, "{err}"),
699 Self::FromHexError(err) => write!(f, "{err}"),
700 }
701 }
702}
703
704impl core::error::Error for ParseBlockIdError {
705 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
706 match self {
707 Self::ParseIntError(err) => Some(err),
708 Self::FromHexError(err) => Some(err),
709 Self::ParseError(_) => None,
710 }
711 }
712}
713
714impl From<ParseIntError> for ParseBlockIdError {
715 fn from(err: ParseIntError) -> Self {
716 Self::ParseIntError(err)
717 }
718}
719
720impl From<FromHexError> for ParseBlockIdError {
721 fn from(err: FromHexError) -> Self {
722 Self::FromHexError(err)
723 }
724}
725
726impl FromStr for BlockId {
727 type Err = ParseBlockIdError;
728 fn from_str(s: &str) -> Result<Self, Self::Err> {
729 if s.starts_with("0x") {
730 return match s.len() {
731 66 => B256::from_str(s).map(Into::into).map_err(ParseBlockIdError::FromHexError),
732 _ => U64::from_str(s).map(Into::into).map_err(ParseBlockIdError::ParseError),
733 };
734 }
735
736 match s {
737 "latest" | "finalized" | "safe" | "earliest" | "pending" => {
738 Ok(BlockNumberOrTag::from_str(s).unwrap().into())
739 }
740 _ => s.parse::<u64>().map_err(ParseBlockIdError::ParseIntError).map(Into::into),
741 }
742 }
743}
744
745#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
747#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
748#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
749pub struct NumHash {
750 pub number: u64,
752 pub hash: B256,
754}
755
756pub type ForkBlock = NumHash;
758
759pub type BlockNumHash = NumHash;
761
762impl NumHash {
763 pub const fn new(number: u64, hash: B256) -> Self {
765 Self { number, hash }
766 }
767
768 pub const fn into_components(self) -> (u64, B256) {
770 (self.number, self.hash)
771 }
772
773 pub fn matches_block_or_num(&self, block: &HashOrNumber) -> bool {
775 match block {
776 HashOrNumber::Hash(hash) => self.hash == *hash,
777 HashOrNumber::Number(number) => self.number == *number,
778 }
779 }
780}
781
782impl From<(u64, B256)> for NumHash {
783 fn from(val: (u64, B256)) -> Self {
784 Self { number: val.0, hash: val.1 }
785 }
786}
787
788impl From<(B256, u64)> for NumHash {
789 fn from(val: (B256, u64)) -> Self {
790 Self { hash: val.0, number: val.1 }
791 }
792}
793
794#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
796#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
797#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
798pub enum HashOrNumber {
799 Hash(B256),
801 Number(u64),
803}
804
805pub type BlockHashOrNumber = HashOrNumber;
807
808impl HashOrNumber {
811 #[inline]
813 pub const fn as_number(self) -> Option<u64> {
814 match self {
815 Self::Hash(_) => None,
816 Self::Number(num) => Some(num),
817 }
818 }
819
820 #[inline]
822 pub const fn as_hash(self) -> Option<B256> {
823 match self {
824 Self::Hash(hash) => Some(hash),
825 Self::Number(_) => None,
826 }
827 }
828}
829
830impl From<B256> for HashOrNumber {
831 fn from(value: B256) -> Self {
832 Self::Hash(value)
833 }
834}
835
836impl From<&B256> for HashOrNumber {
837 fn from(value: &B256) -> Self {
838 (*value).into()
839 }
840}
841
842impl From<u64> for HashOrNumber {
843 fn from(value: u64) -> Self {
844 Self::Number(value)
845 }
846}
847
848impl From<U64> for HashOrNumber {
849 fn from(value: U64) -> Self {
850 value.to::<u64>().into()
851 }
852}
853
854impl From<RpcBlockHash> for HashOrNumber {
855 fn from(value: RpcBlockHash) -> Self {
856 Self::Hash(value.into())
857 }
858}
859
860impl Encodable for HashOrNumber {
862 fn encode(&self, out: &mut dyn bytes::BufMut) {
863 match self {
864 Self::Hash(block_hash) => block_hash.encode(out),
865 Self::Number(block_number) => block_number.encode(out),
866 }
867 }
868 fn length(&self) -> usize {
869 match self {
870 Self::Hash(block_hash) => block_hash.length(),
871 Self::Number(block_number) => block_number.length(),
872 }
873 }
874}
875
876impl Decodable for HashOrNumber {
878 fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
879 let header: u8 = *buf.first().ok_or(RlpError::InputTooShort)?;
880 if header == 0xa0 {
883 Ok(B256::decode(buf)?.into())
887 } else {
888 Ok(u64::decode(buf)?.into())
893 }
894 }
895}
896
897impl fmt::Display for HashOrNumber {
898 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
899 match self {
900 Self::Hash(hash) => write!(f, "{hash}"),
901 Self::Number(num) => write!(f, "{num}"),
902 }
903 }
904}
905
906#[derive(Debug)]
908pub struct ParseBlockHashOrNumberError {
909 input: alloc::string::String,
910 parse_int_error: ParseIntError,
911 hex_error: alloy_primitives::hex::FromHexError,
912}
913
914impl fmt::Display for ParseBlockHashOrNumberError {
915 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
916 write!(
917 f,
918 "failed to parse {:?} as a number: {} or hash: {}",
919 self.input, self.parse_int_error, self.hex_error
920 )
921 }
922}
923
924impl core::error::Error for ParseBlockHashOrNumberError {}
925
926impl FromStr for HashOrNumber {
927 type Err = ParseBlockHashOrNumberError;
928
929 fn from_str(s: &str) -> Result<Self, Self::Err> {
930 use alloc::string::ToString;
931
932 match u64::from_str(s) {
933 Ok(val) => Ok(val.into()),
934 Err(parse_int_error) => match B256::from_str(s) {
935 Ok(val) => Ok(val.into()),
936 Err(hex_error) => Err(ParseBlockHashOrNumberError {
937 input: s.to_string(),
938 parse_int_error,
939 hex_error,
940 }),
941 },
942 }
943 }
944}
945
946#[cfg(test)]
947mod tests {
948 use super::*;
949 use alloc::{string::ToString, vec::Vec};
950 use alloy_primitives::b256;
951
952 const HASH: B256 = b256!("1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9");
953
954 #[test]
955 fn block_id_from_str() {
956 assert_eq!("0x0".parse::<BlockId>().unwrap(), BlockId::number(0));
957 assert_eq!("0x24A931".parse::<BlockId>().unwrap(), BlockId::number(2402609));
958 assert_eq!(
959 "0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
960 .parse::<BlockId>()
961 .unwrap(),
962 HASH.into()
963 );
964 }
965
966 #[test]
967 #[cfg(feature = "serde")]
968 fn compact_block_number_serde() {
969 let num: BlockNumberOrTag = 1u64.into();
970 let serialized = serde_json::to_string(&num).unwrap();
971 assert_eq!(serialized, "\"0x1\"");
972 }
973
974 #[test]
975 fn block_id_as_u64() {
976 assert_eq!(BlockId::number(123).as_u64(), Some(123));
977 assert_eq!(BlockId::number(0).as_u64(), Some(0));
978 assert_eq!(BlockId::earliest().as_u64(), None);
979 assert_eq!(BlockId::latest().as_u64(), None);
980 assert_eq!(BlockId::pending().as_u64(), None);
981 assert_eq!(BlockId::safe().as_u64(), None);
982 assert_eq!(BlockId::hash(BlockHash::ZERO).as_u64(), None);
983 assert_eq!(BlockId::hash_canonical(BlockHash::ZERO).as_u64(), None);
984 }
985
986 #[test]
987 #[cfg(feature = "serde")]
988 fn can_parse_eip1898_block_ids() {
989 let num = serde_json::json!(
990 { "blockNumber": "0x0" }
991 );
992 let id = serde_json::from_value::<BlockId>(num).unwrap();
993 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Number(0u64)));
994
995 let num = serde_json::json!(
996 { "blockNumber": "pending" }
997 );
998 let id = serde_json::from_value::<BlockId>(num).unwrap();
999 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Pending));
1000
1001 let num = serde_json::json!(
1002 { "blockNumber": "latest" }
1003 );
1004 let id = serde_json::from_value::<BlockId>(num).unwrap();
1005 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Latest));
1006
1007 let num = serde_json::json!(
1008 { "blockNumber": "finalized" }
1009 );
1010 let id = serde_json::from_value::<BlockId>(num).unwrap();
1011 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Finalized));
1012
1013 let num = serde_json::json!(
1014 { "blockNumber": "safe" }
1015 );
1016 let id = serde_json::from_value::<BlockId>(num).unwrap();
1017 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Safe));
1018
1019 let num = serde_json::json!(
1020 { "blockNumber": "earliest" }
1021 );
1022 let id = serde_json::from_value::<BlockId>(num).unwrap();
1023 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Earliest));
1024
1025 let num = serde_json::json!("0x0");
1026 let id = serde_json::from_value::<BlockId>(num).unwrap();
1027 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Number(0u64)));
1028
1029 let num = serde_json::json!("pending");
1030 let id = serde_json::from_value::<BlockId>(num).unwrap();
1031 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Pending));
1032
1033 let num = serde_json::json!("latest");
1034 let id = serde_json::from_value::<BlockId>(num).unwrap();
1035 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Latest));
1036
1037 let num = serde_json::json!("finalized");
1038 let id = serde_json::from_value::<BlockId>(num).unwrap();
1039 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Finalized));
1040
1041 let num = serde_json::json!("safe");
1042 let id = serde_json::from_value::<BlockId>(num).unwrap();
1043 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Safe));
1044
1045 let num = serde_json::json!("earliest");
1046 let id = serde_json::from_value::<BlockId>(num).unwrap();
1047 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Earliest));
1048
1049 let num = serde_json::json!(
1050 { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" }
1051 );
1052 let id = serde_json::from_value::<BlockId>(num).unwrap();
1053 assert_eq!(
1054 id,
1055 BlockId::Hash(
1056 "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
1057 .parse::<B256>()
1058 .unwrap()
1059 .into()
1060 )
1061 );
1062 }
1063
1064 #[test]
1065 fn display_rpc_block_hash() {
1066 let hash = RpcBlockHash::from_hash(HASH, Some(true));
1067
1068 assert_eq!(
1069 hash.to_string(),
1070 "canonical hash 0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
1071 );
1072
1073 let hash = RpcBlockHash::from_hash(HASH, None);
1074
1075 assert_eq!(
1076 hash.to_string(),
1077 "hash 0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
1078 );
1079 }
1080
1081 #[test]
1082 fn display_block_id() {
1083 let id = BlockId::hash(HASH);
1084
1085 assert_eq!(
1086 id.to_string(),
1087 "hash 0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
1088 );
1089
1090 let id = BlockId::hash_canonical(HASH);
1091
1092 assert_eq!(
1093 id.to_string(),
1094 "canonical hash 0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
1095 );
1096
1097 let id = BlockId::number(100000);
1098
1099 assert_eq!(id.to_string(), "0x186a0");
1100
1101 let id = BlockId::latest();
1102
1103 assert_eq!(id.to_string(), "latest");
1104
1105 let id = BlockId::safe();
1106
1107 assert_eq!(id.to_string(), "safe");
1108
1109 let id = BlockId::finalized();
1110
1111 assert_eq!(id.to_string(), "finalized");
1112
1113 let id = BlockId::earliest();
1114
1115 assert_eq!(id.to_string(), "earliest");
1116
1117 let id = BlockId::pending();
1118
1119 assert_eq!(id.to_string(), "pending");
1120 }
1121
1122 #[test]
1123 fn test_block_number_or_tag() {
1124 let latest = BlockNumberOrTag::Latest;
1126 assert_eq!(latest.as_number(), None);
1127 assert!(latest.is_latest());
1128 assert!(!latest.is_number());
1129 assert!(!latest.is_finalized());
1130 assert!(!latest.is_safe());
1131 assert!(!latest.is_pending());
1132 assert!(!latest.is_earliest());
1133
1134 let finalized = BlockNumberOrTag::Finalized;
1136 assert_eq!(finalized.as_number(), None);
1137 assert!(finalized.is_finalized());
1138 assert!(!finalized.is_latest());
1139 assert!(!finalized.is_number());
1140 assert!(!finalized.is_safe());
1141 assert!(!finalized.is_pending());
1142 assert!(!finalized.is_earliest());
1143
1144 let safe = BlockNumberOrTag::Safe;
1146 assert_eq!(safe.as_number(), None);
1147 assert!(safe.is_safe());
1148 assert!(!safe.is_latest());
1149 assert!(!safe.is_number());
1150 assert!(!safe.is_finalized());
1151 assert!(!safe.is_pending());
1152 assert!(!safe.is_earliest());
1153
1154 let earliest = BlockNumberOrTag::Earliest;
1156 assert_eq!(earliest.as_number(), None);
1157 assert!(earliest.is_earliest());
1158 assert!(!earliest.is_latest());
1159 assert!(!earliest.is_number());
1160 assert!(!earliest.is_finalized());
1161 assert!(!earliest.is_safe());
1162 assert!(!earliest.is_pending());
1163
1164 let pending = BlockNumberOrTag::Pending;
1166 assert_eq!(pending.as_number(), None);
1167 assert!(pending.is_pending());
1168 assert!(!pending.is_latest());
1169 assert!(!pending.is_number());
1170 assert!(!pending.is_finalized());
1171 assert!(!pending.is_safe());
1172 assert!(!pending.is_earliest());
1173
1174 let number = BlockNumberOrTag::Number(42);
1176 assert_eq!(number.as_number(), Some(42));
1177 assert!(number.is_number());
1178 assert!(!number.is_latest());
1179 assert!(!number.is_finalized());
1180 assert!(!number.is_safe());
1181 assert!(!number.is_pending());
1182 assert!(!number.is_earliest());
1183 }
1184
1185 #[test]
1186 fn test_block_number_or_tag_from() {
1187 let num = 100u64;
1189 let block: BlockNumberOrTag = num.into();
1190 assert_eq!(block, BlockNumberOrTag::Number(100));
1191
1192 let num = U64::from(200);
1194 let block: BlockNumberOrTag = num.into();
1195 assert_eq!(block, BlockNumberOrTag::Number(200));
1196 }
1197
1198 #[test]
1199 fn test_block_id() {
1200 let hash = BlockHash::random();
1201
1202 let block_id_hash = BlockId::hash(hash);
1204 assert_eq!(block_id_hash.as_block_hash(), Some(hash));
1205 assert!(block_id_hash.is_hash());
1206 assert!(!block_id_hash.is_number());
1207 assert!(!block_id_hash.is_latest());
1208 assert!(!block_id_hash.is_pending());
1209 assert!(!block_id_hash.is_safe());
1210 assert!(!block_id_hash.is_finalized());
1211 assert!(!block_id_hash.is_earliest());
1212
1213 let block_id_number = BlockId::number(123);
1215 assert_eq!(block_id_number.as_u64(), Some(123));
1216 assert!(block_id_number.is_number());
1217 assert!(!block_id_number.is_hash());
1218 assert!(!block_id_number.is_latest());
1219 assert!(!block_id_number.is_pending());
1220 assert!(!block_id_number.is_safe());
1221 assert!(!block_id_number.is_finalized());
1222 assert!(!block_id_number.is_earliest());
1223
1224 let block_latest = BlockId::latest();
1226 assert!(block_latest.is_latest());
1227 assert!(!block_latest.is_number());
1228 assert!(!block_latest.is_hash());
1229 assert!(!block_latest.is_pending());
1230 assert!(!block_latest.is_safe());
1231 assert!(!block_latest.is_finalized());
1232 assert!(!block_latest.is_earliest());
1233
1234 let block_pending = BlockId::pending();
1236 assert!(block_pending.is_pending());
1237 assert!(!block_pending.is_latest());
1238 assert!(!block_pending.is_number());
1239 assert!(!block_pending.is_hash());
1240 assert!(!block_pending.is_safe());
1241 assert!(!block_pending.is_finalized());
1242 assert!(!block_pending.is_earliest());
1243
1244 let block_safe = BlockId::safe();
1246 assert!(block_safe.is_safe());
1247 assert!(!block_safe.is_latest());
1248 assert!(!block_safe.is_number());
1249 assert!(!block_safe.is_hash());
1250 assert!(!block_safe.is_pending());
1251 assert!(!block_safe.is_finalized());
1252 assert!(!block_safe.is_earliest());
1253
1254 let block_finalized = BlockId::finalized();
1256 assert!(block_finalized.is_finalized());
1257 assert!(!block_finalized.is_latest());
1258 assert!(!block_finalized.is_number());
1259 assert!(!block_finalized.is_hash());
1260 assert!(!block_finalized.is_pending());
1261 assert!(!block_finalized.is_safe());
1262 assert!(!block_finalized.is_earliest());
1263
1264 let block_earliest = BlockId::earliest();
1266 assert!(block_earliest.is_earliest());
1267 assert!(!block_earliest.is_latest());
1268 assert!(!block_earliest.is_number());
1269 assert!(!block_earliest.is_hash());
1270 assert!(!block_earliest.is_pending());
1271 assert!(!block_earliest.is_safe());
1272 assert!(!block_earliest.is_finalized());
1273
1274 assert!(BlockId::default().is_latest());
1276 assert!(!BlockId::default().is_number());
1277 assert!(!BlockId::default().is_hash());
1278 assert!(!BlockId::default().is_pending());
1279 assert!(!BlockId::default().is_safe());
1280 assert!(!BlockId::default().is_finalized());
1281 assert!(!BlockId::default().is_earliest());
1282 }
1283
1284 #[test]
1285 fn test_u64_to_block_id() {
1286 let num: u64 = 123;
1288 let block_id: BlockId = num.into();
1289
1290 match block_id {
1291 BlockId::Number(BlockNumberOrTag::Number(n)) => assert_eq!(n, 123),
1292 _ => panic!("Expected BlockId::Number with 123"),
1293 }
1294
1295 let num: U64 = U64::from(456);
1297 let block_id: BlockId = num.into();
1298
1299 match block_id {
1300 BlockId::Number(BlockNumberOrTag::Number(n)) => assert_eq!(n, 456),
1301 _ => panic!("Expected BlockId::Number with 456"),
1302 }
1303
1304 let num: u64 = 789;
1306 let block_id: BlockId = HashOrNumber::Number(num).into();
1307
1308 match block_id {
1309 BlockId::Number(BlockNumberOrTag::Number(n)) => assert_eq!(n, 789),
1310 _ => panic!("Expected BlockId::Number with 789"),
1311 }
1312 }
1313
1314 #[test]
1315 fn test_block_number_or_tag_to_block_id() {
1316 let block_number_or_tag = BlockNumberOrTag::Pending;
1317 let block_id: BlockId = block_number_or_tag.into();
1318
1319 match block_id {
1320 BlockId::Number(BlockNumberOrTag::Pending) => {}
1321 _ => panic!("Expected BlockId::Number with Pending"),
1322 }
1323 }
1324
1325 #[test]
1326 fn test_hash_or_number_to_block_id_hash() {
1327 let hash: B256 = B256::random();
1329 let block_id: BlockId = HashOrNumber::Hash(hash).into();
1330
1331 match block_id {
1332 BlockId::Hash(rpc_block_hash) => assert_eq!(rpc_block_hash.block_hash, hash),
1333 _ => panic!("Expected BlockId::Hash"),
1334 }
1335
1336 let hash: B256 = B256::random();
1338 let block_id: BlockId = hash.into();
1339
1340 match block_id {
1341 BlockId::Hash(rpc_block_hash) => assert_eq!(rpc_block_hash.block_hash, hash),
1342 _ => panic!("Expected BlockId::Hash"),
1343 }
1344
1345 let hash: B256 = B256::random();
1347 let block_id: BlockId = (hash, Some(true)).into();
1348
1349 match block_id {
1350 BlockId::Hash(rpc_block_hash) => {
1351 assert_eq!(rpc_block_hash.block_hash, hash);
1352 assert_eq!(rpc_block_hash.require_canonical, Some(true));
1353 }
1354 _ => panic!("Expected BlockId::Hash with canonical flag"),
1355 }
1356 }
1357
1358 #[test]
1359 fn test_hash_or_number_as_number() {
1360 let hash_or_number = HashOrNumber::Number(123);
1362 assert_eq!(hash_or_number.as_number(), Some(123));
1363
1364 let hash = B256::random();
1366 let hash_or_number = HashOrNumber::Hash(hash);
1367 assert_eq!(hash_or_number.as_number(), None);
1368 }
1369
1370 #[test]
1371 fn test_hash_or_number_as_hash() {
1372 let hash = B256::random();
1374 let hash_or_number = HashOrNumber::Hash(hash);
1375 assert_eq!(hash_or_number.as_hash(), Some(hash));
1376
1377 let hash_or_number = HashOrNumber::Number(456);
1379 assert_eq!(hash_or_number.as_hash(), None);
1380 }
1381
1382 #[test]
1383 fn test_hash_or_number_conversions() {
1384 let hash = B256::random();
1386 let hash_or_number: HashOrNumber = hash.into();
1387 assert_eq!(hash_or_number, HashOrNumber::Hash(hash));
1388
1389 let hash_ref: HashOrNumber = (&hash).into();
1391 assert_eq!(hash_ref, HashOrNumber::Hash(hash));
1392
1393 let number: u64 = 123;
1395 let hash_or_number: HashOrNumber = number.into();
1396 assert_eq!(hash_or_number, HashOrNumber::Number(number));
1397
1398 let u64_value = U64::from(456);
1400 let hash_or_number: HashOrNumber = u64_value.into();
1401 assert_eq!(hash_or_number, HashOrNumber::Number(u64_value.to::<u64>()));
1402
1403 let rpc_block_hash = RpcBlockHash { block_hash: hash, require_canonical: Some(true) };
1405 let hash_or_number: HashOrNumber = rpc_block_hash.into();
1406 assert_eq!(hash_or_number, HashOrNumber::Hash(hash));
1407 }
1408
1409 #[test]
1410 fn test_hash_or_number_rlp_roundtrip_hash() {
1411 let original_hash = B256::random();
1413 let hash_or_number: HashOrNumber = HashOrNumber::Hash(original_hash);
1414
1415 let mut buf = Vec::new();
1417 hash_or_number.encode(&mut buf);
1418
1419 let decoded: HashOrNumber = HashOrNumber::decode(&mut &buf[..]).expect("Decoding failed");
1421
1422 assert_eq!(decoded, hash_or_number);
1424 }
1425
1426 #[test]
1427 fn test_hash_or_number_rlp_roundtrip_u64() {
1428 let original_number: u64 = 12345;
1430 let hash_or_number: HashOrNumber = HashOrNumber::Number(original_number);
1431
1432 let mut buf = Vec::new();
1434 hash_or_number.encode(&mut buf);
1435
1436 let decoded: HashOrNumber = HashOrNumber::decode(&mut &buf[..]).expect("Decoding failed");
1438
1439 assert_eq!(decoded, hash_or_number);
1441 }
1442
1443 #[test]
1444 fn test_numhash() {
1445 let number: u64 = 42;
1446 let hash = B256::random();
1447
1448 let num_hash = NumHash::new(number, hash);
1449
1450 assert_eq!(num_hash.number, number);
1452 assert_eq!(num_hash.hash, hash);
1453
1454 assert_eq!(num_hash.into_components(), (number, hash));
1456 }
1457
1458 #[test]
1459 fn test_numhash_matches_block_or_num() {
1460 let number: u64 = 42;
1461 let hash = B256::random();
1462
1463 let num_hash = NumHash::new(number, hash);
1464
1465 let block_hash = HashOrNumber::Hash(hash);
1467 assert!(num_hash.matches_block_or_num(&block_hash));
1468
1469 let block_number = HashOrNumber::Number(number);
1471 assert!(num_hash.matches_block_or_num(&block_number));
1472
1473 let different_hash = B256::random();
1475 let non_matching_hash = HashOrNumber::Hash(different_hash);
1476 assert!(!num_hash.matches_block_or_num(&non_matching_hash));
1477
1478 let different_number: u64 = 43;
1480 let non_matching_number = HashOrNumber::Number(different_number);
1481 assert!(!num_hash.matches_block_or_num(&non_matching_number));
1482 }
1483
1484 #[test]
1485 fn test_numhash_conversions() {
1486 let number: u64 = 42;
1488 let hash = B256::random();
1489
1490 let num_hash_from_tuple: NumHash = (number, hash).into();
1491
1492 assert_eq!(num_hash_from_tuple.number, number);
1493 assert_eq!(num_hash_from_tuple.hash, hash);
1494
1495 let number: u64 = 42;
1497 let hash = B256::random();
1498
1499 let num_hash_from_reversed_tuple: NumHash = (hash, number).into();
1500
1501 assert_eq!(num_hash_from_reversed_tuple.number, number);
1502 assert_eq!(num_hash_from_reversed_tuple.hash, hash);
1503 }
1504
1505 #[test]
1506 #[cfg(feature = "serde")]
1507 fn test_block_id_from_str() {
1508 let hex_id = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
1510 assert_eq!(
1511 BlockId::from_str(hex_id).unwrap(),
1512 BlockId::Hash(RpcBlockHash::from_hash(B256::from_str(hex_id).unwrap(), None))
1513 );
1514
1515 assert_eq!(BlockId::from_str("latest").unwrap(), BlockNumberOrTag::Latest.into());
1517 assert_eq!(BlockId::from_str("finalized").unwrap(), BlockNumberOrTag::Finalized.into());
1518 assert_eq!(BlockId::from_str("safe").unwrap(), BlockNumberOrTag::Safe.into());
1519 assert_eq!(BlockId::from_str("earliest").unwrap(), BlockNumberOrTag::Earliest.into());
1520 assert_eq!(BlockId::from_str("pending").unwrap(), BlockNumberOrTag::Pending.into());
1521
1522 let numeric_string = "12345";
1524 let parsed_numeric_string = BlockId::from_str(numeric_string);
1525 assert!(parsed_numeric_string.is_ok());
1526
1527 assert_eq!(
1529 BlockId::from_str("0x12345").unwrap(),
1530 BlockId::Number(BlockNumberOrTag::Number(74565))
1531 );
1532
1533 let invalid_string = "invalid_block_id";
1535 let parsed_invalid_string = BlockId::from_str(invalid_string);
1536 assert!(parsed_invalid_string.is_err());
1537 }
1538
1539 #[test]
1541 #[cfg(feature = "serde")]
1542 fn can_parse_blockid_u64() {
1543 let num = serde_json::json!(
1544 {"blockNumber": "0xaf"}
1545 );
1546
1547 let id = serde_json::from_value::<BlockId>(num);
1548 assert_eq!(id.unwrap(), BlockId::from(175));
1549 }
1550
1551 #[test]
1552 #[cfg(feature = "serde")]
1553 fn can_parse_block_hash() {
1554 let block_hash =
1555 B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
1556 .unwrap();
1557 let block_hash_json = serde_json::json!(
1558 { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}
1559 );
1560 let id = serde_json::from_value::<BlockId>(block_hash_json).unwrap();
1561 assert_eq!(id, BlockId::from(block_hash,));
1562 }
1563
1564 #[test]
1565 #[cfg(feature = "serde")]
1566 fn can_parse_block_hash_with_canonical() {
1567 let block_hash =
1568 B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
1569 .unwrap();
1570 let block_id = BlockId::Hash(RpcBlockHash::from_hash(block_hash, Some(true)));
1571 let block_hash_json = serde_json::json!(
1572 { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true }
1573 );
1574 let id = serde_json::from_value::<BlockId>(block_hash_json).unwrap();
1575 assert_eq!(id, block_id)
1576 }
1577 #[test]
1578 #[cfg(feature = "serde")]
1579 fn can_parse_blockid_tags() {
1580 let tags = [
1581 ("latest", BlockNumberOrTag::Latest),
1582 ("finalized", BlockNumberOrTag::Finalized),
1583 ("safe", BlockNumberOrTag::Safe),
1584 ("pending", BlockNumberOrTag::Pending),
1585 ];
1586 for (value, tag) in tags {
1587 let num = serde_json::json!({ "blockNumber": value });
1588 let id = serde_json::from_value::<BlockId>(num);
1589 assert_eq!(id.unwrap(), BlockId::from(tag))
1590 }
1591 }
1592 #[test]
1593 #[cfg(feature = "serde")]
1594 fn repeated_keys_is_err() {
1595 let num = serde_json::json!({"blockNumber": 1, "requireCanonical": true, "requireCanonical": false});
1596 assert!(serde_json::from_value::<BlockId>(num).is_err());
1597 let num =
1598 serde_json::json!({"blockNumber": 1, "requireCanonical": true, "blockNumber": 23});
1599 assert!(serde_json::from_value::<BlockId>(num).is_err());
1600 }
1601
1602 #[test]
1604 #[cfg(feature = "serde")]
1605 fn serde_blockid_tags() {
1606 let block_ids = [
1607 BlockNumberOrTag::Latest,
1608 BlockNumberOrTag::Finalized,
1609 BlockNumberOrTag::Safe,
1610 BlockNumberOrTag::Pending,
1611 ]
1612 .map(BlockId::from);
1613 for block_id in &block_ids {
1614 let serialized = serde_json::to_string(&block_id).unwrap();
1615 let deserialized: BlockId = serde_json::from_str(&serialized).unwrap();
1616 assert_eq!(deserialized, *block_id)
1617 }
1618 }
1619
1620 #[test]
1621 #[cfg(feature = "serde")]
1622 fn serde_blockid_number() {
1623 let block_id = BlockId::from(100u64);
1624 let serialized = serde_json::to_string(&block_id).unwrap();
1625 let deserialized: BlockId = serde_json::from_str(&serialized).unwrap();
1626 assert_eq!(deserialized, block_id)
1627 }
1628
1629 #[test]
1630 #[cfg(feature = "serde")]
1631 fn serde_blockid_hash() {
1632 let block_id = BlockId::from(B256::default());
1633 let serialized = serde_json::to_string(&block_id).unwrap();
1634 let deserialized: BlockId = serde_json::from_str(&serialized).unwrap();
1635 assert_eq!(deserialized, block_id)
1636 }
1637
1638 #[test]
1639 #[cfg(feature = "serde")]
1640 fn serde_blockid_hash_from_str() {
1641 let val = "\"0x898753d8fdd8d92c1907ca21e68c7970abd290c647a202091181deec3f30a0b2\"";
1642 let block_hash: B256 = serde_json::from_str(val).unwrap();
1643 let block_id: BlockId = serde_json::from_str(val).unwrap();
1644 assert_eq!(block_id, BlockId::Hash(block_hash.into()));
1645 }
1646
1647 #[test]
1648 #[cfg(feature = "serde")]
1649 fn serde_rpc_payload_block_tag() {
1650 let payload = r#"{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},"latest"],"id":1,"jsonrpc":"2.0"}"#;
1651 let value: serde_json::Value = serde_json::from_str(payload).unwrap();
1652 let block_id_param = value.pointer("/params/1").unwrap();
1653 let block_id: BlockId = serde_json::from_value::<BlockId>(block_id_param.clone()).unwrap();
1654 assert_eq!(BlockId::Number(BlockNumberOrTag::Latest), block_id);
1655 }
1656
1657 #[test]
1658 #[cfg(feature = "serde")]
1659 fn serde_rpc_payload_block_object() {
1660 let example_payload = r#"{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},{"blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}],"id":1,"jsonrpc":"2.0"}"#;
1661 let value: serde_json::Value = serde_json::from_str(example_payload).unwrap();
1662 let block_id_param = value.pointer("/params/1").unwrap().to_string();
1663 let block_id: BlockId = serde_json::from_str::<BlockId>(&block_id_param).unwrap();
1664 let hash =
1665 B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
1666 .unwrap();
1667 assert_eq!(BlockId::from(hash), block_id);
1668 let serialized = serde_json::to_string(&BlockId::from(hash)).unwrap();
1669 assert_eq!("{\"blockHash\":\"0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3\"}", serialized)
1670 }
1671
1672 #[test]
1673 #[cfg(feature = "serde")]
1674 fn serde_rpc_payload_block_number() {
1675 let example_payload = r#"{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},{"blockNumber": "0x0"}],"id":1,"jsonrpc":"2.0"}"#;
1676 let value: serde_json::Value = serde_json::from_str(example_payload).unwrap();
1677 let block_id_param = value.pointer("/params/1").unwrap().to_string();
1678 let block_id: BlockId = serde_json::from_str::<BlockId>(&block_id_param).unwrap();
1679 assert_eq!(BlockId::from(0u64), block_id);
1680 let serialized = serde_json::to_string(&BlockId::from(0u64)).unwrap();
1681 assert_eq!("\"0x0\"", serialized)
1682 }
1683
1684 #[test]
1685 #[should_panic]
1686 #[cfg(feature = "serde")]
1687 fn serde_rpc_payload_block_number_duplicate_key() {
1688 let payload = r#"{"blockNumber": "0x132", "blockNumber": "0x133"}"#;
1689 let parsed_block_id = serde_json::from_str::<BlockId>(payload);
1690 parsed_block_id.unwrap();
1691 }
1692
1693 #[test]
1694 #[cfg(feature = "serde")]
1695 fn serde_rpc_payload_block_hash() {
1696 let payload = r#"{"blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}"#;
1697 let parsed = serde_json::from_str::<BlockId>(payload).unwrap();
1698 let expected = BlockId::from(
1699 B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
1700 .unwrap(),
1701 );
1702 assert_eq!(parsed, expected);
1703 }
1704
1705 #[test]
1706 #[cfg(feature = "serde")]
1707 fn serde_blocknumber_non_0xprefix() {
1708 let s = "\"2\"";
1709 let err = serde_json::from_str::<BlockNumberOrTag>(s).unwrap_err();
1710 assert_eq!(err.to_string(), HexStringMissingPrefixError::default().to_string());
1711 }
1712
1713 #[cfg(feature = "serde")]
1714 #[derive(Debug, serde::Deserialize, PartialEq)]
1715 struct TestLenientStruct {
1716 #[serde(deserialize_with = "super::lenient_block_number_or_tag::deserialize")]
1717 block: BlockNumberOrTag,
1718 }
1719
1720 #[test]
1721 #[cfg(feature = "serde")]
1722 fn test_lenient_block_number_or_tag() {
1723 let lenient_struct: TestLenientStruct =
1725 serde_json::from_str(r#"{"block": "0x1"}"#).unwrap();
1726 assert_eq!(lenient_struct.block, BlockNumberOrTag::Number(1));
1727
1728 let lenient_struct: TestLenientStruct =
1729 serde_json::from_str(r#"{"block": "123"}"#).unwrap();
1730 assert_eq!(lenient_struct.block, BlockNumberOrTag::Number(123));
1731
1732 let lenient_struct: TestLenientStruct =
1734 serde_json::from_str(r#"{"block": "latest"}"#).unwrap();
1735 assert_eq!(lenient_struct.block, BlockNumberOrTag::Latest);
1736
1737 let lenient_struct: TestLenientStruct =
1738 serde_json::from_str(r#"{"block": "finalized"}"#).unwrap();
1739 assert_eq!(lenient_struct.block, BlockNumberOrTag::Finalized);
1740
1741 let lenient_struct: TestLenientStruct =
1742 serde_json::from_str(r#"{"block": "safe"}"#).unwrap();
1743 assert_eq!(lenient_struct.block, BlockNumberOrTag::Safe);
1744
1745 let lenient_struct: TestLenientStruct =
1746 serde_json::from_str(r#"{"block": "earliest"}"#).unwrap();
1747 assert_eq!(lenient_struct.block, BlockNumberOrTag::Earliest);
1748
1749 let lenient_struct: TestLenientStruct =
1750 serde_json::from_str(r#"{"block": "pending"}"#).unwrap();
1751 assert_eq!(lenient_struct.block, BlockNumberOrTag::Pending);
1752
1753 let lenient_struct: TestLenientStruct = serde_json::from_str(r#"{"block": 123}"#).unwrap();
1755 assert_eq!(lenient_struct.block, BlockNumberOrTag::Number(123));
1756
1757 let lenient_struct: TestLenientStruct = serde_json::from_str(r#"{"block": 0}"#).unwrap();
1758 assert_eq!(lenient_struct.block, BlockNumberOrTag::Number(0));
1759
1760 assert!(serde_json::from_str::<TestLenientStruct>(r#"{"block": "invalid"}"#).is_err());
1762 assert!(serde_json::from_str::<TestLenientStruct>(r#"{"block": null}"#).is_err());
1763 assert!(serde_json::from_str::<TestLenientStruct>(r#"{"block": {}}"#).is_err());
1764 }
1765
1766 #[test]
1767 fn test_lenient_block_number_or_tag_wrapper() {
1768 let block_number: LenientBlockNumberOrTag = serde_json::from_str("\"latest\"").unwrap();
1770 assert_eq!(block_number.0, BlockNumberOrTag::Latest);
1771
1772 let block_number: LenientBlockNumberOrTag = serde_json::from_str("123").unwrap();
1773 assert_eq!(block_number.0, BlockNumberOrTag::Number(123));
1774
1775 let block_number: LenientBlockNumberOrTag = serde_json::from_str("\"0x1\"").unwrap();
1776 assert_eq!(block_number.0, BlockNumberOrTag::Number(1));
1777 }
1778}