From 9b7d184fd69eeb318fc2b7e74229e317f4dd6323 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 31 Jan 2023 18:37:33 +0100 Subject: [PATCH] feat(core): more type parsing (#2095) * feat(core): more type parsing * c * doc --- ethers-core/src/types/block.rs | 58 +++++++++++++++++++++++----------- ethers-core/src/types/ens.rs | 10 ++++-- 2 files changed, 47 insertions(+), 21 deletions(-) diff --git a/ethers-core/src/types/block.rs b/ethers-core/src/types/block.rs index 89b1dd69..0359c4b8 100644 --- a/ethers-core/src/types/block.rs +++ b/ethers-core/src/types/block.rs @@ -1,9 +1,7 @@ -// Taken from +// Modified from + use crate::types::{Address, Bloom, Bytes, Transaction, TxHash, H256, U256, U64}; use chrono::{DateTime, TimeZone, Utc}; -#[cfg(not(feature = "celo"))] -use core::cmp::Ordering; - use serde::{ de::{MapAccess, Visitor}, ser::SerializeStruct, @@ -13,6 +11,7 @@ use std::{fmt, fmt::Formatter, str::FromStr}; use thiserror::Error; /// The block type returned from RPC calls. +/// /// This is generic over a `TX` type which will be either the hash or the full transaction, /// i.e. `Block` or `Block`. #[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)] @@ -142,6 +141,8 @@ impl Block { /// Reference: #[cfg(not(feature = "celo"))] pub fn next_block_base_fee(&self) -> Option { + use core::cmp::Ordering; + let target_usage = self.gas_target(); let base_fee_per_gas = self.base_fee_per_gas?; @@ -397,10 +398,10 @@ impl From> for Block { } } -#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)] -#[cfg(feature = "celo")] /// Commit-reveal data for generating randomness in the /// [Celo protocol](https://docs.celo.org/celo-codebase/protocol/identity/randomness) +#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)] +#[cfg(feature = "celo")] pub struct Randomness { /// The committed randomness for that block pub committed: Bytes, @@ -408,9 +409,9 @@ pub struct Randomness { pub revealed: Bytes, } +/// SNARK-friendly epoch block signature and bitmap #[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)] #[cfg(feature = "celo")] -/// SNARK-friendly epoch block signature and bitmap pub struct EpochSnarkData { /// The bitmap showing which validators signed on the epoch block pub bitmap: Bytes, @@ -418,8 +419,8 @@ pub struct EpochSnarkData { pub signature: Bytes, } +/// A [block hash](H256) or [block number](BlockNumber). #[derive(Copy, Clone, Debug, PartialEq, Eq)] -/// A Block Hash or Block Number pub enum BlockId { // TODO: May want to expand this to include the requireCanonical field // @@ -530,7 +531,21 @@ impl<'de> Deserialize<'de> for BlockId { } } -/// A block Number (or tag - "latest", "earliest", "pending") +impl FromStr for BlockId { + type Err = String; + + fn from_str(s: &str) -> Result { + let s = s.strip_prefix("0x").unwrap_or(s); + if s.len() == 64 { + let hash = s.parse::().map_err(|e| e.to_string()); + hash.map(Self::Hash) + } else { + s.parse().map(Self::Number) + } + } +} + +/// A block number or tag. #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)] pub enum BlockNumber { /// Latest block @@ -624,15 +639,22 @@ impl FromStr for BlockNumber { type Err = String; fn from_str(s: &str) -> Result { - let block = match s { - "latest" => Self::Latest, - "finalized" => Self::Finalized, - "safe" => Self::Safe, - "earliest" => Self::Earliest, - "pending" => Self::Pending, - n => BlockNumber::Number(n.parse::().map_err(|err| err.to_string())?), - }; - Ok(block) + match s { + "latest" => Ok(Self::Latest), + "finalized" => Ok(Self::Finalized), + "safe" => Ok(Self::Safe), + "earliest" => Ok(Self::Earliest), + "pending" => Ok(Self::Pending), + n => { + if let Ok(n) = n.parse::() { + Ok(Self::Number(n)) + } else if let Ok(n) = n.parse::() { + Ok(Self::Number(n.into())) + } else { + Err("Invalid block number".into()) + } + } + } } } diff --git a/ethers-core/src/types/ens.rs b/ethers-core/src/types/ens.rs index af8faaab..baa2bebe 100644 --- a/ethers-core/src/types/ens.rs +++ b/ethers-core/src/types/ens.rs @@ -1,7 +1,7 @@ use crate::types::Address; use rlp::{Decodable, Encodable, RlpStream}; use serde::{ser::Error as SerializationError, Deserialize, Deserializer, Serialize, Serializer}; -use std::{cmp::Ordering, convert::Infallible, str::FromStr}; +use std::{cmp::Ordering, str::FromStr}; /// ENS name or Ethereum Address. Not RLP encoded/serialized if it's a name. #[derive(Clone, Debug, PartialEq, Eq)] @@ -100,10 +100,14 @@ impl From
for NameOrAddress { } impl FromStr for NameOrAddress { - type Err = Infallible; + type Err =
::Err; fn from_str(s: &str) -> Result { - Ok(Self::Name(s.to_string())) + if s.starts_with("0x") { + s.parse().map(Self::Address) + } else { + Ok(Self::Name(s.to_string())) + } } }