Skip to content

Commit

Permalink
feat(provider): instantiate recommended fillers by default (#1901)
Browse files Browse the repository at this point in the history
* feat(`provider`): make recommended fillers the default

* fix: event filter tests

* fix

* test

* nit

* fix: doc tests + event_filter tests + return impl Provider

* fix

* docs

* doc nit
  • Loading branch information
yash-atreya authored Jan 10, 2025
1 parent 4fb600d commit e3651c9
Show file tree
Hide file tree
Showing 14 changed files with 116 additions and 55 deletions.
1 change: 1 addition & 0 deletions crates/contract/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ alloy-rpc-client = { workspace = true, features = ["pubsub", "ws"] }
alloy-transport-http.workspace = true
alloy-node-bindings.workspace = true
alloy-provider = { workspace = true, features = ["anvil-node"] }
alloy-signer-local.workspace = true

reqwest.workspace = true
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
Expand Down
2 changes: 1 addition & 1 deletion crates/contract/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ sol! {
}
// Build a provider.
let provider = ProviderBuilder::new().with_recommended_fillers().on_builtin("http://localhost:8545").await?;
let provider = ProviderBuilder::new().on_builtin("http://localhost:8545").await?;
// If `#[sol(bytecode = "0x...")]` is provided, the contract can be deployed with `MyContract::deploy`,
// and a new instance will be created.
Expand Down
12 changes: 5 additions & 7 deletions crates/contract/src/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -569,9 +569,7 @@ mod tests {
use super::*;
use alloy_consensus::Transaction;
use alloy_primitives::{address, b256, bytes, hex, utils::parse_units, B256};
use alloy_provider::{
layers::AnvilProvider, Provider, ProviderBuilder, RootProvider, WalletProvider,
};
use alloy_provider::{Provider, ProviderBuilder, WalletProvider};
use alloy_rpc_types_eth::AccessListItem;
use alloy_sol_types::sol;

Expand Down Expand Up @@ -621,8 +619,8 @@ mod tests {

/// Creates a new call_builder to test field modifications, taken from [call_encoding]
#[allow(clippy::type_complexity)]
fn build_call_builder(
) -> CallBuilder<(), AnvilProvider<RootProvider>, PhantomData<MyContract::doStuffCall>> {
fn build_call_builder() -> CallBuilder<(), impl Provider, PhantomData<MyContract::doStuffCall>>
{
let provider = ProviderBuilder::new().on_anvil();
let contract = MyContract::new(Address::ZERO, provider);
let call_builder = contract.doStuff(U256::ZERO, true).with_cloned_provider();
Expand Down Expand Up @@ -730,7 +728,7 @@ mod tests {

#[tokio::test(flavor = "multi_thread")]
async fn deploy_and_call() {
let provider = ProviderBuilder::new().with_recommended_fillers().on_anvil_with_wallet();
let provider = ProviderBuilder::new().on_anvil_with_wallet();

let expected_address = provider.default_signer_address().create(0);
let my_contract = MyContract::deploy(provider, true).await.unwrap();
Expand All @@ -756,7 +754,7 @@ mod tests {

#[tokio::test(flavor = "multi_thread")]
async fn deploy_and_call_with_priority() {
let provider = ProviderBuilder::new().on_anvil();
let provider = ProviderBuilder::new().on_anvil_with_wallet();
let counter_contract = Counter::deploy(provider.clone()).await.unwrap();
let max_fee_per_gas: U256 = parse_units("50", "gwei").unwrap().into();
let max_priority_fee_per_gas: U256 = parse_units("0.1", "gwei").unwrap().into();
Expand Down
20 changes: 18 additions & 2 deletions crates/contract/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,9 @@ pub(crate) mod subscription {
#[cfg(test)]
mod tests {
use super::*;
use alloy_network::EthereumWallet;
use alloy_primitives::U256;
use alloy_signer_local::PrivateKeySigner;
use alloy_sol_types::sol;

sol! {
Expand Down Expand Up @@ -309,8 +311,15 @@ mod tests {
let _ = tracing_subscriber::fmt::try_init();

let anvil = alloy_node_bindings::Anvil::new().spawn();
let provider = alloy_provider::ProviderBuilder::new().on_http(anvil.endpoint_url());

let pk: PrivateKeySigner =
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80".parse().unwrap();
let wallet = EthereumWallet::from(pk);
let provider = alloy_provider::ProviderBuilder::new()
.wallet(wallet.clone())
.on_http(anvil.endpoint_url());

// let from = address!("f39Fd6e51aad88F6F4ce6aB8827279cffFb92266");
let contract = MyContract::deploy(&provider).await.unwrap();

let event: Event<(), _, MyContract::MyEvent, _> = Event::new(&provider, Filter::new());
Expand Down Expand Up @@ -365,6 +374,7 @@ mod tests {
#[cfg(feature = "pubsub")]
{
let provider = alloy_provider::ProviderBuilder::new()
.wallet(wallet)
.on_builtin(&anvil.ws_endpoint())
.await
.unwrap();
Expand Down Expand Up @@ -410,7 +420,12 @@ mod tests {
let _ = tracing_subscriber::fmt::try_init();

let anvil = alloy_node_bindings::Anvil::new().spawn();
let provider = alloy_provider::ProviderBuilder::new().on_http(anvil.endpoint_url());
let pk: PrivateKeySigner =
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80".parse().unwrap();
let wallet = EthereumWallet::from(pk);
let provider = alloy_provider::ProviderBuilder::new()
.wallet(wallet.clone())
.on_http(anvil.endpoint_url());

let contract = MyContract::deploy(&provider).await.unwrap();

Expand Down Expand Up @@ -465,6 +480,7 @@ mod tests {
#[cfg(feature = "pubsub")]
{
let provider = alloy_provider::ProviderBuilder::new()
.wallet(wallet)
.on_builtin(&anvil.ws_endpoint())
.await
.unwrap();
Expand Down
2 changes: 1 addition & 1 deletion crates/contract/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ mod tests {

#[tokio::test]
async fn contract_interface() {
let provider = ProviderBuilder::new().on_anvil();
let provider = ProviderBuilder::new().on_anvil_with_wallet();

let abi_str = r#"[{"inputs":[],"name":"counter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"increment","outputs":[],"stateMutability":"nonpayable","type":"function"}]"#;
let abi = serde_json::from_str::<JsonAbi>(abi_str).unwrap();
Expand Down
54 changes: 33 additions & 21 deletions crates/provider/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ where
/// This type is similar to [`tower::ServiceBuilder`], with extra complication
/// around maintaining the network and transport types.
///
/// The [`ProviderBuilder`] can be instantiated in two ways, using `ProviderBuilder::new()` or
/// `ProviderBuilder::default()`.
///
/// `ProviderBuilder::new()` will create a new [`ProviderBuilder`] with the [`RecommendedFillers`]
/// enabled, whereas `ProviderBuilder::default()` will instantiate it in its vanilla
/// [`ProviderBuilder`] form i.e with no fillers enabled.
///
/// [`tower::ServiceBuilder`]: https://docs.rs/tower/latest/tower/struct.ServiceBuilder.html
#[derive(Debug)]
pub struct ProviderBuilder<L, F, N = Ethereum> {
Expand All @@ -112,10 +119,31 @@ pub struct ProviderBuilder<L, F, N = Ethereum> {
network: PhantomData<fn() -> N>,
}

impl ProviderBuilder<Identity, Identity, Ethereum> {
/// Create a new [`ProviderBuilder`].
pub const fn new() -> Self {
Self { layer: Identity, filler: Identity, network: PhantomData }
impl
ProviderBuilder<
Identity,
JoinFill<Identity, <alloy_network::Ethereum as RecommendedFillers>::RecommendedFillers>,
Ethereum,
>
{
/// Create a new [`ProviderBuilder`] with the recommended filler enabled.
///
/// Recommended fillers are preconfigured set of fillers that handle gas estimation, nonce
/// management, and chain-id fetching.
///
/// Building a provider with this setting enabled will return a [`crate::fillers::FillProvider`]
/// with [`crate::utils::JoinedRecommendedFillers`].
///
/// You can opt-out of using these fillers by using the `.disable_recommended_fillers()` method.
pub fn new() -> Self {
ProviderBuilder::default().with_recommended_fillers()
}

/// Opt-out of the recommended fillers by reseting the fillers stack in the [`ProviderBuilder`].
///
/// This is equivalent to creating the builder using `ProviderBuilder::default()`.
pub fn disable_recommended_fillers(self) -> ProviderBuilder<Identity, Identity, Ethereum> {
ProviderBuilder { layer: self.layer, filler: Identity, network: self.network }
}
}

Expand Down Expand Up @@ -384,6 +412,7 @@ impl<L, F> ProviderBuilder<L, F, Ethereum> {
>,
{
self.on_anvil_with_wallet_and_config(std::convert::identity)
.expect("failed to build provider")
}

/// Build this provider with anvil, using the BoxTransport. The
Expand Down Expand Up @@ -411,23 +440,6 @@ impl<L, F> ProviderBuilder<L, F, Ethereum> {
pub fn on_anvil_with_wallet_and_config(
self,
f: impl FnOnce(alloy_node_bindings::Anvil) -> alloy_node_bindings::Anvil,
) -> <JoinedEthereumWalletFiller<F> as ProviderLayer<L::Provider>>::Provider
where
F: TxFiller<Ethereum> + ProviderLayer<L::Provider, Ethereum>,
L: crate::builder::ProviderLayer<
crate::layers::AnvilProvider<crate::provider::RootProvider>,
>,
{
self.try_on_anvil_with_wallet_and_config(f).unwrap()
}

/// Build this provider with anvil, using the BoxTransport. The
/// given function is used to configure the anvil instance. This
/// function configures a wallet backed by anvil keys, and is intended for
/// use in tests.
pub fn try_on_anvil_with_wallet_and_config(
self,
f: impl FnOnce(alloy_node_bindings::Anvil) -> alloy_node_bindings::Anvil,
) -> AnvilProviderResult<<JoinedEthereumWalletFiller<F> as ProviderLayer<L::Provider>>::Provider>
where
F: TxFiller<Ethereum> + ProviderLayer<L::Provider, Ethereum>,
Expand Down
5 changes: 2 additions & 3 deletions crates/provider/src/ext/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ mod test {
#[tokio::test]
async fn test_debug_trace_transaction() {
async_ci_only(|| async move {
let provider = ProviderBuilder::new().with_recommended_fillers().on_anvil_with_wallet();
let provider = ProviderBuilder::new().on_anvil_with_wallet();
let from = provider.default_signer_address();

let gas_price = provider.get_gas_price().await.unwrap();
Expand Down Expand Up @@ -542,8 +542,7 @@ mod test {
async_ci_only(|| async move {
run_with_tempdir("reth-test-", |temp_dir| async move {
let reth = Reth::new().dev().disable_discovery().data_dir(temp_dir).spawn();
let provider =
ProviderBuilder::new().with_recommended_fillers().on_http(reth.endpoint_url());
let provider = ProviderBuilder::new().on_http(reth.endpoint_url());

let tx1 = TransactionRequest::default()
.with_from(address!("0000000000000000000000000000000000000123"))
Expand Down
2 changes: 1 addition & 1 deletion crates/provider/src/fillers/chain_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::{
/// # use alloy_rpc_types_eth::TransactionRequest;
/// # use alloy_provider::{ProviderBuilder, RootProvider, Provider};
/// # async fn test<W: NetworkWallet<Ethereum> + Clone>(url: url::Url, wallet: W) -> Result<(), Box<dyn std::error::Error>> {
/// let provider = ProviderBuilder::new()
/// let provider = ProviderBuilder::default()
/// .with_chain_id(1)
/// .wallet(wallet)
/// .on_http(url);
Expand Down
10 changes: 5 additions & 5 deletions crates/provider/src/fillers/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub enum GasFillable {
/// # use alloy_rpc_types_eth::TransactionRequest;
/// # use alloy_provider::{ProviderBuilder, RootProvider, Provider};
/// # async fn test<W: NetworkWallet<Ethereum> + Clone>(url: url::Url, wallet: W) -> Result<(), Box<dyn std::error::Error>> {
/// let provider = ProviderBuilder::new()
/// let provider = ProviderBuilder::default()
/// .with_gas_estimation()
/// .wallet(wallet)
/// .on_http(url);
Expand Down Expand Up @@ -253,7 +253,7 @@ mod tests {

#[tokio::test]
async fn no_gas_price_or_limit() {
let provider = ProviderBuilder::new().with_recommended_fillers().on_anvil_with_wallet();
let provider = ProviderBuilder::new().on_anvil_with_wallet();

// GasEstimationLayer requires chain_id to be set to handle EIP-1559 tx
let tx = TransactionRequest {
Expand All @@ -273,7 +273,7 @@ mod tests {

#[tokio::test]
async fn no_gas_limit() {
let provider = ProviderBuilder::new().with_recommended_fillers().on_anvil_with_wallet();
let provider = ProviderBuilder::new().on_anvil_with_wallet();

let gas_price = provider.get_gas_price().await.unwrap();
let tx = TransactionRequest {
Expand All @@ -292,7 +292,7 @@ mod tests {

#[tokio::test]
async fn no_max_fee_per_blob_gas() {
let provider = ProviderBuilder::new().with_recommended_fillers().on_anvil_with_wallet();
let provider = ProviderBuilder::new().on_anvil_with_wallet();

let sidecar: SidecarBuilder<SimpleCoder> = SidecarBuilder::from_slice(b"Hello World");
let sidecar = sidecar.build().unwrap();
Expand All @@ -319,7 +319,7 @@ mod tests {

#[tokio::test]
async fn zero_max_fee_per_blob_gas() {
let provider = ProviderBuilder::new().with_recommended_fillers().on_anvil_with_wallet();
let provider = ProviderBuilder::new().on_anvil_with_wallet();

let sidecar: SidecarBuilder<SimpleCoder> = SidecarBuilder::from_slice(b"Hello World");
let sidecar = sidecar.build().unwrap();
Expand Down
12 changes: 9 additions & 3 deletions crates/provider/src/fillers/nonce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl NonceManager for CachedNonceManager {
/// # use alloy_rpc_types_eth::TransactionRequest;
/// # use alloy_provider::{ProviderBuilder, RootProvider, Provider};
/// # async fn test<W: NetworkWallet<Ethereum> + Clone>(url: url::Url, wallet: W) -> Result<(), Box<dyn std::error::Error>> {
/// let provider = ProviderBuilder::new()
/// let provider = ProviderBuilder::default()
/// .with_simple_nonce_management()
/// .wallet(wallet)
/// .on_http(url);
Expand Down Expand Up @@ -232,7 +232,10 @@ mod tests {

#[tokio::test]
async fn no_nonce_if_sender_unset() {
let provider = ProviderBuilder::new().with_cached_nonce_management().on_anvil();
let provider = ProviderBuilder::new()
.disable_recommended_fillers()
.with_cached_nonce_management()
.on_anvil();

let tx = TransactionRequest {
value: Some(U256::from(100)),
Expand All @@ -248,7 +251,10 @@ mod tests {

#[tokio::test]
async fn increments_nonce() {
let provider = ProviderBuilder::new().with_cached_nonce_management().on_anvil_with_wallet();
let provider = ProviderBuilder::new()
.disable_recommended_fillers()
.with_cached_nonce_management()
.on_anvil_with_wallet();

let from = provider.default_signer_address();
let tx = TransactionRequest {
Expand Down
10 changes: 6 additions & 4 deletions crates/provider/src/layers/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,10 @@ mod tests {
let cache_layer = CacheLayer::new(100);
let shared_cache = cache_layer.cache();
let anvil = Anvil::new().block_time_f64(0.3).spawn();
let provider = ProviderBuilder::new().layer(cache_layer).on_http(anvil.endpoint_url());
let provider = ProviderBuilder::new()
.disable_recommended_fillers()
.layer(cache_layer)
.on_http(anvil.endpoint_url());

let path = dir.join("rpc-cache-tx.txt");
shared_cache.load_cache(path.clone()).unwrap();
Expand Down Expand Up @@ -724,8 +727,7 @@ mod tests {
run_with_tempdir("get-code", |dir| async move {
let cache_layer = CacheLayer::new(100);
let shared_cache = cache_layer.cache();
let anvil = Anvil::new().spawn();
let provider = ProviderBuilder::new().layer(cache_layer).on_http(anvil.endpoint_url());
let provider = ProviderBuilder::default().with_gas_estimation().layer(cache_layer).on_anvil_with_wallet();

let path = dir.join("rpc-cache-code.txt");
shared_cache.load_cache(path.clone()).unwrap();
Expand All @@ -734,7 +736,7 @@ mod tests {
// solc v0.8.26; solc Counter.sol --via-ir --optimize --bin
"6080806040523460135760df908160198239f35b600080fdfe6080806040526004361015601257600080fd5b60003560e01c9081633fb5c1cb1460925781638381f58a146079575063d09de08a14603c57600080fd5b3460745760003660031901126074576000546000198114605e57600101600055005b634e487b7160e01b600052601160045260246000fd5b600080fd5b3460745760003660031901126074576020906000548152f35b34607457602036600319011260745760043560005500fea2646970667358221220e978270883b7baed10810c4079c941512e93a7ba1cd1108c781d4bc738d9090564736f6c634300081a0033"
).unwrap();
let tx = TransactionRequest::default().with_deploy_code(bytecode);
let tx = TransactionRequest::default().with_nonce(0).with_deploy_code(bytecode).with_chain_id(31337);

let receipt = provider.send_transaction(tx).await.unwrap().get_receipt().await.unwrap();

Expand Down
Loading

0 comments on commit e3651c9

Please sign in to comment.