foundry_cli/opts/
chain.rs

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