> ## Documentation Index
> Fetch the complete documentation index at: https://docs.axiom.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Rust Client SDK

> A reference for the Axiom Rust Client SDK.

export const AXIOM_SDK_VERSION = "v2.0.0";

## Overview

The Axiom Rust SDK is a library for interacting with the Axiom Proving API. It is built on top of the Axiom Proving API and provides a higher-level interface for interacting with the API. This guide covers installation, configuration, and usage of all SDK features.

## Installation

Add the Axiom SDK to your `Cargo.toml`:

<CodeBlock language="toml">
  {`[dependencies]
    axiom-sdk = { git = "https://github.com/axiom-crypto/axiom-api-cli.git", tag = "${AXIOM_SDK_VERSION}" }`}
</CodeBlock>

## Configuration

### Setting Up Your API Key

Before using the SDK, you need to configure your API key. You can do this in several ways:

#### Option 1: Using the CLI (Recommended)

```bash theme={null}
cargo axiom register --api-key <YOUR_API_KEY>
```

#### Option 2: Manual Configuration

Create a configuration file at `~/.axiom/config.json`:

```json theme={null}
{
  "api_url": "https://api.axiom.xyz/v1",
  "api_key": "your-api-key-here",
  "config_id": "your-config-id-here"
}
```

#### Option 3: Programmatic Configuration

```rust theme={null}
use axiom_sdk::{AxiomSdk, AxiomConfig};

let config = AxiomConfig::new(
    "https://api.axiom.xyz/v1".to_string(),
    Some("your-api-key".to_string()),
    Some("your-config-id".to_string()),
);
let sdk = AxiomSdk::new(config);
```

### Progress Callbacks

The SDK supports custom progress callbacks for user feedback during long-running operations:

```rust theme={null}
use axiom_sdk::{AxiomSdk, ProgressCallback};

struct MyCallback;

impl ProgressCallback for MyCallback {
    fn on_success(&self, text: &str) {
        println!("✓ {}", text);
    }
    
    fn on_error(&self, text: &str) {
        eprintln!("✗ {}", text);
    }
    
    fn on_progress_start(&self, message: &str, total: Option<u64>) {
        if let Some(total) = total {
            println!("Starting: {} (total: {})", message, total);
        } else {
            println!("Starting: {}", message);
        }
    }
    
    // Implement other required methods...
    fn on_header(&self, text: &str) { println!("\n=== {} ===", text); }
    fn on_info(&self, text: &str) { println!("ℹ {}", text); }
    fn on_warning(&self, text: &str) { println!("⚠ {}", text); }
    fn on_section(&self, title: &str) { println!("\n--- {} ---", title); }
    fn on_field(&self, key: &str, value: &str) { println!("{}: {}", key, value); }
    fn on_status(&self, text: &str) { print!("\r{}", text); }
    fn on_progress_update(&self, current: u64) { print!("\rProgress: {}", current); }
    fn on_progress_update_message(&self, message: &str) { print!("\r{}", message); }
    fn on_progress_finish(&self, message: &str) { println!("\r{}", message); }
    fn on_clear_line(&self) { print!("\r\x1b[K"); }
    fn on_clear_line_and_reset(&self) { print!("\r\x1b[K"); }
}

// Use your custom callback
let config = load_config()?;
let sdk = AxiomSdk::new(config).with_callback(MyCallback);
```

## Building Programs

The `BuildSdk` trait provides functionality for registering OpenVM guest programs with the
Axiom Proving API.

### Basic Build

```rust theme={null}
use axiom_sdk::build::{BuildSdk, UploadExeArgs};
use std::path::Path;

// Run `cargo openvm build` in this directory first.
let program_dir = Path::new("./my-openvm-guest-program");
let args = UploadExeArgs {
    config_id: None,       // Use default config
    project_id: None,
    project_name: Some("My Project".to_string()),
    bin_name: None,        // Auto-detect binary
    program_name: None,
    default_num_gpus: None,
};

let program_id = sdk.upload_exe(program_dir, args)?;
println!("Program registered with ID: {}", program_id);

// Wait for completion
sdk.wait_for_build_completion(&program_id)?;
```

