|
| 1 | +use crate::utils::{config, optimizer, print as p, profiler}; |
| 2 | +use anyhow::Result; |
| 3 | +use clap::Subcommand; |
| 4 | +use std::path::PathBuf; |
| 5 | + |
| 6 | +#[derive(Subcommand)] |
| 7 | +pub enum GasCommands { |
| 8 | + /// Analyze a compiled Soroban contract for gas/cpu opportunities |
| 9 | + Analyze { |
| 10 | + /// Path to the compiled wasm |
| 11 | + wasm: PathBuf, |
| 12 | + /// Network context (used for fee heuristics) |
| 13 | + #[arg(long)] |
| 14 | + network: Option<String>, |
| 15 | + }, |
| 16 | + /// Emit an "optimized" wasm (lightweight, heuristic-based) |
| 17 | + Optimize { |
| 18 | + /// Path to the input wasm |
| 19 | + #[arg(long)] |
| 20 | + target: PathBuf, |
| 21 | + /// Output path for optimized wasm |
| 22 | + #[arg(long)] |
| 23 | + output: PathBuf, |
| 24 | + }, |
| 25 | +} |
| 26 | + |
| 27 | +pub fn handle(cmd: GasCommands) -> Result<()> { |
| 28 | + match cmd { |
| 29 | + GasCommands::Analyze { wasm, network } => analyze(wasm, network), |
| 30 | + GasCommands::Optimize { target, output } => optimize(target, output), |
| 31 | + } |
| 32 | +} |
| 33 | + |
| 34 | +fn analyze(wasm: PathBuf, network: Option<String>) -> Result<()> { |
| 35 | + config::validate_file_path(&wasm, Some("wasm"))?; |
| 36 | + |
| 37 | + let cfg = config::load()?; |
| 38 | + let network = network.unwrap_or(cfg.network); |
| 39 | + config::validate_network(&network)?; |
| 40 | + |
| 41 | + p::header("Gas Analyzer"); |
| 42 | + p::kv("Network", &network); |
| 43 | + p::kv("Wasm", &wasm.display().to_string()); |
| 44 | + |
| 45 | + let t = profiler::Timer::start(); |
| 46 | + let report = optimizer::analyze_wasm(&wasm)?; |
| 47 | + let elapsed = t.elapsed(); |
| 48 | + |
| 49 | + println!(); |
| 50 | + p::separator(); |
| 51 | + p::kv_accent("Size (bytes)", &report.size_bytes.to_string()); |
| 52 | + p::kv("SHA256", &report.sha256); |
| 53 | + p::kv("Heuristic score", &report.score.to_string()); |
| 54 | + if !report.suggestions.is_empty() { |
| 55 | + println!(); |
| 56 | + p::info("Suggestions:"); |
| 57 | + for s in &report.suggestions { |
| 58 | + println!(" - {}", s); |
| 59 | + } |
| 60 | + } |
| 61 | + p::separator(); |
| 62 | + p::kv("Duration", &format!("{:?}", elapsed)); |
| 63 | + Ok(()) |
| 64 | +} |
| 65 | + |
| 66 | +fn optimize(target: PathBuf, output: PathBuf) -> Result<()> { |
| 67 | + config::validate_file_path(&target, Some("wasm"))?; |
| 68 | + |
| 69 | + p::header("Gas Optimizer"); |
| 70 | + p::kv("Input", &target.display().to_string()); |
| 71 | + p::kv("Output", &output.display().to_string()); |
| 72 | + |
| 73 | + let t = profiler::Timer::start(); |
| 74 | + let result = optimizer::optimize_wasm(&target, &output)?; |
| 75 | + let elapsed = t.elapsed(); |
| 76 | + |
| 77 | + println!(); |
| 78 | + p::success("Optimization output written"); |
| 79 | + p::kv("Bytes in", &result.input_size_bytes.to_string()); |
| 80 | + p::kv("Bytes out", &result.output_size_bytes.to_string()); |
| 81 | + p::kv("Duration", &format!("{:?}", elapsed)); |
| 82 | + Ok(()) |
| 83 | +} |
0 commit comments