Skip to main content

stellar_registry_cli/commands/
fetch_hash.rs

1use clap::Parser;
2use stellar_cli::commands::contract::invoke;
3use stellar_registry_build::named_registry::PrefixedName;
4
5use crate::commands::global;
6
7#[derive(Parser, Debug, Clone)]
8pub struct Cmd {
9    /// Name of published Wasm
10    pub wasm_name: PrefixedName,
11
12    /// Version of published Wasm, if not specified, the latest version will be fetched
13    #[arg(long)]
14    pub version: Option<String>,
15
16    #[command(flatten)]
17    pub config: global::Args,
18}
19
20#[derive(thiserror::Error, Debug)]
21pub enum Error {
22    #[error(transparent)]
23    Invoke(#[from] invoke::Error),
24    #[error(transparent)]
25    Config(#[from] stellar_cli::config::Error),
26    #[error(transparent)]
27    Registry(#[from] stellar_registry_build::Error),
28}
29
30impl Cmd {
31    pub async fn run(&self) -> Result<(), Error> {
32        let hash = self.fetch_hash().await?;
33        println!("{hash}");
34        Ok(())
35    }
36
37    pub async fn fetch_hash(&self) -> Result<String, Error> {
38        let registry = self.wasm_name.registry(&self.config).await?;
39        let mut slop = vec!["fetch_hash", "--wasm-name", &self.wasm_name.name];
40        let version = self.version.clone().map(|v| format!("\"{v}\""));
41        if let Some(version) = version.as_deref() {
42            slop.push("--version");
43            slop.push(version);
44        }
45        let raw = registry
46            .as_contract()
47            .invoke_with_result(&slop, true)
48            .await?;
49        Ok(raw.trim_matches('"').to_string())
50    }
51}
52
53#[cfg(feature = "integration-tests")]
54#[cfg(test)]
55mod tests {
56    use stellar_scaffold_test::RegistryTest;
57
58    #[tokio::test]
59    async fn simple() {
60        let registry = RegistryTest::new().await;
61        let v1 = registry.hello_wasm_v1();
62
63        // First publish the contract
64        registry
65            .registry_cli("publish")
66            .arg("--wasm")
67            .arg(v1.to_str().unwrap())
68            .arg("--binver")
69            .arg("0.0.1")
70            .arg("--wasm-name")
71            .arg("hello")
72            .assert()
73            .success();
74
75        let hash = registry
76            .parse_cmd::<super::Cmd>(&["hello"])
77            .unwrap()
78            .fetch_hash()
79            .await
80            .unwrap();
81        assert!(!hash.is_empty());
82        assert!(hash.len() == 64); // 32 bytes hex encoded
83    }
84
85    #[tokio::test]
86    async fn with_version() {
87        let registry = RegistryTest::new().await;
88        let v1 = registry.hello_wasm_v1();
89        let v2 = registry.hello_wasm_v2();
90
91        // Publish v1
92        registry
93            .registry_cli("publish")
94            .arg("--wasm")
95            .arg(v1.to_str().unwrap())
96            .arg("--binver")
97            .arg("0.0.1")
98            .arg("--wasm-name")
99            .arg("hello")
100            .assert()
101            .success();
102
103        let hash_v1 = registry
104            .parse_cmd::<super::Cmd>(&["hello", "--version", "0.0.1"])
105            .unwrap()
106            .fetch_hash()
107            .await
108            .unwrap();
109
110        // Publish v2
111        registry
112            .registry_cli("publish")
113            .arg("--wasm")
114            .arg(v2.to_str().unwrap())
115            .arg("--binver")
116            .arg("0.0.2")
117            .arg("--wasm-name")
118            .arg("hello")
119            .assert()
120            .success();
121
122        let hash_v2 = registry
123            .parse_cmd::<super::Cmd>(&["hello", "--version", "0.0.2"])
124            .unwrap()
125            .fetch_hash()
126            .await
127            .unwrap();
128
129        // Hashes should be different
130        assert_ne!(hash_v1, hash_v2);
131
132        // Without version should return latest (v2)
133        let hash_latest = registry
134            .parse_cmd::<super::Cmd>(&["hello"])
135            .unwrap()
136            .fetch_hash()
137            .await
138            .unwrap();
139        assert_eq!(hash_v2, hash_latest);
140    }
141
142    #[tokio::test]
143    async fn unverified() {
144        let registry = RegistryTest::new().await;
145        let v1 = registry.hello_wasm_v1();
146
147        registry
148            .registry_cli("publish")
149            .arg("--wasm")
150            .arg(v1.to_str().unwrap())
151            .arg("--binver")
152            .arg("0.0.1")
153            .arg("--wasm-name")
154            .arg("unverified/hello")
155            .assert()
156            .success();
157
158        let hash = registry
159            .parse_cmd::<super::Cmd>(&["unverified/hello"])
160            .unwrap()
161            .fetch_hash()
162            .await
163            .unwrap();
164        assert!(!hash.is_empty());
165    }
166}