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