docs: add docs to ethers-providers

This commit is contained in:
Georgios Konstantopoulos 2020-05-28 19:34:06 +03:00
parent e51fbd06b0
commit 5489f08835
No known key found for this signature in database
GPG Key ID: FA607837CD26EDBC
6 changed files with 85 additions and 18 deletions

View File

@ -17,4 +17,4 @@ url = { version = "2.1.1", default-features = false }
[dev-dependencies] [dev-dependencies]
rustc-hex = "2.1.0" rustc-hex = "2.1.0"
tokio = { version = "0.2.21", features = ["macros"] } tokio = { version = "0.2.21", default-features = false, features = ["rt-core", "macros"] }

View File

@ -1,3 +1,4 @@
/// [Ethereum Name Service](https://docs.ens.domains/) support
// Adapted from https://github.com/hhatto/rust-ens/blob/master/src/lib.rs // Adapted from https://github.com/hhatto/rust-ens/blob/master/src/lib.rs
use ethers_types::{Address, NameOrAddress, Selector, TransactionRequest, H256}; use ethers_types::{Address, NameOrAddress, Selector, TransactionRequest, H256};
use ethers_utils::keccak256; use ethers_utils::keccak256;
@ -6,13 +7,13 @@ use ethers_utils::keccak256;
const ENS_REVERSE_REGISTRAR_DOMAIN: &str = "addr.reverse"; const ENS_REVERSE_REGISTRAR_DOMAIN: &str = "addr.reverse";
// resolver(bytes32) /// resolver(bytes32)
const RESOLVER: Selector = [1, 120, 184, 191]; const RESOLVER: Selector = [1, 120, 184, 191];
// addr(bytes32) /// addr(bytes32)
pub const ADDR_SELECTOR: Selector = [59, 59, 87, 222]; pub const ADDR_SELECTOR: Selector = [59, 59, 87, 222];
// name(bytes32) /// name(bytes32)
pub const NAME_SELECTOR: Selector = [105, 31, 52, 49]; pub const NAME_SELECTOR: Selector = [105, 31, 52, 49];
/// Returns a transaction request for calling the `resolver` method on the ENS server /// Returns a transaction request for calling the `resolver` method on the ENS server
@ -26,6 +27,7 @@ pub fn get_resolver<T: Into<Address>>(ens_address: T, name: &str) -> Transaction
} }
} }
/// Returns a transaction request for calling
pub fn resolve<T: Into<Address>>( pub fn resolve<T: Into<Address>>(
resolver_address: T, resolver_address: T,
selector: Selector, selector: Selector,

View File

@ -1,16 +1,59 @@
//! Ethereum compatible providers //! # Clients for interacting with Ethereum nodes
//! Currently supported:
//! - Raw HTTP POST requests
//! //!
//! TODO: WebSockets, multiple backends, popular APIs etc. //! This crate provides asynchronous [Ethereum JSON-RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC)
//! compliant clients. The client is network-specific in order to provide ENS support and EIP-155
//! replay protection. If you are testing and do not want to use EIP-155, you may use the `Any`
//! network type and override the provider's ENS address with the `ens` method.
//!
//! ```rust
//! use ethers_providers::{HttpProvider, networks::Any};
//! use std::convert::TryFrom;
//! use tokio::runtime::Runtime;
//!
//! let provider = HttpProvider::<Any>::try_from(
//! "https://mainnet.infura.io/v3/9408f47dedf04716a03ef994182cf150"
//! ).unwrap();
//!
//! // Since this is an async function, we need to run it from an async runtime,
//! // such as `tokio`
//! let mut runtime = Runtime::new().expect("Failed to create Tokio runtime");
//! let block = runtime.block_on(provider.get_block(100u64)).unwrap();
//! println!("Got block: {}", serde_json::to_string(&block).unwrap());
//! ```
//!
//! # Ethereum Name Service
//!
//! The provider may also be used to resolve [Ethereum Name Service](https://ens.domains) (ENS) names
//! to addresses (and vice versa). The address of the deployed ENS contract per network is specified in
//! the `networks` module. If you want to use mainnet ENS, you should instantiate your provider as
//! follows:
//!
//! ```rust
//! # use ethers_providers::{HttpProvider, networks::Mainnet};
//! # use std::convert::TryFrom;
//! # use tokio::runtime::Runtime;
//! # let provider = HttpProvider::<Mainnet>::try_from(
//! # "https://mainnet.infura.io/v3/9408f47dedf04716a03ef994182cf150"
//! # ).unwrap();
//! # let mut runtime = Runtime::new().expect("Failed to create Tokio runtime");
//! // Resolve ENS name to Address
//! let name = "vitalik.eth";
//! let address = runtime.block_on(provider.resolve_name(name)).unwrap();
//! let address = address.unwrap();
//!
//! // Lookup ENS name given Address
//! let resolved_name = runtime.block_on(provider.lookup_address(address)).unwrap();
//! let resolved_name = resolved_name.unwrap();
//! assert_eq!(name, resolved_name);
//! ```
mod http; mod http;
mod provider; mod provider;
pub mod networks; pub mod networks;
/// ENS support // ENS support
pub mod ens; mod ens;
use async_trait::async_trait; use async_trait::async_trait;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -22,11 +65,13 @@ pub use provider::Provider;
pub type HttpProvider<N> = Provider<http::Provider, N>; pub type HttpProvider<N> = Provider<http::Provider, N>;
#[async_trait] #[async_trait]
/// Implement this trait in order to plug in different backends /// Trait which must be implemented by data transports to be used with the Ethereum
/// JSON-RPC provider.
pub trait JsonRpcClient: Debug { pub trait JsonRpcClient: Debug {
/// A JSON-RPC Error
type Error: Error; type Error: Error;
/// Sends a request with the provided method and the params serialized as JSON /// Sends a request with the provided JSON-RPC and parameters serialized as JSON
async fn request<T: Serialize + Send + Sync, R: for<'a> Deserialize<'a>>( async fn request<T: Serialize + Send + Sync, R: for<'a> Deserialize<'a>>(
&self, &self,
method: &str, method: &str,

View File

@ -1,16 +1,21 @@
//! Networks are used inside wallets to ensure type-safety across networks. That way //! Networks are used inside wallets and providers to ensure replay protection across networks,
//! a transaction that is designed to work with testnet does not accidentally work //! as well as to allow functions to be called with ENS names instead of Addresses.
//! with mainnet because the URL was changed.
use ethers_types::{Address, H160, U64}; use ethers_types::{Address, H160, U64};
/// Trait for specifying network specific metadata, such as the Chain Id or the ENS
/// address.
pub trait Network { pub trait Network {
/// The network's Chain Id. If None, then EIP-155 is not used and as a result
/// transactions **will not have replay protection**
const CHAIN_ID: Option<U64>; const CHAIN_ID: Option<U64>;
/// The network's ENS address.
const ENS_ADDRESS: Option<Address>; const ENS_ADDRESS: Option<Address>;
// TODO: Default providers? e.g. `mainnet.infura.io/XXX`? // TODO: Default providers? e.g. `mainnet.infura.io/XXX`?
} }
/// Ethereum Mainnet, pre-specified ENS address and ChainID = 1 (for EIP-155)
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Mainnet; pub struct Mainnet;
@ -24,7 +29,9 @@ impl Network for Mainnet {
])); ]));
} }
/// No EIP155 /// Any other network, ChainID is not specified so **there is no replay protection when
/// using this network type**. ENS is also not specified, so any calls to the provider's
/// `lookup_address` and `resolve_name` _will fail_.
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Any; pub struct Any;

