stellar_registry_cli/commands/
upgrade.rs1use 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 #[arg(long)]
12 pub contract_name: PrefixedName,
13
14 #[arg(long)]
17 pub wasm_name: PrefixedName,
18
19 #[arg(long)]
21 pub version: Option<String>,
22
23 #[command(flatten)]
24 pub config: global::Args,
25}
26
27#[derive(thiserror::Error, Debug)]
28pub enum Error {
29 #[error(transparent)]
30 Invoke(#[from] invoke::Error),
31 #[error(transparent)]
32 Strkey(#[from] stellar_strkey::DecodeError),
33 #[error(transparent)]
34 LocatorConfig(#[from] stellar_cli::config::locator::Error),
35 #[error(transparent)]
36 Config(#[from] stellar_cli::config::Error),
37 #[error(transparent)]
38 Io(#[from] std::io::Error),
39 #[error("Upgrade failed: {0:?}")]
40 UpgradeFailed(invoke::Error),
41 #[error(transparent)]
42 Registry(#[from] stellar_registry_build::Error),
43}
44
45impl Cmd {
46 pub async fn run(&self) -> Result<(), Error> {
47 let contract_name = &self.contract_name.name;
48 let wasm_name = &self.wasm_name.name;
49
50 let mut slop = vec![
51 "upgrade_contract",
52 "--name",
53 contract_name,
54 "--wasm-name",
55 wasm_name,
56 ];
57 if let Some(version) = self.version.as_deref() {
58 slop.push("--version");
59 slop.push(version);
60 }
61 let registry = self.contract_name.registry(&self.config).await?;
62 registry
63 .as_contract()
64 .invoke_with_result(&slop, false)
65 .await
66 .map_err(Error::UpgradeFailed)?;
67 let version = if let Some(version) = self.version.as_deref() {
68 version.to_string()
69 } else {
70 registry
71 .as_contract()
72 .invoke_with_result(&["current_version", "--wasm-name", wasm_name], true)
73 .await?
74 };
75 println!("Upgraded {contract_name} to {wasm_name}@{version}",);
76 Ok(())
77 }
78}
79
80#[cfg(feature = "integration-tests")]
81#[cfg(test)]
82mod tests {
83
84 use stellar_cli::commands::{contract::invoke, global};
85
86 use stellar_scaffold_test::RegistryTest;
87
88 use crate::commands::{create_alias, upgrade};
89
90 #[tokio::test]
91 #[allow(clippy::too_many_lines)]
92 async fn simple_upgrade() {
93 let registry = RegistryTest::new().await;
95 let v1 = registry.hello_wasm_v1();
96 let v2 = registry.hello_wasm_v2();
97
98 let _test_env = registry.clone().env;
99
100 registry
104 .registry_cli("publish")
105 .arg("--wasm")
106 .arg(v1.to_str().unwrap())
107 .arg("--binver")
108 .arg("0.0.1")
109 .arg("--wasm-name")
110 .arg("hello")
111 .assert()
112 .success();
113
114 registry
116 .registry_cli("deploy")
117 .arg("--contract-name")
118 .arg("hello")
119 .arg("--wasm-name")
120 .arg("hello")
121 .arg("--")
122 .arg("--admin=alice")
123 .assert()
124 .success();
125
126 registry
127 .parse_cmd::<create_alias::Cmd>(&["hello"])
128 .unwrap()
129 .run()
130 .await
131 .unwrap();
132
133 let res = registry
134 .parse_cmd::<invoke::Cmd>(&["--id=hello", "--", "hello", "--to=world"])
135 .unwrap()
136 .invoke(&global::Args::default())
137 .await
138 .unwrap()
139 .into_result()
140 .unwrap();
141 assert_eq!(res, r#""world""#);
142
143 registry
145 .registry_cli("publish")
146 .arg("--wasm")
147 .arg(v2.to_str().unwrap())
148 .arg("--binver")
149 .arg("0.0.2")
150 .arg("--wasm-name")
151 .arg("hello")
152 .assert()
153 .success();
154 println!("Published new version of hello contract");
155 registry
156 .parse_cmd::<upgrade::Cmd>(&[
157 "--contract-name",
158 "hello",
159 "--wasm-name",
160 "hello",
161 "--version",
162 "\"0.0.2\"",
163 "--source=alice",
164 ])
165 .unwrap()
166 .run()
167 .await
168 .unwrap();
169
170 let res = registry
171 .parse_cmd::<invoke::Cmd>(&["--id=hello", "--", "hi", "--to=world"])
172 .unwrap()
173 .invoke(&global::Args::default())
174 .await
175 .unwrap()
176 .into_result()
177 .unwrap();
178 assert_eq!(res, r#""world""#);
179
180 registry
182 .parse_cmd::<upgrade::Cmd>(&[
183 "--contract-name",
184 "hello",
185 "--wasm-name",
186 "hello",
187 "--version",
188 "\"0.0.1\"",
189 "--source=alice",
190 ])
191 .unwrap()
192 .run()
193 .await
194 .unwrap();
195
196 let res = registry
197 .parse_cmd::<invoke::Cmd>(&["--id=hello", "--", "hello", "--to=world"])
198 .unwrap()
199 .invoke(&global::Args::default())
200 .await
201 .unwrap()
202 .into_result()
203 .unwrap();
204 assert_eq!(res, r#""world""#);
205
206 registry
208 .parse_cmd::<upgrade::Cmd>(&["--contract-name", "hello", "--wasm-name", "hello"])
209 .unwrap()
210 .run()
211 .await
212 .unwrap();
213
214 let res = registry
215 .parse_cmd::<invoke::Cmd>(&["--id=hello", "--", "hi", "--to=world"])
216 .unwrap()
217 .invoke(&global::Args::default())
218 .await
219 .unwrap()
220 .into_result()
221 .unwrap();
222 assert_eq!(res, r#""world""#);
223 }
224
225 #[tokio::test]
226 #[allow(clippy::too_many_lines)]
227 async fn unverified() {
228 let registry = RegistryTest::new().await;
230 let v1 = registry.hello_wasm_v1();
231 let v2 = registry.hello_wasm_v2();
232
233 let _test_env = registry.clone().env;
234
235 registry
239 .registry_cli("publish")
240 .arg("--wasm")
241 .arg(v1.to_str().unwrap())
242 .arg("--binver")
243 .arg("0.0.1")
244 .arg("--wasm-name")
245 .arg("unverified/hello")
246 .assert()
247 .success();
248
249 registry
251 .registry_cli("deploy")
252 .arg("--contract-name")
253 .arg("unverified/hello")
254 .arg("--wasm-name")
255 .arg("unverified/hello")
256 .arg("--")
257 .arg("--admin=alice")
258 .assert()
259 .success();
260
261 registry
262 .parse_cmd::<create_alias::Cmd>(&["unverified/hello"])
263 .unwrap()
264 .run()
265 .await
266 .unwrap();
267
268 let res = registry
269 .parse_cmd::<invoke::Cmd>(&["--id=hello", "--", "hello", "--to=world"])
270 .unwrap()
271 .invoke(&global::Args::default())
272 .await
273 .unwrap()
274 .into_result()
275 .unwrap();
276 assert_eq!(res, r#""world""#);
277
278 registry
280 .registry_cli("publish")
281 .arg("--wasm")
282 .arg(v2.to_str().unwrap())
283 .arg("--binver")
284 .arg("0.0.2")
285 .arg("--wasm-name")
286 .arg("unverified/hello")
287 .assert()
288 .success();
289 println!("Published new version of hello contract");
290 registry
291 .parse_cmd::<upgrade::Cmd>(&[
292 "--contract-name",
293 "unverified/hello",
294 "--wasm-name",
295 "unverified/hello",
296 "--version",
297 "\"0.0.2\"",
298 "--source=alice",
299 ])
300 .unwrap()
301 .run()
302 .await
303 .unwrap();
304
305 let res = registry
306 .parse_cmd::<invoke::Cmd>(&["--id=hello", "--", "hi", "--to=world"])
307 .unwrap()
308 .invoke(&global::Args::default())
309 .await
310 .unwrap()
311 .into_result()
312 .unwrap();
313 assert_eq!(res, r#""world""#);
314
315 registry
317 .parse_cmd::<upgrade::Cmd>(&[
318 "--contract-name",
319 "unverified/hello",
320 "--wasm-name",
321 "unverified/hello",
322 "--version",
323 "\"0.0.1\"",
324 "--source=alice",
325 ])
326 .unwrap()
327 .run()
328 .await
329 .unwrap();
330
331 let res = registry
332 .parse_cmd::<invoke::Cmd>(&["--id=hello", "--", "hello", "--to=world"])
333 .unwrap()
334 .invoke(&global::Args::default())
335 .await
336 .unwrap()
337 .into_result()
338 .unwrap();
339 assert_eq!(res, r#""world""#);
340
341 registry
343 .parse_cmd::<upgrade::Cmd>(&[
344 "--contract-name",
345 "unverified/hello",
346 "--wasm-name",
347 "hello",
348 ])
349 .unwrap()
350 .run()
351 .await
352 .unwrap();
353
354 let res = registry
355 .parse_cmd::<invoke::Cmd>(&["--id=hello", "--", "hi", "--to=world"])
356 .unwrap()
357 .invoke(&global::Args::default())
358 .await
359 .unwrap()
360 .into_result()
361 .unwrap();
362 assert_eq!(res, r#""world""#);
363 }
364}