docs(providers): add doctests and examples
This commit is contained in:
parent
980e7fca8c
commit
f93b8b6919
|
@ -1,5 +1,29 @@
|
|||
//! Minimal HTTP JSON-RPC 2.0 Client
|
||||
//! The request/response code is taken from [here](https://github.com/althea-net/guac_rs/blob/master/web3/src/jsonrpc)
|
||||
//!
|
||||
//! If interacting with Ethereum, consider using the
|
||||
//! [`Provider`](../struct.Provider.html) struct instead.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use ethers_providers::{JsonRpcClient, http::{Provider, ClientError}};
|
||||
//! use ethers_core::types::U64;
|
||||
//! use std::str::FromStr;
|
||||
//!
|
||||
//! async fn get_block(provider: &Provider) -> Result<U64, ClientError> {
|
||||
//! let block_number: U64 = provider.request("eth_blockNumber", None::<()>).await?;
|
||||
//! Ok(block_number)
|
||||
//! }
|
||||
//!
|
||||
//! # async fn foo() -> Result<(), Box<dyn std::error::Error>> {
|
||||
//! let provider = Provider::from_str("http://localhost:8545")?;
|
||||
//! let block = get_block(&provider).await?;
|
||||
//! println!("{:?}", block);
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//!
|
||||
//! ```
|
||||
use crate::{provider::ProviderError, JsonRpcClient};
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
@ -8,12 +32,27 @@ use serde::{Deserialize, Serialize};
|
|||
use serde_json::Value;
|
||||
use std::{
|
||||
fmt,
|
||||
str::FromStr,
|
||||
sync::atomic::{AtomicU64, Ordering},
|
||||
};
|
||||
use thiserror::Error;
|
||||
use url::Url;
|
||||
|
||||
/// An HTTP Client
|
||||
/// A low-level JSON-RPC Client over HTTP.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use ethers_providers::{JsonRpcClient, http::Provider};
|
||||
/// use ethers_core::types::U64;
|
||||
/// use std::str::FromStr;
|
||||
///
|
||||
/// # async fn foo() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let provider = Provider::from_str("http://localhost:8545")?;
|
||||
/// let block_number: U64 = provider.request("eth_blockNumber", None::<()>).await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct Provider {
|
||||
id: AtomicU64,
|
||||
|
@ -29,7 +68,7 @@ pub enum ClientError {
|
|||
ReqwestError(#[from] ReqwestError),
|
||||
#[error(transparent)]
|
||||
/// Thrown if the response could not be parsed
|
||||
JsonRpcError(#[from] JsonRpcError),
|
||||
JsonRpcError(#[from] errors::JsonRpcError),
|
||||
}
|
||||
|
||||
impl From<ClientError> for ProviderError {
|
||||
|
@ -68,6 +107,16 @@ impl JsonRpcClient for Provider {
|
|||
|
||||
impl Provider {
|
||||
/// Initializes a new HTTP Client
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use ethers_providers::http::Provider;
|
||||
/// use url::Url;
|
||||
///
|
||||
/// let url = Url::parse("http://localhost:8545").unwrap();
|
||||
/// let provider = Provider::new(url);
|
||||
/// ```
|
||||
pub fn new(url: impl Into<Url>) -> Self {
|
||||
Self {
|
||||
id: AtomicU64::new(0),
|
||||
|
@ -77,6 +126,15 @@ impl Provider {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromStr for Provider {
|
||||
type Err = url::ParseError;
|
||||
|
||||
fn from_str(src: &str) -> Result<Self, Self::Err> {
|
||||
let url = Url::parse(src)?;
|
||||
Ok(Provider::new(url))
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Provider {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
|
@ -87,18 +145,22 @@ impl Clone for Provider {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Error)]
|
||||
/// A JSON-RPC 2.0 error
|
||||
pub struct JsonRpcError {
|
||||
// leak private type w/o exposing it
|
||||
mod errors {
|
||||
use super::*;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Error)]
|
||||
/// A JSON-RPC 2.0 error
|
||||
pub struct JsonRpcError {
|
||||
/// The error code
|
||||
pub code: i64,
|
||||
/// The error message
|
||||
pub message: String,
|
||||
/// Additional data
|
||||
pub data: Option<Value>,
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for JsonRpcError {
|
||||
impl fmt::Display for JsonRpcError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
|
@ -106,6 +168,7 @@ impl fmt::Display for JsonRpcError {
|
|||
self.code, self.message, self.data
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
@ -140,13 +203,13 @@ struct Response<T> {
|
|||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[serde(untagged)]
|
||||
enum ResponseData<R> {
|
||||
Error { error: JsonRpcError },
|
||||
Error { error: errors::JsonRpcError },
|
||||
Success { result: R },
|
||||
}
|
||||
|
||||
impl<R> ResponseData<R> {
|
||||
/// Consume response and return value
|
||||
fn into_result(self) -> Result<R, JsonRpcError> {
|
||||
fn into_result(self) -> Result<R, errors::JsonRpcError> {
|
||||
match self {
|
||||
ResponseData::Success { result } => Ok(result),
|
||||
ResponseData::Error { error } => Err(error),
|
||||
|
|
|
@ -19,9 +19,8 @@ pub trait JsonRpcClient: Debug + Clone {
|
|||
type Error: Error + Into<ProviderError>;
|
||||
|
||||
/// 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>>(
|
||||
&self,
|
||||
method: &str,
|
||||
params: Option<T>,
|
||||
) -> Result<R, Self::Error>;
|
||||
async fn request<T, R>(&self, method: &str, params: Option<T>) -> Result<R, Self::Error>
|
||||
where
|
||||
T: Serialize + Send + Sync,
|
||||
R: for<'a> Deserialize<'a>;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ use std::{convert::TryFrom, fmt::Debug};
|
|||
|
||||
/// An abstract provider for interacting with the [Ethereum 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
|
||||
/// with a data transport
|
||||
/// (e.g. HTTP, Websockets etc.)
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Provider<P>(P, Option<Address>);
|
||||
|
|
Loading…
Reference in New Issue