1use crate::{
2 fillers::{
3 CachedNonceManager, ChainIdFiller, FillerControlFlow, GasFiller, JoinFill, NonceFiller,
4 NonceManager, RecommendedFillers, SimpleNonceManager, TxFiller, WalletFiller,
5 },
6 layers::{CallBatchLayer, ChainLayer},
7 provider::SendableTx,
8 Provider, RootProvider,
9};
10use alloy_chains::NamedChain;
11use alloy_network::{Ethereum, IntoWallet, Network};
12use alloy_primitives::ChainId;
13use alloy_rpc_client::{ClientBuilder, RpcClient};
14use alloy_transport::{TransportConnect, TransportError, TransportResult};
15use std::marker::PhantomData;
16
17pub trait ProviderLayer<P: Provider<N>, N: Network = Ethereum> {
21 type Provider: Provider<N>;
23
24 fn layer(&self, inner: P) -> Self::Provider;
26}
27
28#[derive(Clone, Copy, Debug)]
30pub struct Identity;
31
32impl<N> TxFiller<N> for Identity
33where
34 N: Network,
35{
36 type Fillable = ();
37
38 fn status(&self, _tx: &<N as Network>::TransactionRequest) -> FillerControlFlow {
39 FillerControlFlow::Finished
40 }
41
42 fn fill_sync(&self, _tx: &mut SendableTx<N>) {}
43
44 async fn prepare<P>(
45 &self,
46 _provider: &P,
47 _tx: &N::TransactionRequest,
48 ) -> TransportResult<Self::Fillable> {
49 Ok(())
50 }
51
52 async fn fill(
53 &self,
54 _to_fill: Self::Fillable,
55 tx: SendableTx<N>,
56 ) -> TransportResult<SendableTx<N>> {
57 Ok(tx)
58 }
59}
60
61impl<P, N> ProviderLayer<P, N> for Identity
62where
63 N: Network,
64 P: Provider<N>,
65{
66 type Provider = P;
67
68 fn layer(&self, inner: P) -> Self::Provider {
69 inner
70 }
71}
72
73#[derive(Debug)]
75pub struct Stack<Inner, Outer> {
76 inner: Inner,
77 outer: Outer,
78}
79
80impl<Inner, Outer> Stack<Inner, Outer> {
81 pub const fn new(inner: Inner, outer: Outer) -> Self {
83 Self { inner, outer }
84 }
85}
86
87impl<P, N, Inner, Outer> ProviderLayer<P, N> for Stack<Inner, Outer>
88where
89 N: Network,
90 P: Provider<N>,
91 Inner: ProviderLayer<P, N>,
92 Outer: ProviderLayer<Inner::Provider, N>,
93{
94 type Provider = Outer::Provider;
95
96 fn layer(&self, provider: P) -> Self::Provider {
97 let inner = self.inner.layer(provider);
98
99 self.outer.layer(inner)
100 }
101}
102
103#[derive(Debug)]
117pub struct ProviderBuilder<L, F, N = Ethereum> {
118 layer: L,
119 filler: F,
120 network: PhantomData<fn() -> N>,
121}
122
123impl
124 ProviderBuilder<
125 Identity,
126 JoinFill<Identity, <Ethereum as RecommendedFillers>::RecommendedFillers>,
127 Ethereum,
128 >
129{
130 pub fn new() -> Self {
140 ProviderBuilder::default().with_recommended_fillers()
141 }
142
143 pub fn disable_recommended_fillers(self) -> ProviderBuilder<Identity, Identity, Ethereum> {
148 ProviderBuilder { layer: self.layer, filler: Identity, network: self.network }
149 }
150}
151
152impl<N> Default for ProviderBuilder<Identity, Identity, N> {
153 fn default() -> Self {
154 Self { layer: Identity, filler: Identity, network: PhantomData }
155 }
156}
157
158impl ProviderBuilder<Identity, Identity, Ethereum> {
159 pub fn new_with_network<Net: RecommendedFillers>(
162 ) -> ProviderBuilder<Identity, JoinFill<Identity, Net::RecommendedFillers>, Net> {
163 ProviderBuilder {
164 layer: Identity,
165 filler: JoinFill::new(Identity, Net::recommended_fillers()),
166 network: PhantomData,
167 }
168 }
169}
170
171impl<L, N: Network> ProviderBuilder<L, Identity, N> {
172 pub fn with_recommended_fillers(
175 self,
176 ) -> ProviderBuilder<L, JoinFill<Identity, N::RecommendedFillers>, N>
177 where
178 N: RecommendedFillers,
179 {
180 self.filler(N::recommended_fillers())
181 }
182}
183
184impl<L, F, N> ProviderBuilder<L, F, N> {
185 pub fn layer<Inner>(self, layer: Inner) -> ProviderBuilder<Stack<Inner, L>, F, N> {
197 ProviderBuilder {
198 layer: Stack::new(layer, self.layer),
199 filler: self.filler,
200 network: PhantomData,
201 }
202 }
203
204 pub fn filler<F2>(self, filler: F2) -> ProviderBuilder<L, JoinFill<F, F2>, N> {
208 ProviderBuilder {
209 layer: self.layer,
210 filler: JoinFill::new(self.filler, filler),
211 network: PhantomData,
212 }
213 }
214
215 pub fn network<Net: Network>(self) -> ProviderBuilder<L, F, Net> {
224 ProviderBuilder { layer: self.layer, filler: self.filler, network: PhantomData }
225 }
226
227 pub fn with_chain(self, chain: NamedChain) -> ProviderBuilder<Stack<ChainLayer, L>, F, N> {
232 self.layer(ChainLayer::new(chain))
233 }
234
235 pub fn with_gas_estimation(self) -> ProviderBuilder<L, JoinFill<F, GasFiller>, N> {
241 self.filler(GasFiller)
242 }
243
244 pub fn with_nonce_management<M: NonceManager>(
248 self,
249 nonce_manager: M,
250 ) -> ProviderBuilder<L, JoinFill<F, NonceFiller<M>>, N> {
251 self.filler(NonceFiller::new(nonce_manager))
252 }
253
254 pub fn with_simple_nonce_management(
258 self,
259 ) -> ProviderBuilder<L, JoinFill<F, NonceFiller<SimpleNonceManager>>, N> {
260 self.with_nonce_management(SimpleNonceManager::default())
261 }
262
263 pub fn with_cached_nonce_management(
267 self,
268 ) -> ProviderBuilder<L, JoinFill<F, NonceFiller<CachedNonceManager>>, N> {
269 self.with_nonce_management(CachedNonceManager::default())
270 }
271
272 pub fn fetch_chain_id(self) -> ProviderBuilder<L, JoinFill<F, ChainIdFiller>, N> {
277 self.filler(ChainIdFiller::default())
278 }
279
280 pub fn with_chain_id(
284 self,
285 chain_id: ChainId,
286 ) -> ProviderBuilder<L, JoinFill<F, ChainIdFiller>, N> {
287 self.filler(ChainIdFiller::new(Some(chain_id)))
288 }
289
290 pub fn wallet<W: IntoWallet<N>>(
294 self,
295 wallet: W,
296 ) -> ProviderBuilder<L, JoinFill<F, WalletFiller<W::NetworkWallet>>, N>
297 where
298 N: Network,
299 {
300 self.filler(WalletFiller::new(wallet.into_wallet()))
301 }
302
303 pub fn with_call_batching(self) -> ProviderBuilder<Stack<CallBatchLayer, L>, F, N> {
309 self.layer(CallBatchLayer::new())
310 }
311
312 pub fn connect_provider<P>(self, provider: P) -> F::Provider
317 where
318 L: ProviderLayer<P, N>,
319 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
320 P: Provider<N>,
321 N: Network,
322 {
323 let Self { layer, filler, network: PhantomData } = self;
324 let stack = Stack::new(layer, filler);
325 stack.layer(provider)
326 }
327
328 #[deprecated(since = "0.12.6", note = "use `connect_provider` instead")]
331 pub fn on_provider<P>(self, provider: P) -> F::Provider
332 where
333 L: ProviderLayer<P, N>,
334 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
335 P: Provider<N>,
336 N: Network,
337 {
338 let Self { layer, filler, network: PhantomData } = self;
339 let stack = Stack::new(layer, filler);
340 stack.layer(provider)
341 }
342
343 pub fn connect_client(self, client: RpcClient) -> F::Provider
349 where
350 L: ProviderLayer<RootProvider<N>, N>,
351 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
352 N: Network,
353 {
354 self.connect_provider(RootProvider::new(client))
355 }
356
357 #[deprecated(since = "0.12.6", note = "use `connect_client` instead")]
363 pub fn on_client(self, client: RpcClient) -> F::Provider
364 where
365 L: ProviderLayer<RootProvider<N>, N>,
366 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
367 N: Network,
368 {
369 self.connect_provider(RootProvider::new(client))
370 }
371
372 pub fn connect_mocked_client(self, asserter: alloy_transport::mock::Asserter) -> F::Provider
378 where
379 L: ProviderLayer<RootProvider<N>, N>,
380 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
381 N: Network,
382 {
383 self.connect_client(RpcClient::mocked(asserter))
384 }
385
386 #[deprecated(since = "0.12.6", note = "use `connect_mocked_client` instead")]
392 pub fn on_mocked_client(self, asserter: alloy_transport::mock::Asserter) -> F::Provider
393 where
394 L: ProviderLayer<RootProvider<N>, N>,
395 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
396 N: Network,
397 {
398 self.connect_client(RpcClient::mocked(asserter))
399 }
400
401 #[doc(alias = "on_builtin")]
405 pub async fn connect(self, s: &str) -> Result<F::Provider, TransportError>
406 where
407 L: ProviderLayer<RootProvider<N>, N>,
408 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
409 N: Network,
410 {
411 let client = ClientBuilder::default().connect(s).await?;
412 Ok(self.connect_client(client))
413 }
414
415 pub async fn connect_with<C>(self, connect: &C) -> Result<F::Provider, TransportError>
417 where
418 L: ProviderLayer<RootProvider<N>, N>,
419 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
420 N: Network,
421 C: TransportConnect,
422 {
423 connect
424 .get_transport()
425 .await
426 .map(|t| RpcClient::new(t, connect.is_local()))
427 .map(|client| self.connect_client(client))
428 }
429
430 #[cfg(feature = "pubsub")]
435 pub async fn connect_pubsub_with<C>(self, connect: C) -> Result<F::Provider, TransportError>
436 where
437 L: ProviderLayer<RootProvider<N>, N>,
438 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
439 N: Network,
440 C: alloy_pubsub::PubSubConnect,
441 {
442 ClientBuilder::default().pubsub(connect).await.map(|client| self.connect_client(client))
443 }
444
445 #[deprecated = "use `connect` instead"]
449 #[doc(hidden)]
450 pub async fn on_builtin(self, s: &str) -> Result<F::Provider, TransportError>
451 where
452 L: ProviderLayer<RootProvider<N>, N>,
453 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
454 N: Network,
455 {
456 self.connect(s).await
457 }
458
459 #[cfg(feature = "ws")]
461 pub async fn connect_ws(
462 self,
463 connect: alloy_transport_ws::WsConnect,
464 ) -> Result<F::Provider, TransportError>
465 where
466 L: ProviderLayer<RootProvider<N>, N>,
467 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
468 N: Network,
469 {
470 let client = ClientBuilder::default().ws(connect).await?;
471 Ok(self.connect_client(client))
472 }
473
474 #[cfg(feature = "ws")]
476 #[deprecated(since = "0.12.6", note = "use `connect_ws` instead")]
477 pub async fn on_ws(
478 self,
479 connect: alloy_transport_ws::WsConnect,
480 ) -> Result<F::Provider, TransportError>
481 where
482 L: ProviderLayer<RootProvider<N>, N>,
483 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
484 N: Network,
485 {
486 let client = ClientBuilder::default().ws(connect).await?;
487 Ok(self.connect_client(client))
488 }
489
490 #[cfg(feature = "ipc")]
492 pub async fn connect_ipc<T>(
493 self,
494 connect: alloy_transport_ipc::IpcConnect<T>,
495 ) -> Result<F::Provider, TransportError>
496 where
497 alloy_transport_ipc::IpcConnect<T>: alloy_pubsub::PubSubConnect,
498 L: ProviderLayer<RootProvider<N>, N>,
499 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
500 N: Network,
501 {
502 let client = ClientBuilder::default().ipc(connect).await?;
503 Ok(self.connect_client(client))
504 }
505
506 #[cfg(feature = "ipc")]
508 #[deprecated(since = "0.12.6", note = "use `connect_ipc` instead")]
509 pub async fn on_ipc<T>(
510 self,
511 connect: alloy_transport_ipc::IpcConnect<T>,
512 ) -> Result<F::Provider, TransportError>
513 where
514 alloy_transport_ipc::IpcConnect<T>: alloy_pubsub::PubSubConnect,
515 L: ProviderLayer<RootProvider<N>, N>,
516 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
517 N: Network,
518 {
519 let client = ClientBuilder::default().ipc(connect).await?;
520 Ok(self.connect_client(client))
521 }
522
523 #[cfg(any(test, feature = "reqwest"))]
525 pub fn connect_http(self, url: reqwest::Url) -> F::Provider
526 where
527 L: ProviderLayer<crate::RootProvider<N>, N>,
528 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
529 N: Network,
530 {
531 let client = ClientBuilder::default().http(url);
532 self.connect_client(client)
533 }
534
535 #[cfg(any(test, feature = "reqwest"))]
537 pub fn connect_reqwest<C>(self, client: C, url: reqwest::Url) -> F::Provider
538 where
539 L: ProviderLayer<crate::RootProvider<N>, N>,
540 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
541 N: Network,
542 C: Into<reqwest::Client>,
543 {
544 let client = ClientBuilder::default().http_with_client(client.into(), url);
545 self.connect_client(client)
546 }
547
548 #[cfg(any(test, feature = "reqwest"))]
550 pub fn with_reqwest<B>(self, url: reqwest::Url, builder: B) -> F::Provider
551 where
552 L: ProviderLayer<crate::RootProvider<N>, N>,
553 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
554 N: Network,
555 B: FnOnce(reqwest::ClientBuilder) -> reqwest::Client,
556 {
557 self.connect_reqwest(builder(reqwest::ClientBuilder::default()), url)
558 }
559
560 #[cfg(any(test, feature = "reqwest"))]
562 #[deprecated(since = "0.12.6", note = "use `connect_http` instead")]
563 pub fn on_http(self, url: reqwest::Url) -> F::Provider
564 where
565 L: ProviderLayer<RootProvider<N>, N>,
566 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
567 N: Network,
568 {
569 let client = ClientBuilder::default().http(url);
570 self.connect_client(client)
571 }
572
573 #[cfg(feature = "hyper")]
575 pub fn connect_hyper_http(self, url: url::Url) -> F::Provider
576 where
577 L: ProviderLayer<crate::RootProvider<N>, N>,
578 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
579 N: Network,
580 {
581 let client = ClientBuilder::default().hyper_http(url);
582 self.connect_client(client)
583 }
584
585 #[cfg(feature = "hyper")]
587 #[deprecated(since = "0.12.6", note = "use `connect_hyper_http` instead")]
588 pub fn on_hyper_http(self, url: url::Url) -> F::Provider
589 where
590 L: ProviderLayer<RootProvider<N>, N>,
591 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
592 N: Network,
593 {
594 let client = ClientBuilder::default().hyper_http(url);
595 self.connect_client(client)
596 }
597}
598
599#[cfg(any(test, feature = "anvil-node"))]
600type JoinedEthereumWalletFiller<F> = JoinFill<F, WalletFiller<alloy_network::EthereumWallet>>;
601
602#[cfg(any(test, feature = "anvil-node"))]
603type AnvilProviderResult<T> = Result<T, alloy_node_bindings::NodeError>;
604
605#[cfg(any(test, feature = "anvil-node"))]
606impl<L, F, N: Network> ProviderBuilder<L, F, N> {
607 pub fn connect_anvil(self) -> F::Provider
609 where
610 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
611 L: crate::builder::ProviderLayer<
612 crate::layers::AnvilProvider<crate::provider::RootProvider<N>, N>,
613 N,
614 >,
615 {
616 self.connect_anvil_with_config(std::convert::identity)
617 }
618
619 #[deprecated(since = "0.12.6", note = "use `connect_anvil` instead")]
621 pub fn on_anvil(self) -> F::Provider
622 where
623 L: ProviderLayer<crate::layers::AnvilProvider<RootProvider<N>, N>, N>,
624 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
625 {
626 self.connect_anvil_with_config(std::convert::identity)
627 }
628
629 pub fn connect_anvil_with_wallet(
633 self,
634 ) -> <JoinedEthereumWalletFiller<F> as ProviderLayer<L::Provider, N>>::Provider
635 where
636 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
637 L: crate::builder::ProviderLayer<
638 crate::layers::AnvilProvider<crate::provider::RootProvider<N>, N>,
639 N,
640 >,
641 alloy_network::EthereumWallet: alloy_network::NetworkWallet<N>,
642 {
643 self.connect_anvil_with_wallet_and_config(std::convert::identity)
644 .expect("failed to build provider")
645 }
646
647 #[deprecated(since = "0.12.6", note = "use `connect_anvil_with_wallet` instead")]
651 pub fn on_anvil_with_wallet(
652 self,
653 ) -> <JoinedEthereumWalletFiller<F> as ProviderLayer<L::Provider, N>>::Provider
654 where
655 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
656 L: crate::builder::ProviderLayer<
657 crate::layers::AnvilProvider<crate::provider::RootProvider<N>, N>,
658 N,
659 >,
660 alloy_network::EthereumWallet: alloy_network::NetworkWallet<N>,
661 {
662 self.connect_anvil_with_wallet_and_config(std::convert::identity)
663 .expect("failed to build provider")
664 }
665
666 pub fn connect_anvil_with_config(
669 self,
670 f: impl FnOnce(alloy_node_bindings::Anvil) -> alloy_node_bindings::Anvil,
671 ) -> F::Provider
672 where
673 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
674 L: crate::builder::ProviderLayer<
675 crate::layers::AnvilProvider<crate::provider::RootProvider<N>, N>,
676 N,
677 >,
678 {
679 let anvil_layer = crate::layers::AnvilLayer::from(f(Default::default()));
680 let url = anvil_layer.endpoint_url();
681
682 let rpc_client = ClientBuilder::default().http(url);
683
684 self.layer(anvil_layer).connect_client(rpc_client)
685 }
686
687 #[deprecated(since = "0.12.6", note = "use `connect_anvil_with_config` instead")]
690 pub fn on_anvil_with_config(
691 self,
692 f: impl FnOnce(alloy_node_bindings::Anvil) -> alloy_node_bindings::Anvil,
693 ) -> F::Provider
694 where
695 L: ProviderLayer<crate::layers::AnvilProvider<RootProvider<N>, N>, N>,
696 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
697 {
698 let anvil_layer = crate::layers::AnvilLayer::from(f(Default::default()));
699 let url = anvil_layer.endpoint_url();
700
701 let rpc_client = ClientBuilder::default().http(url);
702
703 self.layer(anvil_layer).connect_client(rpc_client)
704 }
705
706 pub fn connect_anvil_with_wallet_and_config(
709 self,
710 f: impl FnOnce(alloy_node_bindings::Anvil) -> alloy_node_bindings::Anvil,
711 ) -> AnvilProviderResult<
712 <JoinedEthereumWalletFiller<F> as ProviderLayer<L::Provider, N>>::Provider,
713 >
714 where
715 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
716 L: crate::builder::ProviderLayer<
717 crate::layers::AnvilProvider<crate::provider::RootProvider<N>, N>,
718 N,
719 >,
720 alloy_network::EthereumWallet: alloy_network::NetworkWallet<N>,
721 {
722 let anvil_layer = crate::layers::AnvilLayer::from(f(Default::default()));
723 let url = anvil_layer.endpoint_url();
724
725 let wallet = anvil_layer
726 .instance()
727 .wallet()
728 .ok_or(alloy_node_bindings::NodeError::NoKeysAvailable)?;
729
730 let rpc_client = ClientBuilder::default().http(url);
731
732 Ok(self.wallet(wallet).layer(anvil_layer).connect_client(rpc_client))
733 }
734
735 #[deprecated(since = "0.12.6", note = "use `connect_anvil_with_wallet_and_config` instead")]
738 pub fn on_anvil_with_wallet_and_config(
739 self,
740 f: impl FnOnce(alloy_node_bindings::Anvil) -> alloy_node_bindings::Anvil,
741 ) -> AnvilProviderResult<
742 <JoinedEthereumWalletFiller<F> as ProviderLayer<L::Provider, N>>::Provider,
743 >
744 where
745 F: TxFiller<N> + ProviderLayer<L::Provider, N>,
746 L: crate::builder::ProviderLayer<
747 crate::layers::AnvilProvider<crate::provider::RootProvider<N>, N>,
748 N,
749 >,
750 alloy_network::EthereumWallet: alloy_network::NetworkWallet<N>,
751 {
752 let anvil_layer = crate::layers::AnvilLayer::from(f(Default::default()));
753 let url = anvil_layer.endpoint_url();
754
755 let wallet = anvil_layer
756 .instance()
757 .wallet()
758 .ok_or(alloy_node_bindings::NodeError::NoKeysAvailable)?;
759
760 let rpc_client = ClientBuilder::default().http(url);
761
762 Ok(self.wallet(wallet).layer(anvil_layer).connect_client(rpc_client))
763 }
764}
765
766#[cfg(test)]
767mod tests {
768 use super::*;
769 use crate::Provider;
770 use alloy_network::AnyNetwork;
771
772 #[tokio::test]
773 async fn basic() {
774 let provider = ProviderBuilder::new()
775 .with_cached_nonce_management()
776 .with_call_batching()
777 .connect_http("http://localhost:8545".parse().unwrap());
778 let _ = provider.get_account(Default::default());
779 let provider = provider.erased();
780 let _ = provider.get_account(Default::default());
781 }
782
783 #[tokio::test]
784 #[cfg(feature = "reqwest")]
785 async fn test_connect_reqwest() {
786 let provider = ProviderBuilder::new()
787 .with_cached_nonce_management()
788 .with_call_batching()
789 .connect_reqwest(
790 reqwest::Client::new(),
791 reqwest::Url::parse("http://localhost:8545").unwrap(),
792 );
793 let _ = provider.get_account(Default::default());
794 let provider = provider.erased();
795 let _ = provider.get_account(Default::default());
796 }
797
798 #[tokio::test]
799 #[cfg(feature = "reqwest")]
800 async fn test_with_reqwest() {
801 let provider = ProviderBuilder::new()
802 .with_cached_nonce_management()
803 .with_call_batching()
804 .with_reqwest(reqwest::Url::parse("http://localhost:8545").unwrap(), |builder| {
805 builder
806 .user_agent("alloy/test")
807 .timeout(std::time::Duration::from_secs(10))
808 .build()
809 .expect("failed to build reqwest client")
810 });
811 let _ = provider.get_account(Default::default());
812 let provider = provider.erased();
813 let _ = provider.get_account(Default::default());
814 }
815
816 #[tokio::test]
817 async fn compile_with_network() {
818 let p = ProviderBuilder::new_with_network::<AnyNetwork>().connect_anvil();
819 let num = p.get_block_number().await.unwrap();
820 assert_eq!(num, 0);
821 }
822}