soroban_cli/commands/contract/info/
meta.rs

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