stellar_registry_cli/commands/
create_alias.rs1use clap::Parser;
2
3use stellar_cli::commands::contract::invoke;
4use stellar_registry_build::named_registry::PrefixedName;
5use stellar_strkey::Contract;
6
7use crate::commands::global;
8
9#[derive(Parser, Debug, Clone)]
10pub struct Cmd {
11 pub contract: PrefixedName,
14
15 pub local_name: Option<String>,
17
18 #[arg(short, long)]
20 pub force: bool,
21
22 #[command(flatten)]
23 pub config: global::Args,
24}
25
26#[derive(thiserror::Error, Debug)]
27pub enum Error {
28 #[error(transparent)]
29 Invoke(#[from] invoke::Error),
30 #[error(transparent)]
31 Strkey(#[from] stellar_strkey::DecodeError),
32 #[error(transparent)]
33 LocatorConfig(#[from] stellar_cli::config::locator::Error),
34 #[error(transparent)]
35 Config(#[from] stellar_cli::config::Error),
36 #[error(transparent)]
37 Registry(#[from] stellar_registry_build::Error),
38 #[error(
39 "Existing alias \"{1}\" exists. Overwrite with -f or provide a different local name like: \"create-alias {0} other-{1}\"."
40 )]
41 AliasExists(PrefixedName, String),
42}
43
44impl Cmd {
45 pub async fn run(&self) -> Result<(), Error> {
46 let network_passphrase = self.config.get_network()?.network_passphrase;
47 let alias = self.local_name.as_deref().unwrap_or(&self.contract.name);
48 let contract = self.get_contract_id().await?;
49
50 if !self.force
52 && self
53 .config
54 .locator
55 .get_contract_id(alias, &network_passphrase)?
56 .is_some()
57 {
58 return Err(Error::AliasExists(self.contract.clone(), alias.to_string()));
59 }
60
61 self.config
63 .locator
64 .save_contract_id(&network_passphrase, &contract, alias)?;
65 eprintln!("✅ Successfully registered contract alias '{alias}' for {contract}");
66 Ok(())
67 }
68
69 pub async fn get_contract_id(&self) -> Result<Contract, Error> {
70 let registry = &self.contract.registry(&self.config).await?;
71 eprintln!("Fetching contract ID via registry...");
72 Ok(registry.fetch_contract_id(&self.contract.name).await?)
73 }
74}
75
76#[cfg(feature = "integration-tests")]
77#[cfg(test)]
78mod tests {
79
80 use stellar_scaffold_test::{AssertExt, RegistryTest};
81
82 fn publish_and_deploy(registry: &RegistryTest, name: &str) {
83 let wasm_path = registry.hello_wasm_v1();
85
86 registry
88 .registry_cli("publish")
89 .arg("--wasm")
90 .arg(&wasm_path)
91 .arg("--binver")
92 .arg("0.0.2")
93 .arg("--wasm-name")
94 .arg(name)
95 .assert()
96 .success();
97
98 registry
100 .registry_cli("deploy")
101 .arg("--contract-name")
102 .arg(name)
103 .arg("--wasm-name")
104 .arg(name)
105 .arg("--version")
106 .arg("0.0.2")
107 .arg("--")
108 .arg("--admin=alice")
109 .assert()
110 .success();
111 }
112
113 #[tokio::test]
114 async fn test_run() {
115 let registry = RegistryTest::new().await;
116 let test_env = registry.clone().env;
117
118 publish_and_deploy(®istry, "hello");
119
120 let cmd = registry.parse_cmd::<super::Cmd>(&["hello"]).unwrap();
122
123 cmd.run().await.unwrap();
125 assert!(
126 test_env
127 .cwd
128 .join(".config/stellar/contract-ids/hello.json")
129 .exists()
130 );
131 }
132
133 #[tokio::test]
134 async fn name_collision() {
135 let registry = RegistryTest::new().await;
136 let test_env = registry.clone().env;
137
138 publish_and_deploy(®istry, "hello");
139 publish_and_deploy(®istry, "unverified/hello");
140
141 registry
143 .parse_cmd::<super::Cmd>(&["hello"])
144 .unwrap()
145 .run()
146 .await
147 .unwrap();
148
149 assert!(
150 test_env
151 .cwd
152 .join(".config/stellar/contract-ids/hello.json")
153 .exists()
154 );
155
156 let contract_id = test_env
157 .stellar("contract")
158 .args(["alias", "show", "hello"])
159 .assert()
160 .stdout_as_str();
161
162 let cmd = registry
164 .parse_cmd::<super::Cmd>(&["unverified/hello"])
165 .unwrap()
166 .run()
167 .await;
168
169 cmd.unwrap_err();
171
172 assert_eq!(
174 contract_id,
175 test_env
176 .stellar("contract")
177 .args(["alias", "show", "hello"])
178 .assert()
179 .success()
180 .stdout_as_str()
181 );
182 }
183
184 #[tokio::test]
185 async fn name_collision_with_overwrite() {
186 let registry = RegistryTest::new().await;
187 let test_env = registry.clone().env;
188
189 publish_and_deploy(®istry, "hello");
190 publish_and_deploy(®istry, "unverified/hello");
191
192 registry
194 .parse_cmd::<super::Cmd>(&["hello"])
195 .unwrap()
196 .run()
197 .await
198 .unwrap();
199
200 assert!(
201 test_env
202 .cwd
203 .join(".config/stellar/contract-ids/hello.json")
204 .exists()
205 );
206
207 let contract_id = test_env
208 .stellar("contract")
209 .args(["alias", "show", "hello"])
210 .assert()
211 .stdout_as_str();
212
213 let cmd = registry
215 .parse_cmd::<super::Cmd>(&["unverified/hello", "-f"])
216 .unwrap()
217 .run()
218 .await;
219
220 cmd.unwrap();
222
223 assert_ne!(
225 contract_id,
226 test_env
227 .stellar("contract")
228 .args(["alias", "show", "hello"])
229 .assert()
230 .success()
231 .stdout_as_str()
232 );
233 }
234
235 #[tokio::test]
236 async fn alternate_local_name() {
237 let registry = RegistryTest::new().await;
238 let test_env = registry.clone().env;
239
240 publish_and_deploy(®istry, "hello");
241 publish_and_deploy(®istry, "unverified/hello");
242
243 registry
245 .parse_cmd::<super::Cmd>(&["hello"])
246 .unwrap()
247 .run()
248 .await
249 .unwrap();
250
251 assert!(
252 test_env
253 .cwd
254 .join(".config/stellar/contract-ids/hello.json")
255 .exists()
256 );
257
258 let contract_id = test_env
259 .stellar("contract")
260 .args(["alias", "show", "hello"])
261 .assert()
262 .stdout_as_str();
263
264 let cmd = registry
266 .parse_cmd::<super::Cmd>(&["unverified/hello", "unverified_hello"])
267 .unwrap()
268 .run()
269 .await;
270
271 cmd.unwrap();
273
274 assert_eq!(
276 contract_id,
277 test_env
278 .stellar("contract")
279 .args(["alias", "show", "hello"])
280 .assert()
281 .success()
282 .stdout_as_str()
283 );
284
285 assert!(
287 test_env
288 .cwd
289 .join(".config/stellar/contract-ids/unverified_hello.json")
290 .exists()
291 );
292 }
293
294 #[tokio::test]
295 async fn unverified() {
296 let registry = RegistryTest::new().await;
297 let test_env = registry.clone().env;
298
299 publish_and_deploy(®istry, "unverified/hello");
300
301 let cmd = registry
303 .parse_cmd::<super::Cmd>(&["unverified/hello"])
304 .unwrap();
305
306 cmd.run().await.unwrap();
308 assert!(
309 test_env
310 .cwd
311 .join(".config/stellar/contract-ids/hello.json")
312 .exists()
313 );
314 }
315}