soroban_cli/commands/contract/info/
meta.rs

1use std::fmt::Debug;
2
3use crate::commands::contract::info::meta::Error::{NoMetaPresent, NoSACMeta};
4use crate::commands::contract::info::shared::{self, fetch, Fetched, MetasInfoOutput};
5use crate::commands::global;
6use crate::print::Print;
7use clap::{command, Parser};
8use soroban_spec_tools::contract;
9use soroban_spec_tools::contract::Spec;
10use stellar_xdr::curr::{ScMetaEntry, ScMetaV0};
11
12#[derive(Parser, Debug, Clone)]
13pub struct Cmd {
14    #[command(flatten)]
15    pub common: shared::Args,
16    /// Format of the output
17    #[arg(long, default_value = "text")]
18    pub output: MetasInfoOutput,
19}
20
21#[derive(thiserror::Error, Debug)]
22pub enum Error {
23    #[error(transparent)]
24    Wasm(#[from] shared::Error),
25    #[error(transparent)]
26    Spec(#[from] contract::Error),
27    #[error("Stellar asset contract doesn't contain meta information")]
28    NoSACMeta(),
29    #[error("no meta present in provided WASM file")]
30    NoMetaPresent(),
31    #[error(transparent)]
32    Json(#[from] serde_json::Error),
33}
34
35impl Cmd {
36    pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> {
37        let print = Print::new(global_args.quiet);
38        let Fetched { contract, .. } = fetch(&self.common, &print).await?;
39
40        let spec = match contract {
41            shared::Contract::Wasm { wasm_bytes } => Spec::new(&wasm_bytes)?,
42            shared::Contract::StellarAssetContract => return Err(NoSACMeta()),
43        };
44
45        let Some(meta_base64) = spec.meta_base64 else {
46            return Err(NoMetaPresent());
47        };
48
49        let res = match self.output {
50            MetasInfoOutput::XdrBase64 => meta_base64,
51            MetasInfoOutput::Json => serde_json::to_string(&spec.meta)?,
52            MetasInfoOutput::JsonFormatted => serde_json::to_string_pretty(&spec.meta)?,
53            MetasInfoOutput::Text => {
54                let mut meta_str = "Contract meta:\n".to_string();
55
56                for meta_entry in &spec.meta {
57                    match meta_entry {
58                        ScMetaEntry::ScMetaV0(ScMetaV0 { key, val }) => {
59                            let key = key.to_string();
60                            let val = match key.as_str() {
61                                "rsver" => format!("{val} (Rust version)"),
62                                "rssdkver" => {
63                                    format!("{val} (Soroban SDK version and it's commit hash)")
64                                }
65                                _ => val.to_string(),
66                            };
67                            meta_str.push_str(&format!(" • {key}: {val}\n"));
68                        }
69                    }
70                }
71
72                meta_str
73            }
74        };
75
76        println!("{res}");
77
78        Ok(())
79    }
80}