Skip to main content

soroban_cli/commands/contract/info/
hash.rs

1use std::path::PathBuf;
2
3use clap::Parser;
4
5use crate::{
6    commands::global,
7    config::{
8        self, locator,
9        network::{self},
10    },
11    wasm,
12};
13
14#[derive(Parser, Debug, Clone)]
15#[command(group(
16    clap::ArgGroup::new("source")
17        .required(true)
18        .args(&["wasm", "contract_id"]),
19))]
20#[group(skip)]
21pub struct Cmd {
22    /// Path to a local .wasm file.
23    #[arg(long, conflicts_with = "contract_id")]
24    pub wasm: Option<PathBuf>,
25    /// Contract ID or alias of a deployed contract.
26    #[arg(
27        long,
28        visible_alias = "id",
29        env = "STELLAR_CONTRACT_ID",
30        conflicts_with = "wasm"
31    )]
32    pub contract_id: Option<config::UnresolvedContract>,
33    #[command(flatten)]
34    pub network: network::Args,
35    #[command(flatten)]
36    pub locator: locator::Args,
37}
38
39#[derive(thiserror::Error, Debug)]
40pub enum Error {
41    #[error(transparent)]
42    Wasm(#[from] wasm::Error),
43    #[error(transparent)]
44    Network(#[from] network::Error),
45    #[error(transparent)]
46    Locator(#[from] locator::Error),
47}
48
49impl Cmd {
50    pub async fn run(&self, _global_args: &global::Args) -> Result<(), Error> {
51        let hash = if let Some(path) = &self.wasm {
52            wasm::Args { wasm: path.clone() }.hash()?
53        } else if let Some(contract_id) = &self.contract_id {
54            let network = self.network.get(&self.locator)?;
55            let resolved =
56                contract_id.resolve_contract_id(&self.locator, &network.network_passphrase)?;
57            wasm::fetch_wasm_hash_from_contract(&resolved, &network).await?
58        } else {
59            unreachable!("clap ArgGroup guarantees one of --wasm or --contract-id is set");
60        };
61
62        println!("{hash}");
63        Ok(())
64    }
65}