@@ -8,10 +8,17 @@ use crate::commands::global;
88
99#[ derive( Parser , Debug , Clone ) ]
1010pub struct Cmd {
11- /// Name of deployed contract. Can use prefix of not using verified registry.
11+ /// Name of deployed contract. Can use prefix if not using verified registry.
1212 /// E.g. `unverified/<name>`
1313 pub contract : PrefixedName ,
1414
15+ /// Optional custom local name for the alias. If not provided, uses the name from the registry.
16+ pub local_name : Option < String > ,
17+
18+ /// Force overwrite if an alias with the same name already exists.
19+ #[ arg( short, long) ]
20+ pub force : bool ,
21+
1522 #[ command( flatten) ]
1623 pub config : global:: Args ,
1724}
@@ -28,13 +35,29 @@ pub enum Error {
2835 Config ( #[ from] stellar_cli:: config:: Error ) ,
2936 #[ error( transparent) ]
3037 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 ) ,
3142}
3243
3344impl Cmd {
3445 pub async fn run ( & self ) -> Result < ( ) , Error > {
3546 let network_passphrase = self . config . get_network ( ) ?. network_passphrase ;
36- let alias = & self . contract . name ;
47+ let alias = self . local_name . as_deref ( ) . unwrap_or ( & self . contract . name ) ;
3748 let contract = self . get_contract_id ( ) . await ?;
49+
50+ // Check if alias already exists
51+ 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+
3861 // Only create alias mapping, don't fetch wasm here
3962 self . config
4063 . locator
@@ -54,14 +77,9 @@ impl Cmd {
5477#[ cfg( test) ]
5578mod tests {
5679
57- use stellar_scaffold_test:: RegistryTest ;
58-
59- #[ tokio:: test]
60- async fn test_run ( ) {
61- // Create test environment
62- let registry = RegistryTest :: new ( ) . await ;
63- let test_env = registry. clone ( ) . env ;
80+ use stellar_scaffold_test:: { AssertExt , RegistryTest } ;
6481
82+ fn publish_and_deploy ( registry : & RegistryTest , name : & str ) {
6583 // Path to the hello world contract WASM
6684 let wasm_path = registry. hello_wasm_v1 ( ) ;
6785
@@ -73,28 +91,36 @@ mod tests {
7391 . arg ( "--binver" )
7492 . arg ( "0.0.2" )
7593 . arg ( "--wasm-name" )
76- . arg ( "hello" )
94+ . arg ( name )
7795 . assert ( )
7896 . success ( ) ;
7997
8098 // Then deploy it
8199 registry
82100 . registry_cli ( "deploy" )
83101 . arg ( "--contract-name" )
84- . arg ( "hello" )
102+ . arg ( name )
85103 . arg ( "--wasm-name" )
86- . arg ( "hello" )
104+ . arg ( name )
87105 . arg ( "--version" )
88106 . arg ( "0.0.2" )
89107 . arg ( "--" )
90108 . arg ( "--admin=alice" )
91109 . assert ( )
92110 . success ( ) ;
111+ }
93112
94- // Create test command for install
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 ( & registry, "hello" ) ;
119+
120+ // Create test command for create-alias
95121 let cmd = registry. parse_cmd :: < super :: Cmd > ( & [ "hello" ] ) . unwrap ( ) ;
96122
97- // Run the install command
123+ // Run the create-alias command
98124 cmd. run ( ) . await . unwrap ( ) ;
99125 assert ! (
100126 test_env
@@ -105,39 +131,172 @@ mod tests {
105131 }
106132
107133 #[ tokio:: test]
108- async fn unverified ( ) {
109- // Create test environment
134+ async fn name_collision ( ) {
110135 let registry = RegistryTest :: new ( ) . await ;
111136 let test_env = registry. clone ( ) . env ;
112137
113- // Path to the hello world contract WASM
114- let wasm_path = registry . hello_wasm_v1 ( ) ;
138+ publish_and_deploy ( & registry , " hello" ) ;
139+ publish_and_deploy ( & registry , "unverified/hello" ) ;
115140
116- // First publish the contract
141+ // Run create-alias command
117142 registry
118- . registry_cli ( "publish" )
119- . arg ( "--wasm" )
120- . arg ( & wasm_path)
121- . arg ( "--binver" )
122- . arg ( "0.0.2" )
123- . arg ( "--wasm-name" )
124- . arg ( "unverified/hello" )
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" ] )
125159 . assert ( )
126- . success ( ) ;
160+ . stdout_as_str ( ) ;
127161
128- // Then deploy it
162+ // Run the create-alias command
163+ let cmd = registry
164+ . parse_cmd :: < super :: Cmd > ( & [ "unverified/hello" ] )
165+ . unwrap ( )
166+ . run ( )
167+ . await ;
168+
169+ // assert that cmd returns error (panics if result is ok)
170+ cmd. unwrap_err ( ) ;
171+
172+ // assert the alias still points at the same contract id
173+ 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 ( & registry, "hello" ) ;
190+ publish_and_deploy ( & registry, "unverified/hello" ) ;
191+
192+ // Run create-alias command
129193 registry
130- . registry_cli ( "deploy" )
131- . arg ( "--contract-name" )
132- . arg ( "unverified/hello" )
133- . arg ( "--wasm-name" )
134- . arg ( "unverified/hello" )
135- . arg ( "--version" )
136- . arg ( "0.0.2" )
137- . arg ( "--" )
138- . arg ( "--admin=alice" )
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" ] )
139210 . assert ( )
140- . success ( ) ;
211+ . stdout_as_str ( ) ;
212+
213+ // Run the create-alias command
214+ let cmd = registry
215+ . parse_cmd :: < super :: Cmd > ( & [ "unverified/hello" , "-f" ] )
216+ . unwrap ( )
217+ . run ( )
218+ . await ;
219+
220+ // assert that cmd succeeded
221+ cmd. unwrap ( ) ;
222+
223+ // assert the alias changed
224+ 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 ( & registry, "hello" ) ;
241+ publish_and_deploy ( & registry, "unverified/hello" ) ;
242+
243+ // Run create-alias command
244+ 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+ // Run the create-alias command
265+ let cmd = registry
266+ . parse_cmd :: < super :: Cmd > ( & [ "unverified/hello" , "unverified_hello" ] )
267+ . unwrap ( )
268+ . run ( )
269+ . await ;
270+
271+ // assert that cmd succeeded
272+ cmd. unwrap ( ) ;
273+
274+ // assert the "hello" alias is the same
275+ 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 we created a differently-named alias for unverified/hello
286+ 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 ( & registry, "unverified/hello" ) ;
141300
142301 // Create test command for install
143302 let cmd = registry
0 commit comments