Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: ProviderCall #788

Merged
merged 46 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
26f9273
feature: ProviderCall
prestwich May 27, 2024
f14aa77
refactor: replace output types
prestwich May 31, 2024
0b0b835
doc: add note about fn pointers
prestwich May 31, 2024
478ac23
resolve conflicts
yash-atreya Jun 27, 2024
1cb1579
feat: convert `EthCall` to `ProviderCall`
yash-atreya Jun 27, 2024
2ff402b
doc nits
yash-atreya Jun 27, 2024
569d168
use `ClientRef` instead of `WeakClient` in `RpcWithBlock`
yash-atreya Jun 27, 2024
b06e897
Revert "use `ClientRef` instead of `WeakClient` in `RpcWithBlock`"
yash-atreya Jun 28, 2024
b16ab35
feat: RpcCallWithBlock enum val in provider call
yash-atreya Jul 1, 2024
095ed89
nits
yash-atreya Jul 2, 2024
faf3d87
feat: integrate `RpcWithBlock` into `ProviderCall`
yash-atreya Jul 8, 2024
821fe39
resolve conflicts
yash-atreya Jul 30, 2024
cca6525
rm `RpcWithBlock` val from ProviderCall
yash-atreya Jul 30, 2024
f8ced1d
feat(provider): caller trait for with_block calls
yash-atreya Aug 5, 2024
b9ae66a
rm `WeakClient` from `RpcWithBlock`
yash-atreya Aug 5, 2024
2e43c22
introduce `Caller` into `RpcWithBlock`
yash-atreya Aug 5, 2024
e8a4b03
use `WithBlockCall` in `RpcWithBlock`. polling doesn't work.
yash-atreya Aug 5, 2024
250de00
nit
yash-atreya Aug 5, 2024
7a747a8
feat(provider): add `WithBlockFut` - polls `ProviderCall` and maps re…
yash-atreya Aug 5, 2024
0c4f4fe
nit
yash-atreya Aug 5, 2024
8ea73c9
revert 2ff402
yash-atreya Aug 5, 2024
a77d9f9
Revert "feat: convert `EthCall` to `ProviderCall`"
yash-atreya Aug 5, 2024
5e88a37
Merge branch 'main' into prestwich/provider-call-fut
yash-atreya Aug 5, 2024
6001e44
doc nits
yash-atreya Aug 5, 2024
a05f71c
feat(provider): introduce `Caller` to `EthCall`. Arc it so that its c…
yash-atreya Aug 6, 2024
50116aa
feat(provider): add `EthCaller` - converts EthCall into ProviderCall …
yash-atreya Aug 6, 2024
0a8c1af
update `EthCallFut`
yash-atreya Aug 6, 2024
d0a184a
impl poll_preparing and poll_running on `EthCallFut` instead of `EthC…
yash-atreya Aug 6, 2024
0b30b86
poll `ProviderCall` in `EthCall`using `EthCaller`
yash-atreya Aug 6, 2024
3ed9035
nit
yash-atreya Aug 6, 2024
a3dad97
wrap Caller in Arc to make `RpcWithBlock` cloneable
yash-atreya Aug 7, 2024
3683a9c
store in `ProvideCall` fut instance in `States`
yash-atreya Aug 7, 2024
f967b67
store `ProviderCall` fut in `EthCallFutInner`
yash-atreya Aug 7, 2024
2cb9e50
feat(provider): add `ParamsWithBlock` for `RpcWithBlock`
yash-atreya Aug 7, 2024
aa9e9f7
rm `block_id` from `Caller` trait
yash-atreya Aug 7, 2024
460fa46
impl `Caller` for `WeakClient`
yash-atreya Aug 7, 2024
f2ca144
refactor(`ProviderCall`): don't rely on `Caller` in `RpcWithBlock` (#…
klkvr Aug 21, 2024
9f48291
resolve conflicts
yash-atreya Aug 21, 2024
e1f0cae
Merge branch 'main' into prestwich/provider-call-fut
yash-atreya Aug 23, 2024
4e199ce
refac(provider): use `ProviderCall` as return in trait
yash-atreya Aug 26, 2024
3822252
nit
yash-atreya Aug 26, 2024
b4744ab
resolve conflicts
yash-atreya Aug 26, 2024
d06bf26
resolve conflicts
yash-atreya Aug 26, 2024
e175c13
doc nits
yash-atreya Sep 9, 2024
5a8bba4
Merge branch 'main' into prestwich/provider-call-fut
yash-atreya Sep 17, 2024
8f53e56
fix
yash-atreya Sep 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/contract/src/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ impl<T: Transport + Clone, P: Provider<T, N>, D: CallDecoder, N: Network> CallBu
/// If this is not desired, use [`call_raw`](Self::call_raw) to get the raw output data.
#[doc(alias = "eth_call")]
#[doc(alias = "call_with_overrides")]
pub fn call(&self) -> EthCall<'_, '_, '_, D, T, N> {
pub fn call(&self) -> EthCall<'_, '_, D, T, N> {
self.call_raw().with_decoder(&self.decoder)
}

Expand All @@ -457,7 +457,7 @@ impl<T: Transport + Clone, P: Provider<T, N>, D: CallDecoder, N: Network> CallBu
/// Does not decode the output of the call, returning the raw output data instead.
///
/// See [`call`](Self::call) for more information.
pub fn call_raw(&self) -> EthCall<'_, '_, '_, (), T, N> {
pub fn call_raw(&self) -> EthCall<'_, '_, (), T, N> {
let call = self.provider.call(&self.request).block(self.block);
let call = match &self.state {
Some(state) => call.overrides(state),
Expand Down
38 changes: 18 additions & 20 deletions crates/contract/src/eth_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,44 +24,44 @@ mod private {
/// An [`alloy_provider::EthCall`] with an abi decoder.
#[must_use = "EthCall must be awaited to execute the call"]
#[derive(Clone, Debug)]
pub struct EthCall<'req, 'state, 'coder, D, T, N>
pub struct EthCall<'req, 'coder, D, T, N>
where
T: Transport + Clone,
N: Network,
D: CallDecoder,
{
inner: alloy_provider::EthCall<'req, 'state, T, N, Bytes>,
inner: alloy_provider::EthCall<'req, T, N, Bytes>,

decoder: &'coder D,
}

impl<'req, 'state, 'coder, D, T, N> EthCall<'req, 'state, 'coder, D, T, N>
impl<'req, 'coder, D, T, N> EthCall<'req, 'coder, D, T, N>
where
T: Transport + Clone,
N: Network,
D: CallDecoder,
{
/// Create a new [`EthCall`].
pub const fn new(
inner: alloy_provider::EthCall<'req, 'state, T, N, Bytes>,
inner: alloy_provider::EthCall<'req, T, N, Bytes>,
decoder: &'coder D,
) -> Self {
Self { inner, decoder }
}
}

impl<'req, 'state, T, N> EthCall<'req, 'state, 'static, (), T, N>
impl<'req, T, N> EthCall<'req, 'static, (), T, N>
where
T: Transport + Clone,
N: Network,
{
/// Create a new [`EthCall`].
pub const fn new_raw(inner: alloy_provider::EthCall<'req, 'state, T, N, Bytes>) -> Self {
pub const fn new_raw(inner: alloy_provider::EthCall<'req, T, N, Bytes>) -> Self {
Self::new(inner, &RAW_CODER)
}
}

impl<'req, 'state, 'coder, D, T, N> EthCall<'req, 'state, 'coder, D, T, N>
impl<'req, 'coder, D, T, N> EthCall<'req, 'coder, D, T, N>
where
T: Transport + Clone,
N: Network,
Expand All @@ -71,15 +71,15 @@ where
pub fn with_decoder<'new_coder, E>(
self,
decoder: &'new_coder E,
) -> EthCall<'req, 'state, 'new_coder, E, T, N>
) -> EthCall<'req, 'new_coder, E, T, N>
where
E: CallDecoder,
{
EthCall { inner: self.inner, decoder }
}

/// Set the state overrides for this call.
pub fn overrides(mut self, overrides: &'state StateOverride) -> Self {
pub fn overrides(mut self, overrides: &'req StateOverride) -> Self {
self.inner = self.inner.overrides(overrides);
self
}
Expand All @@ -91,27 +91,26 @@ where
}
}

impl<'req, 'state, T, N> From<alloy_provider::EthCall<'req, 'state, T, N, Bytes>>
for EthCall<'req, 'state, 'static, (), T, N>
impl<'req, T, N> From<alloy_provider::EthCall<'req, T, N, Bytes>>
for EthCall<'req, 'static, (), T, N>
where
T: Transport + Clone,
N: Network,
{
fn from(inner: alloy_provider::EthCall<'req, 'state, T, N, Bytes>) -> Self {
fn from(inner: alloy_provider::EthCall<'req, T, N, Bytes>) -> Self {
Self { inner, decoder: &RAW_CODER }
}
}

impl<'req, 'state, 'coder, D, T, N> std::future::IntoFuture
for EthCall<'req, 'state, 'coder, D, T, N>
impl<'req, 'coder, D, T, N> std::future::IntoFuture for EthCall<'req, 'coder, D, T, N>
where
D: CallDecoder + Unpin,
T: Transport + Clone,
N: Network,
{
type Output = Result<D::CallOutput>;

type IntoFuture = EthCallFut<'req, 'state, 'coder, D, T, N>;
type IntoFuture = EthCallFut<'req, 'coder, D, T, N>;

fn into_future(self) -> Self::IntoFuture {
EthCallFut { inner: self.inner.into_future(), decoder: self.decoder }
Expand All @@ -121,20 +120,19 @@ where
/// Future for the [`EthCall`] type. This future wraps an RPC call with an abi
/// decoder.
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[derive(Clone, Debug)]
#[derive(Debug)]
#[allow(unnameable_types)]
pub struct EthCallFut<'req, 'state, 'coder, D, T, N>
pub struct EthCallFut<'req, 'coder, D, T, N>
where
T: Transport + Clone,
N: Network,
D: CallDecoder,
{
inner: <alloy_provider::EthCall<'req, 'state, T, N, Bytes> as IntoFuture>::IntoFuture,
inner: <alloy_provider::EthCall<'req, T, N, Bytes> as IntoFuture>::IntoFuture,
decoder: &'coder D,
}

impl<'req, 'state, 'coder, D, T, N> std::future::Future
for EthCallFut<'req, 'state, 'coder, D, T, N>
impl<'req, 'coder, D, T, N> std::future::Future for EthCallFut<'req, 'coder, D, T, N>
where
D: CallDecoder + Unpin,
T: Transport + Clone,
Expand Down
15 changes: 12 additions & 3 deletions crates/json-rpc/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ impl<Params> Request<Params> {
pub fn set_subscription_status(&mut self, sub: bool) {
self.meta.set_subscription_status(sub);
}

/// Change type of the request parameters.
pub fn map_params<NewParams>(
self,
map: impl FnOnce(Params) -> NewParams,
) -> Request<NewParams> {
Request { meta: self.meta, params: map(self.params) }
}
}

/// A [`Request`] that has been partially serialized.
Expand Down Expand Up @@ -113,11 +121,12 @@ where

impl<Params> Request<&Params>
where
Params: Clone,
Params: ToOwned,
Params::Owned: RpcParam,
{
/// Clone the request, including the request parameters.
pub fn into_owned_params(self) -> Request<Params> {
Request { meta: self.meta, params: self.params.clone() }
pub fn into_owned_params(self) -> Request<Params::Owned> {
Request { meta: self.meta, params: self.params.to_owned() }
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/provider/src/ext/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,14 @@ where
trace_types: &'b [TraceType],
) -> RpcWithBlock<T, (&'a <N as Network>::TransactionRequest, &'b [TraceType]), TraceResults>
{
RpcWithBlock::new(self.weak_client(), "trace_call", (request, trace_types))
self.client().request("trace_call", (request, trace_types)).into()
}

fn trace_call_many<'a>(
&self,
request: TraceCallList<'a, N>,
) -> RpcWithBlock<T, (TraceCallList<'a, N>,), Vec<TraceResults>> {
RpcWithBlock::new(self.weak_client(), "trace_callMany", (request,))
self.client().request("trace_callMany", (request,)).into()
}

async fn trace_transaction(
Expand Down
11 changes: 6 additions & 5 deletions crates/provider/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,24 @@ extern crate tracing;
mod builder;
pub use builder::{Identity, ProviderBuilder, ProviderLayer, Stack};

mod chain;

pub mod ext;

pub mod fillers;
pub mod layers;

mod chain;

mod heart;
pub use heart::{
PendingTransaction, PendingTransactionBuilder, PendingTransactionConfig,
PendingTransactionError, WatchTxError,
};

pub mod layers;

mod provider;
pub use provider::{
builder, EthCall, FilterPollerBuilder, Provider, RootProvider, RpcWithBlock, SendableTx,
WalletProvider,
builder, Caller, EthCall, EthCallParams, FilterPollerBuilder, ParamsWithBlock, Provider,
ProviderCall, RootProvider, RpcWithBlock, SendableTx, WalletProvider,
};

pub mod utils;
Expand Down
47 changes: 47 additions & 0 deletions crates/provider/src/provider/caller.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use crate::ProviderCall;
use alloy_json_rpc::{RpcParam, RpcReturn};
use alloy_rpc_client::WeakClient;
use alloy_transport::{RpcError, Transport, TransportErrorKind, TransportResult};
use std::borrow::Cow;

// TODO: Make `EthCall` specific. Ref: https://github.com/alloy-rs/alloy/pull/788#discussion_r1748862509.

/// Trait that helpes convert `EthCall` into a `ProviderCall`.
pub trait Caller<T, Params, Resp>: Send + Sync
klkvr marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given we're now wonly using this for EthCall, I think we should make it more call-specific, eg make it accept TransactionRequest, block and overrides directly to allow implementations to directly call underlying evm with them.

where
T: Transport + Clone,
Params: RpcParam,
Resp: RpcReturn,
{
/// Method that needs to be implemented to convert to a `ProviderCall`.
///
/// This method handles serialization of the params and sends the request to relevant data
/// source and returns a `ProviderCall`.
fn call(
&self,
method: Cow<'static, str>,
params: Params,
) -> TransportResult<ProviderCall<T, serde_json::Value, Resp>>;
}

impl<T, Params, Resp> Caller<T, Params, Resp> for WeakClient<T>
where
T: Transport + Clone,
Params: RpcParam,
Resp: RpcReturn,
{
fn call(
&self,
method: Cow<'static, str>,
params: Params,
) -> TransportResult<ProviderCall<T, serde_json::Value, Resp>> {
let client = self.upgrade().ok_or_else(TransportErrorKind::backend_gone)?;

// serialize the params
let ser = serde_json::to_value(params).map_err(RpcError::ser_err)?;

let rpc_call = client.request(method, ser);

Ok(ProviderCall::RpcCall(rpc_call))
}
}
Loading