Skip to content

Commit

Permalink
fix(provider): Prevent panic from having 0 keys when calling `on_anvi…
Browse files Browse the repository at this point in the history
…l_with_wallet_and_config` (alloy-rs#1055)

* node-bindings: Add AnvilError::NoKeysAvailable

* prevent panic from having 0 keys

* fix the error handlings for `on_anvil_with_wallet`

* fix clippy

* fix(clippy): Add type alias

* Add `try_on_anvil_with_wallet_and_config` and call it in `on_anvil_with_wallet_and_config`

* Revert test changes

* Fix docs
  • Loading branch information
moricho authored and j75689 committed Aug 1, 2024
1 parent c7a9311 commit 03032dd
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 9 deletions.
4 changes: 4 additions & 0 deletions crates/node-bindings/src/anvil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ pub enum AnvilError {
/// An error occurred while parsing a hex string.
#[error(transparent)]
FromHexError(#[from] hex::FromHexError),

/// No keys available in anvil instance.
#[error("no keys available in anvil instance")]
NoKeysAvailable,
}

/// Builder for launching `anvil`.
Expand Down
49 changes: 40 additions & 9 deletions crates/provider/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use alloy_chains::NamedChain;
use alloy_network::{Ethereum, Network};
use alloy_primitives::ChainId;
use alloy_rpc_client::{BuiltInConnectionString, ClientBuilder, RpcClient};

use alloy_transport::{BoxTransport, Transport, TransportError, TransportResult};
use std::marker::PhantomData;

Expand Down Expand Up @@ -347,6 +346,11 @@ impl<L, F, N> ProviderBuilder<L, F, N> {
}
}

type JoinedEthereumWalletFiller<F> = JoinFill<F, WalletFiller<alloy_network::EthereumWallet>>;

#[cfg(any(test, feature = "anvil-node"))]
type AnvilProviderResult<T> = Result<T, alloy_node_bindings::anvil::AnvilError>;

// Enabled when the `anvil` feature is enabled, or when both in test and the
// `reqwest` feature is enabled.
#[cfg(any(test, feature = "anvil-node"))]
Expand All @@ -372,7 +376,7 @@ impl<L, F> ProviderBuilder<L, F, Ethereum> {
/// use in tests.
pub fn on_anvil_with_wallet(
self,
) -> <JoinFill<F, WalletFiller<alloy_network::EthereumWallet>> as ProviderLayer<
) -> <JoinedEthereumWalletFiller<F> as ProviderLayer<
L::Provider,
alloy_transport_http::Http<reqwest::Client>,
>>::Provider
Expand Down Expand Up @@ -413,17 +417,42 @@ impl<L, F> ProviderBuilder<L, F, Ethereum> {
self.layer(anvil_layer).on_http(url)
}

/// Build this provider with anvil, using an Reqwest HTTP transport. 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.
/// Build this provider with anvil, using an Reqwest HTTP transport.
/// This calls `try_on_anvil_with_wallet_and_config` and panics on error.
pub fn on_anvil_with_wallet_and_config(
self,
f: impl FnOnce(alloy_node_bindings::Anvil) -> alloy_node_bindings::Anvil,
) -> <JoinFill<F, WalletFiller<alloy_network::EthereumWallet>> as ProviderLayer<
) -> <JoinedEthereumWalletFiller<F> as ProviderLayer<
L::Provider,
alloy_transport_http::Http<reqwest::Client>,
>>::Provider
where
F: TxFiller<Ethereum>
+ ProviderLayer<L::Provider, alloy_transport_http::Http<reqwest::Client>, Ethereum>,
L: crate::builder::ProviderLayer<
crate::layers::AnvilProvider<
crate::provider::RootProvider<alloy_transport_http::Http<reqwest::Client>>,
alloy_transport_http::Http<reqwest::Client>,
>,
alloy_transport_http::Http<reqwest::Client>,
>,
{
self.try_on_anvil_with_wallet_and_config(f).unwrap()
}

/// Build this provider with anvil, using an Reqwest HTTP transport. 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,
alloy_transport_http::Http<reqwest::Client>,
>>::Provider,
>
where
F: TxFiller<Ethereum>
+ ProviderLayer<L::Provider, alloy_transport_http::Http<reqwest::Client>, Ethereum>,
Expand All @@ -439,7 +468,9 @@ impl<L, F> ProviderBuilder<L, F, Ethereum> {
let url = anvil_layer.endpoint_url();

let default_keys = anvil_layer.instance().keys().to_vec();
let (default_key, remaining_keys) = default_keys.split_first().expect("no keys available");
let (default_key, remaining_keys) = default_keys
.split_first()
.ok_or(alloy_node_bindings::anvil::AnvilError::NoKeysAvailable)?;

let default_signer = alloy_signer_local::LocalSigner::from(default_key.clone());
let mut wallet = alloy_network::EthereumWallet::from(default_signer);
Expand All @@ -448,7 +479,7 @@ impl<L, F> ProviderBuilder<L, F, Ethereum> {
wallet.register_signer(alloy_signer_local::LocalSigner::from(key.clone()))
});

self.wallet(wallet).layer(anvil_layer).on_http(url)
Ok(self.wallet(wallet).layer(anvil_layer).on_http(url))
}
}

Expand Down

0 comments on commit 03032dd

Please sign in to comment.