View File

@ -13,7 +13,9 @@ use url::{ParseError, Url};
use std::{convert::TryFrom, fmt::Debug, marker::PhantomData}; use std::{convert::TryFrom, fmt::Debug, marker::PhantomData};
/// An abstract provider for interacting with the [Ethereum JSON RPC /// An abstract provider for interacting with the [Ethereum JSON RPC
/// API](https://github.com/ethereum/wiki/wiki/JSON-RPC) /// API](https://github.com/ethereum/wiki/wiki/JSON-RPC). Must be instantiated
/// with a [`Network`](networks/trait.Network.html) and a data transport
/// (e.g. HTTP, Websockets etc.)
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Provider<P, N>(P, PhantomData<N>, Option<Address>); pub struct Provider<P, N>(P, PhantomData<N>, Option<Address>);
@ -204,6 +206,10 @@ impl<P: JsonRpcClient, N: Network> Provider<P, N> {
} }
/// Returns the ENS name the `address` resolves to (or None if not configured). /// Returns the ENS name the `address` resolves to (or None if not configured).
/// # Panics
///
/// If the bytes returned from the ENS registrar/resolver cannot be interpreted as
/// a string. This should theoretically never happen.
pub async fn lookup_address(&self, address: Address) -> Result<Option<String>, P::Error> { pub async fn lookup_address(&self, address: Address) -> Result<Option<String>, P::Error> {
let ens_name = ens::reverse_address(address); let ens_name = ens::reverse_address(address);
self.query_resolver(ParamType::String, &ens_name, ens::NAME_SELECTOR) self.query_resolver(ParamType::String, &ens_name, ens::NAME_SELECTOR)
@ -244,6 +250,7 @@ impl<P: JsonRpcClient, N: Network> Provider<P, N> {
Ok(Some(decode_bytes(param, data))) Ok(Some(decode_bytes(param, data)))
} }
/// Overrides the default ENS address set by the provider's `Network` type.
pub fn ens<T: Into<Address>>(mut self, ens: T) -> Self { pub fn ens<T: Into<Address>>(mut self, ens: T) -> Self {
self.2 = Some(ens.into()); self.2 = Some(ens.into());
self self

View File

@ -74,6 +74,12 @@ pub enum BlockId {
Number(BlockNumber), Number(BlockNumber),
} }
impl From<u64> for BlockId {
fn from(num: u64) -> Self {
BlockNumber::Number(num.into()).into()
}
}
impl From<U64> for BlockId { impl From<U64> for BlockId {
fn from(num: U64) -> Self { fn from(num: U64) -> Self {
BlockNumber::Number(num).into() BlockNumber::Number(num).into()