Skip to main content

stellar_registry_cli/commands/
register_contract.rs

1use clap::Parser;
2use stellar_cli::{commands::contract::invoke, config};
3use stellar_registry_build::{named_registry::PrefixedName, registry::Registry};
4
5use crate::commands::global;
6
7#[derive(Parser, Debug, Clone)]
8pub struct Cmd {
9    /// Name to register for the contract. Can use prefix if not using verified registry.
10    /// E.g. `unverified/<name>`
11    #[arg(long)]
12    pub contract_name: PrefixedName,
13
14    /// Contract address to register
15    #[arg(long)]
16    pub contract_address: String,
17
18    /// Owner of the contract registration
19    #[arg(long)]
20    pub owner: Option<String>,
21
22    /// Prepares and simulates without invoking
23    #[arg(long)]
24    pub dry_run: bool,
25
26    #[command(flatten)]
27    pub config: global::Args,
28}
29
30#[derive(thiserror::Error, Debug)]
31pub enum Error {
32    #[error(transparent)]
33    Invoke(#[from] invoke::Error),
34    #[error(transparent)]
35    Config(#[from] config::Error),
36    #[error(transparent)]
37    Registry(#[from] stellar_registry_build::Error),
38}
39
40impl Cmd {
41    pub async fn run(&self) -> Result<(), Error> {
42        let owner = if let Some(owner) = self.owner.clone() {
43            owner
44        } else {
45            self.config.source_account().await?.to_string()
46        };
47
48        let args = [
49            "register_contract",
50            "--contract_name",
51            &self.contract_name.name,
52            "--contract_address",
53            &self.contract_address,
54            "--owner",
55            &owner,
56        ];
57
58        let registry = Registry::new(&self.config, self.contract_name.channel.as_deref()).await?;
59
60        registry.as_contract().invoke(&args, self.dry_run).await?;
61
62        eprintln!(
63            "{}Successfully registered contract '{}' at {}",
64            if self.dry_run { "Dry Run: " } else { "" },
65            self.contract_name.name,
66            self.contract_address
67        );
68        Ok(())
69    }
70}
71
72#[cfg(feature = "integration-tests")]
73#[cfg(test)]
74mod tests {
75    use stellar_cli::commands::contract::deploy::wasm;
76    use stellar_scaffold_test::RegistryTest;
77
78    #[tokio::test]
79    async fn simple() {
80        let registry = RegistryTest::new().await;
81        let v1 = registry.hello_wasm_v1();
82
83        // Deploy a contract directly (not through registry)
84        let deploy_cmd = registry
85            .parse_cmd::<wasm::Cmd>(&[
86                "--wasm",
87                v1.to_str().unwrap(),
88                "--source",
89                "alice",
90                "--fee=10000000",
91                "--",
92                "--admin=alice",
93            ])
94            .unwrap();
95        let contract_id = deploy_cmd
96            .execute(&deploy_cmd.config, false, false)
97            .await
98            .unwrap()
99            .into_result()
100            .unwrap()
101            .to_string();
102
103        // Now register it in the registry
104        registry
105            .registry_cli("register-contract")
106            .arg("--contract-name")
107            .arg("my-hello")
108            .arg("--contract-address")
109            .arg(&contract_id)
110            .assert()
111            .success();
112
113        // Verify we can fetch the contract ID
114        let fetched_id = registry
115            .parse_cmd::<crate::commands::fetch_contract_id::Cmd>(&["my-hello"])
116            .unwrap()
117            .fetch_contract_id()
118            .await
119            .unwrap();
120        assert_eq!(contract_id, fetched_id.to_string());
121    }
122
123    #[tokio::test]
124    async fn unverified() {
125        let registry = RegistryTest::new().await;
126        let v1 = registry.hello_wasm_v1();
127
128        // Deploy a contract directly (not through registry)
129        let deploy_cmd = registry
130            .parse_cmd::<wasm::Cmd>(&[
131                "--wasm",
132                v1.to_str().unwrap(),
133                "--source",
134                "alice",
135                "--fee=10000000",
136                "--",
137                "--admin=alice",
138            ])
139            .unwrap();
140        let contract_id = deploy_cmd
141            .execute(&deploy_cmd.config, false, false)
142            .await
143            .unwrap()
144            .into_result()
145            .unwrap()
146            .to_string();
147
148        // Now register it in the unverified registry
149        registry
150            .registry_cli("register-contract")
151            .arg("--contract-name")
152            .arg("unverified/my-hello")
153            .arg("--contract-address")
154            .arg(&contract_id)
155            .assert()
156            .success();
157
158        // Verify we can fetch the contract ID
159        let fetched_id = registry
160            .parse_cmd::<crate::commands::fetch_contract_id::Cmd>(&["unverified/my-hello"])
161            .unwrap()
162            .fetch_contract_id()
163            .await
164            .unwrap();
165        assert_eq!(contract_id, fetched_id.to_string());
166    }
167}