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
|
//! 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)
|
//! 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 crate::{provider::ProviderError, JsonRpcClient};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
@ -8,12 +32,27 @@ use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::{
|
use std::{
|
||||||
fmt,
|
fmt,
|
||||||
|
str::FromStr,
|
||||||
sync::atomic::{AtomicU64, Ordering},
|
sync::atomic::{AtomicU64, Ordering},
|
||||||
};
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use url::Url;
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct Provider {
|
pub struct Provider {
|
||||||
id: AtomicU64,
|
id: AtomicU64,
|
||||||
|
@ -29,7 +68,7 @@ pub enum ClientError {
|
||||||
ReqwestError(#[from] ReqwestError),
|
ReqwestError(#[from] ReqwestError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
/// Thrown if the response could not be parsed
|
/// Thrown if the response could not be parsed
|
||||||
JsonRpcError(#[from] JsonRpcError),
|
JsonRpcError(#[from] errors::JsonRpcError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ClientError> for ProviderError {
|
impl From<ClientError> for ProviderError {
|
||||||
|
@ -68,6 +107,16 @@ impl JsonRpcClient for Provider {
|
||||||
|
|
||||||
impl Provider {
|
impl Provider {
|
||||||
/// Initializes a new HTTP Client
|
/// 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 {
|
pub fn new(url: impl Into<Url>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: AtomicU64::new(0),
|
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 {
|
impl Clone for Provider {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -87,24 +145,29 @@ impl Clone for Provider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, Error)]
|
// leak private type w/o exposing it
|
||||||
/// A JSON-RPC 2.0 error
|
mod errors {
|
||||||
pub struct JsonRpcError {
|
use super::*;
|
||||||
/// The error code
|
|
||||||
pub code: i64,
|
|
||||||
/// The error message
|
|
||||||
pub message: String,
|
|
||||||
/// Additional data
|
|
||||||
pub data: Option<Value>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for JsonRpcError {
|
#[derive(Serialize, Deserialize, Debug, Clone, Error)]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
/// A JSON-RPC 2.0 error
|
||||||
write!(
|
pub struct JsonRpcError {
|
||||||
f,
|
/// The error code
|
||||||
"(code: {}, message: {}, data: {:?})",
|
pub code: i64,
|
||||||
self.code, self.message, self.data
|
/// The error message
|
||||||
)
|
pub message: String,
|
||||||
|
/// Additional data
|
||||||
|
pub data: Option<Value>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for JsonRpcError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"(code: {}, message: {}, data: {:?})",
|
||||||
|
self.code, self.message, self.data
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,13 +203,13 @@ struct Response<T> {
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
enum ResponseData<R> {
|
enum ResponseData<R> {
|
||||||
Error { error: JsonRpcError },
|
Error { error: errors::JsonRpcError },
|
||||||
Success { result: R },
|
Success { result: R },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> ResponseData<R> {
|
impl<R> ResponseData<R> {
|
||||||
/// Consume response and return value
|
/// Consume response and return value
|
||||||
fn into_result(self) -> Result<R, JsonRpcError> {
|
fn into_result(self) -> Result<R, errors::JsonRpcError> {
|
||||||
match self {
|
match self {
|
||||||
ResponseData::Success { result } => Ok(result),
|
ResponseData::Success { result } => Ok(result),
|
||||||
ResponseData::Error { error } => Err(error),
|
ResponseData::Error { error } => Err(error),
|
||||||
|
|
|
@ -19,9 +19,8 @@ pub trait JsonRpcClient: Debug + Clone {
|
||||||
type Error: Error + Into<ProviderError>;
|
type Error: Error + Into<ProviderError>;
|
||||||
|
|
||||||
/// Sends a request with the provided JSON-RPC and parameters 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, R>(&self, method: &str, params: Option<T>) -> Result<R, Self::Error>
|
||||||
&self,
|
where
|
||||||
method: &str,
|
T: Serialize + Send + Sync,
|
||||||
params: Option<T>,
|
R: for<'a> Deserialize<'a>;
|
||||||
) -> Result<R, Self::Error>;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ use std::{convert::TryFrom, fmt::Debug};
|
||||||
|
|
||||||
/// 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). Must be instantiated
|
/// 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.)
|
/// (e.g. HTTP, Websockets etc.)
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Provider<P>(P, Option<Address>);
|
pub struct Provider<P>(P, Option<Address>);
|
||||||
|
|
Loading…
Reference in New Issue