use std::fmt::Debug;
use crate::commands::contract::info::interface::Error::NoInterfacePresent;
use crate::commands::contract::info::shared::{self, fetch, Fetched};
use crate::commands::global;
use crate::print::Print;
use clap::Parser;
use soroban_spec_rust::ToFormattedString;
use soroban_spec_tools::contract;
use soroban_spec_tools::contract::Spec;
#[derive(Parser, Debug, Clone)]
pub struct Cmd {
#[command(flatten)]
pub common: shared::Args,
#[arg(long, default_value = "rust")]
pub output: InfoOutput,
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, clap::ValueEnum, Default)]
pub enum InfoOutput {
#[default]
Rust,
XdrBase64,
Json,
JsonFormatted,
}
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error(transparent)]
Wasm(#[from] shared::Error),
#[error(transparent)]
Spec(#[from] contract::Error),
#[error("no interface present in provided WASM file")]
NoInterfacePresent(),
#[error(transparent)]
Json(#[from] serde_json::Error),
}
impl Cmd {
pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> {
let print = Print::new(global_args.quiet);
let Fetched { contract, .. } = fetch(&self.common, &print).await?;
let (base64, spec) = match contract {
shared::Contract::Wasm { wasm_bytes } => {
let spec = Spec::new(&wasm_bytes)?;
if spec.env_meta_base64.is_none() {
return Err(NoInterfacePresent());
}
(spec.spec_base64.unwrap(), spec.spec)
}
shared::Contract::StellarAssetContract => {
Spec::spec_to_base64(stellar_asset_spec::xdr())?
}
};
let res = match self.output {
InfoOutput::XdrBase64 => base64,
InfoOutput::Json => serde_json::to_string(&spec)?,
InfoOutput::JsonFormatted => serde_json::to_string_pretty(&spec)?,
InfoOutput::Rust => soroban_spec_rust::generate_without_file(&spec)
.to_formatted_string()
.expect("Unexpected spec format error"),
};
println!("{res}");
Ok(())
}
}