chore: remove leftover file
This got checked in by accident
This commit is contained in:
parent
3459b1d350
commit
ded8f50ef4
|
@ -1,204 +0,0 @@
|
|||
use crate::{provider::ProviderError, JsonRpcClient};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use reqwest::{Client, Error as ReqwestError};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::{
|
||||
fmt,
|
||||
str::FromStr,
|
||||
sync::atomic::{AtomicU64, Ordering},
|
||||
};
|
||||
use thiserror::Error;
|
||||
use url::Url;
|
||||
|
||||
/// A low-level JSON-RPC Client over HTTP.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use ethers::{types::U64, providers::{JsonRpcClient, Http}};
|
||||
/// use std::str::FromStr;
|
||||
///
|
||||
/// # async fn foo() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let provider = Http::from_str("http://localhost:8545")?;
|
||||
/// let block_number: U64 = provider.request("eth_blockNumber", None::<()>).await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct Provider {
|
||||
id: AtomicU64,
|
||||
client: Client,
|
||||
url: Url,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
/// Error thrown when sending an HTTP request
|
||||
pub enum WsError {
|
||||
/// Thrown if the request failed
|
||||
#[error(transparent)]
|
||||
ReqwestError(#[from] ReqwestError),
|
||||
#[error(transparent)]
|
||||
/// Thrown if the response could not be parsed
|
||||
JsonRpcError(#[from] errors::JsonRpcError),
|
||||
}
|
||||
|
||||
impl From<ClientError> for ProviderError {
|
||||
fn from(src: ClientError) -> Self {
|
||||
ProviderError::JsonRpcClientError(Box::new(src))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl JsonRpcClient for Provider {
|
||||
type Error = ClientError;
|
||||
|
||||
/// Sends a POST request with the provided method and the params serialized as JSON
|
||||
/// over HTTP
|
||||
async fn request<T: Serialize + Send + Sync, R: for<'a> Deserialize<'a>>(
|
||||
&self,
|
||||
method: &str,
|
||||
params: T,
|
||||
) -> Result<R, ClientError> {
|
||||
let next_id = self.id.load(Ordering::SeqCst) + 1;
|
||||
self.id.store(next_id, Ordering::SeqCst);
|
||||
|
||||
let payload = Request::new(next_id, method, params);
|
||||
|
||||
let res = self
|
||||
.client
|
||||
.post(self.url.as_ref())
|
||||
.json(&payload)
|
||||
.send()
|
||||
.await?;
|
||||
let res = res.json::<Response<R>>().await?;
|
||||
|
||||
Ok(res.data.into_result()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl Provider {
|
||||
/// Initializes a new HTTP Client
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use ethers::providers::Http;
|
||||
/// use url::Url;
|
||||
///
|
||||
/// let url = Url::parse("http://localhost:8545").unwrap();
|
||||
/// let provider = Http::new(url);
|
||||
/// ```
|
||||
pub fn new(url: impl Into<Url>) -> Self {
|
||||
Self {
|
||||
id: AtomicU64::new(0),
|
||||
client: Client::new(),
|
||||
url: url.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
id: AtomicU64::new(0),
|
||||
client: self.client.clone(),
|
||||
url: self.url.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"(code: {}, message: {}, data: {:?})",
|
||||
self.code, self.message, self.data
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
/// A JSON-RPC request
|
||||
struct Request<'a, T> {
|
||||
id: u64,
|
||||
jsonrpc: &'a str,
|
||||
method: &'a str,
|
||||
params: T,
|
||||
}
|
||||
|
||||
impl<'a, T> Request<'a, T> {
|
||||
/// Creates a new JSON RPC request
|
||||
fn new(id: u64, method: &'a str, params: T) -> Self {
|
||||
Self {
|
||||
id,
|
||||
jsonrpc: "2.0",
|
||||
method,
|
||||
params,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
struct Response<T> {
|
||||
id: u64,
|
||||
jsonrpc: String,
|
||||
#[serde(flatten)]
|
||||
data: ResponseData<T>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[serde(untagged)]
|
||||
enum ResponseData<R> {
|
||||
Error { error: errors::JsonRpcError },
|
||||
Success { result: R },
|
||||
}
|
||||
|
||||
impl<R> ResponseData<R> {
|
||||
/// Consume response and return value
|
||||
fn into_result(self) -> Result<R, errors::JsonRpcError> {
|
||||
match self {
|
||||
ResponseData::Success { result } => Ok(result),
|
||||
ResponseData::Error { error } => Err(error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn response() {
|
||||
let response: Response<u64> =
|
||||
serde_json::from_str(r#"{"jsonrpc": "2.0", "result": 19, "id": 1}"#).unwrap();
|
||||
assert_eq!(response.id, 1);
|
||||
assert_eq!(response.data.into_result().unwrap(), 19);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue