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(Debug)]
237pub enum ParseBlockNumberError {
238 ParseIntErr(ParseIntError),
240 ParseErr(ParseError),
242 MissingPrefix(HexStringMissingPrefixError),
244}
245
246impl core::error::Error for ParseBlockNumberError {
248 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
249 match self {
250 Self::ParseIntErr(err) => Some(err),
251 Self::MissingPrefix(err) => Some(err),
252 Self::ParseErr(_) => None,
253 }
254 }
255}
256
257impl fmt::Display for ParseBlockNumberError {
258 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
259 match self {
260 Self::ParseIntErr(err) => write!(f, "{err}"),
261 Self::ParseErr(err) => write!(f, "{err}"),
262 Self::MissingPrefix(err) => write!(f, "{err}"),
263 }
264 }
265}
266
267impl From<ParseIntError> for ParseBlockNumberError {
268 fn from(err: ParseIntError) -> Self {
269 Self::ParseIntErr(err)
270 }
271}
272
273impl From<ParseError> for ParseBlockNumberError {
274 fn from(err: ParseError) -> Self {
275 Self::ParseErr(err)
276 }
277}
278
279impl From<HexStringMissingPrefixError> for ParseBlockNumberError {
280 fn from(err: HexStringMissingPrefixError) -> Self {
281 Self::MissingPrefix(err)
282 }
283}
284
285#[derive(Clone, Copy, Debug, Default)]
287#[non_exhaustive]
288pub struct HexStringMissingPrefixError;
289
290impl fmt::Display for HexStringMissingPrefixError {
291 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
292 f.write_str("hex string without 0x prefix")
293 }
294}
295
296impl core::error::Error for HexStringMissingPrefixError {}
297
298#[derive(Clone, Copy, PartialEq, Eq)]
301pub enum BlockId {
302 Hash(RpcBlockHash),
304 Number(BlockNumberOrTag),
306}
307
308impl BlockId {
309 pub const fn as_block_hash(&self) -> Option<BlockHash> {
311 match self {
312 Self::Hash(hash) => Some(hash.block_hash),
313 Self::Number(_) => None,
314 }
315 }
316
317 pub const fn as_u64(&self) -> Option<u64> {
319 match self {
320 Self::Number(x) => x.as_number(),
321 _ => None,
322 }
323 }
324
325 pub const fn is_latest(&self) -> bool {
327 matches!(self, Self::Number(BlockNumberOrTag::Latest))
328 }
329
330 pub const fn is_pending(&self) -> bool {
332 matches!(self, Self::Number(BlockNumberOrTag::Pending))
333 }
334
335 pub const fn is_safe(&self) -> bool {
337 matches!(self, Self::Number(BlockNumberOrTag::Safe))
338 }
339
340 pub const fn is_finalized(&self) -> bool {
342 matches!(self, Self::Number(BlockNumberOrTag::Finalized))
343 }
344
345 pub const fn is_earliest(&self) -> bool {
347 matches!(self, Self::Number(BlockNumberOrTag::Earliest))
348 }
349
350 pub const fn is_number(&self) -> bool {
352 matches!(self, Self::Number(BlockNumberOrTag::Number(_)))
353 }
354 pub const fn is_hash(&self) -> bool {
356 matches!(self, Self::Hash(_))
357 }
358
359 pub const fn pending() -> Self {
361 Self::Number(BlockNumberOrTag::Pending)
362 }
363
364 pub const fn latest() -> Self {
366 Self::Number(BlockNumberOrTag::Latest)
367 }
368
369 pub const fn earliest() -> Self {
371 Self::Number(BlockNumberOrTag::Earliest)
372 }
373
374 pub const fn finalized() -> Self {
376 Self::Number(BlockNumberOrTag::Finalized)
377 }
378
379 pub const fn safe() -> Self {
381 Self::Number(BlockNumberOrTag::Safe)
382 }
383
384 pub const fn number(num: u64) -> Self {
386 Self::Number(BlockNumberOrTag::Number(num))
387 }
388
389 pub const fn hash(block_hash: BlockHash) -> Self {
391 Self::Hash(RpcBlockHash { block_hash, require_canonical: None })
392 }
393
394 pub const fn hash_canonical(block_hash: BlockHash) -> Self {
396 Self::Hash(RpcBlockHash { block_hash, require_canonical: Some(true) })
397 }
398}
399
400impl Default for BlockId {
401 fn default() -> Self {
402 BlockNumberOrTag::Latest.into()
403 }
404}
405
406impl From<u64> for BlockId {
407 fn from(num: u64) -> Self {
408 BlockNumberOrTag::Number(num).into()
409 }
410}
411
412impl From<U64> for BlockId {
413 fn from(value: U64) -> Self {
414 value.to::<u64>().into()
415 }
416}
417
418impl From<BlockNumberOrTag> for BlockId {
419 fn from(num: BlockNumberOrTag) -> Self {
420 Self::Number(num)
421 }
422}
423
424impl From<HashOrNumber> for BlockId {
425 fn from(block: HashOrNumber) -> Self {
426 match block {
427 HashOrNumber::Hash(hash) => hash.into(),
428 HashOrNumber::Number(num) => num.into(),
429 }
430 }
431}
432
433impl From<B256> for BlockId {
434 fn from(block_hash: B256) -> Self {
435 RpcBlockHash { block_hash, require_canonical: None }.into()
436 }
437}
438
439impl From<(B256, Option<bool>)> for BlockId {
440 fn from(hash_can: (B256, Option<bool>)) -> Self {
441 RpcBlockHash { block_hash: hash_can.0, require_canonical: hash_can.1 }.into()
442 }
443}
444
445impl From<RpcBlockHash> for BlockId {
446 fn from(value: RpcBlockHash) -> Self {
447 Self::Hash(value)
448 }
449}
450
451#[cfg(feature = "serde")]
452impl serde::Serialize for BlockId {
453 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
454 where
455 S: serde::Serializer,
456 {
457 use serde::ser::SerializeStruct;
458
459 match self {
460 Self::Hash(RpcBlockHash { block_hash, require_canonical }) => {
461 let mut s = serializer.serialize_struct("BlockIdEip1898", 1)?;
462 s.serialize_field("blockHash", block_hash)?;
463 if let Some(require_canonical) = require_canonical {
464 s.serialize_field("requireCanonical", require_canonical)?;
465 }
466 s.end()
467 }
468 Self::Number(num) => num.serialize(serializer),
469 }
470 }
471}
472
473#[cfg(feature = "serde")]
474impl<'de> serde::Deserialize<'de> for BlockId {
475 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
476 where
477 D: serde::Deserializer<'de>,
478 {
479 struct BlockIdVisitor;
480
481 impl<'de> serde::de::Visitor<'de> for BlockIdVisitor {
482 type Value = BlockId;
483
484 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
485 formatter.write_str("Block identifier following EIP-1898")
486 }
487
488 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
489 where
490 E: serde::de::Error,
491 {
492 if v.len() == 66 {
495 Ok(v.parse::<B256>().map_err(serde::de::Error::custom)?.into())
496 } else {
497 Ok(BlockId::Number(v.parse().map_err(serde::de::Error::custom)?))
499 }
500 }
501
502 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
503 where
504 A: serde::de::MapAccess<'de>,
505 {
506 let mut number = None;
507 let mut block_hash = None;
508 let mut require_canonical = None;
509 while let Some(key) = map.next_key::<alloc::string::String>()? {
510 match key.as_str() {
511 "blockNumber" => {
512 if number.is_some() || block_hash.is_some() {
513 return Err(serde::de::Error::duplicate_field("blockNumber"));
514 }
515 if require_canonical.is_some() {
516 return Err(serde::de::Error::custom(
517 "Non-valid require_canonical field",
518 ));
519 }
520 number = Some(map.next_value::<BlockNumberOrTag>()?)
521 }
522 "blockHash" => {
523 if number.is_some() || block_hash.is_some() {
524 return Err(serde::de::Error::duplicate_field("blockHash"));
525 }
526
527 block_hash = Some(map.next_value::<B256>()?);
528 }
529 "requireCanonical" => {
530 if number.is_some() || require_canonical.is_some() {
531 return Err(serde::de::Error::duplicate_field("requireCanonical"));
532 }
533
534 require_canonical = Some(map.next_value::<bool>()?)
535 }
536 key => {
537 return Err(serde::de::Error::unknown_field(
538 key,
539 &["blockNumber", "blockHash", "requireCanonical"],
540 ))
541 }
542 }
543 }
544
545 #[expect(clippy::option_if_let_else)]
546 if let Some(number) = number {
547 Ok(number.into())
548 } else if let Some(block_hash) = block_hash {
549 Ok((block_hash, require_canonical).into())
550 } else {
551 Err(serde::de::Error::custom(
552 "Expected `blockNumber` or `blockHash` with `requireCanonical` optionally",
553 ))
554 }
555 }
556 }
557
558 deserializer.deserialize_any(BlockIdVisitor)
559 }
560}
561
562impl fmt::Display for BlockId {
563 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
564 match self {
565 Self::Hash(hash) => hash.fmt(f),
566 Self::Number(num) => num.fmt(f),
567 }
568 }
569}
570
571impl fmt::Debug for BlockId {
572 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
573 match self {
574 Self::Hash(hash) => hash.fmt(f),
575 Self::Number(num) => num.fmt(f),
576 }
577 }
578}
579
580#[derive(Debug)]
582pub enum ParseBlockIdError {
583 ParseIntError(ParseIntError),
585 ParseError(ParseError),
587 FromHexError(FromHexError),
589}
590
591impl fmt::Display for ParseBlockIdError {
592 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
593 match self {
594 Self::ParseIntError(err) => write!(f, "{err}"),
595 Self::ParseError(err) => write!(f, "{err}"),
596 Self::FromHexError(err) => write!(f, "{err}"),
597 }
598 }
599}
600
601impl core::error::Error for ParseBlockIdError {
602 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
603 match self {
604 Self::ParseIntError(err) => Some(err),
605 Self::FromHexError(err) => Some(err),
606 Self::ParseError(_) => None,
607 }
608 }
609}
610
611impl From<ParseIntError> for ParseBlockIdError {
612 fn from(err: ParseIntError) -> Self {
613 Self::ParseIntError(err)
614 }
615}
616
617impl From<FromHexError> for ParseBlockIdError {
618 fn from(err: FromHexError) -> Self {
619 Self::FromHexError(err)
620 }
621}
622
623impl FromStr for BlockId {
624 type Err = ParseBlockIdError;
625 fn from_str(s: &str) -> Result<Self, Self::Err> {
626 if s.starts_with("0x") {
627 return match s.len() {
628 66 => B256::from_str(s).map(Into::into).map_err(ParseBlockIdError::FromHexError),
629 _ => U64::from_str(s).map(Into::into).map_err(ParseBlockIdError::ParseError),
630 };
631 }
632
633 match s {
634 "latest" | "finalized" | "safe" | "earliest" | "pending" => {
635 Ok(BlockNumberOrTag::from_str(s).unwrap().into())
636 }
637 _ => s.parse::<u64>().map_err(ParseBlockIdError::ParseIntError).map(Into::into),
638 }
639 }
640}
641
642#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
644#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
645#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
646pub struct NumHash {
647 pub number: u64,
649 pub hash: B256,
651}
652
653pub type ForkBlock = NumHash;
655
656pub type BlockNumHash = NumHash;
658
659impl NumHash {
660 pub const fn new(number: u64, hash: B256) -> Self {
662 Self { number, hash }
663 }
664
665 pub const fn into_components(self) -> (u64, B256) {
667 (self.number, self.hash)
668 }
669
670 pub fn matches_block_or_num(&self, block: &HashOrNumber) -> bool {
672 match block {
673 HashOrNumber::Hash(hash) => self.hash == *hash,
674 HashOrNumber::Number(number) => self.number == *number,
675 }
676 }
677}
678
679impl From<(u64, B256)> for NumHash {
680 fn from(val: (u64, B256)) -> Self {
681 Self { number: val.0, hash: val.1 }
682 }
683}
684
685impl From<(B256, u64)> for NumHash {
686 fn from(val: (B256, u64)) -> Self {
687 Self { hash: val.0, number: val.1 }
688 }
689}
690
691#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
693#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
694#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
695pub enum HashOrNumber {
696 Hash(B256),
698 Number(u64),
700}
701
702pub type BlockHashOrNumber = HashOrNumber;
704
705impl HashOrNumber {
708 #[inline]
710 pub const fn as_number(self) -> Option<u64> {
711 match self {
712 Self::Hash(_) => None,
713 Self::Number(num) => Some(num),
714 }
715 }
716
717 #[inline]
719 pub const fn as_hash(self) -> Option<B256> {
720 match self {
721 Self::Hash(hash) => Some(hash),
722 Self::Number(_) => None,
723 }
724 }
725}
726
727impl From<B256> for HashOrNumber {
728 fn from(value: B256) -> Self {
729 Self::Hash(value)
730 }
731}
732
733impl From<&B256> for HashOrNumber {
734 fn from(value: &B256) -> Self {
735 (*value).into()
736 }
737}
738
739impl From<u64> for HashOrNumber {
740 fn from(value: u64) -> Self {
741 Self::Number(value)
742 }
743}
744
745impl From<U64> for HashOrNumber {
746 fn from(value: U64) -> Self {
747 value.to::<u64>().into()
748 }
749}
750
751impl From<RpcBlockHash> for HashOrNumber {
752 fn from(value: RpcBlockHash) -> Self {
753 Self::Hash(value.into())
754 }
755}
756
757impl Encodable for HashOrNumber {
759 fn encode(&self, out: &mut dyn bytes::BufMut) {
760 match self {
761 Self::Hash(block_hash) => block_hash.encode(out),
762 Self::Number(block_number) => block_number.encode(out),
763 }
764 }
765 fn length(&self) -> usize {
766 match self {
767 Self::Hash(block_hash) => block_hash.length(),
768 Self::Number(block_number) => block_number.length(),
769 }
770 }
771}
772
773impl Decodable for HashOrNumber {
775 fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
776 let header: u8 = *buf.first().ok_or(RlpError::InputTooShort)?;
777 if header == 0xa0 {
780 Ok(B256::decode(buf)?.into())
784 } else {
785 Ok(u64::decode(buf)?.into())
790 }
791 }
792}
793
794impl fmt::Display for HashOrNumber {
795 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
796 match self {
797 Self::Hash(hash) => write!(f, "{hash}"),
798 Self::Number(num) => write!(f, "{num}"),
799 }
800 }
801}
802
803#[derive(Debug)]
805pub struct ParseBlockHashOrNumberError {
806 input: alloc::string::String,
807 parse_int_error: ParseIntError,
808 hex_error: alloy_primitives::hex::FromHexError,
809}
810
811impl fmt::Display for ParseBlockHashOrNumberError {
812 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
813 write!(
814 f,
815 "failed to parse {:?} as a number: {} or hash: {}",
816 self.input, self.parse_int_error, self.hex_error
817 )
818 }
819}
820
821impl core::error::Error for ParseBlockHashOrNumberError {}
822
823impl FromStr for HashOrNumber {
824 type Err = ParseBlockHashOrNumberError;
825
826 fn from_str(s: &str) -> Result<Self, Self::Err> {
827 use alloc::string::ToString;
828
829 match u64::from_str(s) {
830 Ok(val) => Ok(val.into()),
831 Err(parse_int_error) => match B256::from_str(s) {
832 Ok(val) => Ok(val.into()),
833 Err(hex_error) => Err(ParseBlockHashOrNumberError {
834 input: s.to_string(),
835 parse_int_error,
836 hex_error,
837 }),
838 },
839 }
840 }
841}
842
843#[cfg(test)]
844mod tests {
845 use super::*;
846 use alloc::{string::ToString, vec::Vec};
847 use alloy_primitives::b256;
848
849 const HASH: B256 = b256!("1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9");
850
851 #[test]
852 fn block_id_from_str() {
853 assert_eq!("0x0".parse::<BlockId>().unwrap(), BlockId::number(0));
854 assert_eq!("0x24A931".parse::<BlockId>().unwrap(), BlockId::number(2402609));
855 assert_eq!(
856 "0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
857 .parse::<BlockId>()
858 .unwrap(),
859 HASH.into()
860 );
861 }
862
863 #[test]
864 #[cfg(feature = "serde")]
865 fn compact_block_number_serde() {
866 let num: BlockNumberOrTag = 1u64.into();
867 let serialized = serde_json::to_string(&num).unwrap();
868 assert_eq!(serialized, "\"0x1\"");
869 }
870
871 #[test]
872 fn block_id_as_u64() {
873 assert_eq!(BlockId::number(123).as_u64(), Some(123));
874 assert_eq!(BlockId::number(0).as_u64(), Some(0));
875 assert_eq!(BlockId::earliest().as_u64(), None);
876 assert_eq!(BlockId::latest().as_u64(), None);
877 assert_eq!(BlockId::pending().as_u64(), None);
878 assert_eq!(BlockId::safe().as_u64(), None);
879 assert_eq!(BlockId::hash(BlockHash::ZERO).as_u64(), None);
880 assert_eq!(BlockId::hash_canonical(BlockHash::ZERO).as_u64(), None);
881 }
882
883 #[test]
884 #[cfg(feature = "serde")]
885 fn can_parse_eip1898_block_ids() {
886 let num = serde_json::json!(
887 { "blockNumber": "0x0" }
888 );
889 let id = serde_json::from_value::<BlockId>(num).unwrap();
890 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Number(0u64)));
891
892 let num = serde_json::json!(
893 { "blockNumber": "pending" }
894 );
895 let id = serde_json::from_value::<BlockId>(num).unwrap();
896 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Pending));
897
898 let num = serde_json::json!(
899 { "blockNumber": "latest" }
900 );
901 let id = serde_json::from_value::<BlockId>(num).unwrap();
902 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Latest));
903
904 let num = serde_json::json!(
905 { "blockNumber": "finalized" }
906 );
907 let id = serde_json::from_value::<BlockId>(num).unwrap();
908 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Finalized));
909
910 let num = serde_json::json!(
911 { "blockNumber": "safe" }
912 );
913 let id = serde_json::from_value::<BlockId>(num).unwrap();
914 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Safe));
915
916 let num = serde_json::json!(
917 { "blockNumber": "earliest" }
918 );
919 let id = serde_json::from_value::<BlockId>(num).unwrap();
920 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Earliest));
921
922 let num = serde_json::json!("0x0");
923 let id = serde_json::from_value::<BlockId>(num).unwrap();
924 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Number(0u64)));
925
926 let num = serde_json::json!("pending");
927 let id = serde_json::from_value::<BlockId>(num).unwrap();
928 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Pending));
929
930 let num = serde_json::json!("latest");
931 let id = serde_json::from_value::<BlockId>(num).unwrap();
932 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Latest));
933
934 let num = serde_json::json!("finalized");
935 let id = serde_json::from_value::<BlockId>(num).unwrap();
936 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Finalized));
937
938 let num = serde_json::json!("safe");
939 let id = serde_json::from_value::<BlockId>(num).unwrap();
940 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Safe));
941
942 let num = serde_json::json!("earliest");
943 let id = serde_json::from_value::<BlockId>(num).unwrap();
944 assert_eq!(id, BlockId::Number(BlockNumberOrTag::Earliest));
945
946 let num = serde_json::json!(
947 { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" }
948 );
949 let id = serde_json::from_value::<BlockId>(num).unwrap();
950 assert_eq!(
951 id,
952 BlockId::Hash(
953 "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
954 .parse::<B256>()
955 .unwrap()
956 .into()
957 )
958 );
959 }
960
961 #[test]
962 fn display_rpc_block_hash() {
963 let hash = RpcBlockHash::from_hash(HASH, Some(true));
964
965 assert_eq!(
966 hash.to_string(),
967 "canonical hash 0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
968 );
969
970 let hash = RpcBlockHash::from_hash(HASH, None);
971
972 assert_eq!(
973 hash.to_string(),
974 "hash 0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
975 );
976 }
977
978 #[test]
979 fn display_block_id() {
980 let id = BlockId::hash(HASH);
981
982 assert_eq!(
983 id.to_string(),
984 "hash 0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
985 );
986
987 let id = BlockId::hash_canonical(HASH);
988
989 assert_eq!(
990 id.to_string(),
991 "canonical hash 0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
992 );
993
994 let id = BlockId::number(100000);
995
996 assert_eq!(id.to_string(), "0x186a0");
997
998 let id = BlockId::latest();
999
1000 assert_eq!(id.to_string(), "latest");
1001
1002 let id = BlockId::safe();
1003
1004 assert_eq!(id.to_string(), "safe");
1005
1006 let id = BlockId::finalized();
1007
1008 assert_eq!(id.to_string(), "finalized");
1009
1010 let id = BlockId::earliest();
1011
1012 assert_eq!(id.to_string(), "earliest");
1013
1014 let id = BlockId::pending();
1015
1016 assert_eq!(id.to_string(), "pending");
1017 }
1018
1019 #[test]
1020 fn test_block_number_or_tag() {
1021 let latest = BlockNumberOrTag::Latest;
1023 assert_eq!(latest.as_number(), None);
1024 assert!(latest.is_latest());
1025 assert!(!latest.is_number());
1026 assert!(!latest.is_finalized());
1027 assert!(!latest.is_safe());
1028 assert!(!latest.is_pending());
1029 assert!(!latest.is_earliest());
1030
1031 let finalized = BlockNumberOrTag::Finalized;
1033 assert_eq!(finalized.as_number(), None);
1034 assert!(finalized.is_finalized());
1035 assert!(!finalized.is_latest());
1036 assert!(!finalized.is_number());
1037 assert!(!finalized.is_safe());
1038 assert!(!finalized.is_pending());
1039 assert!(!finalized.is_earliest());
1040
1041 let safe = BlockNumberOrTag::Safe;
1043 assert_eq!(safe.as_number(), None);
1044 assert!(safe.is_safe());
1045 assert!(!safe.is_latest());
1046 assert!(!safe.is_number());
1047 assert!(!safe.is_finalized());
1048 assert!(!safe.is_pending());
1049 assert!(!safe.is_earliest());
1050
1051 let earliest = BlockNumberOrTag::Earliest;
1053 assert_eq!(earliest.as_number(), None);
1054 assert!(earliest.is_earliest());
1055 assert!(!earliest.is_latest());
1056 assert!(!earliest.is_number());
1057 assert!(!earliest.is_finalized());
1058 assert!(!earliest.is_safe());
1059 assert!(!earliest.is_pending());
1060
1061 let pending = BlockNumberOrTag::Pending;
1063 assert_eq!(pending.as_number(), None);
1064 assert!(pending.is_pending());
1065 assert!(!pending.is_latest());
1066 assert!(!pending.is_number());
1067 assert!(!pending.is_finalized());
1068 assert!(!pending.is_safe());
1069 assert!(!pending.is_earliest());
1070
1071 let number = BlockNumberOrTag::Number(42);
1073 assert_eq!(number.as_number(), Some(42));
1074 assert!(number.is_number());
1075 assert!(!number.is_latest());
1076 assert!(!number.is_finalized());
1077 assert!(!number.is_safe());
1078 assert!(!number.is_pending());
1079 assert!(!number.is_earliest());
1080 }
1081
1082 #[test]
1083 fn test_block_number_or_tag_from() {
1084 let num = 100u64;
1086 let block: BlockNumberOrTag = num.into();
1087 assert_eq!(block, BlockNumberOrTag::Number(100));
1088
1089 let num = U64::from(200);
1091 let block: BlockNumberOrTag = num.into();
1092 assert_eq!(block, BlockNumberOrTag::Number(200));
1093 }
1094
1095 #[test]
1096 fn test_block_id() {
1097 let hash = BlockHash::random();
1098
1099 let block_id_hash = BlockId::hash(hash);
1101 assert_eq!(block_id_hash.as_block_hash(), Some(hash));
1102 assert!(block_id_hash.is_hash());
1103 assert!(!block_id_hash.is_number());
1104 assert!(!block_id_hash.is_latest());
1105 assert!(!block_id_hash.is_pending());
1106 assert!(!block_id_hash.is_safe());
1107 assert!(!block_id_hash.is_finalized());
1108 assert!(!block_id_hash.is_earliest());
1109
1110 let block_id_number = BlockId::number(123);
1112 assert_eq!(block_id_number.as_u64(), Some(123));
1113 assert!(block_id_number.is_number());
1114 assert!(!block_id_number.is_hash());
1115 assert!(!block_id_number.is_latest());
1116 assert!(!block_id_number.is_pending());
1117 assert!(!block_id_number.is_safe());
1118 assert!(!block_id_number.is_finalized());
1119 assert!(!block_id_number.is_earliest());
1120
1121 let block_latest = BlockId::latest();
1123 assert!(block_latest.is_latest());
1124 assert!(!block_latest.is_number());
1125 assert!(!block_latest.is_hash());
1126 assert!(!block_latest.is_pending());
1127 assert!(!block_latest.is_safe());
1128 assert!(!block_latest.is_finalized());
1129 assert!(!block_latest.is_earliest());
1130
1131 let block_pending = BlockId::pending();
1133 assert!(block_pending.is_pending());
1134 assert!(!block_pending.is_latest());
1135 assert!(!block_pending.is_number());
1136 assert!(!block_pending.is_hash());
1137 assert!(!block_pending.is_safe());
1138 assert!(!block_pending.is_finalized());
1139 assert!(!block_pending.is_earliest());
1140
1141 let block_safe = BlockId::safe();
1143 assert!(block_safe.is_safe());
1144 assert!(!block_safe.is_latest());
1145 assert!(!block_safe.is_number());
1146 assert!(!block_safe.is_hash());
1147 assert!(!block_safe.is_pending());
1148 assert!(!block_safe.is_finalized());
1149 assert!(!block_safe.is_earliest());
1150
1151 let block_finalized = BlockId::finalized();
1153 assert!(block_finalized.is_finalized());
1154 assert!(!block_finalized.is_latest());
1155 assert!(!block_finalized.is_number());
1156 assert!(!block_finalized.is_hash());
1157 assert!(!block_finalized.is_pending());
1158 assert!(!block_finalized.is_safe());
1159 assert!(!block_finalized.is_earliest());
1160
1161 let block_earliest = BlockId::earliest();
1163 assert!(block_earliest.is_earliest());
1164 assert!(!block_earliest.is_latest());
1165 assert!(!block_earliest.is_number());
1166 assert!(!block_earliest.is_hash());
1167 assert!(!block_earliest.is_pending());
1168 assert!(!block_earliest.is_safe());
1169 assert!(!block_earliest.is_finalized());
1170
1171 assert!(BlockId::default().is_latest());
1173 assert!(!BlockId::default().is_number());
1174 assert!(!BlockId::default().is_hash());
1175 assert!(!BlockId::default().is_pending());
1176 assert!(!BlockId::default().is_safe());
1177 assert!(!BlockId::default().is_finalized());
1178 assert!(!BlockId::default().is_earliest());
1179 }
1180
1181 #[test]
1182 fn test_u64_to_block_id() {
1183 let num: u64 = 123;
1185 let block_id: BlockId = num.into();
1186
1187 match block_id {
1188 BlockId::Number(BlockNumberOrTag::Number(n)) => assert_eq!(n, 123),
1189 _ => panic!("Expected BlockId::Number with 123"),
1190 }
1191
1192 let num: U64 = U64::from(456);
1194 let block_id: BlockId = num.into();
1195
1196 match block_id {
1197 BlockId::Number(BlockNumberOrTag::Number(n)) => assert_eq!(n, 456),
1198 _ => panic!("Expected BlockId::Number with 456"),
1199 }
1200
1201 let num: u64 = 789;
1203 let block_id: BlockId = HashOrNumber::Number(num).into();
1204
1205 match block_id {
1206 BlockId::Number(BlockNumberOrTag::Number(n)) => assert_eq!(n, 789),
1207 _ => panic!("Expected BlockId::Number with 789"),
1208 }
1209 }
1210
1211 #[test]
1212 fn test_block_number_or_tag_to_block_id() {
1213 let block_number_or_tag = BlockNumberOrTag::Pending;
1214 let block_id: BlockId = block_number_or_tag.into();
1215
1216 match block_id {
1217 BlockId::Number(BlockNumberOrTag::Pending) => {}
1218 _ => panic!("Expected BlockId::Number with Pending"),
1219 }
1220 }
1221
1222 #[test]
1223 fn test_hash_or_number_to_block_id_hash() {
1224 let hash: B256 = B256::random();
1226 let block_id: BlockId = HashOrNumber::Hash(hash).into();
1227
1228 match block_id {
1229 BlockId::Hash(rpc_block_hash) => assert_eq!(rpc_block_hash.block_hash, hash),
1230 _ => panic!("Expected BlockId::Hash"),
1231 }
1232
1233 let hash: B256 = B256::random();
1235 let block_id: BlockId = hash.into();
1236
1237 match block_id {
1238 BlockId::Hash(rpc_block_hash) => assert_eq!(rpc_block_hash.block_hash, hash),
1239 _ => panic!("Expected BlockId::Hash"),
1240 }
1241
1242 let hash: B256 = B256::random();
1244 let block_id: BlockId = (hash, Some(true)).into();
1245
1246 match block_id {
1247 BlockId::Hash(rpc_block_hash) => {
1248 assert_eq!(rpc_block_hash.block_hash, hash);
1249 assert_eq!(rpc_block_hash.require_canonical, Some(true));
1250 }
1251 _ => panic!("Expected BlockId::Hash with canonical flag"),
1252 }
1253 }
1254
1255 #[test]
1256 fn test_hash_or_number_as_number() {
1257 let hash_or_number = HashOrNumber::Number(123);
1259 assert_eq!(hash_or_number.as_number(), Some(123));
1260
1261 let hash = B256::random();
1263 let hash_or_number = HashOrNumber::Hash(hash);
1264 assert_eq!(hash_or_number.as_number(), None);
1265 }
1266
1267 #[test]
1268 fn test_hash_or_number_as_hash() {
1269 let hash = B256::random();
1271 let hash_or_number = HashOrNumber::Hash(hash);
1272 assert_eq!(hash_or_number.as_hash(), Some(hash));
1273
1274 let hash_or_number = HashOrNumber::Number(456);
1276 assert_eq!(hash_or_number.as_hash(), None);
1277 }
1278
1279 #[test]
1280 fn test_hash_or_number_conversions() {
1281 let hash = B256::random();
1283 let hash_or_number: HashOrNumber = hash.into();
1284 assert_eq!(hash_or_number, HashOrNumber::Hash(hash));
1285
1286 let hash_ref: HashOrNumber = (&hash).into();
1288 assert_eq!(hash_ref, HashOrNumber::Hash(hash));
1289
1290 let number: u64 = 123;
1292 let hash_or_number: HashOrNumber = number.into();
1293 assert_eq!(hash_or_number, HashOrNumber::Number(number));
1294
1295 let u64_value = U64::from(456);
1297 let hash_or_number: HashOrNumber = u64_value.into();
1298 assert_eq!(hash_or_number, HashOrNumber::Number(u64_value.to::<u64>()));
1299
1300 let rpc_block_hash = RpcBlockHash { block_hash: hash, require_canonical: Some(true) };
1302 let hash_or_number: HashOrNumber = rpc_block_hash.into();
1303 assert_eq!(hash_or_number, HashOrNumber::Hash(hash));
1304 }
1305
1306 #[test]
1307 fn test_hash_or_number_rlp_roundtrip_hash() {
1308 let original_hash = B256::random();
1310 let hash_or_number: HashOrNumber = HashOrNumber::Hash(original_hash);
1311
1312 let mut buf = Vec::new();
1314 hash_or_number.encode(&mut buf);
1315
1316 let decoded: HashOrNumber = HashOrNumber::decode(&mut &buf[..]).expect("Decoding failed");
1318
1319 assert_eq!(decoded, hash_or_number);
1321 }
1322
1323 #[test]
1324 fn test_hash_or_number_rlp_roundtrip_u64() {
1325 let original_number: u64 = 12345;
1327 let hash_or_number: HashOrNumber = HashOrNumber::Number(original_number);
1328
1329 let mut buf = Vec::new();
1331 hash_or_number.encode(&mut buf);
1332
1333 let decoded: HashOrNumber = HashOrNumber::decode(&mut &buf[..]).expect("Decoding failed");
1335
1336 assert_eq!(decoded, hash_or_number);
1338 }
1339
1340 #[test]
1341 fn test_numhash() {
1342 let number: u64 = 42;
1343 let hash = B256::random();
1344
1345 let num_hash = NumHash::new(number, hash);
1346
1347 assert_eq!(num_hash.number, number);
1349 assert_eq!(num_hash.hash, hash);
1350
1351 assert_eq!(num_hash.into_components(), (number, hash));
1353 }
1354
1355 #[test]
1356 fn test_numhash_matches_block_or_num() {
1357 let number: u64 = 42;
1358 let hash = B256::random();
1359
1360 let num_hash = NumHash::new(number, hash);
1361
1362 let block_hash = HashOrNumber::Hash(hash);
1364 assert!(num_hash.matches_block_or_num(&block_hash));
1365
1366 let block_number = HashOrNumber::Number(number);
1368 assert!(num_hash.matches_block_or_num(&block_number));
1369
1370 let different_hash = B256::random();
1372 let non_matching_hash = HashOrNumber::Hash(different_hash);
1373 assert!(!num_hash.matches_block_or_num(&non_matching_hash));
1374
1375 let different_number: u64 = 43;
1377 let non_matching_number = HashOrNumber::Number(different_number);
1378 assert!(!num_hash.matches_block_or_num(&non_matching_number));
1379 }
1380
1381 #[test]
1382 fn test_numhash_conversions() {
1383 let number: u64 = 42;
1385 let hash = B256::random();
1386
1387 let num_hash_from_tuple: NumHash = (number, hash).into();
1388
1389 assert_eq!(num_hash_from_tuple.number, number);
1390 assert_eq!(num_hash_from_tuple.hash, hash);
1391
1392 let number: u64 = 42;
1394 let hash = B256::random();
1395
1396 let num_hash_from_reversed_tuple: NumHash = (hash, number).into();
1397
1398 assert_eq!(num_hash_from_reversed_tuple.number, number);
1399 assert_eq!(num_hash_from_reversed_tuple.hash, hash);
1400 }
1401
1402 #[test]
1403 #[cfg(feature = "serde")]
1404 fn test_block_id_from_str() {
1405 let hex_id = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
1407 assert_eq!(
1408 BlockId::from_str(hex_id).unwrap(),
1409 BlockId::Hash(RpcBlockHash::from_hash(B256::from_str(hex_id).unwrap(), None))
1410 );
1411
1412 assert_eq!(BlockId::from_str("latest").unwrap(), BlockNumberOrTag::Latest.into());
1414 assert_eq!(BlockId::from_str("finalized").unwrap(), BlockNumberOrTag::Finalized.into());
1415 assert_eq!(BlockId::from_str("safe").unwrap(), BlockNumberOrTag::Safe.into());
1416 assert_eq!(BlockId::from_str("earliest").unwrap(), BlockNumberOrTag::Earliest.into());
1417 assert_eq!(BlockId::from_str("pending").unwrap(), BlockNumberOrTag::Pending.into());
1418
1419 let numeric_string = "12345";
1421 let parsed_numeric_string = BlockId::from_str(numeric_string);
1422 assert!(parsed_numeric_string.is_ok());
1423
1424 assert_eq!(
1426 BlockId::from_str("0x12345").unwrap(),
1427 BlockId::Number(BlockNumberOrTag::Number(74565))
1428 );
1429
1430 let invalid_string = "invalid_block_id";
1432 let parsed_invalid_string = BlockId::from_str(invalid_string);
1433 assert!(parsed_invalid_string.is_err());
1434 }
1435
1436 #[test]
1438 #[cfg(feature = "serde")]
1439 fn can_parse_blockid_u64() {
1440 let num = serde_json::json!(
1441 {"blockNumber": "0xaf"}
1442 );
1443
1444 let id = serde_json::from_value::<BlockId>(num);
1445 assert_eq!(id.unwrap(), BlockId::from(175));
1446 }
1447
1448 #[test]
1449 #[cfg(feature = "serde")]
1450 fn can_parse_block_hash() {
1451 let block_hash =
1452 B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
1453 .unwrap();
1454 let block_hash_json = serde_json::json!(
1455 { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}
1456 );
1457 let id = serde_json::from_value::<BlockId>(block_hash_json).unwrap();
1458 assert_eq!(id, BlockId::from(block_hash,));
1459 }
1460
1461 #[test]
1462 #[cfg(feature = "serde")]
1463 fn can_parse_block_hash_with_canonical() {
1464 let block_hash =
1465 B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
1466 .unwrap();
1467 let block_id = BlockId::Hash(RpcBlockHash::from_hash(block_hash, Some(true)));
1468 let block_hash_json = serde_json::json!(
1469 { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true }
1470 );
1471 let id = serde_json::from_value::<BlockId>(block_hash_json).unwrap();
1472 assert_eq!(id, block_id)
1473 }
1474 #[test]
1475 #[cfg(feature = "serde")]
1476 fn can_parse_blockid_tags() {
1477 let tags = [
1478 ("latest", BlockNumberOrTag::Latest),
1479 ("finalized", BlockNumberOrTag::Finalized),
1480 ("safe", BlockNumberOrTag::Safe),
1481 ("pending", BlockNumberOrTag::Pending),
1482 ];
1483 for (value, tag) in tags {
1484 let num = serde_json::json!({ "blockNumber": value });
1485 let id = serde_json::from_value::<BlockId>(num);
1486 assert_eq!(id.unwrap(), BlockId::from(tag))
1487 }
1488 }
1489 #[test]
1490 #[cfg(feature = "serde")]
1491 fn repeated_keys_is_err() {
1492 let num = serde_json::json!({"blockNumber": 1, "requireCanonical": true, "requireCanonical": false});
1493 assert!(serde_json::from_value::<BlockId>(num).is_err());
1494 let num =
1495 serde_json::json!({"blockNumber": 1, "requireCanonical": true, "blockNumber": 23});
1496 assert!(serde_json::from_value::<BlockId>(num).is_err());
1497 }
1498
1499 #[test]
1501 #[cfg(feature = "serde")]
1502 fn serde_blockid_tags() {
1503 let block_ids = [
1504 BlockNumberOrTag::Latest,
1505 BlockNumberOrTag::Finalized,
1506 BlockNumberOrTag::Safe,
1507 BlockNumberOrTag::Pending,
1508 ]
1509 .map(BlockId::from);
1510 for block_id in &block_ids {
1511 let serialized = serde_json::to_string(&block_id).unwrap();
1512 let deserialized: BlockId = serde_json::from_str(&serialized).unwrap();
1513 assert_eq!(deserialized, *block_id)
1514 }
1515 }
1516
1517 #[test]
1518 #[cfg(feature = "serde")]
1519 fn serde_blockid_number() {
1520 let block_id = BlockId::from(100u64);
1521 let serialized = serde_json::to_string(&block_id).unwrap();
1522 let deserialized: BlockId = serde_json::from_str(&serialized).unwrap();
1523 assert_eq!(deserialized, block_id)
1524 }
1525
1526 #[test]
1527 #[cfg(feature = "serde")]
1528 fn serde_blockid_hash() {
1529 let block_id = BlockId::from(B256::default());
1530 let serialized = serde_json::to_string(&block_id).unwrap();
1531 let deserialized: BlockId = serde_json::from_str(&serialized).unwrap();
1532 assert_eq!(deserialized, block_id)
1533 }
1534
1535 #[test]
1536 #[cfg(feature = "serde")]
1537 fn serde_blockid_hash_from_str() {
1538 let val = "\"0x898753d8fdd8d92c1907ca21e68c7970abd290c647a202091181deec3f30a0b2\"";
1539 let block_hash: B256 = serde_json::from_str(val).unwrap();
1540 let block_id: BlockId = serde_json::from_str(val).unwrap();
1541 assert_eq!(block_id, BlockId::Hash(block_hash.into()));
1542 }
1543
1544 #[test]
1545 #[cfg(feature = "serde")]
1546 fn serde_rpc_payload_block_tag() {
1547 let payload = r#"{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},"latest"],"id":1,"jsonrpc":"2.0"}"#;
1548 let value: serde_json::Value = serde_json::from_str(payload).unwrap();
1549 let block_id_param = value.pointer("/params/1").unwrap();
1550 let block_id: BlockId = serde_json::from_value::<BlockId>(block_id_param.clone()).unwrap();
1551 assert_eq!(BlockId::Number(BlockNumberOrTag::Latest), block_id);
1552 }
1553
1554 #[test]
1555 #[cfg(feature = "serde")]
1556 fn serde_rpc_payload_block_object() {
1557 let example_payload = r#"{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},{"blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}],"id":1,"jsonrpc":"2.0"}"#;
1558 let value: serde_json::Value = serde_json::from_str(example_payload).unwrap();
1559 let block_id_param = value.pointer("/params/1").unwrap().to_string();
1560 let block_id: BlockId = serde_json::from_str::<BlockId>(&block_id_param).unwrap();
1561 let hash =
1562 B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
1563 .unwrap();
1564 assert_eq!(BlockId::from(hash), block_id);
1565 let serialized = serde_json::to_string(&BlockId::from(hash)).unwrap();
1566 assert_eq!("{\"blockHash\":\"0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3\"}", serialized)
1567 }
1568
1569 #[test]
1570 #[cfg(feature = "serde")]
1571 fn serde_rpc_payload_block_number() {
1572 let example_payload = r#"{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},{"blockNumber": "0x0"}],"id":1,"jsonrpc":"2.0"}"#;
1573 let value: serde_json::Value = serde_json::from_str(example_payload).unwrap();
1574 let block_id_param = value.pointer("/params/1").unwrap().to_string();
1575 let block_id: BlockId = serde_json::from_str::<BlockId>(&block_id_param).unwrap();
1576 assert_eq!(BlockId::from(0u64), block_id);
1577 let serialized = serde_json::to_string(&BlockId::from(0u64)).unwrap();
1578 assert_eq!("\"0x0\"", serialized)
1579 }
1580
1581 #[test]
1582 #[should_panic]
1583 #[cfg(feature = "serde")]
1584 fn serde_rpc_payload_block_number_duplicate_key() {
1585 let payload = r#"{"blockNumber": "0x132", "blockNumber": "0x133"}"#;
1586 let parsed_block_id = serde_json::from_str::<BlockId>(payload);
1587 parsed_block_id.unwrap();
1588 }
1589
1590 #[test]
1591 #[cfg(feature = "serde")]
1592 fn serde_rpc_payload_block_hash() {
1593 let payload = r#"{"blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}"#;
1594 let parsed = serde_json::from_str::<BlockId>(payload).unwrap();
1595 let expected = BlockId::from(
1596 B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
1597 .unwrap(),
1598 );
1599 assert_eq!(parsed, expected);
1600 }
1601
1602 #[test]
1603 #[cfg(feature = "serde")]
1604 fn serde_blocknumber_non_0xprefix() {
1605 let s = "\"2\"";
1606 let err = serde_json::from_str::<BlockNumberOrTag>(s).unwrap_err();
1607 assert_eq!(err.to_string(), HexStringMissingPrefixError::default().to_string());
1608 }
1609}