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

feat(provider): instantiate recommended fillers by default #1901

Merged
merged 9 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
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
47 changes: 26 additions & 21 deletions crates/provider/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,24 @@ 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.
yash-atreya marked this conversation as resolved.
Show resolved Hide resolved
///
/// 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()
}
}

Expand All @@ -125,6 +139,13 @@ impl<N> Default for ProviderBuilder<Identity, Identity, N> {
}
}

impl<L, F, N> ProviderBuilder<L, F, N> {
/// Opt-out of the recommended fillers by reseting the fillers stack in the [`ProviderBuilder`].
pub fn disable_recommended_fillers(self) -> ProviderBuilder<L, Identity, N> {
yash-atreya marked this conversation as resolved.
Show resolved Hide resolved
ProviderBuilder { layer: self.layer, filler: Identity, network: self.network }
}
}

impl<L, N: Network> ProviderBuilder<L, Identity, N> {
/// Add preconfigured set of layers handling gas estimation, nonce
/// management, and chain-id fetching.
Expand Down Expand Up @@ -384,6 +405,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 +433,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
25 changes: 20 additions & 5 deletions crates/provider/src/provider/trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1106,7 +1106,7 @@ impl<N: Network> Provider<N> for RootProvider<N> {

#[cfg(test)]
mod tests {
use std::time::Duration;
use std::{str::FromStr, time::Duration};

use super::*;
use crate::{builder, ProviderBuilder, WalletProvider};
Expand Down Expand Up @@ -1407,7 +1407,7 @@ mod tests {

#[tokio::test]
async fn test_send_tx() {
let provider = ProviderBuilder::new().on_anvil();
let provider = ProviderBuilder::new().on_anvil_with_wallet();
let tx = TransactionRequest {
value: Some(U256::from(100)),
to: Some(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into()),
Expand All @@ -1430,7 +1430,7 @@ mod tests {

#[tokio::test]
async fn test_watch_confirmed_tx() {
let provider = ProviderBuilder::new().on_anvil();
let provider = ProviderBuilder::new().on_anvil_with_wallet();
let tx = TransactionRequest {
value: Some(U256::from(100)),
to: Some(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into()),
Expand Down Expand Up @@ -1622,7 +1622,7 @@ mod tests {

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

let req = TransactionRequest::default()
.from(provider.default_signer_address())
Expand Down Expand Up @@ -1767,7 +1767,6 @@ mod tests {
let wallet = EthereumWallet::from(signer);

let provider = ProviderBuilder::new()
.with_recommended_fillers()
.network::<AnyNetwork>()
.wallet(wallet)
.on_http(anvil.endpoint_url());
Expand Down Expand Up @@ -1840,4 +1839,20 @@ mod tests {
.unwrap();
assert!(block.transactions.is_hashes());
}

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

let tx = TransactionRequest::default()
.with_kind(alloy_primitives::TxKind::Create)
.value(U256::from(1235))
.with_input(Bytes::from_str("ffffffffffffff").unwrap());

let err = provider.send_transaction(tx).await.unwrap_err().to_string();
assert!(err.contains("missing properties: [(\"NonceManager\", [\"from\"])]"));
}
}
Loading
Loading