alloy_zksync/provider/layers/
anvil_zksync.rs

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