feat: add get_block

This commit is contained in:
Georgios Konstantopoulos 2020-05-24 23:11:47 +03:00
parent e28d34e996
commit ee03703ed4
No known key found for this signature in database
GPG Key ID: FA607837CD26EDBC
4 changed files with 172 additions and 39 deletions

View File

@ -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<P: JsonRpcClient> Provider<P> {
self.0.request("eth_blockNumber", None::<()>).await
}
pub async fn get_block(&self, id: impl Into<BlockId>) -> Result<Block<TxHash>, P::Error> {
self.get_block_gen(id.into(), false).await
}
pub async fn get_block_with_txs(
&self,
id: impl Into<BlockId>,
) -> Result<Block<Transaction>, P::Error> {
self.get_block_gen(id.into(), true).await
}
async fn get_block_gen<Tx: for<'a> Deserialize<'a>>(
&self,
id: BlockId,
include_txs: bool,
) -> Result<Block<Tx>, 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<T: Send + Sync + Into<TxHash>>(
&self,

136
src/types/block.rs Normal file
View File

@ -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<TX> {
/// Hash of the block
pub hash: Option<H256>,
/// 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<U64>,
/// 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<Bloom>,
/// Timestamp
pub timestamp: U256,
/// Difficulty
pub difficulty: U256,
/// Total difficulty
#[serde(rename = "totalDifficulty")]
pub total_difficulty: Option<U256>,
/// Seal fields
#[serde(default, rename = "sealFields")]
pub seal_fields: Vec<Bytes>,
/// Uncles' hashes
pub uncles: Vec<H256>,
/// Transactions
pub transactions: Vec<TX>,
/// Size in bytes
pub size: Option<U256>,
/// Mix Hash
#[serde(rename = "mixHash")]
pub mix_hash: Option<H256>,
/// Nonce
pub nonce: Option<U64>,
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum BlockId {
Hash(H256),
Number(BlockNumber),
}
impl From<U64> for BlockId {
fn from(num: U64) -> Self {
BlockNumber::Number(num).into()
}
}
impl From<BlockNumber> for BlockId {
fn from(num: BlockNumber) -> Self {
BlockId::Number(num)
}
}
impl From<H256> for BlockId {
fn from(hash: H256) -> Self {
BlockId::Hash(hash)
}
}
impl Serialize for BlockId {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<T: Into<U64>> From<T> for BlockNumber {
fn from(num: T) -> Self {
BlockNumber::Number(num.into())
}
}
impl Serialize for BlockNumber {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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"),
}
}
}

View File

@ -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<T: Into<U64>> From<T> for BlockNumber {
fn from(num: T) -> Self {
BlockNumber::Number(num.into())
}
}
impl Serialize for BlockNumber {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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"),
}
}
}

View File

@ -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};