Преглед изворни кода

cli: Fix custom `provider.cluster` (#3428)

acheron пре 9 месеци
родитељ
комит
135d7e02c0
2 измењених фајлова са 46 додато и 7 уклоњено
  1. 1 0
      CHANGELOG.md
  2. 45 7
      cli/src/config.rs

+ 1 - 0
CHANGELOG.md

@@ -102,6 +102,7 @@ The minor version will be incremented upon a breaking change and the patch versi
 - cli: Avoid extra IDL generation during `verify` ([#3398](https://github.com/coral-xyz/anchor/pull/3398)).
 - cli: Avoid extra IDL generation during `verify` ([#3398](https://github.com/coral-xyz/anchor/pull/3398)).
 - lang: Require `zero` accounts to be unique ([#3409](https://github.com/coral-xyz/anchor/pull/3409)).
 - lang: Require `zero` accounts to be unique ([#3409](https://github.com/coral-xyz/anchor/pull/3409)).
 - lang: Deduplicate `zero` accounts against `init` accounts ([#3422](https://github.com/coral-xyz/anchor/pull/3422)).
 - lang: Deduplicate `zero` accounts against `init` accounts ([#3422](https://github.com/coral-xyz/anchor/pull/3422)).
+- cli: Fix custom `provider.cluster` ([#3428](https://github.com/coral-xyz/anchor/pull/3428)).
 
 
 ### Breaking
 ### Breaking
 
 

+ 45 - 7
cli/src/config.rs

@@ -7,7 +7,8 @@ use dirs::home_dir;
 use heck::ToSnakeCase;
 use heck::ToSnakeCase;
 use reqwest::Url;
 use reqwest::Url;
 use serde::de::{self, MapAccess, Visitor};
 use serde::de::{self, MapAccess, Visitor};
-use serde::{Deserialize, Deserializer, Serialize};
+use serde::ser::SerializeMap;
+use serde::{Deserialize, Deserializer, Serialize, Serializer};
 use solana_cli_config::{Config as SolanaConfig, CONFIG_FILE};
 use solana_cli_config::{Config as SolanaConfig, CONFIG_FILE};
 use solana_sdk::clock::Slot;
 use solana_sdk::clock::Slot;
 use solana_sdk::pubkey::Pubkey;
 use solana_sdk::pubkey::Pubkey;
@@ -590,11 +591,29 @@ struct _Config {
 
 
 #[derive(Debug, Serialize, Deserialize)]
 #[derive(Debug, Serialize, Deserialize)]
 struct Provider {
 struct Provider {
-    #[serde(deserialize_with = "des_cluster")]
+    #[serde(serialize_with = "ser_cluster", deserialize_with = "des_cluster")]
     cluster: Cluster,
     cluster: Cluster,
     wallet: String,
     wallet: String,
 }
 }
 
 
+fn ser_cluster<S: Serializer>(cluster: &Cluster, s: S) -> Result<S::Ok, S::Error> {
+    match cluster {
+        Cluster::Custom(http, ws) => {
+            match (Url::parse(http), Url::parse(ws)) {
+                // If `ws` was derived from `http`, serialize `http` as string
+                (Ok(h), Ok(w)) if h.domain() == w.domain() => s.serialize_str(http),
+                _ => {
+                    let mut map = s.serialize_map(Some(2))?;
+                    map.serialize_entry("http", http)?;
+                    map.serialize_entry("ws", ws)?;
+                    map.end()
+                }
+            }
+        }
+        _ => s.serialize_str(&cluster.to_string()),
+    }
+}
+
 fn des_cluster<'de, D>(deserializer: D) -> Result<Cluster, D::Error>
 fn des_cluster<'de, D>(deserializer: D) -> Result<Cluster, D::Error>
 where
 where
     D: Deserializer<'de>,
     D: Deserializer<'de>,
@@ -1465,15 +1484,34 @@ mod tests {
         wallet = \"id.json\"
         wallet = \"id.json\"
     ";
     ";
 
 
-    const CUSTOM_CONFIG: &str = "
+    #[test]
+    fn parse_custom_cluster_str() {
+        let config = Config::from_str(
+            "
         [provider]
         [provider]
-        cluster = { http = \"http://my-url.com\", ws = \"ws://my-url.com\" }
+        cluster = \"http://my-url.com\"
         wallet = \"id.json\"
         wallet = \"id.json\"
-    ";
+    ",
+        )
+        .unwrap();
+        assert!(!config.features.skip_lint);
+
+        // Make sure the layout of `provider.cluster` stays the same after serialization
+        assert!(config
+            .to_string()
+            .contains(r#"cluster = "http://my-url.com""#));
+    }
 
 
     #[test]
     #[test]
-    fn parse_custom_cluster() {
-        let config = Config::from_str(CUSTOM_CONFIG).unwrap();
+    fn parse_custom_cluster_map() {
+        let config = Config::from_str(
+            "
+        [provider]
+        cluster = { http = \"http://my-url.com\", ws = \"ws://my-url.com\" }
+        wallet = \"id.json\"
+    ",
+        )
+        .unwrap();
         assert!(!config.features.skip_lint);
         assert!(!config.features.skip_lint);
     }
     }