Skip to main content

foundry_cli/opts/
chain.rs

1use clap::builder::{PossibleValuesParser, TypedValueParser};
2use eyre::Result;
3use foundry_config::{Chain, NamedChain};
4use std::ffi::OsStr;
5
6/// Custom Clap value parser for [`Chain`]s.
7///
8/// Displays all possible chains when an invalid chain is provided.
9#[derive(Clone, Debug)]
10pub struct ChainValueParser {
11    pub inner: PossibleValuesParser,
12}
13
14impl Default for ChainValueParser {
15    fn default() -> Self {
16        Self { inner: PossibleValuesParser::from(NamedChain::VARIANT_NAMES) }
17    }
18}
19
20impl TypedValueParser for ChainValueParser {
21    type Value = Chain;
22
23    fn parse_ref(
24        &self,
25        cmd: &clap::Command,
26        arg: Option<&clap::Arg>,
27        value: &OsStr,
28    ) -> Result<Self::Value, clap::Error> {
29        let s =
30            value.to_str().ok_or_else(|| clap::Error::new(clap::error::ErrorKind::InvalidUtf8))?;
31        if let Ok(id) = s.parse() {
32            Ok(Chain::from_id(id))
33        } else {
34            // NamedChain::VARIANT_NAMES is a subset of all possible variants, since there are
35            // aliases: amoy instead of polygon-amoy etc
36            //
37            // Parse first as NamedChain, if it fails parse with NamedChain::VARIANT_NAMES for
38            // displaying the error to the user
39            s.parse()
40                .map_err(|_| self.inner.parse_ref(cmd, arg, value).unwrap_err())
41                .map(Chain::from_named)
42        }
43    }
44}