Skip to main content

tempo_faucet/
args.rs

1use alloy::{
2    network::EthereumWallet,
3    primitives::{Address, B256, U256},
4    providers::{DynProvider, Provider, ProviderBuilder},
5    signers::local::PrivateKeySigner,
6};
7use clap::Args;
8use tempo_alloy::{TempoNetwork, provider::ext::TempoProviderBuilderExt};
9
10/// Faucet-specific CLI arguments
11#[derive(Debug, Clone, Default, Args, PartialEq, Eq)]
12#[command(next_help_heading = "Faucet")]
13pub struct FaucetArgs {
14    /// Whether the faucet is enabled
15    #[arg(
16        id = "faucet.enabled",
17        long = "faucet.enabled",
18        default_value_t = false
19    )]
20    pub enabled: bool,
21
22    /// Faucet funding private key
23    #[arg(
24        long = "faucet.private-key",
25        requires = "faucet.enabled",
26        required_if_eq("faucet.enabled", "true")
27    )]
28    pub private_key: Option<B256>,
29
30    /// Amount for each faucet funding transaction
31    #[arg(
32        long = "faucet.amount",
33        requires = "faucet.enabled",
34        required_if_eq("faucet.enabled", "true")
35    )]
36    pub amount: Option<U256>,
37
38    /// Target token address for the faucet to be funding with
39    #[arg(
40        long = "faucet.address",
41        requires = "faucet.enabled",
42        required_if_eq("faucet.enabled", "true"),
43        num_args(0..)
44    )]
45    pub token_addresses: Option<Vec<Address>>,
46
47    #[arg(
48        long = "faucet.node-address",
49        default_value = "http://localhost:8545",
50        requires = "faucet.enabled"
51    )]
52    pub node_address: String,
53}
54
55impl FaucetArgs {
56    pub fn wallet(&self) -> EthereumWallet {
57        let signer: PrivateKeySigner = PrivateKeySigner::from_bytes(
58            &self.private_key.expect("No faucet private key provided"),
59        )
60        .expect("Failed to decode private key");
61        EthereumWallet::new(signer)
62    }
63
64    pub fn addresses(&self) -> Vec<Address> {
65        self.token_addresses
66            .clone()
67            .expect("No TIP20 token addresses provided")
68    }
69
70    pub fn amount(&self) -> U256 {
71        self.amount.expect("No TIP20 token amount provided")
72    }
73
74    pub fn provider(&self) -> DynProvider<TempoNetwork> {
75        ProviderBuilder::new_with_network::<TempoNetwork>()
76            .with_expiring_nonces()
77            .wallet(self.wallet())
78            .connect_http(
79                self.node_address
80                    .parse()
81                    .expect("Failed to parse node address"),
82            )
83            .erased()
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90    use clap::Parser;
91
92    /// A helper type to parse Args more easily
93    #[derive(Parser)]
94    struct CommandParser {
95        #[command(flatten)]
96        args: FaucetArgs,
97    }
98
99    #[test]
100    fn faucet_args_default_sanity_test() {
101        assert!(CommandParser::try_parse_from(["tempo"]).is_ok());
102    }
103}