ethers-types docs
This commit is contained in:
parent
bc523b6d60
commit
e51fbd06b0
|
@ -31,12 +31,7 @@ impl<'a, 'b, P, N, D: Detokenize> Event<'a, 'b, P, N, D> {
|
|||
}
|
||||
|
||||
pub fn topic0<T: Into<ValueOrArray<H256>>>(mut self, topic: T) -> Self {
|
||||
self.filter.topics.push(topic.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn topics(mut self, topics: &[ValueOrArray<H256>]) -> Self {
|
||||
self.filter.topics.extend_from_slice(topics);
|
||||
self.filter.topics[0] = topic.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//! This module implements extensions to the `ethabi` API.
|
||||
//! Taken from: https://github.com/gnosis/ethcontract-rs/blob/master/common/src/abiext.rs
|
||||
// Adapted from [Gnosis' ethcontract](https://github.com/gnosis/ethcontract-rs/blob/master/common/src/abiext.rs)
|
||||
use crate::Selector;
|
||||
use ethers_utils::id;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//! Contract Functions Output types.
|
||||
//! Adapted from: https://github.com/tomusdrw/rust-web3/blob/master/src/contract/tokens.rs
|
||||
// Adapted from: [rust-web3](https://github.com/tomusdrw/rust-web3/blob/master/src/contract/tokens.rs)
|
||||
#![allow(clippy::all)]
|
||||
use crate::{abi::Token, Address, Bytes, H256, U128, U256};
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Adapted from https://github.com/tomusdrw/rust-web3/blob/master/src/types/log.rs
|
||||
use crate::{Address, BlockNumber, Bytes, H256, U256, U64};
|
||||
use ethers_utils::keccak256;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{ser::SerializeSeq, Deserialize, Serialize, Serializer};
|
||||
use std::str::FromStr;
|
||||
|
||||
/// A log produced by a transaction.
|
||||
|
@ -60,7 +61,7 @@ pub struct Log {
|
|||
pub removed: Option<bool>,
|
||||
}
|
||||
|
||||
/// Filter
|
||||
/// Filter for
|
||||
#[derive(Default, Debug, PartialEq, Clone, Serialize)]
|
||||
pub struct Filter {
|
||||
/// From Block
|
||||
|
@ -78,9 +79,10 @@ pub struct Filter {
|
|||
address: Option<Address>,
|
||||
|
||||
/// Topics
|
||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||
// TODO: Split in an event name + 3 topics
|
||||
pub topics: Vec<ValueOrArray<H256>>,
|
||||
// TODO: We could improve the low level API here by using ethabi's RawTopicFilter
|
||||
// and/or TopicFilter
|
||||
#[serde(serialize_with = "skip_nones")]
|
||||
pub topics: [Option<ValueOrArray<H256>>; 4],
|
||||
|
||||
/// Limit
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
|
@ -117,16 +119,30 @@ impl Filter {
|
|||
/// given the event in string form, it hashes it and adds it to the topics to monitor
|
||||
pub fn event(self, event_name: &str) -> Self {
|
||||
let hash = H256::from(keccak256(event_name.as_bytes()));
|
||||
self.topic(hash)
|
||||
self.topic0(hash)
|
||||
}
|
||||
|
||||
pub fn topic<T: Into<ValueOrArray<H256>>>(mut self, topic: T) -> Self {
|
||||
self.topics.push(topic.into());
|
||||
/// Sets topic0 (the event name for non-anonymous events)
|
||||
pub fn topic0<T: Into<ValueOrArray<H256>>>(mut self, topic: T) -> Self {
|
||||
self.topics[0] = Some(topic.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn topics(mut self, topics: &[ValueOrArray<H256>]) -> Self {
|
||||
self.topics.extend_from_slice(topics);
|
||||
/// Sets the 1st indexed topic
|
||||
pub fn topic1<T: Into<ValueOrArray<H256>>>(mut self, topic: T) -> Self {
|
||||
self.topics[1] = Some(topic.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the 2nd indexed topic
|
||||
pub fn topic2<T: Into<ValueOrArray<H256>>>(mut self, topic: T) -> Self {
|
||||
self.topics[2] = Some(topic.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the 3rd indexed topic
|
||||
pub fn topic3<T: Into<ValueOrArray<H256>>>(mut self, topic: T) -> Self {
|
||||
self.topics[3] = Some(topic.into());
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -136,12 +152,17 @@ impl Filter {
|
|||
}
|
||||
}
|
||||
|
||||
/// Union type for representing a single value or a vector of values inside a filter
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum ValueOrArray<T> {
|
||||
/// A single value
|
||||
Value(T),
|
||||
/// A vector of values
|
||||
Array(Vec<T>),
|
||||
}
|
||||
|
||||
// TODO: Implement more common types - or adjust this to work with all Tokenizable items
|
||||
|
||||
impl From<H256> for ValueOrArray<H256> {
|
||||
fn from(src: H256) -> Self {
|
||||
ValueOrArray::Value(src)
|
||||
|
@ -156,13 +177,21 @@ impl From<Address> for ValueOrArray<H256> {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<U256> for ValueOrArray<H256> {
|
||||
fn from(src: U256) -> Self {
|
||||
let mut bytes = [0; 32];
|
||||
src.to_big_endian(&mut bytes);
|
||||
ValueOrArray::Value(H256::from(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Serialize for ValueOrArray<T>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
S: Serializer,
|
||||
{
|
||||
match self {
|
||||
ValueOrArray::Value(inner) => inner.serialize(serializer),
|
||||
|
@ -170,3 +199,45 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// adapted from https://github.com/serde-rs/serde/issues/550#issuecomment-246746639
|
||||
fn skip_nones<T, S>(elements: &[Option<T>], serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
S: Serializer,
|
||||
{
|
||||
// get number of Some elements
|
||||
let len = elements.iter().filter(|opt| opt.is_some()).count();
|
||||
|
||||
let mut seq = serializer.serialize_seq(Some(len))?;
|
||||
for elem in elements {
|
||||
if elem.is_some() {
|
||||
seq.serialize_element(elem)?;
|
||||
}
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use ethers_utils::serialize;
|
||||
|
||||
#[test]
|
||||
fn filter_serialization_test() {
|
||||
let t1 = "9729a6fbefefc8f6005933898b13dc45c3a2c8b7"
|
||||
.parse::<Address>()
|
||||
.unwrap();
|
||||
let t3 = U256::from(123);
|
||||
let filter = Filter::new()
|
||||
.address_str("f817796F60D268A36a57b8D2dF1B97B14C0D0E1d")
|
||||
.unwrap()
|
||||
.event("ValueChanged(address,string,string)") // event name
|
||||
.topic1(t1)
|
||||
.topic2(t3);
|
||||
|
||||
dbg!(&filter);
|
||||
let ser = serialize(&filter).to_string();
|
||||
assert_eq!(ser, "{\"address\":\"0xf817796f60d268a36a57b8d2df1b97b14c0d0e1d\",\"topics\":[\"0xe826f71647b8486f2bae59832124c70792fba044036720a54ec8dacdd5df4fcb\",\"0x0000000000000000000000009729a6fbefefc8f6005933898b13dc45c3a2c8b7\",\"0x000000000000000000000000000000000000000000000000000000000000007b\"]}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
pub type Selector = [u8; 4];
|
||||
|
||||
// Re-export common ethereum datatypes with more specific names
|
||||
|
||||
/// A transaction Hash
|
||||
pub use ethereum_types::H256 as TxHash;
|
||||
|
||||
pub use ethereum_types::{Address, Bloom, H160, H256, U128, U256, U64};
|
||||
|
||||
mod transaction;
|
||||
pub use transaction::{Overrides, Transaction, TransactionReceipt, TransactionRequest};
|
||||
pub use transaction::{Transaction, TransactionReceipt, TransactionRequest};
|
||||
|
||||
mod bytes;
|
||||
pub use bytes::Bytes;
|
||||
|
|
|
@ -6,31 +6,6 @@ use rlp::RlpStream;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
|
||||
/// Override params for interacting with a contract
|
||||
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Debug)]
|
||||
pub struct Overrides {
|
||||
/// Sender address or ENS name
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub from: Option<Address>,
|
||||
|
||||
/// Supplied gas (None for sensible default)
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub gas: Option<U256>,
|
||||
|
||||
/// Gas price (None for sensible default)
|
||||
#[serde(rename = "gasPrice")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub gas_price: Option<U256>,
|
||||
|
||||
/// Transfered value (None for no transfer)
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub value: Option<U256>,
|
||||
|
||||
/// Transaction nonce (None for next available nonce)
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub nonce: Option<U256>,
|
||||
}
|
||||
|
||||
/// Parameters for sending a transaction
|
||||
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Debug)]
|
||||
pub struct TransactionRequest {
|
||||
|
|
|
@ -24,12 +24,17 @@ impl FromStr for PrivateKey {
|
|||
}
|
||||
}
|
||||
|
||||
/// An error which may be thrown when attempting to sign a transaction with
|
||||
/// missing fields
|
||||
#[derive(Clone, Debug, Error)]
|
||||
pub enum TxError {
|
||||
/// Thrown if the `nonce` field is missing
|
||||
#[error("no nonce was specified")]
|
||||
NonceMissing,
|
||||
/// Thrown if the `gas_price` field is missing
|
||||
#[error("no gas price was specified")]
|
||||
GasPriceMissing,
|
||||
/// Thrown if the `gas` field is missing
|
||||
#[error("no gas was specified")]
|
||||
GasMissing,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,40 @@
|
|||
//! Various Ethereum Related Datatypes
|
||||
|
||||
//! # Ethereum Related DataTypes
|
||||
//!
|
||||
//! This library provides type definitions for Ethereum's main datatypes
|
||||
//!
|
||||
//! # Signing an ethereum-prefixed message
|
||||
//!
|
||||
//! Signing in Ethereum is done by first prefixing the message with
|
||||
//! `"\x19Ethereum Signed Message:\n" + message.length`, and then
|
||||
//! signing the hash of the result.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use ethers_types::{PrivateKey, Address};
|
||||
//!
|
||||
//! let message = "Some data";
|
||||
//! let key = PrivateKey::new(&mut rand::thread_rng());
|
||||
//! let address = Address::from(key);
|
||||
//!
|
||||
//! // Sign the message
|
||||
//! let signature = key.sign(message);
|
||||
//!
|
||||
//! // Recover the signer from the message
|
||||
//! let recovered = signature.recover(message).unwrap();
|
||||
//!
|
||||
//! assert_eq!(recovered, address);
|
||||
//! ```
|
||||
//!
|
||||
//! # ABI Encoding and Decoding
|
||||
//!
|
||||
//! This crate re-exports the [`ethabi`](http://docs.rs/ethabi) crate's functions
|
||||
//! under the `abi` module
|
||||
//!
|
||||
//! # A note about `secp256k1` and `rand`
|
||||
//!
|
||||
//! The version of `rand` used in the `secp256k1` crate is not compatible with the
|
||||
//! latest one in crates at the time of writing (rand version 0.5.1, secp256k1 version 0.17.1)
|
||||
//! As a result, the RNGs used for generating private keys must use a compatible rand crate
|
||||
//! version. For convenience, we re-export it so that consumers can use it as `ethers_types::rand`.
|
||||
mod crypto;
|
||||
pub use crypto::*;
|
||||
|
||||
|
@ -8,3 +43,6 @@ pub use chainstate::*;
|
|||
|
||||
#[cfg(feature = "abi")]
|
||||
pub mod abi;
|
||||
|
||||
// Convenience re-export
|
||||
pub use ethers_utils as utils;
|
||||
|
|
Loading…
Reference in New Issue