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