@@ -25,7 +25,7 @@ use ethcore::client::*;
|
||||
use ethcore::views::*;
|
||||
use ethcore::ethereum::denominations::shannon;
|
||||
use v1::traits::{Eth, EthFilter};
|
||||
use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, OptionalValue, Index};
|
||||
use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, OptionalValue, Index, Filter, Log};
|
||||
|
||||
/// Eth rpc implementation.
|
||||
pub struct EthClient {
|
||||
@@ -197,8 +197,18 @@ impl Eth for EthClient {
|
||||
from_params::<(BlockNumber, Index)>(params)
|
||||
.and_then(|(number, index)| self.transaction(TransactionId::Location(number.into(), index.value())))
|
||||
}
|
||||
}
|
||||
|
||||
fn logs(&self, params: Params) -> Result<Value, Error> {
|
||||
from_params::<(Filter,)>(params)
|
||||
.and_then(|(filter,)| {
|
||||
let logs = self.client.logs(filter.into())
|
||||
.into_iter()
|
||||
.map(From::from)
|
||||
.collect::<Vec<Log>>();
|
||||
to_value(&logs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Eth filter rpc implementation.
|
||||
pub struct EthFilterClient {
|
||||
|
||||
@@ -19,37 +19,64 @@ use serde_json::value;
|
||||
use jsonrpc_core::Value;
|
||||
use util::hash::*;
|
||||
use v1::types::BlockNumber;
|
||||
use ethcore::filter::Filter as EthFilter;
|
||||
use ethcore::client::BlockId;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Topic {
|
||||
Single(H256),
|
||||
Multiple(Vec<H256>),
|
||||
Null
|
||||
pub enum VariadicValue<T> where T: Deserialize {
|
||||
Single(T),
|
||||
Multiple(Vec<T>),
|
||||
Null,
|
||||
}
|
||||
|
||||
impl Deserialize for Topic {
|
||||
fn deserialize<D>(deserializer: &mut D) -> Result<Topic, D::Error>
|
||||
impl<T> Deserialize for VariadicValue<T> where T: Deserialize {
|
||||
fn deserialize<D>(deserializer: &mut D) -> Result<VariadicValue<T>, D::Error>
|
||||
where D: Deserializer {
|
||||
let v = try!(Value::deserialize(deserializer));
|
||||
|
||||
if v.is_null() {
|
||||
return Ok(Topic::Null);
|
||||
return Ok(VariadicValue::Null);
|
||||
}
|
||||
|
||||
Deserialize::deserialize(&mut value::Deserializer::new(v.clone())).map(Topic::Single)
|
||||
.or_else(|_| Deserialize::deserialize(&mut value::Deserializer::new(v.clone())).map(Topic::Multiple))
|
||||
Deserialize::deserialize(&mut value::Deserializer::new(v.clone())).map(VariadicValue::Single)
|
||||
.or_else(|_| Deserialize::deserialize(&mut value::Deserializer::new(v.clone())).map(VariadicValue::Multiple))
|
||||
.map_err(|_| Error::syntax("")) // unreachable, but types must match
|
||||
}
|
||||
}
|
||||
|
||||
pub type FilterAddress = VariadicValue<Address>;
|
||||
pub type Topic = VariadicValue<H256>;
|
||||
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
pub struct Filter {
|
||||
#[serde(rename="fromBlock")]
|
||||
pub from_block: Option<BlockNumber>,
|
||||
#[serde(rename="toBlock")]
|
||||
pub to_block: Option<BlockNumber>,
|
||||
pub address: Option<Address>,
|
||||
pub topics: Option<Vec<Topic>>
|
||||
pub address: Option<FilterAddress>,
|
||||
pub topics: Option<Vec<Topic>>,
|
||||
}
|
||||
|
||||
impl Into<EthFilter> for Filter {
|
||||
fn into(self) -> EthFilter {
|
||||
EthFilter {
|
||||
from_block: self.from_block.map_or_else(|| BlockId::Earliest, Into::into),
|
||||
to_block: self.to_block.map_or_else(|| BlockId::Latest, Into::into),
|
||||
address: self.address.and_then(|address| match address {
|
||||
VariadicValue::Null => None,
|
||||
VariadicValue::Single(a) => Some(vec![a]),
|
||||
VariadicValue::Multiple(a) => Some(a)
|
||||
}),
|
||||
topics: {
|
||||
let mut iter = self.topics.map_or_else(Vec::new, |topics| topics.into_iter().take(4).map(|topic| match topic {
|
||||
VariadicValue::Null => None,
|
||||
VariadicValue::Single(t) => Some(vec![t]),
|
||||
VariadicValue::Multiple(t) => Some(t)
|
||||
}).filter_map(|m| m).collect()).into_iter();
|
||||
[iter.next(), iter.next(), iter.next(), iter.next()]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -65,9 +92,9 @@ mod tests {
|
||||
let s = r#"["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", null, ["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x0000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebccc"]]"#;
|
||||
let deserialized: Vec<Topic> = serde_json::from_str(s).unwrap();
|
||||
assert_eq!(deserialized, vec![
|
||||
Topic::Single(H256::from_str("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b").unwrap()),
|
||||
Topic::Null,
|
||||
Topic::Multiple(vec![
|
||||
VariadicValue::Single(H256::from_str("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b").unwrap()),
|
||||
VariadicValue::Null,
|
||||
VariadicValue::Multiple(vec![
|
||||
H256::from_str("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b").unwrap(),
|
||||
H256::from_str("0000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebccc").unwrap()
|
||||
])
|
||||
|
||||
83
rpc/src/v1/types/log.rs
Normal file
83
rpc/src/v1/types/log.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use util::hash::*;
|
||||
use util::uint::*;
|
||||
use ethcore::log_entry::LocalizedLogEntry;
|
||||
use v1::types::Bytes;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Log {
|
||||
address: Address,
|
||||
topics: Vec<H256>,
|
||||
data: Bytes,
|
||||
#[serde(rename="blockHash")]
|
||||
block_hash: H256,
|
||||
#[serde(rename="blockNumber")]
|
||||
block_number: U256,
|
||||
#[serde(rename="transactionHash")]
|
||||
transaction_hash: H256,
|
||||
#[serde(rename="transactionIndex")]
|
||||
transaction_index: U256,
|
||||
#[serde(rename="logIndex")]
|
||||
log_index: U256,
|
||||
}
|
||||
|
||||
impl From<LocalizedLogEntry> for Log {
|
||||
fn from(e: LocalizedLogEntry) -> Log {
|
||||
Log {
|
||||
address: e.entry.address,
|
||||
topics: e.entry.topics,
|
||||
data: Bytes::new(e.entry.data),
|
||||
block_hash: e.block_hash,
|
||||
block_number: From::from(e.block_number),
|
||||
transaction_hash: e.transaction_hash,
|
||||
transaction_index: From::from(e.transaction_index),
|
||||
log_index: From::from(e.log_index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json;
|
||||
use std::str::FromStr;
|
||||
use util::hash::*;
|
||||
use util::uint::*;
|
||||
use v1::types::{Bytes, Log};
|
||||
|
||||
#[test]
|
||||
fn log_serialization() {
|
||||
let s = r#"{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x04510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x00","logIndex":"0x01"}"#;
|
||||
|
||||
let log = Log {
|
||||
address: Address::from_str("33990122638b9132ca29c723bdf037f1a891a70c").unwrap(),
|
||||
topics: vec![
|
||||
H256::from_str("a6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc").unwrap(),
|
||||
H256::from_str("4861736852656700000000000000000000000000000000000000000000000000").unwrap()
|
||||
],
|
||||
data: Bytes::new(vec![]),
|
||||
block_hash: H256::from_str("ed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5").unwrap(),
|
||||
block_number: U256::from(0x4510c),
|
||||
transaction_hash: H256::new(),
|
||||
transaction_index: U256::zero(),
|
||||
log_index: U256::one()
|
||||
};
|
||||
|
||||
let serialized = serde_json::to_string(&log).unwrap();
|
||||
assert_eq!(serialized, s);
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ mod block_number;
|
||||
mod bytes;
|
||||
mod filter;
|
||||
mod index;
|
||||
mod log;
|
||||
mod optionals;
|
||||
mod sync;
|
||||
mod transaction;
|
||||
@@ -28,6 +29,7 @@ pub use self::block_number::BlockNumber;
|
||||
pub use self::bytes::Bytes;
|
||||
pub use self::filter::Filter;
|
||||
pub use self::index::Index;
|
||||
pub use self::log::Log;
|
||||
pub use self::optionals::OptionalValue;
|
||||
pub use self::sync::{SyncStatus, SyncInfo};
|
||||
pub use self::transaction::Transaction;
|
||||
|
||||
Reference in New Issue
Block a user