From 6d9d8fb6054356ecc2c5cbe4ad643324137773b4 Mon Sep 17 00:00:00 2001 From: Leonardo Yvens Date: Wed, 13 May 2020 17:24:08 -0300 Subject: [PATCH] Support eth_call by block hash --- src/api/eth.rs | 4 ++-- src/contract/mod.rs | 44 +++++++++++++++++++++++++++++++++++++++----- src/types/block.rs | 10 +++++++--- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/api/eth.rs b/src/api/eth.rs index 6ba39d6d..3799ac9d 100644 --- a/src/api/eth.rs +++ b/src/api/eth.rs @@ -39,9 +39,9 @@ impl Eth { } /// Call a constant method of contract without changing the state of the blockchain. - pub fn call(&self, req: CallRequest, block: Option) -> CallFuture { + pub fn call(&self, req: CallRequest, block: Option) -> CallFuture { let req = helpers::serialize(&req); - let block = helpers::serialize(&block.unwrap_or(BlockNumber::Latest)); + let block = helpers::serialize(&block.unwrap_or(BlockNumber::Latest.into())); CallFuture::new(self.transport.execute("eth_call", vec![req, block])) } diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 5b8ebe8b..595b543c 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -5,7 +5,7 @@ use ethabi; use crate::api::{Eth, Namespace}; use crate::confirm; use crate::contract::tokens::{Detokenize, Tokenize}; -use crate::types::{Address, BlockNumber, Bytes, CallRequest, TransactionCondition, TransactionRequest, H256, U256}; +use crate::types::{Address, BlockId, Bytes, CallRequest, TransactionCondition, TransactionRequest, H256, U256}; use crate::Transport; use std::{collections::HashMap, hash::Hash, time}; @@ -222,7 +222,7 @@ impl Contract { where R: Detokenize, A: Into>, - B: Into>, + B: Into>, P: Tokenize, { self.abi @@ -256,7 +256,7 @@ mod tests { use crate::api::{self, Namespace}; use crate::helpers::tests::TestTransport; use crate::rpc; - use crate::types::{Address, BlockNumber, H256, U256}; + use crate::types::{Address, BlockId, BlockNumber, H256, U256}; use crate::Transport; use futures::Future; @@ -276,7 +276,13 @@ mod tests { // when token - .query("name", (), None, Options::default(), BlockNumber::Number(1.into())) + .query( + "name", + (), + None, + Options::default(), + BlockId::Number(BlockNumber::Number(1.into())), + ) .wait() .unwrap() }; @@ -293,6 +299,34 @@ mod tests { assert_eq!(result, "Hello World!".to_owned()); } + #[test] + fn should_call_constant_function_by_hash() { + // given + let mut transport = TestTransport::default(); + transport.set_response(rpc::Value::String("0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c48656c6c6f20576f726c64210000000000000000000000000000000000000000".into())); + + let result: String = { + let token = contract(&transport); + + // when + token + .query("name", (), None, Options::default(), BlockId::Hash(H256::default())) + .wait() + .unwrap() + }; + + // then + transport.assert_request( + "eth_call", + &[ + "{\"data\":\"0x06fdde03\",\"to\":\"0x0000000000000000000000000000000000000001\"}".into(), + "{\"blockHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}".into(), + ], + ); + transport.assert_no_more_requests(); + assert_eq!(result, "Hello World!".to_owned()); + } + #[test] fn should_query_with_params() { // given @@ -311,7 +345,7 @@ mod tests { Options::with(|options| { options.gas_price = Some(10_000_000.into()); }), - BlockNumber::Latest, + BlockId::Number(BlockNumber::Latest), ) .wait() .unwrap() diff --git a/src/types/block.rs b/src/types/block.rs index 8ee8bdae..953f9607 100644 --- a/src/types/block.rs +++ b/src/types/block.rs @@ -1,5 +1,5 @@ use crate::types::{Bytes, H160, H2048, H256, H64, U256, U64}; -use serde::{Deserialize, Serialize, Serializer}; +use serde::{ser::SerializeStruct, Deserialize, Serialize, Serializer}; /// The block header type returned from RPC calls. #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] @@ -144,7 +144,7 @@ impl Serialize for BlockNumber { } /// Block Identifier -#[derive(Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub enum BlockId { /// By Hash Hash(H256), @@ -158,7 +158,11 @@ impl Serialize for BlockId { S: Serializer, { match *self { - BlockId::Hash(ref x) => serializer.serialize_str(&format!("0x{}", x)), + 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), } }