soroban_cli/commands/contract/info/
env_meta.rs

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