The SDK reads the OpenVM v2 build output from its default locations: the transpiled VMEXE
at `openvm/release/<bin>.vmexe` (a sibling of `target/`) and the raw ELF at
`target/<openvm-target>/release/<bin>`. A custom `CARGO_TARGET_DIR` or a workspace-level
target directory is not currently supported.

### Build with Custom Configuration

`UploadExeArgs` lets you pin the VM configuration, select a binary, and control how programs
are organized into projects.

#### Configuration Source

Set `config_id` to register the program against a specific VM configuration instead of the
system default. The ID must reference a existing config.

```rust theme={null}
use axiom_sdk::build::UploadExeArgs;

let args = UploadExeArgs {
    config_id: Some("cfg_...".to_string()),
    project_id: Some("existing-project-id".to_string()),
    project_name: None,
    bin_name: Some("my-binary".to_string()),
    program_name: Some("my-program-name".to_string()),
    default_num_gpus: Some(1),
};

let program_id = sdk.upload_exe("./my-program", args)?;
```

#### Binary Target Selection

When your `Cargo.toml` contains multiple binary targets, set `bin_name` to choose which
ELF and VMEXE pair is uploaded. If the crate produces exactly one binary, leave it as
`None` and the SDK detects it.

#### Project Organization

You can control how your programs are organized by either creating new projects or adding programs to existing ones. This is useful for maintaining logical groupings of related programs or when you want to keep all your experimental builds separate from production code.

Set `project_id` to add the program to an existing project, or `project_name` to create a
new one. Use `program_name` to give the program itself a recognizable name instead of the
generated one.

### Managing Build Artifacts

Once you've initiated a build, the SDK provides comprehensive tools to monitor progress, inspect results, and download the generated artifacts. This section covers the various ways to interact with your build results.

#### Listing and Inspecting Programs

The SDK allows you to retrieve information about all your programs, including their current status and any error messages.

```rust theme={null}
// List all programs
let programs = sdk.list_programs()?;
for program in programs {
    println!("Program: {} ({})", program.name, program.id);
    println!("Status: {}", program.status);
    if let Some(error) = program.error_message {
        println!("Error: {}", error);
    }
}
```

**Program Information Available:**

* **Name**: Human-readable identifier for your program
* **ID**: Unique identifier used for API operations
* **Status**: Current build state (pending, building, ready, failed)
* **Error Messages**: Detailed error information if the build failed

#### Monitoring Build Status

You can check the status of a specific build to determine when it's ready or if it has encountered any issues.

```rust theme={null}
// Get specific build status
let build_status = sdk.get_build_status("program-id")?;
println!("Build status: {}", build_status.status);
```

**Build Status Types:**

* **Pending**: Build is queued and waiting to start
* **Building**: Build is currently in progress
* **Ready**: Build completed successfully and artifacts are available
* **Failed**: Build encountered an error and cannot proceed

#### Downloading Build Artifacts

Once a build is complete, you can download various artifacts that were generated during the build process.

```rust theme={null}
// Download build artifacts
sdk.download_program("program-id", "elf")?;
sdk.download_program("program-id", "exe")?;
```

Accepted artifact types are `exe`, `elf`, `source` and `app_exe_commit`.

## Generating Proofs

The `ProveSdk` trait handles proof generation for your built programs.

### Basic Proof Generation

```rust theme={null}
use axiom_sdk::{prove::{ProveSdk, ProveArgs}, ProofType};
use cargo_openvm::input::Input;

let args = ProveArgs {
    program_id: Some("your-program-id".to_string()),
    input: Some(Input::HexBytes("0x01".to_string())), // Bytes input
    proof_type: Some(ProofType::Stark),
};

let proof_id = sdk.generate_new_proof(args)?;
println!("Proof generation started: {}", proof_id);

// Wait for completion
sdk.wait_for_proof_completion(&proof_id)?;
```

### Input Formats

The SDK supports multiple input formats:

```rust theme={null}
use cargo_openvm::input::Input;
use std::path::PathBuf;

// Hex bytes input (must start with 0x01 for bytes or 0x02 for field elements)
let hex_input = Input::HexBytes("0x01010101".to_string());

// JSON file input
let file_input = Input::FilePath(PathBuf::from("./input.json"));

// The JSON file should contain:
// {
//   "input": [
//     "0x01010101",   // bytes
//     "0x02123456"    // field elements
//   ]
// }
```

