use alloy::providers::{Provider, ProviderLayer, RootProvider};
use std::sync::{Arc, OnceLock};
use url::Url;
use crate::{
network::Zksync,
node_bindings::{AnvilZKsync, AnvilZKsyncInstance},
};
#[derive(Debug, Clone, Default)]
pub struct AnvilZKsyncLayer {
anvil: AnvilZKsync,
instance: OnceLock<Arc<AnvilZKsyncInstance>>,
}
impl AnvilZKsyncLayer {
pub fn instance(&self) -> &Arc<AnvilZKsyncInstance> {
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()
}
}
impl From<AnvilZKsync> for AnvilZKsyncLayer {
fn from(anvil: AnvilZKsync) -> Self {
Self {
anvil,
instance: OnceLock::new(),
}
}
}
impl<P> ProviderLayer<P, Zksync> for AnvilZKsyncLayer
where
P: Provider<Zksync>,
{
type Provider = AnvilZKsyncProvider<P>;
fn layer(&self, inner: P) -> Self::Provider {
let anvil = self.instance();
AnvilZKsyncProvider::new(inner, anvil.clone())
}
}
#[derive(Clone, Debug)]
pub struct AnvilZKsyncProvider<P> {
inner: P,
_anvil: Arc<AnvilZKsyncInstance>,
}
impl<P> AnvilZKsyncProvider<P>
where
P: Provider<Zksync>,
{
pub fn new(inner: P, _anvil: Arc<AnvilZKsyncInstance>) -> Self {
Self { inner, _anvil }
}
}
impl<P> Provider<Zksync> for AnvilZKsyncProvider<P>
where
P: Provider<Zksync>,
{
#[inline(always)]
fn root(&self) -> &RootProvider<Zksync> {
self.inner.root()
}
}