diff --git a/ethcore/src/client.rs b/ethcore/src/client.rs index befe8ebb5..7a9888b5d 100644 --- a/ethcore/src/client.rs +++ b/ethcore/src/client.rs @@ -37,15 +37,21 @@ use extras::TransactionAddress; pub use blockchain::TreeRoute; /// Uniquely identifies block. +#[derive(Debug, PartialEq)] pub enum BlockId { /// Block's sha3. /// Querying by hash is always faster. Hash(H256), /// Block number within canon blockchain. - Number(BlockNumber) + Number(BlockNumber), + /// Earliest block (genesis). + Earliest, + /// Latest mined block. + Latest } /// Uniquely identifies transaction. +#[derive(Debug, PartialEq)] pub enum TransactionId { /// Transaction's sha3. Hash(H256), @@ -347,7 +353,9 @@ impl Client { fn block_hash(&self, id: BlockId) -> Option { match id { BlockId::Hash(hash) => Some(hash), - BlockId::Number(number) => self.chain.read().unwrap().block_hash(number) + BlockId::Number(number) => self.chain.read().unwrap().block_hash(number), + BlockId::Earliest => self.chain.read().unwrap().block_hash(0), + BlockId::Latest => Some(self.chain.read().unwrap().best_block_hash()) } } } diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index d9f65adc0..204a4a257 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -183,8 +183,12 @@ impl Eth for EthClient { }) } - fn transaction_by_block_number_and_index(&self, _params: Params) -> Result { - unimplemented!() + fn transaction_by_block_number_and_index(&self, params: Params) -> Result { + from_params::<(BlockNumber, Index)>(params) + .and_then(|(number, index)| match self.client.transaction(TransactionId::Location(number.into(), index.value())) { + Some(t) => to_value(&Transaction::from(t)), + None => Ok(Value::Null) + }) } } diff --git a/rpc/src/v1/types/block_number.rs b/rpc/src/v1/types/block_number.rs index bfe20f177..b524d8450 100644 --- a/rpc/src/v1/types/block_number.rs +++ b/rpc/src/v1/types/block_number.rs @@ -16,6 +16,7 @@ use serde::{Deserialize, Deserializer, Error}; use serde::de::Visitor; +use ethcore::client::BlockId; /// Represents rpc api block number param. #[derive(Debug, PartialEq)] @@ -53,8 +54,20 @@ impl Visitor for BlockNumberVisitor { } } +impl Into for BlockNumber { + fn into(self) -> BlockId { + match self { + BlockNumber::Num(n) => BlockId::Number(n), + BlockNumber::Earliest => BlockId::Earliest, + BlockNumber::Latest => BlockId::Latest, + BlockNumber::Pending => BlockId::Latest // TODO: change this once blockid support pending + } + } +} + #[cfg(test)] mod tests { + use ethcore::client::BlockId; use super::*; use serde_json; @@ -64,5 +77,13 @@ mod tests { let deserialized: Vec = serde_json::from_str(s).unwrap(); assert_eq!(deserialized, vec![BlockNumber::Num(10), BlockNumber::Num(10), BlockNumber::Latest, BlockNumber::Earliest, BlockNumber::Pending]) } + + #[test] + fn block_number_into() { + assert_eq!(BlockId::Number(100), BlockNumber::Num(100).into()); + assert_eq!(BlockId::Earliest, BlockNumber::Earliest.into()); + assert_eq!(BlockId::Latest, BlockNumber::Latest.into()); + assert_eq!(BlockId::Latest, BlockNumber::Pending.into()); + } } diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index 384b5bd65..d8cd5e54a 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -80,7 +80,9 @@ impl TestBlockChainClient { fn block_hash(&self, id: BlockId) -> Option { match id { BlockId::Hash(hash) => Some(hash), - BlockId::Number(n) => self.numbers.read().unwrap().get(&(n as usize)).cloned() + BlockId::Number(n) => self.numbers.read().unwrap().get(&(n as usize)).cloned(), + BlockId::Earliest => self.numbers.read().unwrap().get(&0).cloned(), + BlockId::Latest => self.numbers.read().unwrap().get(&(self.numbers.read().unwrap().len() - 1)).cloned() } } }