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 {
|
pub fn topic0<T: Into<ValueOrArray<H256>>>(mut self, topic: T) -> Self {
|
||||||
self.filter.topics.push(topic.into());
|
self.filter.topics[0] = topic.into();
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn topics(mut self, topics: &[ValueOrArray<H256>]) -> Self {
|
|
||||||
self.filter.topics.extend_from_slice(topics);
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//! This module implements extensions to the `ethabi` API.
|
//! 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 crate::Selector;
|
||||||
use ethers_utils::id;
|
use ethers_utils::id;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//! Contract Functions Output types.
|
//! 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)]
|
#![allow(clippy::all)]
|
||||||
use crate::{abi::Token, Address, Bytes, H256, U128, U256};
|
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 crate::{Address, BlockNumber, Bytes, H256, U256, U64};
|
||||||
use ethers_utils::keccak256;
|
use ethers_utils::keccak256;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{ser::SerializeSeq, Deserialize, Serialize, Serializer};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
/// A log produced by a transaction.
|
/// A log produced by a transaction.
|
||||||
|
@ -60,7 +61,7 @@ pub struct Log {
|
||||||
pub removed: Option<bool>,
|
pub removed: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Filter
|
/// Filter for
|
||||||
#[derive(Default, Debug, PartialEq, Clone, Serialize)]
|
#[derive(Default, Debug, PartialEq, Clone, Serialize)]
|
||||||
pub struct Filter {
|
pub struct Filter {
|
||||||
/// From Block
|
/// From Block
|
||||||
|
@ -78,9 +79,10 @@ pub struct Filter {
|
||||||
address: Option<Address>,
|
address: Option<Address>,
|
||||||
|
|
||||||
/// Topics
|
/// Topics
|
||||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
// TODO: We could improve the low level API here by using ethabi's RawTopicFilter
|
||||||
// TODO: Split in an event name + 3 topics
|
// and/or TopicFilter
|
||||||
pub topics: Vec<ValueOrArray<H256>>,
|
#[serde(serialize_with = "skip_nones")]
|
||||||
|
pub topics: [Option<ValueOrArray<H256>>; 4],
|
||||||
|
|
||||||
/// Limit
|
/// Limit
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[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
|
/// 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 {
|
pub fn event(self, event_name: &str) -> Self {
|
||||||
let hash = H256::from(keccak256(event_name.as_bytes()));
|
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 {
|
/// Sets topic0 (the event name for non-anonymous events)
|
||||||
self.topics.push(topic.into());
|
pub fn topic0<T: Into<ValueOrArray<H256>>>(mut self, topic: T) -> Self {
|
||||||
|
self.topics[0] = Some(topic.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn topics(mut self, topics: &[ValueOrArray<H256>]) -> Self {
|
/// Sets the 1st indexed topic
|
||||||
self.topics.extend_from_slice(topics);
|
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
|
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)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum ValueOrArray<T> {
|
pub enum ValueOrArray<T> {
|
||||||
|
/// A single value
|
||||||
Value(T),
|
Value(T),
|
||||||
|
/// A vector of values
|
||||||
Array(Vec<T>),
|
Array(Vec<T>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Implement more common types - or adjust this to work with all Tokenizable items
|
||||||
|
|
||||||
impl From<H256> for ValueOrArray<H256> {
|
impl From<H256> for ValueOrArray<H256> {
|
||||||
fn from(src: H256) -> Self {
|
fn from(src: H256) -> Self {
|
||||||
ValueOrArray::Value(src)
|
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>
|
impl<T> Serialize for ValueOrArray<T>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
{
|
{
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
ValueOrArray::Value(inner) => inner.serialize(serializer),
|
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];
|
pub type Selector = [u8; 4];
|
||||||
|
|
||||||
// Re-export common ethereum datatypes with more specific names
|
// Re-export common ethereum datatypes with more specific names
|
||||||
|
|
||||||
|
/// A transaction Hash
|
||||||
pub use ethereum_types::H256 as TxHash;
|
pub use ethereum_types::H256 as TxHash;
|
||||||
|
|
||||||
pub use ethereum_types::{Address, Bloom, H160, H256, U128, U256, U64};
|
pub use ethereum_types::{Address, Bloom, H160, H256, U128, U256, U64};
|
||||||
|
|
||||||
mod transaction;
|
mod transaction;
|
||||||
pub use transaction::{Overrides, Transaction, TransactionReceipt, TransactionRequest};
|
pub use transaction::{Transaction, TransactionReceipt, TransactionRequest};
|
||||||
|
|
||||||
mod bytes;
|
mod bytes;
|
||||||
pub use bytes::Bytes;
|
pub use bytes::Bytes;
|
||||||
|
|
|
@ -6,31 +6,6 @@ use rlp::RlpStream;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::str::FromStr;
|
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
|
/// Parameters for sending a transaction
|
||||||
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Debug)]
|
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Debug)]
|
||||||
pub struct TransactionRequest {
|
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)]
|
#[derive(Clone, Debug, Error)]
|
||||||
pub enum TxError {
|
pub enum TxError {
|
||||||
|
/// Thrown if the `nonce` field is missing
|
||||||
#[error("no nonce was specified")]
|
#[error("no nonce was specified")]
|
||||||
NonceMissing,
|
NonceMissing,
|
||||||
|
/// Thrown if the `gas_price` field is missing
|
||||||
#[error("no gas price was specified")]
|
#[error("no gas price was specified")]
|
||||||
GasPriceMissing,
|
GasPriceMissing,
|
||||||
|
/// Thrown if the `gas` field is missing
|
||||||
#[error("no gas was specified")]
|
#[error("no gas was specified")]
|
||||||
GasMissing,
|
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;
|
mod crypto;
|
||||||
pub use crypto::*;
|
pub use crypto::*;
|
||||||
|
|
||||||
|
@ -8,3 +43,6 @@ pub use chainstate::*;
|
||||||
|
|
||||||
#[cfg(feature = "abi")]
|
#[cfg(feature = "abi")]
|
||||||
pub mod abi;
|
pub mod abi;
|
||||||
|
|
||||||
|
// Convenience re-export
|
||||||
|
pub use ethers_utils as utils;
|
||||||
|
|
Loading…
Reference in New Issue