alloy_zksync/provider/
provider_builder_ext.rs

1use alloy::{
2    providers::{
3        ProviderBuilder, ProviderLayer, RootProvider,
4        fillers::{JoinFill, TxFiller, WalletFiller},
5    },
6    signers::local::LocalSigner,
7};
8
9use crate::{
10    network::Zksync,
11    node_bindings::{AnvilZKsync, AnvilZKsyncError},
12    provider::layers::anvil_zksync::{AnvilZKsyncLayer, AnvilZKsyncProvider},
13    wallet::ZksyncWallet,
14};
15
16type AnvilZKsyncProviderResult<T> = Result<T, AnvilZKsyncError>;
17type JoinedZksyncWalletFiller<F> = JoinFill<F, WalletFiller<ZksyncWallet>>;
18
19/// ZKsync-specific extensions for the [`ProviderBuilder`](https://docs.rs/alloy/latest/alloy/providers/struct.ProviderBuilder.html).
20pub trait ProviderBuilderExt<L, F>: Sized
21where
22    F: TxFiller<Zksync> + ProviderLayer<L::Provider, Zksync>,
23    L: ProviderLayer<AnvilZKsyncProvider<RootProvider<Zksync>>, Zksync>,
24{
25    /// Build a provider that would spawn `anvil-zksync` instance in background and will use it.
26    fn on_anvil_zksync(self) -> F::Provider;
27
28    /// Same as [`on_anvil_zksync`](Self::on_anvil_zksync), but also configures a wallet backed by anvil-zksync keys.
29    fn on_anvil_zksync_with_wallet(
30        self,
31    ) -> <JoinedZksyncWalletFiller<F> as ProviderLayer<L::Provider, Zksync>>::Provider;
32
33    /// Same as [`on_anvil_zksync`](Self::on_anvil_zksync), allows to configure `anvil-zksync`.
34    fn on_anvil_zksync_with_config(self, f: impl FnOnce(AnvilZKsync) -> AnvilZKsync)
35    -> F::Provider;
36
37    /// Same as [`on_anvil_zksync_with_wallet`](Self::on_anvil_zksync_with_wallet), allows to configure `anvil-zksync`.
38    fn on_anvil_zksync_with_wallet_and_config(
39        self,
40        f: impl FnOnce(AnvilZKsync) -> AnvilZKsync,
41    ) -> <JoinedZksyncWalletFiller<F> as ProviderLayer<L::Provider, Zksync>>::Provider;
42
43    /// Fallible version of [`on_anvil_zksync_with_wallet_and_config`](Self::on_anvil_zksync_with_wallet_and_config).
44    fn try_on_anvil_zksync_with_wallet_and_config(
45        self,
46        f: impl FnOnce(AnvilZKsync) -> AnvilZKsync,
47    ) -> AnvilZKsyncProviderResult<
48        <JoinedZksyncWalletFiller<F> as ProviderLayer<L::Provider, Zksync>>::Provider,
49    >;
50}
51
52impl<L, F> ProviderBuilderExt<L, F> for ProviderBuilder<L, F, Zksync>
53where
54    F: TxFiller<Zksync> + ProviderLayer<L::Provider, Zksync>,
55    L: ProviderLayer<AnvilZKsyncProvider<RootProvider<Zksync>>, Zksync>,
56{
57    fn on_anvil_zksync(self) -> F::Provider {
58        self.on_anvil_zksync_with_config(std::convert::identity)
59    }
60
61    fn on_anvil_zksync_with_wallet(
62        self,
63    ) -> <JoinedZksyncWalletFiller<F> as ProviderLayer<L::Provider, Zksync>>::Provider {
64        self.on_anvil_zksync_with_wallet_and_config(std::convert::identity)
65    }
66
67    fn on_anvil_zksync_with_config(
68        self,
69        f: impl FnOnce(AnvilZKsync) -> AnvilZKsync,
70    ) -> F::Provider {
71        let anvil_zksync_layer = AnvilZKsyncLayer::from(f(Default::default()));
72        let url = anvil_zksync_layer.endpoint_url();
73
74        self.layer(anvil_zksync_layer).connect_http(url)
75    }
76
77    fn on_anvil_zksync_with_wallet_and_config(
78        self,
79        f: impl FnOnce(AnvilZKsync) -> AnvilZKsync,
80    ) -> <JoinedZksyncWalletFiller<F> as ProviderLayer<L::Provider, Zksync>>::Provider {
81        self.try_on_anvil_zksync_with_wallet_and_config(f).unwrap()
82    }
83
84    /// Build this provider with anvil-zksync, using an Reqwest HTTP transport. The
85    /// given function is used to configure the anvil-zksync instance. This
86    /// function configures a wallet backed by anvil-zksync keys, and is intended for
87    /// use in tests.
88    fn try_on_anvil_zksync_with_wallet_and_config(
89        self,
90        f: impl FnOnce(AnvilZKsync) -> AnvilZKsync,
91    ) -> AnvilZKsyncProviderResult<
92        <JoinedZksyncWalletFiller<F> as ProviderLayer<L::Provider, Zksync>>::Provider,
93    > {
94        use alloy::signers::Signer;
95
96        let anvil_zksync_layer = AnvilZKsyncLayer::from(f(Default::default()));
97        let url = anvil_zksync_layer.endpoint_url();
98
99        let default_keys = anvil_zksync_layer.instance().keys().to_vec();
100        let (default_key, remaining_keys) = default_keys
101            .split_first()
102            .ok_or(crate::node_bindings::AnvilZKsyncError::NoKeysAvailable)?;
103
104        let default_signer = LocalSigner::from(default_key.clone())
105            .with_chain_id(Some(anvil_zksync_layer.instance().chain_id()));
106        let mut wallet = ZksyncWallet::from(default_signer);
107
108        for key in remaining_keys {
109            let signer = LocalSigner::from(key.clone());
110            wallet.register_signer(signer)
111        }
112
113        Ok(self
114            .wallet(wallet)
115            .layer(anvil_zksync_layer)
116            .connect_http(url))
117    }
118}