alloy_provider/layers/
anvil.rsuse alloy_network::Ethereum;
use alloy_node_bindings::{Anvil, AnvilInstance};
use alloy_transport::Transport;
use reqwest::Url;
use std::{
marker::PhantomData,
sync::{Arc, OnceLock},
};
use crate::{Provider, ProviderLayer, RootProvider};
#[derive(Debug, Clone, Default)]
pub struct AnvilLayer {
anvil: Anvil,
instance: OnceLock<Arc<AnvilInstance>>,
}
impl AnvilLayer {
pub fn instance(&self) -> &Arc<AnvilInstance> {
self.instance.get_or_init(|| Arc::new(self.anvil.clone().spawn()))
}
#[doc(alias = "http_endpoint_url")]
pub fn endpoint_url(&self) -> Url {
self.instance().endpoint_url()
}
pub fn ws_endpoint_url(&self) -> Url {
self.instance().ws_endpoint_url()
}
}
impl From<Anvil> for AnvilLayer {
fn from(anvil: Anvil) -> Self {
Self { anvil, instance: OnceLock::new() }
}
}
impl<P, T> ProviderLayer<P, T, Ethereum> for AnvilLayer
where
P: Provider<T>,
T: Transport + Clone,
{
type Provider = AnvilProvider<P, T>;
fn layer(&self, inner: P) -> Self::Provider {
let anvil = self.instance();
AnvilProvider::new(inner, anvil.clone())
}
}
#[derive(Clone, Debug)]
pub struct AnvilProvider<P, T> {
inner: P,
_anvil: Arc<AnvilInstance>,
_pd: PhantomData<fn() -> T>,
}
impl<P, T> AnvilProvider<P, T>
where
P: Provider<T>,
T: Transport + Clone,
{
pub fn new(inner: P, _anvil: Arc<AnvilInstance>) -> Self {
Self { inner, _anvil, _pd: PhantomData }
}
}
impl<P, T> Provider<T> for AnvilProvider<P, T>
where
P: Provider<T>,
T: Transport + Clone,
{
#[inline(always)]
fn root(&self) -> &RootProvider<T> {
self.inner.root()
}
}