soroban_cli/commands/contract/info/
interface.rs

1use std::fmt::Debug;
2
3use crate::commands::contract::info::interface::Error::NoInterfacePresent;
4use crate::commands::contract::info::shared::{self, fetch, Fetched};
5use crate::commands::global;
6use crate::print::Print;
7use clap::{command, Parser};
8use soroban_spec_rust::ToFormattedString;
9use soroban_spec_tools::contract;
10use soroban_spec_tools::contract::Spec;
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 = "rust")]
18    pub output: InfoOutput,
19}
20
21#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, clap::ValueEnum, Default)]
22pub enum InfoOutput {
23    /// Rust code output of the contract interface
24    #[default]
25    Rust,
26    /// XDR output of the info entry
27    XdrBase64,
28    /// JSON output of the info entry (one line, not formatted)
29    Json,
30    /// Formatted (multiline) JSON output of the info entry
31    JsonFormatted,
32}
33
34#[derive(thiserror::Error, Debug)]
35pub enum Error {
36    #[error(transparent)]
37    Wasm(#[from] shared::Error),
38    #[error(transparent)]
39    Spec(#[from] contract::Error),
40    #[error("no interface present in provided WASM file")]
41    NoInterfacePresent(),
42    #[error(transparent)]
43    Json(#[from] serde_json::Error),
44}
45
46impl Cmd {
47    pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> {
48        let print = Print::new(global_args.quiet);
49        let Fetched { contract, .. } = fetch(&self.common, &print).await?;
50
51        let (base64, spec) = match contract {
52            shared::Contract::Wasm { wasm_bytes } => {
53                let spec = Spec::new(&wasm_bytes)?;
54
55                if spec.env_meta_base64.is_none() {
56                    return Err(NoInterfacePresent());
57                }
58
59                (spec.spec_base64.unwrap(), spec.spec)
60            }
61            shared::Contract::StellarAssetContract => {
62                Spec::spec_to_base64(stellar_asset_spec::xdr())?
63            }
64        };
65
66        let res = match self.output {
67            InfoOutput::XdrBase64 => base64,
68            InfoOutput::Json => serde_json::to_string(&spec)?,
69            InfoOutput::JsonFormatted => serde_json::to_string_pretty(&spec)?,
70            InfoOutput::Rust => soroban_spec_rust::generate_without_file(&spec)
71                .to_formatted_string()
72                .expect("Unexpected spec format error"),
73        };
74
75        println!("{res}");
76
77        Ok(())
78    }
79}