### EVM Proof Generation

```rust theme={null}
let args = ProveArgs {
    program_id: Some("your-program-id".to_string()),
    input: Some(Input::FilePath(PathBuf::from("./input.json"))),
    proof_type: Some(ProofType::Evm),
};

let proof_id = sdk.generate_new_proof(args)?;
sdk.wait_for_proof_completion(&proof_id)?;
```

### Managing Proofs

Once you've initiated proof generation, the SDK provides comprehensive tools to monitor progress, inspect results, and download the generated proofs. This section covers the various ways to interact with your proof generation jobs and retrieve the final artifacts.

#### Listing and Inspecting Proofs

The SDK allows you to retrieve information about all proofs generated for a specific program.

```rust theme={null}
// List proofs for a program
let proofs = sdk.list_proofs("program-id")?;
for proof in proofs {
    println!("Proof: {} ({})", proof.id, proof.state);
    println!("Type: {}", proof.proof_type);
    if let Some(error) = proof.error_message {
        println!("Error: {}", error);
    }
}
```

**Proof Information Available:**

* **ID**: Unique identifier for the proof generation job
* **State**: Current status of the proof generation (pending, proving, ready, failed)
* **Type**: The type of proof being generated (STARK or EVM)
* **Error Messages**: Detailed error information if the proof generation failed

#### Downloading Proof Artifacts

Once proof generation is complete, you can download the generated proofs in various formats. The SDK provides flexibility in how and where you save these artifacts.

```rust theme={null}
// Download proof artifacts
use std::path::PathBuf;

sdk.get_generated_proof("proof-id", &ProofType::Stark, None)?; // Auto path
sdk.get_generated_proof(
    "proof-id", 
    &ProofType::Evm, 
    Some(PathBuf::from("./my-proof.json"))
)?; // Custom path

// Download proof logs
sdk.get_proof_logs("proof-id")?;
```

## Running Programs

The `RunSdk` trait allows you to execute programs without generating proofs, useful for testing and debugging.

### Basic Execution

```rust theme={null}
use axiom_sdk::run::{RunSdk, RunArgs};
use cargo_openvm::input::Input;

let args = RunArgs {
    program_id: Some("your-program-id".to_string()),
    input: Some(Input::HexBytes("0x01010101".to_string())),
};

let execution_id = sdk.execute_program(args)?;
println!("Execution started: {}", execution_id);

// Wait for completion
sdk.wait_for_execution_completion(&execution_id)?;
```

### Handling Execution Results

```rust theme={null}
// Get execution status
let execution = sdk.get_execution_status("execution-id")?;
println!("Status: {}", execution.status);

if let Some(cycles) = execution.total_cycle {
    println!("Total cycles: {}", cycles);
}

if let Some(ticks) = execution.total_tick {
    println!("Total ticks: {}", ticks);
}

if let Some(public_values) = &execution.public_values {
    println!("Public values: {}", serde_json::to_string_pretty(public_values)?);
}

// Save results to file
if let Some(results_path) = sdk.save_execution_results(&execution) {
    println!("Results saved to: {}", results_path);
}
```

## Verifying Proofs

The `VerifySdk` trait provides proof verification capabilities.

### EVM Proof Verification

```rust theme={null}
use axiom_sdk::verify::VerifySdk;
use std::path::PathBuf;

let proof_path = PathBuf::from("./evm-proof.json");
let verify_id = sdk.verify_evm(None, proof_path)?; // Use default config
println!("Verification started: {}", verify_id);

// Wait for completion
sdk.wait_for_evm_verify_completion(&verify_id)?;
```

#### Custom Configuration for EVM Verification

```rust theme={null}
let verify_id = sdk.verify_evm(
    Some("custom-config-id"), 
    PathBuf::from("./proof.json")
)?;
```

### STARK Proof Verification

```rust theme={null}
let proof_path = PathBuf::from("./stark-proof.json");
let verify_id = sdk.verify_stark("program-id", proof_path)?;
sdk.wait_for_stark_verify_completion(&verify_id)?;
```

## Configuration Management

The `ConfigSdk` trait provides access to VM configurations and related artifacts.

### Getting Configuration Metadata

