soroban_cli/commands/contract/info/
env_meta.rs

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