tempo_bench/cmd/
signer_providers.rs

1use std::sync::Arc;
2
3use alloy::{
4    providers::{
5        DynProvider, Provider, ProviderBuilder, RootProvider,
6        fillers::{CachedNonceManager, FillProvider, TxFiller},
7    },
8    signers::local::{MnemonicBuilder, PrivateKeySigner},
9    transports::http::reqwest::Url,
10};
11use indicatif::ProgressIterator;
12use rand::seq::IndexedRandom;
13use tempo_alloy::TempoNetwork;
14
15type BenchProvider<F> = FillProvider<F, RootProvider<TempoNetwork>, TempoNetwork>;
16type UnsignedProviderFactory<F> =
17    Box<dyn Fn(Url, CachedNonceManager) -> BenchProvider<F> + Send + Sync>;
18type SignedProviderFactory = Box<
19    dyn Fn(PrivateKeySigner, Url, CachedNonceManager) -> DynProvider<TempoNetwork> + Send + Sync,
20>;
21
22/// Manages signers and target URLs for creating providers.
23#[derive(Debug, Clone)]
24pub(crate) struct SignerProviderManager<F: TxFiller<TempoNetwork>>(
25    Arc<SignerProviderManagerInner<F>>,
26);
27
28#[derive(Debug)]
29struct SignerProviderManagerInner<F: TxFiller<TempoNetwork>> {
30    /// List of private key signers.
31    signers: Vec<PrivateKeySigner>,
32    /// List of target URLs.
33    target_urls: Vec<Url>,
34    /// Providers without signing capabilities.
35    unsigned_providers: Vec<BenchProvider<F>>,
36    /// List of providers (one per signer) with random target URLs.
37    signer_providers: Vec<(PrivateKeySigner, DynProvider<TempoNetwork>)>,
38}
39
40impl<F: TxFiller<TempoNetwork> + 'static> SignerProviderManager<F> {
41    /// Create a new instance of [`SignerProviderManager`].
42    ///
43    /// 1. Creates `accounts` signers from the `mnemonic` starting with `from_mnemonic_index` index.
44    /// 2. Creates `target_urls` providers without signing capabilities using `unsigned_provider_factory`.
45    /// 3. Creates `accounts` providers with signing capabilities, one per signer,
46    ///    with random target URLs using `signed_provider_factory`.
47    pub fn new(
48        mnemonic: String,
49        from_mnemonic_index: u32,
50        accounts: u64,
51        target_urls: Vec<Url>,
52        unsigned_provider_factory: UnsignedProviderFactory<F>,
53        signed_provider_factory: SignedProviderFactory,
54    ) -> Self {
55        let cached_nonce_manager = CachedNonceManager::default();
56        let signers = (from_mnemonic_index..)
57            .take(accounts as usize)
58            .progress_count(accounts)
59            .map(|i| MnemonicBuilder::from_phrase_nth(&mnemonic, i))
60            .collect::<Vec<_>>();
61        let unsigned_providers = target_urls
62            .iter()
63            .cloned()
64            .map(|target_url| (unsigned_provider_factory)(target_url, cached_nonce_manager.clone()))
65            .collect();
66        let signer_providers = signers
67            .iter()
68            .progress()
69            .cloned()
70            .map(|signer| {
71                let target_url = target_urls.choose(&mut rand::rng()).unwrap().clone();
72                let provider = (signed_provider_factory)(
73                    signer.clone(),
74                    target_url,
75                    cached_nonce_manager.clone(),
76                );
77                (signer, provider)
78            })
79            .collect();
80        Self(Arc::new(SignerProviderManagerInner {
81            signers,
82            target_urls,
83            unsigned_providers,
84            signer_providers,
85        }))
86    }
87
88    /// Returns a list of providers (one per target URL) with no signers and fillers set.
89    pub fn target_url_providers(&self) -> Vec<(&Url, DynProvider<TempoNetwork>)> {
90        self.0
91            .target_urls
92            .iter()
93            .map(|target_url| {
94                let provider = ProviderBuilder::default()
95                    .connect_http(target_url.clone())
96                    .erased();
97                (target_url, provider)
98            })
99            .collect()
100    }
101
102    /// Returns a list of providers (one per signer) with random target URLs.
103    pub fn signer_providers(&self) -> &[(PrivateKeySigner, DynProvider<TempoNetwork>)] {
104        &self.0.signer_providers
105    }
106
107    /// Returns a random signer without signing capabilities.
108    pub fn random_unsigned_provider(&self) -> BenchProvider<F> {
109        self.0
110            .unsigned_providers
111            .choose(&mut rand::rng())
112            .unwrap()
113            .clone()
114    }
115
116    /// Returns a random signer.
117    pub fn random_signer(&self) -> &PrivateKeySigner {
118        self.0.signers.choose(&mut rand::rng()).unwrap()
119    }
120}