```rust theme={null}
use axiom_sdk::config::ConfigSdk;

let metadata = sdk.get_vm_config_metadata(None)?; // Use default config
println!("OpenVM Version: {}", metadata.openvm_version);
println!("Status: {}", metadata.status);
println!("Active: {}", metadata.active);

// Get specific config
let metadata = sdk.get_vm_config_metadata(Some("config-id"))?;
```

### Downloading Configuration Artifacts

```rust theme={null}
use std::path::PathBuf;

// Download EVM verifier contract
sdk.get_evm_verifier(None, None)?; // Auto path
sdk.get_evm_verifier(
    Some("config-id"), 
    Some(PathBuf::from("./verifier.json"))
)?; // Custom path

// Download VM commitment
sdk.get_vm_commitment(None, None)?;

// Download configuration file
sdk.download_config(None, None)?;
```

### Working with Proving Keys

```rust theme={null}
// Get proving key downloader
let pk_downloader = sdk.get_proving_keys(None, "app_pk")?;

// Download with default callback
pk_downloader.download_pk("./app_pk")?;

// Download with custom callback
struct MyCallback;
impl ProgressCallback for MyCallback {
    // ... implement methods
}

pk_downloader.download_pk_with_callback("./app_pk", &MyCallback)?;
```

## Project Management

The `ProjectSdk` trait helps organize your programs into projects.

### Creating and Managing Projects

```rust theme={null}
use axiom_sdk::projects::ProjectSdk;

// Create a new project
let project = sdk.create_project("My New Project")?;
println!("Created project: {}", project.id);

// List projects
let projects = sdk.list_projects(Some(1), Some(20))?; // page 1, 20 items
for project in projects.items {
    println!("Project: {} ({})", project.name, project.id);
    println!("Programs: {}", project.program_count);
    println!("Total proofs: {}", project.total_proofs_run);
}

// Get specific project
let project = sdk.get_project("project-id")?;
println!("Project: {}", project.name);
```

### Managing Project Programs

```rust theme={null}
// List programs in a project
let programs = sdk.list_project_programs("project-id", None, None)?;
for program in programs.items {
    println!("Program: {} in project {}", program.id, program.project_name);
}

// Move program to different project
sdk.move_program_to_project("program-id", "new-project-id")?;
```

## Troubleshooting

This section covers common issues you may encounter when using the Axiom Rust Client SDK, along with detailed solutions and preventive measures.

**1. `CLI not initialized` Error**

```bash theme={null}
# Solution: Register your API key
cargo axiom register --api-key <YOUR_API_KEY>
```

**2. `API key not valid or inactive` Error**

* Check that your API key is correct
* Verify your API key is active in the Axiom dashboard
* Ensure you're using the correct API endpoint

**3. `Not in a Rust project` Error**

* Ensure `Cargo.toml` exists in the directory you passed to `upload_exe`

**3a. `OpenVM build output not found` Error**

* Run `cargo openvm build` in the guest crate before registering the program
* The error names the directory it expected, normally `openvm/release`
* If you set `CARGO_TARGET_DIR` or build from a workspace root, the artifacts land outside the expected paths, which are not currently supported

**4. Registration Failures**

```rust theme={null}
// Inspect the failure reason
let status = sdk.get_build_status(&program_id)?;
println!("Status: {}", status.status);
if let Some(error) = status.error_message {
    println!("Error: {}", error);
}
```

**5. Input Validation Errors**

* Hex strings must start with `0x01` (bytes) or `0x02` (field elements)
* JSON input files must have an `"input"` array
* All input values must be valid hex strings

## API Reference

### Core Types

* `AxiomSdk`: Main SDK struct
* `AxiomConfig`: Configuration for API endpoint, key, and default config ID
* `ProgressCallback`: Trait for handling progress events
* `NoopCallback`: Silent progress callback implementation

### Traits

* `BuildSdk`: Program building functionality
* `ProveSdk`: Proof generation functionality
* `RunSdk`: Program execution functionality
* `VerifySdk`: Proof verification functionality
* `ConfigSdk`: Configuration management functionality
* `ProjectSdk`: Project management functionality

### Enums

* `ProofType`: `Evm` or `Stark`
* `ConfigSource`: `ConfigId(String)` or `ConfigPath(String)`
