diff --git a/crates/relayer/src/config.rs b/crates/relayer/src/config.rs index 10721a7348..98fe08b687 100644 --- a/crates/relayer/src/config.rs +++ b/crates/relayer/src/config.rs @@ -618,18 +618,13 @@ pub enum EventSourceMode { }, } -// NOTE: -// To work around a limitation of serde, which does not allow +// NOTE: To work around a limitation of serde, which does not allow // to specify a default variant if not tag is present, -// every underlying chain config MUST have a field `r#type` of -// type `monotstate::MustBe!("VariantName")`. -// -// For chains other than CosmosSdk, this field MUST NOT be annotated -// with `#[serde(default)]`. -// -// See https://github.com/serde-rs/serde/issues/2231 -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -#[serde(untagged)] +// every underlying chain config struct MUST have a field `r#type` with +// type `monotstate::MustBe!("VariantName")`, eg. the `CosmosSdkConfig` +// struct has a field `r#type: MustBe!("CosmosSdk")`. +#[derive(Clone, Debug, PartialEq, Serialize)] +#[serde(tag = "type")] pub enum ChainConfig { CosmosSdk(CosmosSdkConfig), } @@ -704,6 +699,34 @@ impl ChainConfig { } } +impl<'de> Deserialize<'de> for ChainConfig { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let value = toml::Value::deserialize(deserializer)?; + + let type_value = value + .get("type") + .cloned() + .unwrap_or_else(|| toml::Value::String("CosmosSdk".to_string())); + + let type_str = type_value + .as_str() + .ok_or_else(|| serde::de::Error::custom("invalid chain type, must be a string"))?; + + match type_str { + "CosmosSdk" => CosmosSdkConfig::deserialize(value) + .map(Self::CosmosSdk) + .map_err(|e| serde::de::Error::custom(format!("invalid CosmosSdk config: {e}"))), + + chain_type => Err(serde::de::Error::custom(format!( + "unknown chain type: {chain_type}", + ))), + } + } +} + /// Attempt to load and parse the TOML config file as a `Config`. pub fn load(path: impl AsRef) -> Result { let config_toml = std::fs::read_to_string(&path).map_err(Error::io)?;