alloy_provider/layers/
anvil.rs

1use alloy_network::Ethereum;
2use alloy_node_bindings::{Anvil, AnvilInstance};
3use reqwest::Url;
4use std::sync::{Arc, OnceLock};
5
6use crate::{Provider, ProviderLayer, RootProvider};
7
8/// A layer that wraps an [`Anvil`] config.
9///
10/// The config will be used to spawn an [`AnvilInstance`] when the layer is applied, or when the
11/// user requests any information about the anvil node (e.g. via the [`AnvilLayer::ws_endpoint_url`]
12/// method).
13#[derive(Debug, Clone, Default)]
14pub struct AnvilLayer {
15    anvil: Anvil,
16    instance: OnceLock<Arc<AnvilInstance>>,
17}
18
19impl AnvilLayer {
20    /// Starts the anvil instance, or gets a reference to the existing instance.
21    pub fn instance(&self) -> &Arc<AnvilInstance> {
22        self.instance.get_or_init(|| Arc::new(self.anvil.clone().spawn()))
23    }
24
25    /// Get the instance http endpoint.
26    #[doc(alias = "http_endpoint_url")]
27    pub fn endpoint_url(&self) -> Url {
28        self.instance().endpoint_url()
29    }
30
31    /// Get the instance ws endpoint.
32    pub fn ws_endpoint_url(&self) -> Url {
33        self.instance().ws_endpoint_url()
34    }
35}
36
37impl From<Anvil> for AnvilLayer {
38    fn from(anvil: Anvil) -> Self {
39        Self { anvil, instance: OnceLock::new() }
40    }
41}
42
43impl<P> ProviderLayer<P, Ethereum> for AnvilLayer
44where
45    P: Provider,
46{
47    type Provider = AnvilProvider<P>;
48
49    fn layer(&self, inner: P) -> Self::Provider {
50        let anvil = self.instance();
51        AnvilProvider::new(inner, anvil.clone())
52    }
53}
54
55/// A provider that wraps an [`AnvilInstance`], preventing the instance from
56/// being dropped while the provider is in use.
57#[derive(Clone, Debug)]
58pub struct AnvilProvider<P> {
59    inner: P,
60    anvil: Arc<AnvilInstance>,
61}
62
63impl<P> AnvilProvider<P>
64where
65    P: Provider,
66{
67    /// Creates a new `AnvilProvider` with the given inner provider and anvil
68    /// instance.
69    #[allow(clippy::missing_const_for_fn)]
70    pub fn new(inner: P, anvil: Arc<AnvilInstance>) -> Self {
71        Self { inner, anvil }
72    }
73
74    /// Expose inner anvil instance.
75    pub fn anvil(&self) -> &Arc<AnvilInstance> {
76        &self.anvil
77    }
78}
79
80impl<P> Provider for AnvilProvider<P>
81where
82    P: Provider,
83{
84    #[inline(always)]
85    fn root(&self) -> &RootProvider {
86        self.inner.root()
87    }
88}