docs: add docs to ethers-providers
This commit is contained in:
parent
e51fbd06b0
commit
5489f08835
|
@ -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"] }
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue