alloy_provider/layers/
anvil.rs1use crate::{Provider, ProviderLayer, RootProvider};
2use alloy_network::{Ethereum, Network};
3use alloy_node_bindings::{Anvil, AnvilInstance};
4use reqwest::Url;
5use std::{
6 marker::PhantomData,
7 sync::{Arc, OnceLock},
8};
9
10#[derive(Debug, Clone, Default)]
16pub struct AnvilLayer {
17 anvil: Anvil,
18 instance: OnceLock<Arc<AnvilInstance>>,
19}
20
21impl AnvilLayer {
22 pub fn instance(&self) -> &Arc<AnvilInstance> {
24 self.instance.get_or_init(|| Arc::new(self.anvil.clone().spawn()))
25 }
26
27 #[doc(alias = "http_endpoint_url")]
29 pub fn endpoint_url(&self) -> Url {
30 self.instance().endpoint_url()
31 }
32
33 pub fn ws_endpoint_url(&self) -> Url {
35 self.instance().ws_endpoint_url()
36 }
37}
38
39impl From<Anvil> for AnvilLayer {
40 fn from(anvil: Anvil) -> Self {
41 Self { anvil, instance: OnceLock::new() }
42 }
43}
44
45impl<P: Provider<N>, N: Network> ProviderLayer<P, N> for AnvilLayer {
46 type Provider = AnvilProvider<P, N>;
47
48 fn layer(&self, inner: P) -> Self::Provider {
49 let anvil = self.instance();
50 AnvilProvider::new(inner, anvil.clone())
51 }
52}
53
54#[derive(Clone, Debug)]
57pub struct AnvilProvider<P, N = Ethereum> {
58 inner: P,
59 anvil: Arc<AnvilInstance>,
60 _marker: PhantomData<N>,
61}
62
63impl<P: Provider<N>, N: Network> AnvilProvider<P, N> {
64 #[expect(clippy::missing_const_for_fn)]
67 pub fn new(inner: P, anvil: Arc<AnvilInstance>) -> Self {
68 Self { inner, anvil, _marker: PhantomData }
69 }
70
71 pub const fn anvil(&self) -> &Arc<AnvilInstance> {
73 &self.anvil
74 }
75}
76
77impl<P: Provider<N>, N: Network> Provider<N> for AnvilProvider<P, N> {
78 #[inline(always)]
79 fn root(&self) -> &RootProvider<N> {
80 self.inner.root()
81 }
82}