foundry_cli/opts/
chain.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use clap::builder::{PossibleValuesParser, TypedValueParser};
use eyre::Result;
use foundry_config::{Chain, NamedChain};
use std::ffi::OsStr;
use strum::VariantNames;

/// Custom Clap value parser for [`Chain`]s.
///
/// Displays all possible chains when an invalid chain is provided.
#[derive(Clone, Debug)]
pub struct ChainValueParser {
    pub inner: PossibleValuesParser,
}

impl Default for ChainValueParser {
    fn default() -> Self {
        Self { inner: PossibleValuesParser::from(NamedChain::VARIANTS) }
    }
}

impl TypedValueParser for ChainValueParser {
    type Value = Chain;

    fn parse_ref(
        &self,
        cmd: &clap::Command,
        arg: Option<&clap::Arg>,
        value: &OsStr,
    ) -> Result<Self::Value, clap::Error> {
        let s =
            value.to_str().ok_or_else(|| clap::Error::new(clap::error::ErrorKind::InvalidUtf8))?;
        if let Ok(id) = s.parse() {
            Ok(Chain::from_id(id))
        } else {
            // NamedChain::VARIANTS is a subset of all possible variants, since there are aliases:
            // mumbai instead of polygon-mumbai etc
            //
            // Parse first as NamedChain, if it fails parse with NamedChain::VARIANTS for displaying
            // the error to the user
            s.parse()
                .map_err(|_| self.inner.parse_ref(cmd, arg, value).unwrap_err())
                .map(Chain::from_named)
        }
    }
}