Skip to main content

outlayer_cli/commands/
logs.rs

1use anyhow::{Context, Result};
2
3use crate::api::ApiClient;
4use crate::config::{self, NetworkConfig, ProjectConfig};
5
6/// `outlayer logs` — view execution history (payment key usage)
7pub async fn logs(
8    network: &NetworkConfig,
9    project_config: Option<&ProjectConfig>,
10    nonce: Option<u32>,
11    limit: i64,
12) -> Result<()> {
13    let creds = config::load_credentials(network)?;
14    let api = ApiClient::new(network);
15
16    // Determine nonce from flag, config, or bail
17    let nonce = nonce
18        .or_else(|| {
19            project_config
20                .and_then(|c| c.run.as_ref())
21                .and_then(|r| r.payment_key_nonce)
22        })
23        .context("No payment key nonce. Use --nonce or set payment_key_nonce in outlayer.toml.")?;
24
25    let resp = api
26        .get_payment_key_usage(&creds.account_id, nonce, limit, 0)
27        .await?;
28
29    if resp.usage.is_empty() {
30        eprintln!("No execution history for key nonce {nonce}.");
31        return Ok(());
32    }
33
34    println!(
35        "{:<38} {:<10} {:>10} {:<25}",
36        "CALL_ID", "STATUS", "COST", "PROJECT"
37    );
38
39    for u in &resp.usage {
40        let cost = format_usd(&u.compute_cost);
41        println!(
42            "{:<38} {:<10} {:>10} {:<25}",
43            u.call_id, u.status, cost, u.project_id
44        );
45    }
46
47    if resp.total > limit {
48        eprintln!(
49            "\nShowing {}/{} entries. Use --limit to see more.",
50            resp.usage.len(),
51            resp.total
52        );
53    }
54
55    Ok(())
56}
57
58fn format_usd(minimal_units: &str) -> String {
59    let units: u64 = minimal_units.parse().unwrap_or(0);
60    let dollars = units as f64 / 1_000_000.0;
61    format!("${:.4}", dollars)
62}