Skip to content

Commit

Permalink
try with out [async_trait]
Browse files Browse the repository at this point in the history
  • Loading branch information
hewigovens committed Apr 4, 2024
1 parent 8b328c3 commit 52c5f84
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 4 deletions.
51 changes: 51 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ serde = { version = "^1.0.0", features = ["derive"] }
serde_json = "^1.0.0"

async-trait = "^0.1.0"
futures = "^0.3.0"
10 changes: 7 additions & 3 deletions examples/ethereum-rpc/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
extern crate reqwest_enum;
use ethereum_rpc::EthereumRPC;
use reqwest_enum::jsonrpc::JsonRpcResult;
use reqwest_enum::provider::{JsonRpcProviderType, Provider};
use reqwest_enum::provider::{JsonRpcProviderType, JsonRpcProviderType2, Provider};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let provider = Provider::<EthereumRPC>::default();

let targets = vec![EthereumRPC::ChainId, EthereumRPC::GasPrice];
let results: Vec<JsonRpcResult<String>> = provider.batch(targets).await?;
let targets = vec![
EthereumRPC::ChainId,
EthereumRPC::GasPrice,
EthereumRPC::BlockNumber,
];
let results: Vec<JsonRpcResult<String>> = provider.batch_chunk_by(targets, 2).await?;
for result in results {
match result {
JsonRpcResult::Value(response) => {
Expand Down
3 changes: 2 additions & 1 deletion reqwest-enum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ edition = { workspace = true }

[features]
default = ["jsonrpc"]
jsonrpc = []
jsonrpc = ["dep:futures"]

[dependencies]
reqwest = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
async-trait = { workspace = true }
futures = { workspace = true, optional = true }
2 changes: 2 additions & 0 deletions reqwest-enum/src/jsonrpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@ pub struct JsonRpcError {
pub message: String,
}

#[cfg(feature = "jsonrpc")]
impl std::error::Error for JsonRpcError {}

#[cfg(feature = "jsonrpc")]
impl From<reqwest::Error> for JsonRpcError {
fn from(err: reqwest::Error) -> Self {
JsonRpcError {
Expand Down
72 changes: 72 additions & 0 deletions reqwest-enum/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ pub trait JsonRpcProviderType<T: Target>: ProviderType<T> {
) -> Result<Vec<JsonRpcResult<U>>, JsonRpcError>;
}

use core::future::Future;
use futures::future::join_all;
pub trait JsonRpcProviderType2<T: Target>: ProviderType<T> {
fn batch_chunk_by<U: DeserializeOwned>(
&self,
targets: Vec<T>,
chunk_size: usize,
) -> impl Future<Output = Result<Vec<JsonRpcResult<U>>, JsonRpcError>>;
}

pub type EndpointFn<T> = fn(target: &T) -> String;
pub struct Provider<T: Target> {
/// endpoint closure to customize the endpoint (url / path)
Expand Down Expand Up @@ -94,6 +104,68 @@ where
}
}

impl<T> JsonRpcProviderType2<T> for Provider<T>
where
T: JsonRpcTarget + Send,
{
async fn batch_chunk_by<U: DeserializeOwned>(
&self,
targets: Vec<T>,
chunk_size: usize,
) -> Result<Vec<JsonRpcResult<U>>, JsonRpcError> {
if targets.is_empty() || chunk_size == 0 {
return Err(JsonRpcError {
code: -32600,
message: "Invalid Request".into(),
});
}

let chunk_targets = targets.chunks(chunk_size).collect::<Vec<_>>();
let mut rpc_requests = Vec::<reqwest::RequestBuilder>::new();

for (chunk_idx, chunk) in chunk_targets.into_iter().enumerate() {
let target = &chunk[0];
let mut request = self.request_builder(target);
let mut requests = Vec::<JsonRpcRequest>::new();
for (k, v) in chunk.iter().enumerate() {
let request = JsonRpcRequest::new(
v.method_name(),
v.params(),
(chunk_idx * chunk_size + k) as u64,
);
requests.push(request);
}

request = request.body(HTTPBody::from_array(&requests).inner);
rpc_requests.push(request);
}
let bodies = join_all(rpc_requests.into_iter().map(|request| async move {
let response = request.send().await?;
let body = response.json::<Vec<JsonRpcResult<U>>>().await?;
Ok(body)
}))
.await;

let mut results = Vec::<JsonRpcResult<U>>::new();
let mut error: Option<JsonRpcError> = None;

for result in bodies {
match result {
Ok(body) => {
results.extend(body);
}
Err(err) => {
error = Some(err);
}
}
}
if let Some(err) = error {
return Err(err);
}
Ok(results)
}
}

impl<T> Provider<T>
where
T: Target,
Expand Down

0 comments on commit 52c5f84

Please sign in to comment.