use super::*;
use leo_ast::NetworkName;
use leo_errors::CliError;
use snarkvm::prelude::{CanaryV0, MainnetV0, TestnetV0};
use std::path::PathBuf;
#[derive(Parser, Debug)]
pub struct LeoAbi {
#[clap(value_name = "FILE")]
file: PathBuf,
#[clap(long, short, default_value = "testnet")]
network: NetworkName,
#[clap(long, short)]
output: Option<PathBuf>,
}
impl Command for LeoAbi {
type Input = ();
type Output = ();
fn log_span(&self) -> Span {
tracing::span!(tracing::Level::INFO, "Leo")
}
fn prelude(&self, _: Context) -> Result<Self::Input> {
Ok(())
}
fn apply(self, _context: Context, _: Self::Input) -> Result<Self::Output> {
if !self.file.exists() {
return Err(CliError::cli_invalid_input(format!("File not found: {}", self.file.display())).into());
}
match self.file.extension().and_then(|s| s.to_str()) {
Some("aleo") => {}
_ => {
return Err(CliError::cli_invalid_input(format!(
"Expected a .aleo file, got: {}",
self.file.display()
))
.into());
}
}
let content = std::fs::read_to_string(&self.file).map_err(CliError::cli_io_error)?;
let file_name = self.file.file_name().and_then(|s| s.to_str()).unwrap_or("unknown");
let aleo_program = match self.network {
NetworkName::MainnetV0 => leo_disassembler::disassemble_from_str::<MainnetV0>(file_name, &content),
NetworkName::TestnetV0 => leo_disassembler::disassemble_from_str::<TestnetV0>(file_name, &content),
NetworkName::CanaryV0 => leo_disassembler::disassemble_from_str::<CanaryV0>(file_name, &content),
}
.map_err(|e| CliError::failed_to_parse_aleo_file(file_name, e))?;
let abi = leo_abi::aleo::generate(&aleo_program);
let json = serde_json::to_string_pretty(&abi).map_err(|e| CliError::failed_to_serialize_abi(e.to_string()))?;
match self.output {
Some(path) => {
std::fs::write(&path, &json).map_err(CliError::failed_to_write_abi)?;
tracing::info!("ABI written to '{}'.", path.display());
}
None => {
println!("{json}");
}
}
Ok(())
}
}