diff --git a/src/providers/mod.rs b/src/providers/mod.rs index 7a166083..67051be1 100644 --- a/src/providers/mod.rs +++ b/src/providers/mod.rs @@ -7,7 +7,7 @@ mod http; use crate::{ signers::{Client, Signer}, - types::{Address, BlockNumber, Transaction, TransactionRequest, TxHash, U256}, + types::{Address, Block, BlockId, BlockNumber, Transaction, TransactionRequest, TxHash, U256}, utils, }; @@ -79,6 +79,38 @@ impl Provider

{ self.0.request("eth_blockNumber", None::<()>).await } + pub async fn get_block(&self, id: impl Into) -> Result, P::Error> { + self.get_block_gen(id.into(), false).await + } + + pub async fn get_block_with_txs( + &self, + id: impl Into, + ) -> Result, P::Error> { + self.get_block_gen(id.into(), true).await + } + + async fn get_block_gen Deserialize<'a>>( + &self, + id: BlockId, + include_txs: bool, + ) -> Result, P::Error> { + let include_txs = utils::serialize(&include_txs); + + match id { + BlockId::Hash(hash) => { + let hash = utils::serialize(&hash); + let args = vec![hash, include_txs]; + self.0.request("eth_getBlockByHash", Some(args)).await + } + BlockId::Number(num) => { + let num = utils::serialize(&num); + let args = vec![num, include_txs]; + self.0.request("eth_getBlockByNumber", Some(args)).await + } + } + } + /// Gets the transaction which matches the provided hash via the `eth_getTransactionByHash` API pub async fn get_transaction>( &self, diff --git a/src/types/block.rs b/src/types/block.rs new file mode 100644 index 00000000..e964dac1 --- /dev/null +++ b/src/types/block.rs @@ -0,0 +1,136 @@ +use crate::types::{Address, Bloom, Bytes, H256, U256, U64}; +use serde::{ser::SerializeStruct, Deserialize, Serialize, Serializer}; + +/// The block type returned from RPC calls. +/// This is generic over a `TX` type which will be either the hash or the +#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)] +pub struct Block { + /// Hash of the block + pub hash: Option, + /// Hash of the parent + #[serde(rename = "parentHash")] + pub parent_hash: H256, + /// Hash of the uncles + #[serde(rename = "sha3Uncles")] + pub uncles_hash: H256, + /// Miner/author's address. + #[serde(rename = "miner")] + pub author: Address, + /// State root hash + #[serde(rename = "stateRoot")] + pub state_root: H256, + /// Transactions root hash + #[serde(rename = "transactionsRoot")] + pub transactions_root: H256, + /// Transactions receipts root hash + #[serde(rename = "receiptsRoot")] + pub receipts_root: H256, + /// Block number. None if pending. + pub number: Option, + /// Gas Used + #[serde(rename = "gasUsed")] + pub gas_used: U256, + /// Gas Limit + #[serde(rename = "gasLimit")] + pub gas_limit: U256, + /// Extra data + #[serde(rename = "extraData")] + pub extra_data: Bytes, + /// Logs bloom + #[serde(rename = "logsBloom")] + pub logs_bloom: Option, + /// Timestamp + pub timestamp: U256, + /// Difficulty + pub difficulty: U256, + /// Total difficulty + #[serde(rename = "totalDifficulty")] + pub total_difficulty: Option, + /// Seal fields + #[serde(default, rename = "sealFields")] + pub seal_fields: Vec, + /// Uncles' hashes + pub uncles: Vec, + /// Transactions + pub transactions: Vec, + /// Size in bytes + pub size: Option, + /// Mix Hash + #[serde(rename = "mixHash")] + pub mix_hash: Option, + /// Nonce + pub nonce: Option, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum BlockId { + Hash(H256), + Number(BlockNumber), +} + +impl From for BlockId { + fn from(num: U64) -> Self { + BlockNumber::Number(num).into() + } +} + +impl From for BlockId { + fn from(num: BlockNumber) -> Self { + BlockId::Number(num) + } +} + +impl From for BlockId { + fn from(hash: H256) -> Self { + BlockId::Hash(hash) + } +} + +impl Serialize for BlockId { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match *self { + BlockId::Hash(ref x) => { + let mut s = serializer.serialize_struct("BlockIdEip1898", 1)?; + s.serialize_field("blockHash", &format!("{:?}", x))?; + s.end() + } + BlockId::Number(ref num) => num.serialize(serializer), + } + } +} + +/// Block Number +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum BlockNumber { + /// Latest block + Latest, + /// Earliest block (genesis) + Earliest, + /// Pending block (not yet part of the blockchain) + Pending, + /// Block by number from canon chain + Number(U64), +} + +impl> From for BlockNumber { + fn from(num: T) -> Self { + BlockNumber::Number(num.into()) + } +} + +impl Serialize for BlockNumber { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match *self { + BlockNumber::Number(ref x) => serializer.serialize_str(&format!("0x{:x}", x)), + BlockNumber::Latest => serializer.serialize_str("latest"), + BlockNumber::Earliest => serializer.serialize_str("earliest"), + BlockNumber::Pending => serializer.serialize_str("pending"), + } + } +} diff --git a/src/types/block_number.rs b/src/types/block_number.rs index 404699d4..e69de29b 100644 --- a/src/types/block_number.rs +++ b/src/types/block_number.rs @@ -1,35 +0,0 @@ -use super::U64; -use serde::{Serialize, Serializer}; - -/// Block Number -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum BlockNumber { - /// Latest block - Latest, - /// Earliest block (genesis) - Earliest, - /// Pending block (not yet part of the blockchain) - Pending, - /// Block by number from canon chain - Number(U64), -} - -impl> From for BlockNumber { - fn from(num: T) -> Self { - BlockNumber::Number(num.into()) - } -} - -impl Serialize for BlockNumber { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - match *self { - BlockNumber::Number(ref x) => serializer.serialize_str(&format!("0x{:x}", x)), - BlockNumber::Latest => serializer.serialize_str("latest"), - BlockNumber::Earliest => serializer.serialize_str("earliest"), - BlockNumber::Pending => serializer.serialize_str("pending"), - } - } -} diff --git a/src/types/mod.rs b/src/types/mod.rs index a6b0b4ac..7af71d02 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -2,7 +2,7 @@ // Re-export common ethereum datatypes with more specific names pub use ethereum_types::H256 as TxHash; -pub use ethereum_types::{Address, H256, U256, U64}; +pub use ethereum_types::{Address, Bloom, H256, U256, U64}; mod transaction; pub use transaction::{Transaction, TransactionRequest}; @@ -16,5 +16,5 @@ pub use signature::Signature; mod bytes; pub use bytes::Bytes; -mod block_number; -pub use block_number::BlockNumber; +mod block; +pub use block::{Block, BlockId, BlockNumber};